Fork for the GitHub
Revision 0:de13951f30f6, committed 2019-11-14
- Comitter:
- DiegoOstuni
- Date:
- Thu Nov 14 10:34:11 2019 +0000
- Commit message:
- Add files
Changed in this revision
diff -r 000000000000 -r de13951f30f6 .gitignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.gitignore Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,32 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app
diff -r 000000000000 -r de13951f30f6 LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LICENSE Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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.
diff -r 000000000000 -r de13951f30f6 NDEFcommon.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NDEFcommon.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,85 @@ +/** + ****************************************************************************** + * @file common.h + * @author MMY Application Team + * @version $Revision: 3343 $ + * @date $Date: 2017-01-24 16:07:22 +0100 (Tue, 24 Jan 2017) $ + * @brief Header for main.c module + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2017 STMicroelectronics</center></h2> + * + * Licensed under MMY-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __COMMON_H +#define __COMMON_H + +/* Includes ------------------------------------------------------------------*/ +//#include "x_nucleo_nfc04a1_nfctag.h" +#include <string.h> +#include "stdint.h" + +/* Exported types ------------------------------------------------------------*/ +//typedef uint8_t boolean; + +/** + * @brief GPO status information structure definition + */ +typedef struct +{ + uint8_t WritenEEPROM; + uint8_t RfBusy; + uint8_t FieldOn; + uint8_t FieldOff; + uint8_t MsgInMailbox; + uint8_t MailboxMsgRead; + uint8_t RfInterrupt; + uint8_t Rfuser; +} IT_GPO_STATUS; + +/* Exported macro ------------------------------------------------------------*/ +#ifndef MIN +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#endif + +/* +#undef FAIL +#define FAIL 0 + +#undef PASS +#define PASS !FAIL +*/ + +#define NFCTAG_4K_SIZE ((uint32_t) 0x200) +#define NFCTAG_16K_SIZE ((uint32_t) 0x800) +#define NFCTAG_64K_SIZE ((uint32_t) 0x2000) + +/* Exported constants --------------------------------------------------------*/ +#define MAX_NDEF_MEM 0x200 +#define ST25DV_MAX_SIZE NFCTAG_4K_SIZE +#define ST25DV_NDEF_MAX_SIZE MIN(ST25DV_MAX_SIZE,MAX_NDEF_MEM) +#define NFC_DEVICE_MAX_NDEFMEMORY ST25DV_NDEF_MAX_SIZE + +#define RESULTOK 0x00 +#define ERRORCODE_GENERIC 1 + +/* Exported functions ------------------------------------------------------- */ + +#endif /* __COMMON_H */ + +/************************ (C) COPYRIGHT 2017 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.md Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,4 @@ +# libNDEF +libNDEF is a library used for STMicroelectronics X-NUCLEO-NFC04A1 expansion board. +# Overview +It is the library used to manage the content of the TAG (data). But also the specific feature of the tag, for instance: password, gpo, and so on.
diff -r 000000000000 -r de13951f30f6 lib_NDEF.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,749 @@ +/** + ****************************************************************************** + * @file lib_NDEF.c + * @author MMY Application Team + * @version $Revision: 3210 $ + * @date $Date: 2016-12-05 15:37:48 +0100 (Mon, 05 Dec 2016) $ + * @brief This file help to manage NDEF file, to parse and identify them. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" +#include "lib_NDEF_Bluetooth.h" +#include "lib_NDEF_Handover.h" +#include "lib_NDEF_Wifi.h" +#include "mbed.h" + +/** @addtogroup NFC_libraries + * @{ + * @brief <b>This is the library used to manage the content of the TAG (data) + * But also the specific feature of the tag, for instance + * password, gpo... </b> + */ + + +/** @addtogroup libNFC_FORUM + * @{ + * @brief This part of the library manage data which follow NFC forum organisation. + */ + +/** @defgroup libNDEF_Private_Functions + * @{ + */ + + +static uint16_t NDEF_IsNDEFPresent( I2C* mi2cChannel ); +static uint16_t NDEF_ParseRecordHeader( sRecordInfo_t *pRecordStruct ); +static void NDEF_ParseWellKnownType( sRecordInfo_t *pRecordStruct ); +static void NDEF_ParseMediaType( sRecordInfo_t *pRecordStruct ); +static void NDEF_ParseForumExternalType( sRecordInfo_t *pRecordStruct ); +static void NDEF_ParseURI( sRecordInfo_t *pRecordStruct ); +static void NDEF_ParseSP( sRecordInfo_t *pRecordStruct ); +static uint16_t NDEF_IdentifySPRecord( sRecordInfo_t *pRecordStruct, uint8_t* pPayload ); + +/** @brief This buffer is used to store the data sent/received by the TAG. */ +uint8_t NDEF_Buffer [NDEF_MAX_SIZE]; +/** @brief Size of the buffer used to build the NDEF messages. */ +uint32_t NDEF_Buffer_size = NDEF_MAX_SIZE; +/** @brief This buffer is used when it's required to prepare a record before adding it to the NDEF_Buffer. */ +uint8_t NDEF_Record_Buffer [NDEF_RECORD_MAX_SIZE]; +/** @brief Size of the buffer used when a record has to be prepared. */ +uint32_t NDEF_Record_Buffer_size = NDEF_RECORD_MAX_SIZE; + +/* In case of smart Poster composed with different record, 3 records supported so far */ +sRecordInfo_t SPRecordStruct1, SPRecordStruct2, SPRecordStruct3, SPRecordStruct4; +sRecordInfo_t *SPRecordStructAdd[SP_MAX_RECORD] = { &SPRecordStruct1, &SPRecordStruct2, &SPRecordStruct3, &SPRecordStruct4 }; + +/** + * @brief This function checks that the tag contain a NDEF message. + * @retval NDEF_OK : There is a NDEF file stored in tag. + * @retval NDEF_ERROR : No NDEF in the tag. + */ +static uint16_t NDEF_IsNDEFPresent( I2C* mi2cChannel ) +{ + uint16_t FileSize; + + /* Check NDEF existence */ + NfcTag_GetLength(&FileSize, mi2cChannel); + + if( FileSize != 0 ) + return NDEF_OK; + else + return NDEF_ERROR; +} + +/** + * @brief This function identify the type of record. + * @param pRecordStruct : pointer on the record structure to fill. + * @param pPayload : pointer on the payload. + * @retval Status : Status of the operation. + */ +static uint16_t NDEF_IdentifySPRecord( sRecordInfo_t *pRecordStruct, uint8_t* pPayload ) +{ + uint16_t status = NDEF_ERROR; + uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte; + + /* Is ID length field present */ + if( (*pPayload) & IL_Mask ) + { + IDLengthField = ID_LENGTH_FIELD; + } + else + { + IDLengthField = 0; + } + + /* it's a SR */ + if( (*pPayload) & SR_Mask ) + { + TypeNbByte = pPayload[1]; + PayloadLengthField = 1; + if( IDLengthField == ID_LENGTH_FIELD ) + IDNbByte = pPayload[3]; + else + IDNbByte = 0; + } + else + { + TypeNbByte = pPayload[1]; + PayloadLengthField = 4; + if( IDLengthField == ID_LENGTH_FIELD ) + IDNbByte = pPayload[6]; + else + IDNbByte = 0; + } + + SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte; + + /* it's a SR */ + if( pPayload[0] & SR_Mask ) + { + pRecordStruct->RecordFlags = pPayload[0]; + pRecordStruct->TypeLength = TypeNbByte; + pRecordStruct->PayloadLength = pPayload[2]; + pRecordStruct->IDLength = IDNbByte; + memcpy( pRecordStruct->Type, &pPayload[3+IDNbByte], TypeNbByte ); + memcpy( pRecordStruct->ID, &pPayload[3+IDNbByte+TypeNbByte], IDNbByte ); + pRecordStruct->PayloadOffset = SizeOfRecordHeader; + } + else + { + pRecordStruct->RecordFlags = pPayload[0]; + pRecordStruct->TypeLength = TypeNbByte; + pRecordStruct->PayloadLength = ( ((uint32_t)pPayload[2]) << 24 ) | + ( ((uint32_t)pPayload[3]) << 16 ) | + ( ((uint32_t)pPayload[4]) << 8 ) + | pPayload[5] ; + pRecordStruct->IDLength = IDNbByte; + memcpy( pRecordStruct->Type, &pPayload[6+IDNbByte], TypeNbByte ); + memcpy( pRecordStruct->ID, &pPayload[6+IDNbByte+TypeNbByte], IDNbByte ); + pRecordStruct->PayloadOffset = SizeOfRecordHeader; + } + + pRecordStruct->PayloadBufferAdd = pPayload + SizeOfRecordHeader ; + + status = NDEF_ParseRecordHeader( pRecordStruct ); + + return status; +} + +/** + * @brief This function parse the record header and dispatch regarding TNF value. + * @param pRecordStruct : pointer on the record structure to fill. + * @retval NDEF_OK : record identified and structure filled. + * @retval NDEF_ERROR : Not supported. + */ +static uint16_t NDEF_ParseRecordHeader( sRecordInfo_t *pRecordStruct ) +{ + uint16_t status = NDEF_OK; + + switch( (pRecordStruct->RecordFlags & TNF_Mask) ) + { + case TNF_WellKnown: + NDEF_ParseWellKnownType( pRecordStruct ); + break; + + case TNF_MediaType: + NDEF_ParseMediaType( pRecordStruct ); + break; + + case TNF_NFCForumExternal: + NDEF_ParseForumExternalType( pRecordStruct); + break; + + default: + /* currently not supported or unknown*/ + pRecordStruct->NDEF_Type = UNKNOWN_TYPE; + status = NDEF_ERROR; + } + return status; +} + +/** + * @brief This function parse the Well Known type record. + * @param pRecordStruct : pointer on the record structure to fill. + */ +static void NDEF_ParseWellKnownType( sRecordInfo_t *pRecordStruct ) +{ + uint8_t* pPayload; + + pPayload = (uint8_t*)( pRecordStruct->PayloadBufferAdd ); + + if( !memcmp( &(pRecordStruct->Type), SMART_POSTER_TYPE_STRING, pRecordStruct->TypeLength ) ) + { + /* special case where we have to parse others records */ + pRecordStruct->NDEF_Type = SMARTPOSTER_TYPE; + NDEF_ParseSP( pRecordStruct ); + } + + else if( !memcmp( &(pRecordStruct->Type), URI_TYPE_STRING, pRecordStruct->TypeLength ) ) + { + /* it's an URI Type check if it's an URL or SMS or ... */ + /* check identifier */ + if( *pPayload == URI_ID_0x00 ) + { + NDEF_ParseURI( pRecordStruct ); + } + else if( (*pPayload > URI_ID_0x00) && (*pPayload < URI_RFU) ) + { + /* email special case */ + if( *pPayload == (uint8_t) URI_ID_0x06 ) + { + pRecordStruct->NDEF_Type = URI_EMAIL_TYPE; + } + else + { + pRecordStruct->NDEF_Type = WELL_KNOWN_ABRIDGED_URI_TYPE; + } + } + else + { + pRecordStruct->NDEF_Type = UNKNOWN_TYPE; + } + } + + else if( !memcmp( &(pRecordStruct->Type), TEXT_TYPE_STRING, pRecordStruct->TypeLength ) ) + { + pRecordStruct->NDEF_Type = TEXT_TYPE; + } else if ((!memcmp( &(pRecordStruct->Type), NDEF_HANDOVER_SELECT_TYPE_STR, pRecordStruct->TypeLength )) || + (!memcmp( &(pRecordStruct->Type), NDEF_HANDOVER_REQUEST_TYPE_STR, pRecordStruct->TypeLength ) )) + { + pRecordStruct->NDEF_Type = HANDOVER_TYPE; + } + else + pRecordStruct->NDEF_Type = UNKNOWN_TYPE; +} + +/** + * @brief This function parse the Media type record. + * @param pRecordStruct : pointer on the record structure to fill. + */ +static void NDEF_ParseMediaType( sRecordInfo_t *pRecordStruct ) +{ + if( !memcmp( &(pRecordStruct->Type), VCARD_TYPE_STRING, pRecordStruct->TypeLength ) ) + pRecordStruct->NDEF_Type = VCARD_TYPE; + else if( !memcmp( &(pRecordStruct->Type), XVCARD_TYPE_STRING, pRecordStruct->TypeLength ) ) + pRecordStruct->NDEF_Type = VCARD_TYPE; + else if( !memcmp( &(pRecordStruct->Type), XVCARD2_TYPE_STRING, pRecordStruct->TypeLength ) ) + pRecordStruct->NDEF_Type = VCARD_TYPE; + else if (!memcmp(&pRecordStruct->Type, NDEF_BLUETOOTH_BREDR_MIME_TYPE, pRecordStruct->TypeLength)) + pRecordStruct->NDEF_Type = BT_TYPE; + else if (!memcmp(&pRecordStruct->Type, NDEF_BLUETOOTH_BLE_MIME_TYPE, pRecordStruct->TypeLength)) + pRecordStruct->NDEF_Type = BLE_TYPE; + else if (!memcmp(&pRecordStruct->Type, WIFITOKEN_TYPE_STRING, pRecordStruct->TypeLength)) + pRecordStruct->NDEF_Type = URI_WIFITOKEN_TYPE; + else + pRecordStruct->NDEF_Type = UNKNOWN_TYPE; +} + +/** + * @brief This function parse the Forum External type record. + * @param pRecordStruct : pointer on the record structure to fill. + */ +static void NDEF_ParseForumExternalType( sRecordInfo_t *pRecordStruct ) +{ + if( !memcmp( &(pRecordStruct->Type), M24SR_DISCOVERY_APP_STRING, pRecordStruct->TypeLength ) ) + pRecordStruct->NDEF_Type = M24SR_DISCOVERY_APP_TYPE; + else + pRecordStruct->NDEF_Type = UNKNOWN_TYPE; +} + +/** + * @brief This function parse the URI type record. + * @param pRecordStruct : pointer on the record structure to fill. + */ +static void NDEF_ParseURI( sRecordInfo_t *pRecordStruct ) +{ + uint8_t* pPayload; + + pPayload = (uint8_t*)( pRecordStruct->PayloadBufferAdd ); + pPayload++; /* to skip URI identifier first URI payload byte */ + + if( !memcmp( pPayload, SMS_TYPE_STRING, strlen(SMS_TYPE_STRING) ) ) + { + pRecordStruct->NDEF_Type = URI_SMS_TYPE; + } + else if( !memcmp( pPayload, GEO_TYPE_STRING, strlen(GEO_TYPE_STRING) ) ) + { + pRecordStruct->NDEF_Type = URI_GEO_TYPE; + } + else + pRecordStruct->NDEF_Type = UNKNOWN_TYPE; +} + +/** + * @brief This function parse the Smart Poster. + * @param pRecordStruct : pointer on the record structure to fill. + */ +static void NDEF_ParseSP( sRecordInfo_t *pRecordStruct ) +{ + uint8_t* pPayload; + uint32_t PayloadSize = 0; + uint32_t SPPayloadSize = 0; + uint32_t OffsetInSPPayload = 0; + uint32_t RecordPosition = 0; + sRecordInfo_t *pSPRecordStruct; + + /* initialize variable with size of the payload and poiter on data */ + PayloadSize = pRecordStruct->PayloadLength; + + pPayload = (uint8_t*)( pRecordStruct->PayloadBufferAdd ); + + pSPRecordStruct = SPRecordStructAdd[0]; + + /* Initailize the number of record find in the SP payload */ + pRecordStruct->NbOfRecordInSPPayload = 0; + + do + { + pSPRecordStruct = SPRecordStructAdd[RecordPosition]; + /* identify the record in the SP payload */ + if( NDEF_IdentifySPRecord( pSPRecordStruct, pPayload ) == NDEF_OK ) + { + /* store add of structure that will contain the other record information */ + pRecordStruct->NbOfRecordInSPPayload++; + pRecordStruct->SPRecordStructAdd[RecordPosition] = pSPRecordStruct; + + /* After SPRecord + First Record check if we are at the end of NDEF file */ + SPPayloadSize = pSPRecordStruct->PayloadLength; + + OffsetInSPPayload += pSPRecordStruct->PayloadOffset + SPPayloadSize; + pPayload += OffsetInSPPayload; + } + else /* Recommended Action Record for example */ + { + SPPayloadSize = 0; + } + RecordPosition++; + } + while( (OffsetInSPPayload < PayloadSize) && RecordPosition<SP_MAX_RECORD); /* there is another record */ +} + +/** + * @} + */ + +/** @defgroup libNDEF_Public_Functions + * @{ + */ + + +/** + * @brief This function identify the NDEF message stored in tag. + * @param pRecordStruct : Structure to fill with record information. + * @param pNDEF : pointer on the NDEF message data. + * @retval NDEF_OK : record struct filled. + * @retval NDEF_ERROR : record struct not updated. + */ +uint16_t NDEF_IdentifyNDEF( sRecordInfo_t *pRecordStruct, uint8_t* pNDEF, I2C* mi2cChannel ) +{ + uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte; + + /* check NDEF present */ + if( NDEF_IsNDEFPresent(mi2cChannel) != NDEF_OK ) + { + return NDEF_ERROR; + } + + /* Read the NDEF file */ + NfcTag_ReadNDEF( pNDEF, mi2cChannel ); + + /* Is ID length field present */ + if( (*pNDEF) & IL_Mask ) + { + IDLengthField = ID_LENGTH_FIELD; + } + else + { + IDLengthField = 0; + } + + /* it's a SR */ + if( (*pNDEF) & SR_Mask ) + { + /* Analyse short record layout */ + TypeNbByte = pNDEF[1]; + PayloadLengthField = 1; + if( IDLengthField == ID_LENGTH_FIELD ) + IDNbByte = pNDEF[3]; + else + IDNbByte = 0; + } + else + { + /* Analyse normal record layout */ + TypeNbByte = pNDEF[1]; + PayloadLengthField = 4; + if( IDLengthField == ID_LENGTH_FIELD ) + IDNbByte = pNDEF[6]; + else + IDNbByte = 0; + } + + SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte; + + /* Read record header */ + /* it's a SR */ + if( pNDEF[0] & SR_Mask ) + { + pRecordStruct->RecordFlags = pNDEF[0]; + pRecordStruct->TypeLength = TypeNbByte; + pRecordStruct->PayloadLength = pNDEF[2]; + pRecordStruct->IDLength = IDNbByte; + memcpy( pRecordStruct->Type, &pNDEF[3+IDNbByte], TypeNbByte ); + memcpy( pRecordStruct->ID, &pNDEF[3+IDNbByte+TypeNbByte], IDNbByte ); + pRecordStruct->PayloadOffset = SizeOfRecordHeader; + } + else + { + pRecordStruct->RecordFlags = pNDEF[0]; + pRecordStruct->TypeLength = TypeNbByte; + pRecordStruct->PayloadLength = ( ((uint32_t)pNDEF[2]) << 24 ) | + ( ((uint32_t)pNDEF[3]) << 16 ) | + ( ((uint32_t)pNDEF[4]) << 8 ) + | pNDEF[5] ; + pRecordStruct->IDLength = IDNbByte; + memcpy( pRecordStruct->Type, &pNDEF[6+IDNbByte], TypeNbByte ); + memcpy( pRecordStruct->ID, &pNDEF[6+IDNbByte+TypeNbByte], IDNbByte ); + pRecordStruct->PayloadOffset = SizeOfRecordHeader; + } + + pRecordStruct->PayloadBufferAdd = pNDEF; + + NDEF_ParseRecordHeader( pRecordStruct ); + + return NDEF_OK; +} + +/** + * @brief This function read the NDEF content of the TAG. + * @param pNDEF : pointer on the buffer to store NDEF data. + * @retval NDEF_OK : NDEF file data retrieve and store in the buffer. + * @retval NDEF_ERROR : not able to read NDEF from tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot read tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be read. + */ +uint16_t NDEF_ReadNDEF( uint8_t* pNDEF, I2C* mi2cChannel ) +{ + return NfcTag_ReadNDEF( pNDEF, mi2cChannel ); +} + + + +/** + * @brief This function read the NDEF size of the TAG. + * @param Size : pointer to a 16-bit Size (in bytes) to be returned. + * @retval NDEF_OK : NDEF file data retrieve and store in the buffer. + * @retval NDEF_ERROR : not able to read NDEF from tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot read tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be read. + */ +uint16_t NDEF_getNDEFSize(uint16_t* Size, I2C* mi2cChannel) +{ + return NfcTag_GetLength(Size, mi2cChannel); +} +/** + * @brief This function write the NDEF in the TAG. + * @param pNDEF : pointer on the buffer containing the NDEF data. + * @retval NDEF_OK : NDEF file data written in the tag. + * @retval NDEF_ERROR : not able to store NDEF in tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write. + */ +uint16_t NDEF_WriteNDEF( uint16_t NDEF_Size, uint8_t *pNDEF, I2C* mi2cChannel ) +{ + return NfcTag_WriteNDEF( NDEF_Size, pNDEF, mi2cChannel ); + +} + +/** + * @brief This function append the record to an the NDEF in the TAG. + * @param pRecord : pointer on the record with data to be written. + * @retval NDEF_OK : NDEF file data written in the tag. + * @retval NDEF_ERROR : not able to store NDEF in tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write. + */ +uint16_t NDEF_AppendRecord(sRecordInfo_t *Record, I2C* mi2cChannel ) +{ + uint16_t status; + uint16_t NDEF_Size = 0; + uint8_t* pData = NDEF_Buffer; + + status = NDEF_getNDEFSize(&NDEF_Size, mi2cChannel); + if(status != NDEF_OK) return status ; + + if(NDEF_Size != 0) + { + // There are already records in the NDEF + Record->RecordFlags &= ~MB_Mask; + + status = NfcTag_ReadNDEF(pData, mi2cChannel); + if(status != NDEF_OK) return status ; + + uint8_t* pNdefRecord; + sRecordInfo_t LastRecord; + do { + pNdefRecord = pData; + NDEF_IdentifyBuffer(&LastRecord,pData); + pData += LastRecord.PayloadOffset + LastRecord.PayloadLength; + // TO DO: add a security condition to avoid infinite loop if NDEF file is corrupted + } while(!(LastRecord.RecordFlags & ME_Mask)); + LastRecord.RecordFlags &= ~ME_Mask; + *pNdefRecord = LastRecord.RecordFlags; + } else { + // This will be the first message in memory + Record->RecordFlags |= MB_Mask; + } + Record->RecordFlags |= ME_Mask; + uint32_t RecordLength = NDEF_WriteRecord(Record,pData, mi2cChannel); + + + return NfcTag_WriteNDEF( NDEF_Size + RecordLength, NDEF_Buffer, mi2cChannel ); + +} + + + +/** + * @brief This function identify the NDEF message stored in tag. + * @param pRecordStruct : Structure to fill with record information. + * @param pNDEF : pointer on the NDEF message data. + * @retval NDEF_OK : record struct filled. + * @retval NDEF_ERROR : record struct not updated. + */ +uint16_t NDEF_IdentifyBuffer( sRecordInfo_t *pRecordStruct, uint8_t* pNDEF ) +{ + uint16_t SizeOfRecordHeader, TypeNbByte, PayloadLengthField, IDLengthField, IDNbByte; + + /* Is ID length field present */ + if( (*pNDEF) & IL_Mask ) + { + IDLengthField = ID_LENGTH_FIELD; + } + else + { + IDLengthField = 0; + } + + /* it's a SR */ + if( (*pNDEF) & SR_Mask ) + { + /* Analyse short record layout */ + TypeNbByte = pNDEF[1]; + PayloadLengthField = 1; + if( IDLengthField == ID_LENGTH_FIELD ) + IDNbByte = pNDEF[3]; + else + IDNbByte = 0; + } + else + { + /* Analyse normal record layout */ + TypeNbByte = pNDEF[1]; + PayloadLengthField = 4; + if( IDLengthField == ID_LENGTH_FIELD ) + IDNbByte = pNDEF[6]; + else + IDNbByte = 0; + } + + SizeOfRecordHeader = RECORD_FLAG_FIELD + TYPE_LENGTH_FIELD + PayloadLengthField + IDLengthField + TypeNbByte + IDNbByte; + + /* it's a SR */ + if( pNDEF[0] & SR_Mask ) + { + pRecordStruct->RecordFlags = pNDEF[0]; + pRecordStruct->TypeLength = TypeNbByte; + pRecordStruct->PayloadLength = pNDEF[2]; + pRecordStruct->IDLength = IDNbByte; + memcpy( pRecordStruct->Type, &pNDEF[3+IDLengthField], TypeNbByte ); + memcpy( pRecordStruct->ID, &pNDEF[3+IDLengthField+TypeNbByte], IDNbByte ); + pRecordStruct->PayloadOffset = SizeOfRecordHeader; + } + else + { + pRecordStruct->RecordFlags = pNDEF[0]; + pRecordStruct->TypeLength = TypeNbByte; + pRecordStruct->PayloadLength = ( ((uint32_t)pNDEF[2]) << 24 ) | + ( ((uint32_t)pNDEF[3]) << 16 ) | + ( ((uint32_t)pNDEF[4]) << 8 ) + | pNDEF[5] ; + pRecordStruct->IDLength = IDNbByte; + memcpy( pRecordStruct->Type, &pNDEF[6+IDNbByte], TypeNbByte ); + memcpy( pRecordStruct->ID, &pNDEF[6+IDNbByte+TypeNbByte], IDNbByte ); + pRecordStruct->PayloadOffset = SizeOfRecordHeader; + } + + pRecordStruct->PayloadBufferAdd = &pNDEF[pRecordStruct->PayloadOffset]; + + NDEF_ParseRecordHeader( pRecordStruct ); + + return NDEF_OK; +} + +/** + * @brief This function writes a record into a NDEF buffer. (update SR flag if required) + * @param pRecord : Structure with record information to be written. + * @param pNDEF : pointer on the NDEF buffer. + * @retval Length : Length of the written data (in bytes) + */ +uint32_t NDEF_WriteRecord( sRecordInfo_t *pRecord, uint8_t* pNDEF, I2C* mi2cChannel ) +{ + /************************************/ +/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */ +/*----------------------------------*/ +/* MB ME CF SR IL TNF */ +/*----------------------------------*/ +/* TYPE LENGTH */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 3 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 2 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 1 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 0 */ +/*----------------------------------*/ +/* ID LENGTH */ +/*----------------------------------*/ +/* TYPE */ +/*----------------------------------*/ +/* ID */ +/*----------------------------------*/ +/* PAYLOAD */ +/************************************/ + uint8_t * start = pNDEF; + + // start by considering payload length + if(pRecord->PayloadLength <= 0xFF) + pRecord->RecordFlags |= SR_Mask; + else + pRecord->RecordFlags &= ~SR_Mask; + + // Then start writing! + *pNDEF++ = pRecord->RecordFlags; + + *pNDEF++ = pRecord->TypeLength; + + if (!(pRecord->RecordFlags & SR_Mask)) + { + *pNDEF++ = (pRecord->PayloadLength >> 24) & 0xFF; + *pNDEF++ = (pRecord->PayloadLength >> 16) & 0xFF ; + *pNDEF++ = (pRecord->PayloadLength >> 8) & 0xFF; + } + *pNDEF++ = (pRecord->PayloadLength) & 0xFF; + + if(pRecord->RecordFlags & IL_Mask) + *pNDEF++ = (pRecord->IDLength); + + memcpy(pNDEF,pRecord->Type,pRecord->TypeLength); + pNDEF += pRecord->TypeLength; + + if(pRecord->RecordFlags & IL_Mask) + { + memcpy(pNDEF,pRecord->ID,pRecord->IDLength); + pNDEF += pRecord->IDLength; + } + + memcpy(pNDEF,pRecord->PayloadBufferAdd,pRecord->PayloadLength); + pNDEF += pRecord->PayloadLength; + + return (pNDEF - start); +} + +/** + * @brief This function return the length a record data (update SR flag if required) + * @param pRecord : Structure with record information + * @retval Length : Length of the data (in bytes) + */ +uint32_t NDEF_GetRecordLength( sRecordInfo_t *pRecord ) +{ + // start by considering payload length + if(pRecord->PayloadLength <= 0xFF) + pRecord->RecordFlags |= SR_Mask; + else + pRecord->RecordFlags &= ~SR_Mask; + + // Then compute the length + uint32_t length = 1 + // Flags + 1 + // Type length + ((pRecord->RecordFlags & SR_Mask)? 1 : 4) + // Payload length + ((pRecord->RecordFlags & IL_Mask)? 1 : 0) + // ID length + pRecord->TypeLength + // Type + ((pRecord->RecordFlags & IL_Mask)? pRecord->IDLength : 0) + // ID + pRecord->PayloadLength; // Payload; + + return length; +} + +/** + * @brief This function clears the NDEF file + * @retval NDEF Status + */ +uint16_t NDEF_ClearNDEF(I2C* mi2cChannel) +{ + return NDEF_WriteNDEF(0 , NULL, mi2cChannel); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,268 @@ +/** + ****************************************************************************** + * @file lib_NDEF.h + * @author MMY Application Team + * @version $Revision: 2762 $ + * @date $Date: 2016-08-10 16:40:40 +0200 (Wed, 10 Aug 2016) $ + * @brief This file help to manage NDEF file. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_NDEF_H +#define __LIB_NDEF_H + +/* Includes ------------------------------------------------------------------*/ +/* include file which match the HW configuration */ +#include "lib_wrapper.h" +#include <string.h> + + + +#define NDEF_ACTION_COMPLETED 0x9000 + +#ifndef errorchk +#define errorchk(fCall) if (status = (fCall), status != NDEF_ACTION_COMPLETED) \ + {goto Error;} else +#endif + +/* Error codes for Higher level */ +#define NDEF_OK RESULTOK +#define NDEF_ERROR ERRORCODE_GENERIC +#define NDEF_ERROR_MEMORY_TAG 2 +#define NDEF_ERROR_MEMORY_INTERNAL 3 +#define NDEF_ERROR_LOCKED 4 +#define NDEF_ERROR_NOT_FORMATED 5 + +//#define NDEF_MAX_SIZE NFC_DEVICE_MAX_NDEFMEMORY +//#define NDEF_RECORD_MAX_SIZE (512) +#define NDEF_MAX_SIZE (100) +#define NDEF_RECORD_MAX_SIZE (100) + +#define NDEF_SIZE_OFFSET 0 +#define FIRST_RECORD_OFFSET 0 + +#define RECORD_FLAG_FIELD 1 +#define TYPE_LENGTH_FIELD 1 +#define ID_LENGTH_FIELD 1 + + +#define MB_Mask ((uint8_t)(0x80)) +#define ME_Mask ((uint8_t)(0x40)) +#define CF_Mask ((uint8_t)(0x20)) +#define SR_Mask ((uint8_t)(0x10)) +#define IL_Mask ((uint8_t)(0x08)) +#define TNF_Mask ((uint8_t)(0x07)) + +#define TNF_Empty 0x00 +#define TNF_WellKnown 0x01 +#define TNF_MediaType 0x02 +#define TNF_AbsoluteURI 0x03 +#define TNF_NFCForumExternal 0x04 +#define TNF_Unknown 0x05 +#define TNF_Unchanged 0x06 +#define TNF_Reserved 0x07 + +#define SP_MAX_RECORD 4 + +#define AAR_TYPE_STRING "android.com:pkg" +#define AAR_TYPE_STRING_LENGTH 15 + +#define M24SR_DISCOVERY_APP_STRING "st.com:m24sr_discovery_democtrl" +#define M24SR_DISCOVERY_APP_STRING_LENGTH 31 + +#define VCARD_TYPE_STRING "text/vcard" +#define VCARD_TYPE_STRING_LENGTH 10 + +#define XVCARD_TYPE_STRING "text/x-vCard" +#define XVCARD_TYPE_STRING_LENGTH 12 + +#define XVCARD2_TYPE_STRING "text/x-vcard" +#define XVCARD2_TYPE_STRING_LENGTH 12 + +#define SMART_POSTER_TYPE_STRING "Sp" +#define SMART_POSTER_TYPE_STRING_LENGTH 2 + +#define URI_TYPE_STRING "U" +#define URI_TYPE_STRING_LENGTH 1 + +#define SMS_TYPE_STRING "sms:" +#define SMS_TYPE_STRING_LENGTH 4 + +#define GEO_TYPE_STRING "geo:" +#define GEO_TYPE_STRING_LENGTH 4 + +#define URI_LATITUDE_END "," +#define URI_LATITUDE_END_LENGTH 1 + +#define EMAIL_TYPE_STRING "mailto:" +#define EMAIL_TYPE_STRING_LENGTH 7 + +#define URI_FIRST_DATA_END "?" +#define URI_FIRST_DATA_END_LENGTH 1 + +#define SUBJECT_BEGIN_STRING "subject=" +#define SUBJECT_BEGIN_STRING_LENGTH 8 + +#define MESSAGE_BEGIN_STRING "body=" +#define MESSAGE_BEGIN_STRING_LENGTH 5 + +#define URI_SECOND_DATA_END "&" +#define URI_SECOND_DATA_END_LENGTH 1 + +#define TEXT_TYPE_STRING "T" +#define TEXT_TYPE_STRING_LENGTH 1 + +#define ISO_ENGLISH_CODE_STRING "en" +#define ISO_ENGLISH_CODE_STRING_LENGTH 2 + + +#define URI_ID_0x00 0x00 +#define URI_ID_0x01 0x01 +#define URI_ID_0x02 0x02 +#define URI_ID_0x03 0x03 +#define URI_ID_0x04 0x04 +#define URI_ID_0x05 0x05 +#define URI_ID_0x06 0x06 +#define URI_ID_0x07 0x07 +#define URI_ID_0x08 0x08 +#define URI_ID_0x09 0x09 +#define URI_ID_0x0A 0x0A +#define URI_ID_0x0B 0x0B +#define URI_ID_0x0C 0x0C +#define URI_ID_0x0D 0x0D +#define URI_ID_0x0E 0x0E +#define URI_ID_0x0F 0x0F +#define URI_ID_0x10 0x10 +#define URI_ID_0x11 0x11 +#define URI_ID_0x12 0x12 +#define URI_ID_0x13 0x13 +#define URI_ID_0x14 0x14 +#define URI_ID_0x15 0x15 +#define URI_ID_0x16 0x16 +#define URI_ID_0x17 0x17 +#define URI_ID_0x18 0x18 +#define URI_ID_0x19 0x19 +#define URI_ID_0x1A 0x1A +#define URI_ID_0x1B 0x1B +#define URI_ID_0x1C 0x1C +#define URI_ID_0x1D 0x1D +#define URI_ID_0x1E 0x1E +#define URI_ID_0x1F 0x1F +#define URI_ID_0x20 0x20 +#define URI_ID_0x21 0x21 +#define URI_ID_0x22 0x22 +#define URI_ID_0x23 0x23 +#define URI_RFU 0x24 + +#define URI_ID_0x01_STRING "http://www.\0" +#define URI_ID_0x02_STRING "https://www.\0" +#define URI_ID_0x03_STRING "http://\0" +#define URI_ID_0x04_STRING "https://\0" +#define URI_ID_0x05_STRING "tel:\0" +#define URI_ID_0x06_STRING "mailto:\0" +#define URI_ID_0x07_STRING "ftp://anonymous:anonymous@\0" +#define URI_ID_0x08_STRING "ftp://ftp.\0" +#define URI_ID_0x09_STRING "ftps://\0" +#define URI_ID_0x0A_STRING "sftp://\0" +#define URI_ID_0x0B_STRING "smb://\0" +#define URI_ID_0x0C_STRING "nfs://\0" +#define URI_ID_0x0D_STRING "ftp://\0" +#define URI_ID_0x0E_STRING "dav://\0" +#define URI_ID_0x0F_STRING "news:\0" +#define URI_ID_0x10_STRING "telnet://\0" +#define URI_ID_0x11_STRING "imap:\0" +#define URI_ID_0x12_STRING "rtsp://\0" +#define URI_ID_0x13_STRING "urn:\0" +#define URI_ID_0x14_STRING "pop:\0" +#define URI_ID_0x15_STRING "sip:\0" +#define URI_ID_0x16_STRING "sips:\0" +#define URI_ID_0x17_STRING "tftp:\0" +#define URI_ID_0x18_STRING "btspp://\0" +#define URI_ID_0x19_STRING "btl2cap://\0" +#define URI_ID_0x1A_STRING "btgoep://\0" +#define URI_ID_0x1B_STRING "tcpobex://\0" +#define URI_ID_0x1C_STRING "irdaobex://\0" +#define URI_ID_0x1D_STRING "file://\0" +#define URI_ID_0x1E_STRING "urn:epc:id:\0" +#define URI_ID_0x1F_STRING "urn:epc:tag\0" +#define URI_ID_0x20_STRING "urn:epc:pat:\0" +#define URI_ID_0x21_STRING "urn:epc:raw:\0" +#define URI_ID_0x22_STRING "urn:epc:\0" +#define URI_ID_0x23_STRING "urn:nfc:\0" + +// exported variables +extern uint8_t NDEF_Buffer[NDEF_MAX_SIZE]; +extern uint32_t NDEF_Buffer_size; +extern uint8_t NDEF_Record_Buffer [NDEF_RECORD_MAX_SIZE]; +extern uint32_t NDEF_Record_Buffer_size; + +typedef enum +{ + UNKNOWN_TYPE = 0, + VCARD_TYPE, + WELL_KNOWN_ABRIDGED_URI_TYPE, + URI_SMS_TYPE, + URI_GEO_TYPE, + URI_EMAIL_TYPE, + SMARTPOSTER_TYPE, + URL_TYPE, + TEXT_TYPE, + HANDOVER_TYPE, + /* list of "external type" known by this demo, other external type will be addressed as UNKNWON_TYPE */ + M24SR_DISCOVERY_APP_TYPE, + BT_TYPE, + BLE_TYPE, + URI_WIFITOKEN_TYPE +} NDEF_TypeDef; + +typedef struct sRecordInfo sRecordInfo_t; + +struct sRecordInfo +{ + uint8_t RecordFlags; + uint8_t TypeLength; + uint32_t PayloadLength; + uint8_t IDLength; + uint8_t Type[20]; + uint8_t ID[20]; + uint16_t PayloadOffset; + uint8_t* PayloadBufferAdd; /* add where payload content has been stored */ + NDEF_TypeDef NDEF_Type; /* to store identification ID for application */ + sRecordInfo_t *SPRecordStructAdd[SP_MAX_RECORD]; /*in case of smart poster array to store add of other sRecordInfo struct */ + uint8_t NbOfRecordInSPPayload; +}; + +uint16_t NDEF_IdentifyNDEF( sRecordInfo_t *pRecordStruct, uint8_t* pNDEF, I2C* mi2cChannel ); +uint16_t NDEF_IdentifyBuffer( sRecordInfo_t *pRecordStruct, uint8_t* pNDEF ); +uint16_t NDEF_ReadNDEF( uint8_t *pNDEF, I2C* mi2cChannel ); +uint16_t NDEF_WriteNDEF( uint16_t NDEF_Size, uint8_t *pNDEF, I2C* mi2cChannel ); +uint16_t NDEF_ClearNDEF(I2C* mi2cChannel); +uint16_t NDEF_getNDEFSize(uint16_t* Size, I2C* mi2cChannel); +uint32_t NDEF_WriteRecord( sRecordInfo_t *pRecord, uint8_t* pNDEF, I2C* mi2cChannel ); +uint16_t NDEF_AppendRecord(sRecordInfo_t *Record, I2C* mi2cChannel ); +uint32_t NDEF_GetRecordLength( sRecordInfo_t *pRecord ); + +#endif /* __LIB_NDEF_H */ + + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_AAR.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_AAR.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,133 @@ +/** + ****************************************************************************** + * @file lib_NDEF_AAR.c + * @author MMY Application Team + * @version $Revision: 3210 $ + * @date $Date: 2016-12-05 15:37:48 +0100 (Mon, 05 Dec 2016) $ + * @brief This file help to add AAR to NDEF file. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF_AAR.h" + +/** @addtogroup NFC_libraries + * @{ + * @brief <b>This is the library used to manage the content of the TAG (data) + * But also the specific feature of the tag, for instance + * password, gpo... </b> + */ + + +/** @addtogroup libNFC_FORUM + * @{ + * @brief This part of the library manage data which follow NFC forum organisation. + */ + +/** + * @brief This buffer contains the data send/received by TAG + */ +extern uint8_t NDEF_Buffer []; + +/** @defgroup libAAR_Private_Functions + * @{ + */ + +/** + * @} + */ + +/** @defgroup libAAR_Public_Functions + * @{ + * @brief This file is used to manage AAR (stored or loaded in tag) + */ + + +/** + * @brief This function add AAR (Android Application Record) in the tag. + * @param pAARStruct : pointer on structure that contain AAR information. + * @retval NDEF_OK : AAR added. + * @retval NDEF_ERROR : not able to store NDEF in tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write. + */ +uint16_t NDEF_AddAAR( const sAARInfo *pAARStruct, I2C* mi2cChannel ) +{ + uint16_t status = NDEF_ERROR; + +/* AAR: External Type Record Header */ +/************************************/ +/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */ +/*----------------------------------*/ +/* MB ME CF SR IL TNF */ /* <---- IL=0, CF=0 and SR=1 TNF=4 NFC Forum external type*/ +/*----------------------------------*/ +/* TYPE LENGTH */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 3 */ /* <---- Not Used */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 2 */ /* <---- Not Used */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 1 */ /* <---- Not Used */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 0 */ +/*----------------------------------*/ +/* ID LENGTH */ /* <---- Not Used */ +/*----------------------------------*/ +/* TYPE */ /* android.com:pkg */ +/*----------------------------------*/ +/* ID */ /* <---- Not Used */ +/************************************/ + + /* Do we have to add AAR to an existing NDEF message */ + /* retrieve current NDEF size and current record flag*/ + sRecordInfo_t AARrecord; + + /* fill AAR record header */ + AARrecord.RecordFlags = SR_Mask | TNF_NFCForumExternal; + AARrecord.TypeLength = AAR_TYPE_STRING_LENGTH; + + memcpy( AARrecord.Type, AAR_TYPE_STRING, AAR_TYPE_STRING_LENGTH ); + + /* fill AAR payload */ + AARrecord.PayloadBufferAdd = (uint8_t*)pAARStruct->PackageName; + AARrecord.PayloadLength= strlen(pAARStruct->PackageName) ; + + status = NDEF_AppendRecord(&AARrecord, mi2cChannel); + + return status; +} + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_AAR.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_AAR.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,49 @@ +/** + ****************************************************************************** + * @file lib_NDEF_AAR.h + * @author MMY Application Team + * @version $Revision: 3210 $ + * @date $Date: 2016-12-05 15:37:48 +0100 (Mon, 05 Dec 2016) $ + * @brief This file help to manage AAR. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_NDEF_AAR_H +#define __LIB_NDEF_AAR_H + + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" + +typedef struct +{ + char PackageName[80]; +}sAARInfo; + +uint16_t NDEF_AddAAR( const sAARInfo *pAARStruct, I2C* mi2cChannel ); + + + +#endif /* __LIB_NDEF_AAR_H */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Bluetooth.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Bluetooth.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,554 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Bluetooth.c + * @author MMY Application Team + * @version $Revision: 2702 $ + * @date $Date: 2016-07-13 18:45:05 +0200 (Wed, 13 Jul 2016) $ + * @ingroup LibNDEF_Bluetooth + * @brief This file help to manage a NDEF file representing a Bluetooth pairing info. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF_Bluetooth.h" + + + +/** @addtogroup lib_NDEF_Bluetooth Bluetooth OOB library + * @ingroup libNDEF + * @{ + * @brief This module is used to manage a Bluetooth Out-Of-Band NDEF message, to start a communication based on Bluetooth. + * @details The Bluetooth OOB format is described by the Bluetooth v4.0 core specification. + * It consists in a list of Extended Inquiry Responses formated as length-type-value. + * This module allows to build, write & read such data embedded in a NDEF message. + * @section Bluetooth_Library_Usage Bluetooth NDEF Library usage + * @subsection Bluetooth_Write_BrEdr How to write a Bluetooth Br/Edr OOB + * 1. Instanciate & initialize a `Ndef_Bluetooth_OOB_t` structure, specifying: + * - the `NDEF_BLUETOOTH_BREDR` type. + * - the mandatory Device Address field. + * - any other optional EIRs. + * + * Ndef_Bluetooth_OOB_t w_bredr_oob = { .Type = NDEF_BLUETOOTH_BREDR, + * .DeviceAddress = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}, + * .OptionalMask = NDEF_BLUETOOTH_OPTION(BLUETOOTH_EIR_COMPLETE_LOCAL_NAME) | + * NDEF_BLUETOOTH_OPTION(BLUETOOTH_EIR_DEVICE_CLASS) | + * NDEF_BLUETOOTH_OPTION(BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_16), + * .LocalName = "MyDevice", + * .nbUUID16 = 2, + * .ClassUUID16 = {0x111E,0x110B}, + * .DeviceClass = {0x04,0x04,0x20} + * }; + * 2. Clear the NDEF message and call the `NDEF_AppendBluetoothOOB` function to write the OOB: + * + * NDEF_ClearNDEF(); + * NDEF_AppendBluetoothOOB ( &w_bredr_oob, NULL ); + * @note Second parameter of `NDEF_AppendBluetoothOOB` can be used to specify an ID for the OOB record (useful for the NDEF Handover message, where specifying an ID is mandatory) + * @subsection Bluetooth_Write_Ble How to write a Bluetooth LE OOB + * 1. Instanciate & initialize a `Ndef_Bluetooth_OOB_t` structure, specifying: + * - the `NDEF_BLUETOOTH_BLE` type. + * - the mandatory Device Address & LE Role fields. + * - any other optional EIRs. + * + * Ndef_Bluetooth_OOB_t w_ble_oob = { .Type = NDEF_BLUETOOTH_BLE, + * .DeviceAddress = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}, + * .DeviceAddressType = NDEF_BLE_PUBLIC_ADDRESS_TYPE, + * .Role = NDEF_BLE_ROLE_PERIPH_ONLY, + * .OptionalMask = NDEF_BLUETOOTH_OPTION(BLUETOOTH_EIR_COMPLETE_LOCAL_NAME), + * .LocalName = "MyDeviceName", + * }; + * + * 2. Clear the NDEF message and call the `NDEF_AppendBluetoothOOB` function to write the OOB: + * + * NDEF_ClearNDEF(); + * NDEF_AppendBluetoothOOB ( &w_ble_oob, NULL ); + * @note Second parameter of `NDEF_AppendBluetoothOOB` can be used to specify an ID for the OOB record (useful for the NDEF Handover message, where specifying an ID is mandatory) + * + * @subsection Bluetooth_Read How to read a Bluetooth OOB + * 1. Read the 1st record of the NDEF message: + * + * sRecordInfo_t record; + * NDEF_ReadNDEF(NDEF_Buffer); + * NDEF_IdentifyBuffer(record,NDEF_Buffer); + * 2. Decode the Bluetooth OOB: + * + * Ndef_Bluetooth_OOB_t bluetooth_oob; + * NDEF_ReadBluetoothOOB(&record,&bluetooth_oob); + * 3. Use the data from the `Ndef_Bluetooth_OOB_t` structure to start a Bluetooth connexion. + * + * + * + */ + + +/** + * @brief This function copies an array, changing its endianness, usefull to convert data to BLE endianess. + * @param dst Pointer on 1st element of the destination array. + * @param src pointer on 1st element of the source array . + * @param length Number of element to copy. + * @return Pointer to the destination array. + */ +uint8_t* NDEF_BluetoothCopy(uint8_t* dst, uint8_t* src, uint32_t length) +{ + uint32_t index; + for(index = 0 ; index < length; index++) + { + dst[index] = src[length - index - 1]; + } + return dst; +} + +/** + * @brief This function reads a NDEF record and retrieves Bluetooth (BR/EDR or BLE) OOB information if present. + * @param pRecord Pointer on the record structure. + * @param pBluetooth Pointer on the structure to fill . + * @retval NDEF_OK OOB information has been retrieved from the NDEF record. + * @retval NDEF_ERROR OOB information cannot be retrieved. + */ +uint16_t NDEF_ReadBluetoothOOB( sRecordInfo_t *pRecord, Ndef_Bluetooth_OOB_t *pBluetooth ) +{ + uint8_t* pData = pRecord->PayloadBufferAdd; + uint8_t* OOBEnd = pRecord->PayloadBufferAdd + pRecord->PayloadLength; + + pBluetooth->OptionalMask = 0; + pBluetooth->nbServiceData = 0; + pBluetooth->Role = NDEF_BLE_ROLE_UNDEF; + pBluetooth->DeviceAddressType = NDEF_BLE_UNDEF_ADDRESS_TYPE; + pBluetooth->nbUUID16 = 0; + pBluetooth->nbUUID32 = 0; + pBluetooth->nbUUID128 = 0; + pBluetooth->nbServiceSolicitation16 = 0; + pBluetooth->nbServiceSolicitation128 = 0; + + if((pRecord->TypeLength == strlen(NDEF_BLUETOOTH_BREDR_MIME_TYPE)) && + !memcmp(pRecord->Type,NDEF_BLUETOOTH_BREDR_MIME_TYPE,strlen(NDEF_BLUETOOTH_BREDR_MIME_TYPE))) + { + pBluetooth->Type = NDEF_BLUETOOTH_BREDR; + /* Retrieve mandatory OOB data: */ + /* 2 bytes for length and 6 bytes for device addr */ + NDEF_BluetoothCopy((uint8_t*)pBluetooth->DeviceAddress,&pData[2],sizeof(pBluetooth->DeviceAddress)); + pData += 8; + } else if ((pRecord->TypeLength == strlen(NDEF_BLUETOOTH_BLE_MIME_TYPE)) && + !memcmp(pRecord->Type,NDEF_BLUETOOTH_BLE_MIME_TYPE,strlen(NDEF_BLUETOOTH_BLE_MIME_TYPE))) + { + pBluetooth->Type = NDEF_BLUETOOTH_BLE; + /* for BLE, mandatory fields are in EIR */ + } else { + /* This is an unknown MIME type */ + return NDEF_ERROR; + } + + /* EIR format: 1 byte for length, 1 byte for type, n bytes for data */ + while (pData < OOBEnd) + { + NDEF_EIR_t* rEIR = (NDEF_EIR_t*)pData; + /* +1 for EIR length byte */ + pData += rEIR->length + 1; + + /* keep track of all EIR found */ + if(rEIR->type < 0x20) + NDEF_BLUETOOTH_SET_OPTIONAL_MASK(pBluetooth,rEIR->type); + + switch (rEIR->type) + { + case BLUETOOTH_EIR_FLAGS: + pBluetooth->Flags = *rEIR->value; + break; + + case BLUETOOTH_EIR_SERVICE_CLASS_UUID_PARTIAL_16: + case BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_16: + pBluetooth->nbUUID16 = (rEIR->length - 1) / 2 ; + NDEF_BluetoothCopy((uint8_t*)pBluetooth->ClassUUID16,rEIR->value,rEIR->length-1); + break; + + case BLUETOOTH_EIR_SERVICE_CLASS_UUID_PARTIAL_32: + case BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_32: + pBluetooth->nbUUID32 = (rEIR->length - 1) / 4 ; + NDEF_BluetoothCopy((uint8_t*)pBluetooth->ClassUUID32,rEIR->value,rEIR->length-1); + break; + + case BLUETOOTH_EIR_SERVICE_CLASS_UUID_PARTIAL_128: + case BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_128: + pBluetooth->nbUUID128 = (rEIR->length - 1) / 16 ; + NDEF_BluetoothCopy((uint8_t*)pBluetooth->ClassUUID128,rEIR->value,rEIR->length-1); + break; + + case BLUETOOTH_EIR_SHORT_LOCAL_NAME: + case BLUETOOTH_EIR_COMPLETE_LOCAL_NAME: + /* No worry about name length as max EIR length is 0xff using 1 byte for the type metadata */ + memcpy(pBluetooth->LocalName,rEIR->value,rEIR->length-1); + pBluetooth->LocalName[rEIR->length] = '\0'; + break; + + case BLUETOOTH_EIR_TX_POWER_LEVEL: + pBluetooth->TxPowerLevel = *rEIR->value; + break; + + case BLUETOOTH_EIR_DEVICE_CLASS: + NDEF_BluetoothCopy((uint8_t*)pBluetooth->DeviceClass,rEIR->value,sizeof(pBluetooth->DeviceClass)); + break; + + case BLUETOOTH_EIR_SIMPLE_PAIRING_HASH: + NDEF_BluetoothCopy((uint8_t*)pBluetooth->SimplePairingHash,rEIR->value,sizeof(pBluetooth->SimplePairingHash)); + break; + + case BLUETOOTH_EIR_SIMPLE_PAIRING_RANDOMIZER: + NDEF_BluetoothCopy((uint8_t*)pBluetooth->SimplePairingRandomizer,rEIR->value,sizeof(pBluetooth->SimplePairingRandomizer)); + break; + + case BLUETOOTH_EIR_SECURITY_MANAGER_TK_VALUE: + NDEF_BluetoothCopy((uint8_t*)pBluetooth->SecureManagerTK,rEIR->value,sizeof(pBluetooth->SecureManagerTK)); + break; + + case BLUETOOTH_EIR_SECURITY_MANAGER_FLAGS: + pBluetooth->SMFlags = *rEIR->value; + break; + + case BLUETOOTH_EIR_SLAVE_CONNECTION_INTERVAL_RANGE: + NDEF_BluetoothCopy((uint8_t*)pBluetooth->SlaveConnIntervalRange,rEIR->value,sizeof(pBluetooth->SlaveConnIntervalRange)); + break; + + case BLUETOOTH_EIR_SERVICE_SOLICITATION_16: + pBluetooth->nbServiceSolicitation16 = (rEIR->length - 1) / 2 ; + NDEF_BluetoothCopy((uint8_t*)pBluetooth->ServiceSolicitation16,rEIR->value,rEIR->length-1); + break; + + case BLUETOOTH_EIR_SERVICE_SOLICITATION_128: + pBluetooth->nbServiceSolicitation128 = (rEIR->length - 1) / 16 ; + NDEF_BluetoothCopy((uint8_t*)pBluetooth->ServiceSolicitation128,rEIR->value,rEIR->length-1); + break; + + case BLUETOOTH_EIR_SERVICE_DATA: + /* a specific function should be used for this EIR */ + pBluetooth->nbServiceData++; + break; + + case BLUETOOTH_EIR_MANUFACTURER_DATA: + /* a specific function should be used for this EIR */ + pBluetooth->nbManufacturerData++; + break; + + case BLUETOOTH_EIR_APPEARANCE: + pBluetooth->Appearance = *(uint16_t *)rEIR->value; + break; + + case BLUETOOTH_EIR_BLE_DEVICE_ADDRESS: + NDEF_BluetoothCopy((uint8_t*)pBluetooth->DeviceAddress,rEIR->value,sizeof(pBluetooth->DeviceAddress)); + pBluetooth->DeviceAddressType = (Ndef_BLE_Address_Type_t)rEIR->value[sizeof(pBluetooth->DeviceAddress)]; + break; + + case BLUETOOTH_EIR_BLE_ROLE: + pBluetooth->Role = (Ndef_BLE_Role_t) *rEIR->value; + break; + + default: + pBluetooth->nbUnknown++; + break; + } /* switch rEIR->type */ + } /* while (pData < OOBEnd) */ + /* Check that BLE mandatory fields are there */ + if((pBluetooth->Type == NDEF_BLUETOOTH_BLE) && + (!NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_BLE_DEVICE_ADDRESS) || + !NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_BLE_ROLE))) + return NDEF_ERROR; + + return NDEF_OK; +} + +/** + * @brief This function appends a Bluetooth OOB record to the NDEF message, using the OOB data given in the input structure. + * @param pBluetooth Pointer on a `Ndef_Bluetooth_OOB_t` structure containing the OOB information. + * @param RecordID ID to be used for this record (required for Handover case, can be set to NULL in other cases). + * @retval NDEF_OK The Bluetooth OOB record has been appended. + * @retval NDEF_ERROR_MEMORY_INTERNAL The Bluetooth OOB record cannot be appended due to memory size limitation. + * @retval NDEF_ERROR The Bluetooth OOB record cannot be appended. + */ +uint16_t NDEF_AppendBluetoothOOB( Ndef_Bluetooth_OOB_t *pBluetooth, char* RecordID, I2C* mi2cChannel ) +{ + sRecordInfo_t Record; + uint16_t status; + + Record.RecordFlags = TNF_MediaType; + Record.RecordFlags |= (RecordID != NULL) ? IL_Mask : 0; + Record.IDLength = strlen(RecordID); + memcpy(Record.ID,RecordID,Record.IDLength); + + if(pBluetooth->Type == NDEF_BLUETOOTH_BREDR) + { + Record.TypeLength = strlen(NDEF_BLUETOOTH_BREDR_MIME_TYPE); + memcpy(Record.Type, NDEF_BLUETOOTH_BREDR_MIME_TYPE, Record.TypeLength); + } + else if (pBluetooth->Type == NDEF_BLUETOOTH_BLE) + { + Record.TypeLength = strlen(NDEF_BLUETOOTH_BLE_MIME_TYPE); + memcpy(Record.Type, NDEF_BLUETOOTH_BLE_MIME_TYPE, Record.TypeLength); + } + else + { + return NDEF_ERROR; + } + + /* Generate OOB payload */ + Record.PayloadLength = NDEF_GetBluetoothOOBLength(pBluetooth); + Record.PayloadBufferAdd = NDEF_Record_Buffer; + if(Record.PayloadLength > NDEF_RECORD_MAX_SIZE) + return NDEF_ERROR_MEMORY_INTERNAL; + + /* pData: pointer to ease increment of record buffer address (byte granularity) */ + uint8_t* pData = Record.PayloadBufferAdd; + + /* for BR-EDR Device address & length are managed outside EIR */ + if(pBluetooth->Type == NDEF_BLUETOOTH_BREDR) + { + *pData = Record.PayloadLength; + pData += 2; + NDEF_BluetoothCopy(pData,(uint8_t*)pBluetooth->DeviceAddress,sizeof(pBluetooth->DeviceAddress)); + pData+=sizeof(pBluetooth->DeviceAddress); + } + + /* wEIR: pointer to ease write to the buffer. + * length always set with an additional +1 corresponding to the EIR type byte. + * pData increment is always done with an additional +1 corresponding to the EIR length byte. + */ + NDEF_EIR_t* wEIR; + + + if(pBluetooth->Type == NDEF_BLUETOOTH_BLE) + { + /* following EIR are mandatory for BLE */ + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = sizeof(pBluetooth->DeviceAddress) + sizeof(pBluetooth->DeviceAddressType) + 1; + wEIR->type = BLUETOOTH_EIR_BLE_DEVICE_ADDRESS; + NDEF_BluetoothCopy(wEIR->value, (uint8_t*)pBluetooth->DeviceAddress,sizeof(pBluetooth->DeviceAddress)); + wEIR->value[sizeof(pBluetooth->DeviceAddress)] = pBluetooth->DeviceAddressType; + pData += wEIR->length + 1; + + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = sizeof(pBluetooth->Role) + 1; + wEIR->type = BLUETOOTH_EIR_BLE_ROLE; + wEIR->value[0] = pBluetooth->Role; + pData += wEIR->length + 1; + + } + + /* Rely on the optional mask to know if a EIR is required or not */ + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_FLAGS)) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = sizeof(pBluetooth->Flags) + 1; + wEIR->type = BLUETOOTH_EIR_FLAGS; + wEIR->value[0] = pBluetooth->Flags; + pData += wEIR->length + 1; + } + + if(pBluetooth->nbUUID16 > 0) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = 2 * pBluetooth->nbUUID16 + 1; + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_16)) + wEIR->type = BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_16; + else + wEIR->type = BLUETOOTH_EIR_SERVICE_CLASS_UUID_PARTIAL_16; + NDEF_BluetoothCopy(wEIR->value, (uint8_t*) pBluetooth->ClassUUID16, 2 * pBluetooth->nbUUID16); + pData += wEIR->length + 1; + + } + + if(pBluetooth->nbUUID32 > 0) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = 4 * pBluetooth->nbUUID32 + 1; + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_32)) + wEIR->type = BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_32; + else + wEIR->type = BLUETOOTH_EIR_SERVICE_CLASS_UUID_PARTIAL_32; + NDEF_BluetoothCopy(wEIR->value, (uint8_t*)pBluetooth->ClassUUID32, 4 * pBluetooth->nbUUID32); + pData += wEIR->length + 1; + + } + + if(pBluetooth->nbUUID128 > 0) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = 16 * pBluetooth->nbUUID128 + 1; + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_128)) + wEIR->type = BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_128; + else + wEIR->type = BLUETOOTH_EIR_SERVICE_CLASS_UUID_PARTIAL_128; + NDEF_BluetoothCopy(wEIR->value, (uint8_t*) pBluetooth->ClassUUID128, 16 * pBluetooth->nbUUID128); + pData += wEIR->length + 1; + + } + + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SHORT_LOCAL_NAME) || + NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_COMPLETE_LOCAL_NAME)) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = strlen(pBluetooth->LocalName) + 1; + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SHORT_LOCAL_NAME)) + wEIR->type = BLUETOOTH_EIR_SHORT_LOCAL_NAME; + else + wEIR->type = BLUETOOTH_EIR_COMPLETE_LOCAL_NAME; + memcpy(wEIR->value, pBluetooth->LocalName,strlen(pBluetooth->LocalName)); + pData += wEIR->length + 1; + + } + + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_TX_POWER_LEVEL)) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = sizeof(pBluetooth->TxPowerLevel) + 1; + wEIR->type = BLUETOOTH_EIR_TX_POWER_LEVEL; + wEIR->value[0] = pBluetooth->TxPowerLevel; + pData += wEIR->length + 1; + } + + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_DEVICE_CLASS)) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = sizeof(pBluetooth->DeviceClass) + 1; + wEIR->type = BLUETOOTH_EIR_DEVICE_CLASS; + NDEF_BluetoothCopy(wEIR->value, pBluetooth->DeviceClass,sizeof(pBluetooth->DeviceClass)); + pData += wEIR->length + 1; + + } + + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SIMPLE_PAIRING_HASH)) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = sizeof(pBluetooth->SimplePairingHash) + 1; + wEIR->type = BLUETOOTH_EIR_SIMPLE_PAIRING_HASH; + NDEF_BluetoothCopy(wEIR->value, pBluetooth->SimplePairingHash,sizeof(pBluetooth->SimplePairingHash)); + pData += wEIR->length + 1; + + } + + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SIMPLE_PAIRING_RANDOMIZER)) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = sizeof(pBluetooth->SimplePairingRandomizer) + 1; + wEIR->type = BLUETOOTH_EIR_SIMPLE_PAIRING_RANDOMIZER; + NDEF_BluetoothCopy(wEIR->value, pBluetooth->SimplePairingRandomizer,sizeof(pBluetooth->SimplePairingRandomizer)); + pData += wEIR->length + 1; + + } + + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SECURITY_MANAGER_TK_VALUE)) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = sizeof(pBluetooth->SecureManagerTK) + 1; + wEIR->type = BLUETOOTH_EIR_SECURITY_MANAGER_TK_VALUE; + NDEF_BluetoothCopy(wEIR->value, pBluetooth->SecureManagerTK,sizeof(pBluetooth->SecureManagerTK)); + pData += wEIR->length + 1; + + } + + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SECURITY_MANAGER_FLAGS)) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = sizeof(pBluetooth->SMFlags) + 1; + wEIR->type = BLUETOOTH_EIR_SECURITY_MANAGER_FLAGS; + wEIR->value[0] = pBluetooth->SMFlags; + pData += wEIR->length + 1; + + } + + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SLAVE_CONNECTION_INTERVAL_RANGE)) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = sizeof(pBluetooth->SlaveConnIntervalRange) + 1; + wEIR->type = BLUETOOTH_EIR_SLAVE_CONNECTION_INTERVAL_RANGE; + NDEF_BluetoothCopy(wEIR->value, (uint8_t*)pBluetooth->SlaveConnIntervalRange,sizeof(pBluetooth->SlaveConnIntervalRange)); + pData += wEIR->length + 1; + + } + + if(pBluetooth->nbServiceSolicitation16 > 0) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = 2 * pBluetooth->nbServiceSolicitation16 + 1; + wEIR->type = BLUETOOTH_EIR_SERVICE_SOLICITATION_16; + NDEF_BluetoothCopy(wEIR->value, (uint8_t*)pBluetooth->ServiceSolicitation16, 16 * pBluetooth->nbServiceSolicitation16); + pData += wEIR->length + 1; + + } + + if(pBluetooth->nbServiceSolicitation128 > 0) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = 16 * pBluetooth->nbServiceSolicitation128 + 1; + wEIR->type = BLUETOOTH_EIR_SERVICE_SOLICITATION_128; + NDEF_BluetoothCopy(wEIR->value, (uint8_t*) pBluetooth->ServiceSolicitation128, 16 * pBluetooth->nbServiceSolicitation128); + pData += wEIR->length + 1; + + } + + if(NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_APPEARANCE)) + { + wEIR = (NDEF_EIR_t*)pData; + wEIR->length = sizeof(pBluetooth->Appearance) + 1; + wEIR->type = BLUETOOTH_EIR_APPEARANCE; + wEIR->value[0] = pBluetooth->Appearance; + pData += wEIR->length + 1; + + } + + + status = NDEF_AppendRecord(&Record, mi2cChannel); + if(status != NDEF_OK) return status; + + return NDEF_OK; +} + +/** + * @brief This function computeS the payload size for the OOB, using the data given in the input `Ndef_Bluetooth_OOB_t` structure. + * @param pBluetooth Pointer on a `Ndef_Bluetooth_OOB_t` structure containing the OOB information. + * @return Computed length in bytes. + */ +uint32_t NDEF_GetBluetoothOOBLength( Ndef_Bluetooth_OOB_t *pBluetooth ) +{ + uint32_t length = (pBluetooth->Type == NDEF_BLUETOOTH_BREDR) ? sizeof(pBluetooth->DeviceAddress) + 2 : 0; // +2 is for BR/EDR mandatory length + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_FLAGS)? sizeof(pBluetooth->Flags) + 2 : 0 ; + length += pBluetooth->nbUUID16 ? pBluetooth->nbUUID16 * 2 + 2 : 0; + length += pBluetooth->nbUUID32 ? pBluetooth->nbUUID32 * 4 + 2 : 0; + length += pBluetooth->nbUUID128 ? pBluetooth->nbUUID128 * 16 + 2 : 0; + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SHORT_LOCAL_NAME)? strlen(pBluetooth->LocalName) + 2 : 0 ; + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_COMPLETE_LOCAL_NAME)? strlen(pBluetooth->LocalName) + 2 : 0 ; + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_TX_POWER_LEVEL)? sizeof(pBluetooth->TxPowerLevel + 2) : 0 ; + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_DEVICE_CLASS)? sizeof(pBluetooth->DeviceClass) + 2 : 0 ; + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SIMPLE_PAIRING_HASH)? sizeof(pBluetooth->SimplePairingHash) + 2 : 0 ; + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SIMPLE_PAIRING_RANDOMIZER)? sizeof(pBluetooth->SimplePairingRandomizer) + 2 : 0 ; + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SECURITY_MANAGER_TK_VALUE)? sizeof(pBluetooth->SecureManagerTK) + 2 : 0 ; + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SECURITY_MANAGER_FLAGS)? sizeof(pBluetooth->SMFlags) + 2 : 0 ; + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SLAVE_CONNECTION_INTERVAL_RANGE)? sizeof(pBluetooth->SlaveConnIntervalRange) + 2 : 0 ; + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SERVICE_SOLICITATION_16)? pBluetooth->nbServiceSolicitation16 * 2 + 2 : 0 ; + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_SERVICE_SOLICITATION_128)? pBluetooth->nbServiceSolicitation128 * 16 + 2 : 0 ; + length += NDEF_BLUETOOTH_GET_OPTIONAL_MASK(pBluetooth,BLUETOOTH_EIR_APPEARANCE)? sizeof(pBluetooth->Appearance) + 2 : 0 ; + length += (pBluetooth->Type == NDEF_BLUETOOTH_BLE)? sizeof(pBluetooth->DeviceAddress) + sizeof(pBluetooth->DeviceAddressType) + 2 : 0 ; + length += (pBluetooth->Type == NDEF_BLUETOOTH_BLE)? sizeof(pBluetooth->Role) + 2 : 0; + + return length; +} +/** + * @} + */ + +/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Bluetooth.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Bluetooth.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,204 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Bluetooth.h + * @author MMY Application Team + * @version $Revision: 2475 $ + * @date $Date: 2016-06-24 12:11:59 +0200 (Fri, 24 Jun 2016) $ + * @brief This file help to manage a NDEF file representing a Bluetooth pairing info. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_NDEF_BLUETOOTH_H +#define __LIB_NDEF_BLUETOOTH_H + + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" + +/** @addtogroup lib_NDEF_Bluetooth + * @{ + */ + +/** @brief MIME type for the Bluetooth BR/EDR Out-Of-Band data. */ +#define NDEF_BLUETOOTH_BREDR_MIME_TYPE "application/vnd.bluetooth.ep.oob" +/** @brief MIME type for the Bluetooth Low Energy Out-Of-Band data. */ +#define NDEF_BLUETOOTH_BLE_MIME_TYPE "application/vnd.bluetooth.le.oob" + + +/** @brief Enumerates the Extended Inquiry Responses, as defined in the Bluetooth v4.0 core specification. */ +typedef enum { + BLUETOOTH_EIR_FLAGS = 0x01, /**< Bluetooth flags:\n + b0: LE limited Discoverable Mode,\n + b1: LE general Discoverable Mode,\n + b2: BR/EDR not supported,\n + b3: Simultaneous LE & BR/EDR Conroller,\n + b4: Simultaneous LE & BR/EDR Host + */ + BLUETOOTH_EIR_SERVICE_CLASS_UUID_PARTIAL_16 = 0x02, /**< Bluetooth service UUID on 16-bits (partial list) */ + BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_16 = 0x03, /**< Bluetooth service UUID on 16-bits (complete list) */ + BLUETOOTH_EIR_SERVICE_CLASS_UUID_PARTIAL_32 = 0x04, /**< Bluetooth service UUID on 32-bits (partial list) */ + BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_32 = 0x05, /**< Bluetooth service UUID on 32-bits (complete list) */ + BLUETOOTH_EIR_SERVICE_CLASS_UUID_PARTIAL_128 = 0x06, /**< Bluetooth service UUID on 128-bits (partial list) */ + BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_128 = 0x07, /**< Bluetooth service UUID on 128-bits (complete list) */ + BLUETOOTH_EIR_SHORT_LOCAL_NAME = 0x08, /**< Shortened local name */ + BLUETOOTH_EIR_COMPLETE_LOCAL_NAME = 0x09, /**< Complete local name */ + BLUETOOTH_EIR_TX_POWER_LEVEL = 0x0A, /**< TX Power Level (1 byte): 0xXX:-127 to +127dBm */ + BLUETOOTH_EIR_DEVICE_CLASS = 0x0D, /**< Class of device, Format defined in Assigned Numbers */ + BLUETOOTH_EIR_SIMPLE_PAIRING_HASH = 0x0E, /**< Simple Pairing Hash C (16 octets), Format defined in [Vol. 2], Part H Section 7.2.2*/ + BLUETOOTH_EIR_SIMPLE_PAIRING_RANDOMIZER = 0x0F, /**< Simple Pairing Randomizer R (16 octets), Format defined in[Vol. 2], Part H Section 7.2.2 */ + BLUETOOTH_EIR_SECURITY_MANAGER_TK_VALUE = 0x10, /**< TK Value: Value as used in pairing over LE Physical channel. Format defined in [Vol. 3], Part H Section 2.3*/ + BLUETOOTH_EIR_SECURITY_MANAGER_FLAGS = 0x11, /**< Flags (1 octet):\n + b0: OOB Flags Field (0 = OOB data not present, 1 = OOB data present),\n + b1: LE supported (Host) (i.e. bit 65 of LMP Extended Feature bits Page 1),\n + b2: Simultaneous LE and BR/EDR to Same Device Capable (Host) (i.e. bit 66 of LMP Extended Feature bits Page 1)\n + b3: Address type (0 = Public Address, 1 = Random Address) + */ + BLUETOOTH_EIR_SLAVE_CONNECTION_INTERVAL_RANGE = 0x12, /**< Slave Connection Interval Range: The first 2 octets defines the minimum value for the connection interval, The second 2 octets defines the maximum value for the connection interval */ + BLUETOOTH_EIR_SERVICE_SOLICITATION_16 = 0x14, /**< Service UUIDs: List of 16 bit Service UUIDs*/ + BLUETOOTH_EIR_SERVICE_SOLICITATION_128 = 0x15, /**< Service UUIDs: List of 128 bit Service UUID*/ + BLUETOOTH_EIR_SERVICE_DATA = 0x16, /**< Service Data (2 or more octets): The first 2 octets contain the 16 bit Service UUID followed by additional service data */ + BLUETOOTH_EIR_APPEARANCE = 0x19, /**< UUID for `Appearance`: The Appearance characteristic value shall be the enumerated value as defined by Bluetooth Assigned Numbers document. */ + BLUETOOTH_EIR_BLE_DEVICE_ADDRESS = 0x1B, /**< 6 LSB bytes: Device address, 7th byte: Address type (Public/Random) */ + BLUETOOTH_EIR_BLE_ROLE = 0x1C, /**< Device Role: Periph only, Central only, Periph prefered, Central prefered */ + BLUETOOTH_EIR_MANUFACTURER_DATA = 0xFF /**< Manufacturer Specific Data (2 or more octets): The first 2 octets contain the Company Identifier Code followed by additional manufacturer specific data */ +} Ndef_Bluetooth_Eir_Types_t; + + +/** @brief Bluetooth Flag field: LE limited discovery. */ +#define NDEF_BLE_LIMITED_DISCOVERY_FLAG (0x1) +/** @brief Bluetooth Flag field: LE general discovery. */ +#define NDEF_BLE_GENERAL_DISCOVERY_FLAG (0x2) +/** @brief Bluetooth Flag field: BR/EDR compliant. */ +#define NDEF_BLE_NOT_BREDR_COMPLIANT_FLAG (0x4) +/** @brief Bluetooth Flag field: LE & BR/EDR simultaneous support. */ +#define NDEF_BLE_LE_BREDR_SIMULTANEOUS_FLAG (0x8) + +/** @brief Enumerates the Bluetooth LE address types. */ +typedef enum { + NDEF_BLE_PUBLIC_ADDRESS_TYPE = 0x0, /**< Public Device Address. */ + NDEF_BLE_RANDOM_ADDRESS_TYPE = 0x1, /**< Random Device Address. */ + NDEF_BLE_UNDEF_ADDRESS_TYPE = 0xff /**< Device Address is undefined. */ +} Ndef_BLE_Address_Type_t; + +/** @brief Enumerates Bluetooth LE Roles */ +typedef enum { + NDEF_BLE_ROLE_PERIPH_ONLY = 0x0, /**< Only Peripheral Role supported. */ + NDEF_BLE_ROLE_CENTRAL_ONLY = 0x1, /**< Only Central Role supported. */ + NDEF_BLE_ROLE_PERIPH_PREFERRED = 0x2, /**< Peripheral and Central Role supported, Peripheral Role preferred for connection establishment. */ + NDEF_BLE_ROLE_CENTRAL_PREFERRED = 0x3, /**< Peripheral and Central Role supported, Central Role preferred for connection establishment. */ + NDEF_BLE_ROLE_UNDEF = 0xff /**< LE Role is undefined. */ +} Ndef_BLE_Role_t; + +/** @brief Enumerates Bluetooth protocols */ +typedef enum { + NDEF_BLUETOOTH_BREDR, /**< Standard bluetooth */ + NDEF_BLUETOOTH_BLE /**< Bluetooth Low Energy */ +} Ndef_Bluetooth_type_t; + +/** @brief Helper macro to set a particular EIR in the EIR mask of a `Ndef_Bluetooth_OOB_t` instance. + * @param bt Pointer to a `Ndef_Bluetooth_OOB_t` struct + * @param option Index of the option based on the `Ndef_Bluetooth_Eir_Types_t` */ +#define NDEF_BLUETOOTH_SET_OPTIONAL_MASK(bt,option) do { bt->OptionalMask |= (1<<(option)); } while (0) + +/** @brief Helper macro to unset a particular EIR in the EIR mask of a `Ndef_Bluetooth_OOB_t` instance. + * @param bt Pointer to a `Ndef_Bluetooth_OOB_t` struct + * @param option Index of the option based on the `Ndef_Bluetooth_Eir_Types_t` */ +#define NDEF_BLUETOOTH_UNSET_OPTIONAL_MASK(bt,option) do {bt->OptionalMask &= ~(1<<(option)); } while (0) + +/** @brief Helper macro to know if a particular EIR is present in the EIR mask of a `Ndef_Bluetooth_OOB_t` instance. + * @param bt Pointer to a `Ndef_Bluetooth_OOB_t` struct + * @param option Index of the option based on the `Ndef_Bluetooth_Eir_Types_t` */ +#define NDEF_BLUETOOTH_GET_OPTIONAL_MASK(bt,option) ((bt->OptionalMask & (1<<(option))) >> (option)) + +/** @brief Helper macro to create a mask for a particular EIR. + * @param option Index of the option based on the `Ndef_Bluetooth_Eir_Types_t` */ +#define NDEF_BLUETOOTH_OPTION(option) (1<<(option)) + +/** @brief Bluetooth Out-Of-Band data structure. + * @details Some fields are shared by both Br/Edr & LE Bluetooth, some are specific... + * No union used here to comply with the Cube coding guidelines, despite the fact that it could have save memory space. + */ +typedef struct +{ + /* Mandatory fields */ + Ndef_Bluetooth_type_t Type; /**< *Mandatory*: Bluetooth type (Br/Edr or LE). */ + char DeviceAddress[6]; /**< *Mandatory*: Device address. For LE: 6 LSB of Device Address EIR. */ + /* Optionnal common fields */ + uint32_t OptionalMask; /**< This Mask is used to keep track of EIRs present in the OOB: each bit index corresponds to a `Ndef_Bluetooth_Eir_Types_t` value. */ + uint8_t Flags; /**< Flags from BLUETOOTH_EIR_FLAGS. */ + + uint16_t ClassUUID16[0xff/2]; /**< UUIDs from BLUETOOTH_EIR_SERVICE_CLASS_UUID_PARTIAL_16 or BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_16. */ + uint32_t ClassUUID32[0xff/4]; /**< UUIDs from BLUETOOTH_EIR_SERVICE_CLASS_UUID_PARTIAL_32 or BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_32. */ + uint32_t ClassUUID128[0xff/16][4]; /**< UUIDs from BLUETOOTH_EIR_SERVICE_CLASS_UUID_PARTIAL_128 or BLUETOOTH_EIR_SERVICE_CLASS_UUID_COMPLETE_128. */ + uint8_t nbUUID16; /**< Number of UUIDs speficied in ClassUUID16. */ + uint8_t nbUUID32; /**< Number of UUIDs speficied in ClassUUID32. */ + uint8_t nbUUID128; /**< Number of UUIDs speficied in ClassUUID128. */ + + char LocalName[0xff]; /**< Device local name from BLUETOOTH_EIR_SHORT_LOCAL_NAME or BLUETOOTH_EIR_COMPLETE_LOCAL_NAME. */ + uint8_t DeviceClass[3]; /**< Class of device from BLUETOOTH_EIR_DEVICE_CLASS. */ + // if no TPL, TPL is unknown + uint8_t TxPowerLevel; /**< TX power Level from BLUETOOTH_EIR_TX_POWER_LEVEL. */ + + uint8_t SMFlags; /**< Security Manager Flags from BLUETOOTH_EIR_SECURITY_MANAGER_FLAGS. */ + uint16_t SlaveConnIntervalRange[2]; /**< Slave Connection Interval Range from BLUETOOTH_EIR_SLAVE_CONNECTION_INTERVAL_RANGE. */ + uint16_t ServiceSolicitation16[0xff/2]; /**< Service Solicitation from BLUETOOTH_EIR_SERVICE_SOLICITATION_16. */ + uint32_t ServiceSolicitation128[0xff/16][4]; /**< Service Solicitation from BLUETOOTH_EIR_SERVICE_SOLICITATION_128. */ + uint8_t nbServiceSolicitation16; /**< Number of UUIDs in ServiceSolicitation16. */ + uint8_t nbServiceSolicitation128; /**< Number of UUIDs in ServiceSolicitation128. */ + /* for br/edr only */ + uint8_t SimplePairingHash[16]; /**< *For Br/Edr only*: Simple Pairing Hash from BLUETOOTH_EIR_SIMPLE_PAIRING_HASH. */ + uint8_t SimplePairingRandomizer[16]; /**< *For Br/Edr only*: Simple Pairing Randomizer from BLUETOOTH_EIR_SIMPLE_PAIRING_RANDOMIZER. */ + /* BLE mandatory fields */ + Ndef_BLE_Address_Type_t DeviceAddressType; /**< *For LE only*, *Mandatory*: Address Type, MSB of the Device Address EIR (Public or Random) */ + Ndef_BLE_Role_t Role; /**< *For LE only*, *Mandatory*: LE Role from BLUETOOTH_EIR_BLE_ROLE and defined in `Ndef_BLE_Role_t`. */ + /* BLE optional fields */ + uint8_t SecureManagerTK[16]; /**< *For LE only*: Security Manager TK from BLUETOOTH_EIR_SECURITY_MANAGER_TK_VALUE. */ + uint16_t Appearance; /**< *For LE only*: Appearance from BLUETOOTH_EIR_APPEARANCE. */ + /* track number of unparsed EIR */ + uint8_t nbUnknown; /**< Number of EIRs not parsed because of an unknown EIR type. */ + uint8_t nbServiceData; /**< Number of EIRs not parsed because being of type BLUETOOTH_EIR_SERVICE_DATA. */ + uint8_t nbManufacturerData; /**< Number of EIRs not parsed because being of type BLUETOOTH_EIR_MANUFACTURER_DATA. */ +} Ndef_Bluetooth_OOB_t ; + +/** @brief Extended Inquiry Response format. + * @details This structure is used to parse/build EIRs in the Bluetooth OOB. + */ +typedef struct { + uint8_t length; /**< Length of the EIRs, including the type field (1 byte). */ + uint8_t type; /**< EIR type as defined in `Ndef_Bluetooth_Eir_Types_t`. */ + uint8_t value[1]; /**< single-element array, to keep track of the address of the EIR data */ +} NDEF_EIR_t ; + +uint16_t NDEF_ReadBluetoothOOB( sRecordInfo_t *pRecordStruct, Ndef_Bluetooth_OOB_t *pBluetooth ); +uint16_t NDEF_AppendBluetoothOOB( Ndef_Bluetooth_OOB_t *pBluetooth, char* RecordID, I2C* mi2cChannel ); +void NDEF_PrepareBluetoothMessage(Ndef_Bluetooth_OOB_t *pBluetooth, uint8_t *pNDEFMessage, uint16_t *size ); +uint32_t NDEF_GetBluetoothOOBLength( Ndef_Bluetooth_OOB_t *pBluetooth ); + + + +/** @} + */ + +#endif /* __LIB_NDEF_BLUETOOTH_H */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Email.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Email.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,438 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Email.c + * @author MMY Application Team + * @version $Revision: 2702 $ + * @date $Date: 2016-07-13 18:45:05 +0200 (Wed, 13 Jul 2016) $ + * @brief This file help to manage NDEF file that represent Email. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF_Email.h" +#include "stdlib.h" + +/** @addtogroup NFC_libraries + * @{ + * @brief <b>This is the library used to manage the content of the TAG (data) + * But also the specific feature of the tag, for instance + * password, gpo... </b> + */ + + +/** @addtogroup libNFC_FORUM + * @{ + * @brief This part of the library manage data which follow NFC forum organisation. + */ + +/** + * @brief This buffer contains the data send/received by TAG + */ +extern uint8_t NDEF_Buffer []; + + +/** @defgroup libEmail_Private_Functions + * @{ + */ + + +static void NDEF_FillEmailStruct( uint8_t* pPayload, uint32_t PayloadSize, sEmailInfo *pEmailStruct ); +static void NDEF_ReadURI_Email( sRecordInfo_t *pRecordStruct, sEmailInfo *pEmailStruct ); + +/** + * @brief This function fill Email structure with information of NDEF message + * @param pPayload : pointer on the payload data of the NDEF message + * @param PayloadSize : number of data in the payload + * @param pEmailStruct : pointer on the structure to fill + * @retval NONE + */ +static void NDEF_FillEmailStruct( uint8_t* pPayload, uint32_t PayloadSize, sEmailInfo *pEmailStruct ) +{ + uint8_t* pLastByteAdd, *pLook4Word, *pEndString; + uint32_t SizeOfKeyWord = 0; + + pEndString = 0; + + /* First character force to NULL in case not matching found */ +#ifdef NDEF_DYN_ALLOC + pEmailStruct->EmailAdd = NULL; + pEmailStruct->Subject = NULL; + pEmailStruct->Message = NULL; + pEmailStruct->Information = NULL; +#else + *pEmailStruct->EmailAdd = 0; + *pEmailStruct->Subject = 0; + *pEmailStruct->Message = 0; +#endif + + /* Interesting information are stored before picture if any */ + /* Moreover picture is not used in this demonstration SW */ + pLastByteAdd = (uint8_t*)(pPayload + PayloadSize); + + /* first byte should be the "mailto:" well know URI type, skip it */ + pLook4Word = ++pPayload; + + /* Retrieve email add */ + if( pLook4Word != pLastByteAdd ) + { + pEndString = pLook4Word; + while( memcmp( pEndString, URI_FIRST_DATA_END, URI_FIRST_DATA_END_LENGTH ) && (pEndString < pLastByteAdd) ) + { + pEndString++; + } + if( ( !memcmp( pEndString, URI_FIRST_DATA_END, URI_FIRST_DATA_END_LENGTH ) ) || (pEndString == pLastByteAdd) ) + { +#ifdef NDEF_DYN_ALLOC + pEmailStruct->EmailAdd = malloc(pEndString-pLook4Word + 1); + if(pEmailStruct->EmailAdd != NULL) +#endif + { + memcpy( pEmailStruct->EmailAdd, pLook4Word, pEndString-pLook4Word); + /* add end of string character */ + pEmailStruct->EmailAdd[pEndString-pLook4Word] = 0; + } + } + } + + pEndString += URI_FIRST_DATA_END_LENGTH; + pLook4Word = pEndString; + + /* check if e-mail subject is present */ + if( !memcmp( pLook4Word, SUBJECT_BEGIN_STRING, SUBJECT_BEGIN_STRING_LENGTH ) ) + { + SizeOfKeyWord = SUBJECT_BEGIN_STRING_LENGTH; + + /* Retrieve subject */ + if( pLook4Word != pLastByteAdd ) + { + pLook4Word += SizeOfKeyWord; + pEndString = pLook4Word; + while( memcmp( pEndString, URI_SECOND_DATA_END, URI_SECOND_DATA_END_LENGTH ) && (pEndString < pLastByteAdd) ) + { + pEndString++; + } + if( ( !memcmp( pEndString, URI_SECOND_DATA_END, URI_SECOND_DATA_END_LENGTH ) ) || (pEndString == pLastByteAdd) ) + { +#ifdef NDEF_DYN_ALLOC + pEmailStruct->Subject = malloc(pEndString-pLook4Word + 1); + if(pEmailStruct->Subject != NULL) +#endif + { + memcpy( pEmailStruct->Subject, pLook4Word, pEndString-pLook4Word ); + /* add end of string character */ + pEmailStruct->Subject[pEndString-pLook4Word] = 0; + } + } + pEndString += URI_SECOND_DATA_END_LENGTH; + } + } + + pLook4Word = pEndString; + + /* check if e-mail message is present */ + if( !memcmp( pLook4Word, MESSAGE_BEGIN_STRING, MESSAGE_BEGIN_STRING_LENGTH ) ) + { + pEndString += MESSAGE_BEGIN_STRING_LENGTH; + /* Retrieve message */ +#ifdef NDEF_DYN_ALLOC + pEmailStruct->Message = malloc(PayloadSize - (pEndString - pPayload + 1) + 1); + if(pEmailStruct->Message != NULL) +#endif + { + memcpy( pEmailStruct->Message, pEndString, PayloadSize - (pEndString - pPayload + 1) ); + /* add end of string character */ + pEmailStruct->Message[PayloadSize-(pEndString-pPayload+1)] = 0; + } + } +} + +/** + * @brief This function read the Email and store data in a structure. + * @param pRecordStruct : Pointer on the record structure. + * @param pEmailStruct : pointer on the structure to fill. + */ +static void NDEF_ReadURI_Email( sRecordInfo_t *pRecordStruct, sEmailInfo *pEmailStruct ) +{ + uint8_t* pPayload; + uint32_t PayloadSize; + + PayloadSize = pRecordStruct->PayloadLength; + + /* Read record header */ + pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd); + + if( pRecordStruct->NDEF_Type == URI_EMAIL_TYPE ) + NDEF_FillEmailStruct( pPayload , PayloadSize, pEmailStruct ); + +} + +/** + * @} + */ + +/** @defgroup libEmail_Public_Functions + * @{ + * @brief This file is used to manage Email (stored or loaded in tag) + */ + +/** + * @brief This function read NDEF and retrieve Eamil information if any. + * @param pRecordStruct : Pointer on the record structure. + * @param pEmailStruct : pointer on the structure to fill . + * @retval NDEF_OK : Email information from NDEF have been retrieved. + * @retval NDEF_ERROR : not able to read NDEF in tag. + */ +uint16_t NDEF_ReadEmail( sRecordInfo_t *pRecordStruct, sEmailInfo *pEmailStruct ) +{ + uint16_t status = NDEF_ERROR; + sRecordInfo_t *pSPRecordStruct; + uint32_t PayloadSize, RecordPosition; + uint8_t* pData; + + + if( pRecordStruct->NDEF_Type == URI_EMAIL_TYPE ) + { + NDEF_ReadURI_Email( pRecordStruct, pEmailStruct ); + status = NDEF_OK; + } + else if( pRecordStruct->NDEF_Type == SMARTPOSTER_TYPE ) + { + for( RecordPosition = 0; RecordPosition < pRecordStruct->NbOfRecordInSPPayload; RecordPosition++ ) + { + pSPRecordStruct = pRecordStruct->SPRecordStructAdd[RecordPosition]; + if( pSPRecordStruct->NDEF_Type == URI_EMAIL_TYPE ) + { + NDEF_ReadURI_Email( pSPRecordStruct, pEmailStruct ); + status = NDEF_OK; + } + if( pSPRecordStruct->NDEF_Type == TEXT_TYPE ) + { + PayloadSize = pSPRecordStruct->PayloadLength; + + /* The instruction content the UTF-8 language code that is not used here */ + pData = (uint8_t*)pSPRecordStruct->PayloadBufferAdd; + PayloadSize -= *pData + 1; /* remove not usefull data */ + pData += *pData + 1; + + memcpy( pEmailStruct->Information, pData, PayloadSize ); + } + } + } + + return status; +} + +/** + * @brief This function write the NDEF file with the Email data given in the structure. + * @param pEmailStruct : pointer on structure that contain the Email information. + * @retval NDEF_OK : the function is successful. + * @retval NDEF_ERROR : not able to store NDEF in tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write. + */ +uint16_t NDEF_WriteEmail( sEmailInfo *pEmailStruct, I2C * mi2cChannel ) +{ + uint16_t status = NDEF_ERROR, Offset = 0; + + NDEF_PrepareEmailMessage( pEmailStruct, NDEF_Buffer, &Offset ); + + status = NfcTag_WriteNDEF( Offset, NDEF_Buffer, mi2cChannel ); + + return status; +} + +/** + * @brief This function write the NDEF file with the Email data given in the structure. + * @param pEmailStruct : pointer on structure that contain the Email information. + * @param pNDEFMessage : pointer on the NDEF message. + * @param size : to store the size of the NDEF message generated. + */ +void NDEF_PrepareEmailMessage( sEmailInfo *pEmailStruct, uint8_t *pNDEFMessage, uint16_t *size ) +{ + uint16_t Offset = 0; + uint32_t emailSize = 0; + uint32_t infoSize = 0; + uint32_t totalSize = 0; + + /* Email is an URI but can be included in a smart poster to add text to give instruction to user for instance */ + + /* Email (smart poster) Record Header */ +/************************************/ +/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */ +/*----------------------------------*/ +/* MB ME CF SR IL TNF */ /* <---- CF=0, IL=0 and SR=1 TNF=1 NFC Forum Well-known type*/ +/*----------------------------------*/ +/* TYPE LENGTH */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 3 */ /* <---- Used only if SR=0 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 2 */ /* <---- Used only if SR=0 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 1 */ /* <---- Used only if SR=0 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 0 */ +/*----------------------------------*/ +/* ID LENGTH */ /* <---- Not Used */ +/*----------------------------------*/ +/* TYPE */ +/*----------------------------------*/ +/* ID */ /* <---- Not Used */ +/************************************/ + + /* Email : 1+@+1+subject+1+message */ + emailSize = 1 + strlen( pEmailStruct->EmailAdd ) + URI_FIRST_DATA_END_LENGTH + SUBJECT_BEGIN_STRING_LENGTH + + strlen( pEmailStruct->Subject ) + URI_SECOND_DATA_END_LENGTH + MESSAGE_BEGIN_STRING_LENGTH + strlen( pEmailStruct->Message ); + + /* Check if a Smart poster is needed */ + if( pEmailStruct->Information[0] != '\0' ) + { + /* Info : 1+2+info */ + infoSize = 1 + ISO_ENGLISH_CODE_STRING_LENGTH + strlen( pEmailStruct->Information ); + /* Total */ + totalSize = 4 + emailSize + 4 + infoSize; + if( emailSize > 255 ) totalSize += 3; /* Normal Email size */ + if( infoSize > 255 ) totalSize += 3; /* Normal Info size */ + + /* SmartPoster header */ + if( totalSize > 255 ) + { + pNDEFMessage[Offset++] = 0xC1; + pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (totalSize & 0xFF000000) >> 24; + pNDEFMessage[Offset++] = (totalSize & 0x00FF0000) >> 16; + pNDEFMessage[Offset++] = (totalSize & 0x0000FF00) >> 8; + pNDEFMessage[Offset++] = totalSize & 0x000000FF; + } + else + { + pNDEFMessage[Offset++] = 0xD1; + pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (uint8_t)totalSize; + } + memcpy( &pNDEFMessage[Offset], SMART_POSTER_TYPE_STRING, SMART_POSTER_TYPE_STRING_LENGTH ); + Offset += SMART_POSTER_TYPE_STRING_LENGTH; + } + + /* Email header */ + pNDEFMessage[Offset] = 0x81; + if( emailSize < 256 ) pNDEFMessage[Offset] |= 0x10; // Set the SR bit + if( pEmailStruct->Information[0] == '\0' ) pNDEFMessage[Offset] |= 0x40; // Set the ME bit + Offset++; + + pNDEFMessage[Offset++] = URI_TYPE_STRING_LENGTH; + if( emailSize > 255 ) + { + pNDEFMessage[Offset++] = (emailSize & 0xFF000000) >> 24; + pNDEFMessage[Offset++] = (emailSize & 0x00FF0000) >> 16; + pNDEFMessage[Offset++] = (emailSize & 0x0000FF00) >> 8; + pNDEFMessage[Offset++] = emailSize & 0x000000FF; + } + else + { + pNDEFMessage[Offset++] = (uint8_t)emailSize; + } + memcpy( &pNDEFMessage[Offset], URI_TYPE_STRING, URI_TYPE_STRING_LENGTH ); + Offset += URI_TYPE_STRING_LENGTH; + + /* Email pay load */ + pNDEFMessage[Offset++] = URI_ID_0x06; + memcpy( &pNDEFMessage[Offset], pEmailStruct->EmailAdd, strlen(pEmailStruct->EmailAdd) ); + Offset += strlen( pEmailStruct->EmailAdd ); + memcpy( &pNDEFMessage[Offset], URI_FIRST_DATA_END, URI_FIRST_DATA_END_LENGTH ); + Offset += URI_FIRST_DATA_END_LENGTH; + + memcpy( &pNDEFMessage[Offset], SUBJECT_BEGIN_STRING, SUBJECT_BEGIN_STRING_LENGTH ); + Offset += SUBJECT_BEGIN_STRING_LENGTH; + memcpy( &pNDEFMessage[Offset], pEmailStruct->Subject, strlen(pEmailStruct->Subject) ); + Offset += strlen( pEmailStruct->Subject ); + memcpy( &pNDEFMessage[Offset], URI_SECOND_DATA_END, URI_SECOND_DATA_END_LENGTH ); + Offset += URI_SECOND_DATA_END_LENGTH; + + memcpy( &pNDEFMessage[Offset], MESSAGE_BEGIN_STRING, MESSAGE_BEGIN_STRING_LENGTH ); + Offset += MESSAGE_BEGIN_STRING_LENGTH; + memcpy( &pNDEFMessage[Offset], pEmailStruct->Message, strlen(pEmailStruct->Message) ); + Offset += strlen( pEmailStruct->Message ); + + /* Information header */ + if( pEmailStruct->Information[0] != '\0' ) + { + if( infoSize > 255 ) + { + pNDEFMessage[Offset++] = 0x41; + pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (infoSize & 0xFF000000) >> 24; + pNDEFMessage[Offset++] = (infoSize & 0x00FF0000) >> 16; + pNDEFMessage[Offset++] = (infoSize & 0x0000FF00) >> 8; + pNDEFMessage[Offset++] = infoSize & 0x000000FF; + } + else + { + pNDEFMessage[Offset++] = 0x51; + pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (uint8_t)infoSize; + } + + memcpy( &pNDEFMessage[Offset], TEXT_TYPE_STRING, TEXT_TYPE_STRING_LENGTH ); + Offset += TEXT_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = ISO_ENGLISH_CODE_STRING_LENGTH; /* UTF-8 with x byte language code */ + memcpy( &pNDEFMessage[Offset], ISO_ENGLISH_CODE_STRING, ISO_ENGLISH_CODE_STRING_LENGTH ); + Offset += ISO_ENGLISH_CODE_STRING_LENGTH; + + /* Information payload */ + memcpy( &pNDEFMessage[Offset], pEmailStruct->Information, strlen(pEmailStruct->Information) ); + Offset += strlen( pEmailStruct->Information ); + + } + + *size = (uint16_t)(Offset); + +} + +/** + * @brief This function close a NDEF Email buffer freeing associated memory. + * @param pEmailStruct : pointer on structure that contain the Email information. + */ +void NDEF_closeEmail( sEmailInfo *pEmailStruct) +{ +#ifdef NDEF_DYN_ALLOC + if(pEmailStruct->EmailAdd != NULL) free(pEmailStruct->EmailAdd); + if(pEmailStruct->Information != NULL) free(pEmailStruct->Information); + if(pEmailStruct->Message != NULL) free(pEmailStruct->Message); + if(pEmailStruct->Subject != NULL) free(pEmailStruct->Subject); +#endif +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Email.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Email.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,65 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Email.h + * @author MMY Application Team + * @version $Revision: 2688 $ + * @date $Date: 2016-07-12 16:57:52 +0200 (Tue, 12 Jul 2016) $ + * @brief This file help to manage Email NDEF file. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_NDEF_EMAIL_H +#define __LIB_NDEF_EMAIL_H + + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" + +/* "mailto:customer.service@st.com?subject=M24SR S/N 754FHFGJF46G329 WARRANTY&body=this is an auomatic warranty activation email" */ + +#ifdef NDEF_DYN_ALLOC +typedef struct +{ + char *EmailAdd; + char *Subject; + char *Message; + char *Information; +}sEmailInfo; +#else +typedef struct +{ + char EmailAdd[64]; + char Subject[100]; + char Message[2000]; + char Information[400]; +}sEmailInfo; +#endif +uint16_t NDEF_ReadEmail( sRecordInfo_t *pRecordStruct, sEmailInfo *pEmailStruct ); +uint16_t NDEF_WriteEmail( sEmailInfo *pEmailStruct, I2C* mi2cChannel ); +void NDEF_PrepareEmailMessage( sEmailInfo *pEmailStruct, uint8_t *pNDEFMessage, uint16_t *size ); +void NDEF_closeEmail( sEmailInfo *pEmailStruct); + + +#endif /* __LIB_NDEF_EMAIL_H */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Geo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Geo.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,358 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Geo.c + * @author MMY Application Team + * @version $Revision: 2702 $ + * @date $Date: 2016-07-13 18:45:05 +0200 (Wed, 13 Jul 2016) $ + * @brief This file help to manage NDEF file that represent geolocation. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF_Geo.h" + +/** @addtogroup NFC_libraries + * @{ + * @brief <b>This is the library used to manage the content of the TAG (data) + * But also the specific feature of the tag, for instance + * password, gpo... </b> + */ + + +/** @addtogroup libNFC_FORUM + * @{ + * @brief This part of the library manage data which follow NFC forum organisation. + */ + +/** + * @brief This buffer contains the data send/received by TAG + */ +extern uint8_t NDEF_Buffer []; + +/** @defgroup libGeo_Private_Functions + * @{ + */ + +static void NDEF_FillGeoStruct( uint8_t* pPayload, uint32_t PayloadSize, sGeoInfo *pGeoStruct ); +static void NDEF_ReadURI_Geo( sRecordInfo_t *pRecordStruct, sGeoInfo *pGeoStruct ); + +/** + * @brief This function fill Geo structure with information of NDEF message. + * @param pPayload : pointer on the payload data of the NDEF message. + * @param PayloadSize : number of data in the payload. + * @param pGeoStruct : pointer on the structure to fill. + */ +static void NDEF_FillGeoStruct( uint8_t* pPayload, uint32_t PayloadSize, sGeoInfo *pGeoStruct ) +{ + uint8_t* pLastByteAdd, *pLook4Word, *pEndString; + char* pKeyWord; + uint32_t SizeOfKeyWord; + pEndString = 0; + + pKeyWord = GEO_TYPE_STRING; + SizeOfKeyWord = GEO_TYPE_STRING_LENGTH; + + /* First character force to NULL in case not matching found */ + *pGeoStruct->Latitude = 0; + *pGeoStruct->Longitude = 0; + + /* Interresting information are stored before picture if any */ + /* Moreover picture is not used in this demonstration SW */ + pLastByteAdd = (uint8_t*)(pPayload + PayloadSize); + + pLook4Word = pPayload; + while( memcmp( pLook4Word, pKeyWord, SizeOfKeyWord ) && (pLook4Word < pLastByteAdd) ) + { + pLook4Word++; + } + + /* Retrieve phone number */ + if( pLook4Word != pLastByteAdd ) + { + pLook4Word += SizeOfKeyWord; + pEndString = pLook4Word; + while( memcmp( pEndString, URI_LATITUDE_END, URI_LATITUDE_END_LENGTH ) && (pEndString < pLastByteAdd) ) + { + pEndString++; + } + if( pEndString != pLastByteAdd ) + { + memcpy( pGeoStruct->Latitude, pLook4Word, pEndString-pLook4Word ); + /* add end of string character */ + pGeoStruct->Latitude[pEndString-pLook4Word] = 0; + } + } + pEndString += URI_LATITUDE_END_LENGTH; + pLook4Word = pEndString; + + memcpy( pGeoStruct->Longitude, pEndString, PayloadSize - (pEndString - pPayload) ); + /* add end of string character */ + pGeoStruct->Longitude[PayloadSize-(pEndString-pPayload)] = 0; + +} + +/** + * @brief This function read the geoloccation information and store data in a structure. + * @param pRecordStruct : Pointer on the record structure. + * @param pGeoStruct : pointer on the structure to fill. + */ +static void NDEF_ReadURI_Geo( sRecordInfo_t *pRecordStruct, sGeoInfo *pGeoStruct ) +{ + uint8_t* pPayload; + uint32_t PayloadSize; + + PayloadSize = pRecordStruct->PayloadLength; + + /* Read record header */ + pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd); + + if( pRecordStruct->NDEF_Type == URI_GEO_TYPE ) + NDEF_FillGeoStruct( pPayload , PayloadSize, pGeoStruct ); + +} + +/** + * @} + */ + +/** @defgroup libGeo_Public_Functions + * @{ + * @brief This file is used to manage geolocation (stored or loaded in tag) + */ + +/** + * @brief This function read NDEF and retrieve Geo information if any. + * @param pRecordStruct : Pointer on the record structure. + * @param pGeoStruct : pointer on the structure to fill . + * @retval NDEF_OK : Geolocation information from NDEF have been retrieved. + * @retval NDEF_ERROR : not able to read NDEF from tag. + */ +uint16_t NDEF_ReadGeo( sRecordInfo_t *pRecordStruct, sGeoInfo *pGeoStruct ) +{ + uint16_t status = NDEF_ERROR; + sRecordInfo_t *pSPRecordStruct; + uint32_t PayloadSize, RecordPosition; + uint8_t* pData; + + if( pRecordStruct->NDEF_Type == URI_GEO_TYPE ) + { + NDEF_ReadURI_Geo( pRecordStruct, pGeoStruct ); + status = NDEF_OK; + } + else if( pRecordStruct->NDEF_Type == SMARTPOSTER_TYPE ) + { + for( RecordPosition = 0; RecordPosition < pRecordStruct->NbOfRecordInSPPayload; RecordPosition++ ) + { + pSPRecordStruct = pRecordStruct->SPRecordStructAdd[RecordPosition]; + if( pSPRecordStruct->NDEF_Type == URI_GEO_TYPE ) + { + NDEF_ReadURI_Geo( pSPRecordStruct, pGeoStruct ); + status = NDEF_OK; + } + if( pSPRecordStruct->NDEF_Type == TEXT_TYPE ) + { + PayloadSize = pSPRecordStruct->PayloadLength; + + /* The instruction content the UTF-8 language code that is not used here */ + pData = (uint8_t*)pSPRecordStruct->PayloadBufferAdd; + PayloadSize -= *pData + 1; /* remove not usefull data */ + pData += *pData + 1; /* set pointer on usefull data */ + + memcpy( pGeoStruct->Information, pData, PayloadSize ); + /* add end of string character */ + pGeoStruct->Information[PayloadSize] = 0; + } + } + } + + return status; +} + +/** + * @brief This function write the NDEF file with the geolocation data given in the structure. + * @param pGeoStruct : pointer on structure that contain the geolocation information. + * @retval NDEF_OK : the function is succesful. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write. + */ +uint16_t NDEF_WriteGeo( sGeoInfo *pGeoStruct, I2C* mi2cChannel ) +{ + uint16_t status = NDEF_ERROR,Offset = 0; + + NDEF_PrepareGeoMessage( pGeoStruct, NDEF_Buffer, &Offset ); + + status = NfcTag_WriteNDEF( Offset, NDEF_Buffer, mi2cChannel ); + + return status; +} + +/** + * @brief This function write the NDEF file with the geolocation data given in the structure. + * @param pGeoStruct : pointer on structure that contain the geolocation information. + * @param pNDEFMessage : pointer on the NDEF message. + * @param size : to store the size of the NDEF message generated. + */ +void NDEF_PrepareGeoMessage( sGeoInfo *pGeoStruct, uint8_t *pNDEFMessage, uint16_t *size ) +{ + uint16_t Offset = 0; + uint32_t geoSize = 0; + uint32_t infoSize = 0; + uint32_t totalSize = 0; + + /* GEO is an URI but can be included in a smart poster to add text to give instruction to user for instance */ + + /* GEO (smart poster) Record Header */ +/************************************/ +/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */ +/*----------------------------------*/ +/* MB ME CF SR IL TNF */ /* <---- CF=0, IL=0 and SR=1 TNF=1 NFC Forum Well-known type*/ +/*----------------------------------*/ +/* TYPE LENGTH */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 3 */ /* <---- Used only if SR=0 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 2 */ /* <---- Used only if SR=0 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 1 */ /* <---- Used only if SR=0 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 0 */ +/*----------------------------------*/ +/* ID LENGTH */ /* <---- Not Used */ +/*----------------------------------*/ +/* TYPE */ +/*----------------------------------*/ +/* ID */ /* <---- Not Used */ +/************************************/ + + /* GEO : 1+geo:+latitude+1+longitude */ + geoSize = 1 + GEO_TYPE_STRING_LENGTH + strlen(pGeoStruct->Latitude) + URI_LATITUDE_END_LENGTH + strlen(pGeoStruct->Longitude); + + /* Check if a Smart poster is needed */ + if( pGeoStruct->Information[0] != '\0' ) + { + /* Info : 1+2+info */ + infoSize = 1 + ISO_ENGLISH_CODE_STRING_LENGTH + strlen(pGeoStruct->Information); + /* Total */ + totalSize = 4 + geoSize + 4 + infoSize; + if( geoSize > 255 ) totalSize += 3; /* Normal Geo size */ + if( infoSize > 255 ) totalSize += 3; /* Normal Info size */ + + /* SmartPoster header */ + if( totalSize > 255 ) + { + pNDEFMessage[Offset++] = 0xC1; + pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (totalSize & 0xFF000000) >> 24; + pNDEFMessage[Offset++] = (totalSize & 0x00FF0000) >> 16; + pNDEFMessage[Offset++] = (totalSize & 0x0000FF00) >> 8; + pNDEFMessage[Offset++] = totalSize & 0x000000FF; + } + else + { + pNDEFMessage[Offset++] = 0xD1; + pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (uint8_t)totalSize; + } + memcpy( &pNDEFMessage[Offset], SMART_POSTER_TYPE_STRING, SMART_POSTER_TYPE_STRING_LENGTH ); + Offset += SMART_POSTER_TYPE_STRING_LENGTH; + } + + /* GEO header */ + pNDEFMessage[Offset] = 0x81; + if( geoSize < 256 ) pNDEFMessage[Offset] |= 0x10; // Set the SR bit + if( pGeoStruct->Information[0] == '\0' ) pNDEFMessage[Offset] |= 0x40; // Set the ME bit + Offset++; + + pNDEFMessage[Offset++] = URI_TYPE_STRING_LENGTH; + if( geoSize > 255 ) + { + pNDEFMessage[Offset++] = (geoSize & 0xFF000000) >> 24; + pNDEFMessage[Offset++] = (geoSize & 0x00FF0000) >> 16; + pNDEFMessage[Offset++] = (geoSize & 0x0000FF00) >> 8; + pNDEFMessage[Offset++] = geoSize & 0x000000FF; + } + else + { + pNDEFMessage[Offset++] = (uint8_t)geoSize; + } + memcpy( &pNDEFMessage[Offset], URI_TYPE_STRING, URI_TYPE_STRING_LENGTH ); + Offset += URI_TYPE_STRING_LENGTH; + + /* GEO payload */ + pNDEFMessage[Offset++] = URI_ID_0x00; /* URI identifier no abbreviation */ + memcpy( &pNDEFMessage[Offset], GEO_TYPE_STRING, GEO_TYPE_STRING_LENGTH ); + Offset += GEO_TYPE_STRING_LENGTH; + memcpy( &pNDEFMessage[Offset], pGeoStruct->Latitude, strlen(pGeoStruct->Latitude) ); + Offset += strlen( pGeoStruct->Latitude ); + memcpy( &pNDEFMessage[Offset], URI_LATITUDE_END, URI_LATITUDE_END_LENGTH ); + Offset += URI_LATITUDE_END_LENGTH; + memcpy( &pNDEFMessage[Offset], pGeoStruct->Longitude, strlen(pGeoStruct->Longitude) ); + Offset += strlen( pGeoStruct->Longitude ); + + /* Information header */ + if( pGeoStruct->Information[0] != '\0' ) + { + if( infoSize > 255 ) + { + pNDEFMessage[Offset++] = 0x41; + pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (infoSize & 0xFF000000) >> 24; + pNDEFMessage[Offset++] = (infoSize & 0x00FF0000) >> 16; + pNDEFMessage[Offset++] = (infoSize & 0x0000FF00) >> 8; + pNDEFMessage[Offset++] = infoSize & 0x000000FF; + } + else + { + pNDEFMessage[Offset++] = 0x51; + pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (uint8_t)infoSize; + } + + memcpy( &pNDEFMessage[Offset], TEXT_TYPE_STRING, TEXT_TYPE_STRING_LENGTH ); + Offset += TEXT_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = ISO_ENGLISH_CODE_STRING_LENGTH; /* UTF-8 with x byte language code */ + memcpy( &pNDEFMessage[Offset], ISO_ENGLISH_CODE_STRING, ISO_ENGLISH_CODE_STRING_LENGTH ); + Offset += ISO_ENGLISH_CODE_STRING_LENGTH; + + /* Information payload */ + memcpy( &pNDEFMessage[Offset], pGeoStruct->Information, strlen(pGeoStruct->Information) ); + Offset += strlen( pGeoStruct->Information ); + } + + *size = (uint16_t)(Offset); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Geo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Geo.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,52 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Geo.h + * @author MMY Application Team + * @version $Revision: 2475 $ + * @date $Date: 2016-06-24 12:11:59 +0200 (Fri, 24 Jun 2016) $ + * @brief This file help to manage Geolocation NDEF file. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_NDEF_GEO_H +#define __LIB_NDEF_GEO_H + + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" + +typedef struct +{ + char Latitude[20]; + char Longitude[20]; + char Information[100]; +}sGeoInfo; + +uint16_t NDEF_ReadGeo( sRecordInfo_t *pRecordStruct, sGeoInfo *pGeoStruct ); +uint16_t NDEF_WriteGeo( sGeoInfo *pGeoStruct, I2C* mi2cChannel ); +void NDEF_PrepareGeoMessage( sGeoInfo *pGeoStruct, uint8_t *pNDEFMessage, uint16_t *size ); + + +#endif /* __LIB_NDEF_GEO_H */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Handover.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Handover.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,509 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Bluetooth.c + * @author MMY Application Team + * @version $Revision: 2702 $ + * @date $Date: 2016-07-13 18:45:05 +0200 (Wed, 13 Jul 2016) $ + * @brief This file helps to manage a NDEF Handover message. + * @ingroup libNDEF_Handover + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF_Handover.h" + +/** @addtogroup lib_NDEF_Handover NDEF Handover library + * @ingroup libNDEF + * @brief This module is used to manage the NDEF Handover messages, to negociate the switch to a non-nfc protocol of communication. + * @details + * The NDEF Handover process is described by the NFC Forum Connection Handover specification. + * It consists in a specific NDEF message construct, as: + * - NDEF 1st record: Handover Request or Handover Select record + * - Version + * - Collision Resolution (nested record, optional) + * - Random number + * - Alternative Carrier 1 (nested record) + * - Power state + * - Reference Data + * - Auxiliary Data Reference 1 + * - ... + * - Auxiliary Data Reference N + * - ... + * - Alternative Carrier N (nested record) + * - 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). + * - ... + * - 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). + * _________________ + * @section Handover_Library_Usage NDEF Handover Library usage: + * @subsection Static_Handover Static Handover + * 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,...) + * without running the full handover request-select process.\n + * The Handover Select record use in that case is similar to the one used during a regular Handover negociation.\n + * 1. Declare & initialize an instance of `Ndef_Handover_t`, such as: + * + * Ndef_Handover_t wHandover = {.type = NDEF_HANDOVER_SELECT_TYPE, .version = NDEF_HANDOVER_VERSION_1_2}; + * 2. Declare a `sRecordInfo_t` instance: + * + * sRecordInfo_t HandoverRecord; + * 3. Call the `NDEF_CreateHandover` function, to start preparing the Handover Select record + * + * NDEF_CreateHandover(&wHandover,&HandoverRecord); + * 4. Call the `NDEF_AddAlternativeCarrier` for each Alternative Carrier (such as Bluetooth, Wifi, ...) + * 5. Declare and initialize as many `Ndef_Handover_alternative_carrier_t` instances as the number of non-NFC protocol available. + * And then call the `NDEF_AddAlternativeCarrier` for each of them. + * + * Ndef_Handover_alternative_carrier_t wAC_BREDR = {.cps = NDEF_HANDOVER_AC_CPS_ACTIVE, + * .aux_data_ref_count = 0}; + * Ndef_Handover_alternative_carrier_t wAC_BLE = {.cps = NDEF_HANDOVER_AC_CPS_ACTIVE, + * .aux_data_ref_count = 0}; + * Ndef_Handover_alternative_carrier_t wAC_Wifi = {.cps = NDEF_HANDOVER_AC_CPS_ACTIVE, + * .aux_data_ref_count = 0}; + * + * NDEF_AddAlternativeCarrier(&wAC_BREDR,"urn:nfc:handover:bredr", NULL,&HandoverRecord ); + * NDEF_AddAlternativeCarrier(&wAC_BLE,"urn:nfc:handover:ble", NULL,&HandoverRecord ); + * NDEF_AddAlternativeCarrier(&wAC_Wifi,"urn:nfc:handover:wifi", NULL,&HandoverRecord ); + * @note + * 1. In this example a single `Ndef_Handover_alternative_carrier_t` could have been used, as the parameters are the same for all ACs. + * 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. + * + * Ndef_Handover_alternative_carrier_t wAC_Wifi = {.cps = NDEF_HANDOVER_AC_CPS_ACTIVE, + * .aux_data_ref_count = 2}; + * Then, it's required to initialize an array of pointers to these Auxiliary Data Reference, as: + * + * char *aux_data_ref1 = "urn:nfc:handover:wifi:aux_data_ref1"; + * char *aux_data_ref2 = "urn:nfc:handover:wifi:aux_data_ref2"; + * char *wifi_aux_ref_data_array[2] = {aux_data_ref1,aux_data_ref2}; + * And then provide this array as the 3rd argument to the 'NDEF_AddAlternativeCarrier' function: + * + * NDEF_AddAlternativeCarrier(&wAC_Wifi,"urn:nfc:handover:wifi", wifi_aux_ref_data_array,&HandoverRecord ); + * 6. Call the `NDEF_WriteHandover` function to finalize the NDEF message and write it to the tag. + * + * NDEF_WriteHandover(&HandoverRecord, NDEF_Buffer); + * 7. Then call other functions (from the libNDEF or not) to add records, describing the Alternative Carriers, to the NDEF message: + * + * NDEF_AppendBluetoothOOB ( &w_ble_oob, "urn:nfc:handover:ble" ); + * NDEF_AppendBluetoothOOB ( &w_bredr_oob, "urn:nfc:handover:bredr" ); + * @note + * 1. The ID of these additional records (2nd argument in the above example) must match the Data Reference provided within the Handover record. + * 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. + * + * @section Reading_Handover Reading through a Handover Request message + * 1. Read the 1st record of the NDEF message: + * + * sRecordInfo_t rRecord; + * NDEF_ReadNDEF(NDEF_Buffer); + * NDEF_IdentifyBuffer(rRecord,NDEF_Buffer); + * 2. Decode the handover: + * + * Ndef_Handover_t rHandover; + * NDEF_ReadHandover(&rRecord , &rHandover ); + * 3. Read all Alternative Carrier records, and their Auxiliary Data References if any. + * + * uint8_t ac_index, aux_index; + * for(ac_index=0;ac_index<rHandover.nb_alternative_carrier;ac_index++) + * { + * Ndef_Handover_alternative_carrier_t rAC; + * NDEF_ReadAC( ac_index, &rHandover , &rAC ); + * for(aux_index = 0; aux_index < rAC.aux_data_ref_count; aux_index++) + * { + * sRecordInfo_t AuxRecord; + * NDEF_ReadAuxData( aux_index, &rAC, &AuxRecord ); + * // Do something with this Auxiliary Data + * } + * // Process this AC (Extract OOB/or whatever data), and decide if this Carrier is supported or not. + * } + * 4. Choose the prefered Carrier and write a Handover Select record with the prefered AC as described in the @ref Static_Handover section. + * @{ + */ + + + +/** + * @brief This function searches the NDEF message to retrieve the nth Auxiliary Data record if present. + * @param aux_data_nb Position of the Auxiliary Data Reference in the Alternative Carrier. + * @param pAC Pointer on the Alternative Carrier structure where to find the Auxiliary Data Reference. + * @param pRecord Pointer to return the output Auxiliary Data record. + * @retval NDEF_OK The Auxiliary Data record has been retrieved. + * @retval NDEF_ERROR Not able to find the Auxiliary Data in the NDEF message. + */ +uint16_t NDEF_ReadAuxData( uint8_t aux_data_nb, Ndef_Handover_alternative_carrier_t *pAC, sRecordInfo_t *pRecord ) +{ + uint16_t status; + uint8_t* pData = pAC->aux_data_ref_start; + uint8_t current_aux = 0; + uint8_t* aux_id; + uint8_t aux_id_length; + + if((pAC->aux_data_ref_start == NULL) || + (pAC->aux_data_ref_end == NULL) || + (pAC->aux_data_ref_count == 0) || + (aux_data_nb >= pAC->aux_data_ref_count)) + return NDEF_ERROR; + + + while((current_aux < aux_data_nb) && (pData < pAC->aux_data_ref_end)) + { + aux_id_length = *pData++; + aux_id = pData; + pData += aux_id_length; + current_aux++; + } + + pData = pAC->aux_data_ref_end; + /* if ac has been found */ + if(current_aux == aux_data_nb) + { + /* let's now look for the corresponding record - must be after the Handover record */ + do { + status = NDEF_IdentifyBuffer(pRecord,pData); + if(status != NDEF_OK) return status; + pData = pAC->ac_record.PayloadBufferAdd; + + if((pRecord->IDLength == aux_id_length) && + !memcmp(pRecord->ID, aux_id,aux_id_length)) + { + /* this is the record we were looking for, so exit */ + return NDEF_OK; + } + + // go to next record + pData = pRecord->PayloadBufferAdd + pRecord->PayloadLength; + + } while (!(pRecord->RecordFlags & MB_Mask)); + + } + // if we go there, it means that the record ID is not found + return NDEF_ERROR; +} + + + +/** + * @brief This function reads the NDEF message and retrieves the nth Alternative Carrier record if present. + * @param ac_nb Position of the Alternative Carrier Reference in the Handover record. + * @param pHandover Pointer to the Handover record where to find the AC Reference Data. + * @param pAC Pointer used to return the output Alternative Carrier record. + * @retval NDEF_OK The Alternative Carrier record has been retrieved. + * @retval NDEF_ERROR Not able to find the Alternative Carrier in the NDEF message. + */ +uint16_t NDEF_ReadAC( uint8_t ac_nb, Ndef_Handover_t *pHandover , Ndef_Handover_alternative_carrier_t *pAC ) +{ + uint16_t status; + uint8_t* pData = pHandover->ac_start; + uint8_t current_ac = 0; + uint8_t* ac_id; + uint8_t ac_id_length; + sRecordInfo_t NestedRecord; + uint8_t ac_found = 0; + + if((pHandover->ac_start == NULL) || + (pHandover->ac_end == NULL) || + (pHandover->nb_alternative_carrier == 0) || + (ac_nb >= pHandover->nb_alternative_carrier)) + return NDEF_ERROR; + + // Default handover init + pAC->aux_data_ref_count = 0; + + while((current_ac <= ac_nb)&&(current_ac <= pHandover->nb_alternative_carrier) && (pData < pHandover->ac_end)) + { + status = NDEF_IdentifyBuffer(&NestedRecord,pData); + if(status != NDEF_OK) return status; + // go to payload address + pData = NestedRecord.PayloadBufferAdd; + + if(!memcmp(NestedRecord.Type,NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR,strlen(NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR))) + { + if(current_ac == ac_nb) + { + // parse the AC now + pAC->cps = pData[0] & NDEF_HANDOVER_AC_CPS_MASK; + ac_id_length = pData[1]; + ac_id = &pData[2]; + pAC->aux_data_ref_count = pData[2 + ac_id_length]; + pAC->aux_data_ref_start = &pData[3 + ac_id_length]; + pAC->aux_data_ref_end = pData + NestedRecord.PayloadLength; + ac_found = 1; + } + current_ac++; + } + // go to next record + pData += NestedRecord.PayloadLength; + } + pData = pHandover->ac_end; + /* if ac has been found */ + if(ac_found) + { + /* let's now look for the corresponding record - must be after the Handover record */ + do { + status = NDEF_IdentifyBuffer(&pAC->ac_record,pData); + if(status != NDEF_OK) return status; + pData = pAC->ac_record.PayloadBufferAdd; + + if((pAC->ac_record.IDLength == ac_id_length) && + !memcmp(pAC->ac_record.ID, ac_id,ac_id_length)) + { + /* this is the record we were looking for, so exit */ + return NDEF_OK; + } + + // go to next record + pData = pAC->ac_record.PayloadBufferAdd + pAC->ac_record.PayloadLength; + // TO DO: add a security condition to avoid infinite loop if NDEF file is corrupted + } while (!(pAC->ac_record.RecordFlags & ME_Mask)); + + } + // if we go there, it means that the record ID is not found + return NDEF_ERROR; +} + + +/** + * @brief This function reads a record and retrieves the Handover information if present. + * @param pRecord Pointer on the record structure to be read. + * @param pHandover Pointer used to return the Handover information. + * @retval NDEF_OK Handover information has been retrieved from the record. + * @retval NDEF_ERROR Not able to read the Handover information from the record. + */ +uint16_t NDEF_ReadHandover(sRecordInfo_t *pRecord , Ndef_Handover_t *pHandover ) +{ + uint16_t status; + uint8_t* pData = pRecord->PayloadBufferAdd; + uint8_t* pEnd = pData + pRecord->PayloadLength; + sRecordInfo_t NestedRecord; + + /* Default Handover Structure init */ + pHandover->version =0; + pHandover->nb_alternative_carrier =0; + pHandover->has_cr = 0; + pHandover->ac_start = NULL; + pHandover->ac_end = NULL; + + /* A Handover record should never be the end of the NDEF message */ + if(pRecord->RecordFlags & ME_Mask) + return NDEF_ERROR; + + if( !memcmp(pRecord->Type,NDEF_HANDOVER_REQUEST_TYPE_STR,strlen(NDEF_HANDOVER_REQUEST_TYPE_STR)) ) + { + pHandover->type = NDEF_HANDOVER_REQUEST_TYPE; + } else if ( !memcmp(pRecord->Type,NDEF_HANDOVER_SELECT_TYPE_STR,strlen(NDEF_HANDOVER_SELECT_TYPE_STR)) ) + { + pHandover->type = NDEF_HANDOVER_SELECT_TYPE; + } else { + /* This is not a Handover record! */ + return NDEF_ERROR; + } + + pHandover->version = *pData++; + + /* Following records are nested into Hr/s record */ + while (pData < pEnd) + { + status = NDEF_IdentifyBuffer(&NestedRecord,pData); + if(status != NDEF_OK) return status; + /* save record address */ + uint8_t* pACRecord = pData; + /* go to payload address */ + pData = NestedRecord.PayloadBufferAdd; + + /* Parse Collision Resolution if Handover request */ + if(pHandover->type == NDEF_HANDOVER_REQUEST_TYPE) + { + + if(!memcmp(NestedRecord.Type,NDEF_HANDOVER_COLLISION_RESOLUTION_TYPE_STR,strlen(NDEF_HANDOVER_COLLISION_RESOLUTION_TYPE_STR))) + { + pHandover->has_cr = 1; + pHandover->cr_random_number = *(uint16_t*)pData; + } + } + + /* Parse AlternativeCarriers just to know how many they are */ + else if(!memcmp(NestedRecord.Type,NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR,strlen(NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR))) + { + pHandover->nb_alternative_carrier++; + if(pHandover->ac_start == NULL) + pHandover->ac_start = pACRecord; + pHandover->ac_end = pData + NestedRecord.PayloadLength; + /* don't parse the AC now */ + } + else { + /* this is an unexpected type, just ignore it */ + } + /* go to next record */ + pData += NestedRecord.PayloadLength; + + } + + return NDEF_OK; +} + +/** + * @brief This function prepares the Handover record with the data given in the Handover structure. + * @param pHandover Pointer on structure containing the handover basic information. + * @param pRecord Pointer used to return the prepared Handover record. + * @retval NDEF_OK The record has been prepared. + * @retval NDEF_ERROR The record has not been prepared. + */ +uint16_t NDEF_CreateHandover(Ndef_Handover_t *pHandover, sRecordInfo_t* pRecord ) +{ + uint16_t status = NDEF_ERROR; + + /* Use a static buffer to prepare the Handover record */ + pRecord->PayloadBufferAdd = NDEF_Record_Buffer; + /* Alternative, where the user must first allocate the Payload buffer in the record: + * if (pRecord->PayloadBufferAdd == NULL) + * return NDEF_ERROR; + */ + + /* Handover MUST be the first record (SR mask to be updated when actually writing the record) */ + pRecord->RecordFlags = MB_Mask | ME_Mask | TNF_WellKnown; + + if(pHandover->type == NDEF_HANDOVER_SELECT_TYPE) + { + pRecord->TypeLength = strlen(NDEF_HANDOVER_SELECT_TYPE_STR); + memcpy(pRecord->Type, NDEF_HANDOVER_SELECT_TYPE_STR,pRecord->TypeLength); + } + else if (pHandover->type == NDEF_HANDOVER_REQUEST_TYPE) + { + pRecord->TypeLength = strlen(NDEF_HANDOVER_SELECT_TYPE_STR); + memcpy(pRecord->Type, NDEF_HANDOVER_REQUEST_TYPE_STR,pRecord->TypeLength); + } + else + return NDEF_ERROR; + + pRecord->PayloadLength = sizeof(pHandover->version); + *pRecord->PayloadBufferAdd = pHandover->version; + + /* Don't write the record for now, additionnal Alternative Carriers to come as nested records. */ + + return status; +} + + +/** + * @brief This function adds an Alternative Carrier record to a Handover record using the data given in the AC structure. + * @param pAC Pointer on input AC structure. + * @param CarrierDataRef String with the Alternative Carrier Data Reference (ID of the corresponding record in the NDEF message). + * @param AuxDataRefID Array with pointers to the Auxiliary Data References (as many as defined in pAC structure). + * @param pRecord Pointer on the Handover record to be filled with the AC data, must have been previously initialized with the NDEF_CreateHandover function. + * @retval NDEF_OK The Handover record has been updated with AC information. + * @retval NDEF_ERROR The Handover record cannot be updated with the AC information. + * @retval NDEF_ERROR_MEMORY_INTERNAL The internal buffer for records is too small to add the AC information. + */ +uint16_t NDEF_AddAlternativeCarrier(Ndef_Handover_alternative_carrier_t *pAC,char *CarrierDataRef, char **AuxDataRefID, sRecordInfo_t* pRecord, I2C* mi2cChannel ) +{ + /* Specific buffer to prepare the Alternative Carrier record */ + uint8_t NDEF_AlternativeCarrier_Buffer[NDEF_AC_BUFFER_SIZE]; + + /* check that there is enough space in the buffers */ + pAC->ac_record.PayloadLength = NDEF_GetACDataLength(pAC,CarrierDataRef,AuxDataRefID); + if(((pRecord->PayloadLength + pAC->ac_record.PayloadLength) > NDEF_RECORD_MAX_SIZE) || + (pAC->ac_record.PayloadLength > NDEF_AC_BUFFER_SIZE)) + return NDEF_ERROR_MEMORY_INTERNAL; + + /* Use specific buffer to prepare the nested record */ + uint8_t *pData = NDEF_AlternativeCarrier_Buffer; + pAC->ac_record.PayloadBufferAdd = pData; + /* Following line is an alternative where the user must allocate the payload buffer of the ac_record: + * uint8_t* pData = pAC->ac_record.PayloadBufferAdd ; + */ + + if ((pRecord->PayloadBufferAdd == NULL) || + (pRecord->PayloadLength == 0)) + return NDEF_ERROR; + + /* AC is not the first record */ + pAC->ac_record.RecordFlags = TNF_WellKnown; + + pAC->ac_record.TypeLength = strlen(NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR); + memcpy(pAC->ac_record.Type, NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR,pAC->ac_record.TypeLength); + + /* Length : cps byte + data ref length byte + auxiliary data ref count byte + data ref length */ + *pData++ = pAC->cps & NDEF_HANDOVER_AC_CPS_MASK; + *pData++ = strlen(CarrierDataRef); + memcpy(pData, CarrierDataRef, strlen(CarrierDataRef)); + pData += strlen(CarrierDataRef); + *pData++ = pAC->aux_data_ref_count; + + uint8_t AuxDataIndex; + for(AuxDataIndex = 0;AuxDataIndex<pAC->aux_data_ref_count;AuxDataIndex++) + { + *pData++ = strlen(AuxDataRefID[AuxDataIndex]); + memcpy(pData, AuxDataRefID[AuxDataIndex], strlen(AuxDataRefID[AuxDataIndex])); + pData += strlen(AuxDataRefID[AuxDataIndex]); + } + + /* Append the nested record right after the Handover record - increase its length accordingly */ + pRecord->PayloadLength += NDEF_WriteRecord(&pAC->ac_record,pRecord->PayloadBufferAdd + pRecord->PayloadLength, mi2cChannel); + return NDEF_OK; +} + + +/** + * @brief This function returns the length of an Alternative Carrier record data (excluding the record metadata). + * @param pAC Pointer on the input AC structure. + * @param CarrierDataRef String with the Alternative Carrier Data Reference. + * @param AuxDataRefID Array with the Auxiliary Data References (as many as defined in the pAC structure). + * @return The computed length in bytes corresponding to the provided Alternative Carrier information. + */ +uint32_t NDEF_GetACDataLength(Ndef_Handover_alternative_carrier_t *pAC,char *CarrierDataRef, char **AuxDataRefID) +{ + uint8_t AuxDataIndex; + + /* First compute the Data length */ + uint32_t length = 1 + // cps + 1 + // Carrier data ref length + strlen(CarrierDataRef) + // Carrier data ref + 1 + // auxiliary data count + pAC->aux_data_ref_count * 1; // auxiliary data lengths + + /* Then adds the length of the Auxiliary Data */ + for(AuxDataIndex = 0;AuxDataIndex<pAC->aux_data_ref_count;AuxDataIndex++) + { + length += strlen(AuxDataRefID[AuxDataIndex]); + } + + return length; +} + +/** + * @brief This function writes the Handover record into the memory. + * @param pRecord Pointer on the input Handover record. + * @param pNdef Pointer to a NDEF buffer (used to prepare the data before actual writing to the memory). + * @retval NDEF_OK The memory has been written. + * @retval NDEF_ERROR_MEMORY_INTERNAL Cannot write to tag. + * @retval NDEF_ERROR_NOT_FORMATED CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED Tag locked, cannot be write. + */ +uint16_t NDEF_WriteHandover( sRecordInfo_t* pRecord , uint8_t* pNdef, I2C* mi2cChannel) +{ + /* Note: in case of Handover Select for no matching alternative carrier, the ME bit flag must be set by the caller */ + + uint32_t Size = NDEF_WriteRecord(pRecord,pNdef, mi2cChannel); + return NDEF_WriteNDEF(Size,pNdef, mi2cChannel); +} + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Handover.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Handover.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,116 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Bluetooth.h + * @author MMY Application Team + * @version $Revision: 2475 $ + * @date $Date: 2016-06-24 12:11:59 +0200 (Fri, 24 Jun 2016) $ + * @brief This file help to manage Bluetooth NDEF file. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_NDEF_HANDOVER_H +#define __LIB_NDEF_HANDOVER_H + + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" + + +/** @addtogroup lib_NDEF_Handover NDEF Handover library + * @{ + */ + +/** @brief SIze of the buffer used to store an Alternative Carrier (allocated on the stack). + * @details 128 bytes should be enough, the specification recommends to use short URIs as AC identifiers. + */ +#define NDEF_AC_BUFFER_SIZE (128) + +/** @brief NFC Forum Well-Known Type name for a Handover Select record */ +#define NDEF_HANDOVER_SELECT_TYPE_STR "Hs" +/** @brief NFC Forum Well-Known Type name for a Handover Request record */ +#define NDEF_HANDOVER_REQUEST_TYPE_STR "Hr" +/** @brief NFC Forum Well-Known Type name for a Handover Select Select (ascii value) */ +#define NDEF_HANDOVER_SELECT_TYPE 0x4872 +/** @brief NFC Forum Well-Known Type name for a Handover Request record (ascii value) */ +#define NDEF_HANDOVER_REQUEST_TYPE 0x4873 +/** @brief NFC Forum Handover record implemented version */ +#define NDEF_HANDOVER_VERSION_1_2 0x12 + +/** @brief NFC Forum Well-Known Type name for a Colision Resolution record */ +#define NDEF_HANDOVER_COLLISION_RESOLUTION_TYPE_STR "cr" +/** @brief NFC Forum Well-Known Type name for an Alternative Carrier record */ +#define NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR "ac" + +/** @brief NFC Forum Power States values mask */ +#define NDEF_HANDOVER_AC_CPS_MASK (0x3) +/** @brief Enumerates the NFC Forum Power States possible values */ +typedef enum { + NDEF_HANDOVER_AC_CPS_INACTIVE = 0x0, /**< The HW for this Alternative Carrier has to be switch on before proceeding. */ + NDEF_HANDOVER_AC_CPS_ACTIVE = 0x1, /**< The HW for this Alternative Carrier is currently running. */ + NDEF_HANDOVER_AC_CPS_ACTIVATING = 0x2, /**< The HW for this Alternative Carrier is being activated. */ + NDEF_HANDOVER_AC_CPS_UNKNOWN = 0x3 /**< The HW for this Alternative Carrier is unknown. */ +} Ndef_Handover_ac_cps_t; + + + +typedef struct { + uint8_t cps; /**< Current Power State for this Alternative Carrier Hardware. */ + sRecordInfo_t ac_record; /**< The record structure used to store/build the Alternative Carrier record. */ + uint8_t aux_data_ref_count; /**< The number of Auxiliary Data Reference for this Alternative Carrier. */ + /* following fields are only used when reading NDEF */ + uint8_t* aux_data_ref_start; /**< Internal field, managed by the library, to keep track of the Auxiliary Data Reference start address in the AC record. */ + uint8_t* aux_data_ref_end; /**< Internal field, managed by the library, to keep track of the Auxiliary Data Reference end address in the AC record. */ +} Ndef_Handover_alternative_carrier_t; + + +typedef struct { + uint16_t type; /**< Handover type: could be Select or Request. */ + uint8_t version; /**< Version of the Handover record. */ + /* following fields are only used when reading NDEF */ + uint8_t has_cr; /**< Boolean, if true this Handover has a Collision Resolution nested record. */ + uint16_t cr_random_number; /**< Random number for the Collision Resolution. */ + uint8_t nb_alternative_carrier; /**< Number of Alternative Carrier nested records un this Handover. */ + uint8_t* ac_start; /**< Internal field, managed by the library, to keep track of the Alternative Carrier Reference Data start address in the Handover record. */ + uint8_t* ac_end; /**< Internal field, managed by the library, to keep track of the Alternative Carrier Reference Data end address in the Handover record. */ +} Ndef_Handover_t; + + + +uint16_t NDEF_ReadHandover(sRecordInfo_t *pRecord , Ndef_Handover_t *pHandover ); +uint16_t NDEF_ReadAC( uint8_t ac_nb, Ndef_Handover_t *pHandover , Ndef_Handover_alternative_carrier_t *pAC ); +uint16_t NDEF_ReadAuxData( uint8_t aux_data_nb, Ndef_Handover_alternative_carrier_t *pAC, sRecordInfo_t *pRecord ); + +uint16_t NDEF_CreateHandover(Ndef_Handover_t *pHandover, sRecordInfo_t* pRecord ); +uint16_t NDEF_AddAlternativeCarrier(Ndef_Handover_alternative_carrier_t *pAC, char* CarrierDataRef, char **AuxDataRefID, sRecordInfo_t* pRecord ); +uint16_t NDEF_WriteHandover( sRecordInfo_t* pRecord , uint8_t* pNdef, I2C* mi2cChannel); + +uint32_t NDEF_GetACDataLength(Ndef_Handover_alternative_carrier_t *pAC,char *CarrierDataRef, char **AuxDataRefID); + + + +/** @} + */ + +#endif /* __LIB_NDEF_HANDOVER_H */ + +/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_MyApp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_MyApp.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,277 @@ +/** + ****************************************************************************** + * @file lib_NDEF_MyApp.c + * @author MMY Application Team + * @version $Revision: 2762 $ + * @date $Date: 2016-08-10 16:40:40 +0200 (Wed, 10 Aug 2016) $ + * @brief This file help to manage the NDEF file of a private application. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF_MyApp.h" + + +/** @addtogroup NFC_libraries + * @{ + * @brief <b>This is the library used to manage the content of the TAG (data) + * But also the specific feature of the tag, for instance + * password, gpio... </b> + */ + + +/** @addtogroup libNFC_FORUM + * @{ + * @brief This part of the library manage data which follow NFC forum organisation. + */ + +/** + * @brief This buffer contains the data send/received by TAG + */ +extern uint8_t NDEF_Buffer []; + +/** @defgroup libMyApp_Private_Functions + * @{ + */ + +static void NDEF_Extract_M24SRDiscoveryApp_Input( sRecordInfo_t *pRecordStruct, sMyAppInfo *pMyAppStruct ); + +/** + * @brief This function read the NDEF file and store application data in a structure. + * @param pRecordStruct : Pointer on the record structure. + * @param pMyAppStruct : pointer on the structure to fill. + */ +static void NDEF_Extract_M24SRDiscoveryApp_Input( sRecordInfo_t *pRecordStruct, sMyAppInfo *pMyAppStruct ) +{ + uint8_t* pPayload; + uint8_t* pLook4Word; + uint16_t BackGroundColor, FontColor; + uint8_t i; + + /* Read record header */ + pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd); + + /* initialize struct in case not matching found */ + for( i = 0; i < 8; i++ ) + { + /* Set the Back Color */ + pMyAppStruct->LineX[i].BackGroundColor = 0xFFFF; + /* Set the Text Color */ + pMyAppStruct->LineX[i].FontColor = 0x0000; + /* Set the line number */ + pMyAppStruct->LineX[i].LineNb = i + 1; + /* Set the line content */ + memcpy( pMyAppStruct->LineX[i].String, " ", 20 ); + } + + pLook4Word = pPayload; + + for( i = 0; i < 4; i++ ) + { + pMyAppStruct->LedBlinkConf.LedConf[i] = *pLook4Word; + pLook4Word++; + } + pMyAppStruct->LedBlinkConf.Speed = *pLook4Word; + pLook4Word++; + + for( i = 0; i < 8; i++ ) + { + /* Set the line number */ + pMyAppStruct->LineX[i].LineNb = *pLook4Word; + pLook4Word++; + /* Set the Back Color */ + BackGroundColor = (uint16_t)(*pLook4Word << 8); + BackGroundColor = BackGroundColor | (uint16_t)(*++pLook4Word ); + pMyAppStruct->LineX[i].BackGroundColor = BackGroundColor; + pLook4Word++; + /* Set the Text Color */ + FontColor = (uint16_t)(*pLook4Word << 8); + FontColor = FontColor | (uint16_t)(*++pLook4Word); + pMyAppStruct->LineX[i].FontColor = FontColor; + pLook4Word++; + /* Set the line content */ + memcpy( pMyAppStruct->LineX[i].String, (char*)pLook4Word, 20 ); + pLook4Word += 20; + } + +} + +/** + * @} + */ + +/** @defgroup libMyApp_Public_Functions + * @{ + * @brief This file is used to manage proprietary NDEF (stored or loaded in tag) + */ + +/** + * @brief This function read NDEF and retrieve Application information if any. + * @param pRecordStruct : Pointer on the record structure. + * @param pMyAppStruct : pointer on the structure to fill. + * @retval NDEF_OK : NDEF file data read in the tag. + * @retval NDEF_ERROR : not able to read NDEF in tag. + */ +uint16_t NDEF_ReadMyApp( sRecordInfo_t *pRecordStruct, sMyAppInfo *pMyAppStruct ) +{ + uint16_t status = NDEF_ERROR; + + if( pRecordStruct->NDEF_Type == M24SR_DISCOVERY_APP_TYPE ) + { + NDEF_Extract_M24SRDiscoveryApp_Input( pRecordStruct, pMyAppStruct ); + status = NDEF_OK; + } + else + { + status = NDEF_ERROR; + } + + return status; +} + +/** + * @brief This function write the NDEF file with the Application data given in the structure. + * @brief Only used for debug purpose in this firmware version. + * @param pMyAppStruct : pointer on structure that contain the application information. + * @retval NDEF_OK : NDEF file data written in the tag. + * @retval NDEF_ERROR : not able to store NDEF in tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write. + */ +uint16_t NDEF_WriteMyApp( sMyAppInfo *pMyAppStruct, I2C * mi2cChannel ) +{ + uint16_t status = NDEF_ERROR; + uint16_t DataSize; + uint32_t PayloadSize; + uint8_t i; + uint8_t* pPayload; + + +/* External Type Record Header */ +/************************************/ +/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */ +/*----------------------------------*/ +/* MB ME CF SR IL TNF */ /* <---- IL=0, CF=0 and SR=1 TNF=4 NFC Forum external type*/ +/*----------------------------------*/ +/* TYPE LENGTH */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 3 */ /* <---- Not Used */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 2 */ /* <---- Not Used */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 1 */ /* <---- Not Used */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 0 */ /* The payload will always be 5 + 25*8=205 bytes for this application */ +/*----------------------------------*/ +/* ID LENGTH */ /* <---- Not Used */ +/*----------------------------------*/ +/* TYPE */ /* st.com:m24sr_discovery_democtrl */ +/*----------------------------------*/ +/* ID */ /* <---- Not Used */ +/************************************/ + + + /* fill URI record header */ + NDEF_Buffer[0] = 0xD4; /* Record Flag */ + NDEF_Buffer[1] = M24SR_DISCOVERY_APP_STRING_LENGTH; + NDEF_Buffer[2] = 0x00; /* Will be filled at the end when payload size is known */ + + memcpy( &NDEF_Buffer[3], M24SR_DISCOVERY_APP_STRING, M24SR_DISCOVERY_APP_STRING_LENGTH ); + + pPayload = &NDEF_Buffer[ 3 + M24SR_DISCOVERY_APP_STRING_LENGTH]; + PayloadSize = 0; + + /**************************************************************/ + /* BLINK CONFIG data */ + + /* led 1 blinking */ + *pPayload = 0x03; + pPayload++; + /* led 2 blinking */ + *pPayload = 0x02; + pPayload++; + /* led 3 blinking */ + *pPayload = 0x02; + pPayload++; + /* led 4 blinking */ + *pPayload = 0x03; + pPayload++; + /* speed */ + *pPayload = 0x03; + pPayload++; + + PayloadSize += 5; + + /**************************************************************/ + + /**************************************************************/ + /* SCREEN config data */ + for( i = 0; i < 8; i++ ) + { + /* Line number */ + *pPayload = (uint8_t)(i + 1); + pPayload++; + /* Background color */ + *pPayload = 0xFF - (0xFF/i); + pPayload++; + *pPayload = 0xFF - (0xFF/i); + pPayload++; + /* Font Color */ + *pPayload = 0xFF/i; + pPayload++; + *pPayload = 0xFF/i; + pPayload++; + /* String */ + memcpy( pPayload, "ABCDEFGHIJKLMNOPQRST", 20 ); + pPayload += 20; + + PayloadSize += 25; + + } + + NDEF_Buffer[2] = PayloadSize & 0x000000FF; + + DataSize = PayloadSize + 5 + M24SR_DISCOVERY_APP_STRING_LENGTH; + + /* Write NDEF */ + status = NfcTag_WriteNDEF( DataSize, NDEF_Buffer, mi2cChannel ); + + + return status; +} + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_MyApp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_MyApp.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,81 @@ +/** + ****************************************************************************** + * @file lib_NDEF_MyApp.h + * @author MMY Application Team + * @version $Revision: 2822 $ + * @date $Date: 2016-09-05 16:18:16 +0200 (Mon, 05 Sep 2016) $ + * @brief This file illustrate how to use M24SR with a proprietary protocol. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_NDEF_MYAPP_H +#define __LIB_NDEF_MYAPP_H + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" + +#define BLINK_CONFIG "<BLINK_CONFIG>" +#define BLINK_CONFIG_STRING_SIZE 14 +#define BLINK_CONFIG_END "<\\BLINK_CONFIG>" +#define BLINK_CONFIG_END_STRING_SIZE 15 + +#define LINE_DESCR "<LINE_DESCR>" +#define LINE_DESCR_STRING_SIZE 12 +#define LINE_DESCR_END "<\\LINE_DESCR>" +#define LINE_DESCR_END_STRING_SIZE 13 + +#define BLINKING_NONE 0x00 +#define BLINKING_SLOW 0x01 +#define BLINKING_MEDIUM 0x02 +#define BLINKING_FAST 0x03 + +#define MYAPP_NB_LINES ((uint8_t)8) +#define MYAPP_LED_CONF_INITAL_STATE ((uint8_t) 0x1) +#define MYAPP_LED_CONF_BLINKING ((uint8_t) 0x2) + +typedef struct +{ + uint8_t LedConf[4]; + uint8_t Speed; +}sLedBlinkConfig; + +typedef struct +{ + uint8_t LineNb; + uint16_t BackGroundColor; + uint16_t FontColor; + char String[20]; +}sLineConfig; + +typedef struct +{ + sLedBlinkConfig LedBlinkConf; + sLineConfig LineX[MYAPP_NB_LINES]; +}sMyAppInfo; + +uint16_t NDEF_ReadMyApp( sRecordInfo_t *pRecordStruct, sMyAppInfo *pMyAppStruct ); +uint16_t NDEF_WriteMyApp( sMyAppInfo *pMyAppStruct, I2C * mi2cChannel ); + +#endif /* __LIB_NDEF_MYAPP_H */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_SMS.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_SMS.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,370 @@ +/** + ****************************************************************************** + * @file lib_NDEF_SMS.c + * @author MMY Application Team + * @version $Revision: 2702 $ + * @date $Date: 2016-07-13 18:45:05 +0200 (Wed, 13 Jul 2016) $ + * @brief This file help to manage NDEF file that represent SMS. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF_SMS.h" + + +/** @addtogroup NFC_libraries + * @{ + * @brief <b>This is the library used to manage the content of the TAG (data) + * But also the specific feature of the tag, for instance + * password, gpo... </b> + */ + + +/** @addtogroup libNFC_FORUM + * @{ + * @brief This part of the library manage data which follow NFC forum organisation. + */ + +/** + * @brief This buffer contains the data send/received by TAG + */ +extern uint8_t NDEF_Buffer []; + +/** @defgroup libSMS_Private_Functions + * @{ + */ + +static void NDEF_FillSMSStruct( uint8_t* pPayload, uint32_t PayloadSize, sSMSInfo *pSMSStruct ); +static void NDEF_ReadURI_SMS( sRecordInfo_t *pRecordStruct, sSMSInfo *pSMSStruct ); + +/** + * @brief This function fill SMS structure with information of NDEF message. + * @param pPayload : pointer on the payload data of the NDEF message. + * @param PayloadSize : number of data in the payload. + * @param pSMSStruct : pointer on the structure to fill. + */ +static void NDEF_FillSMSStruct( uint8_t* pPayload, uint32_t PayloadSize, sSMSInfo *pSMSStruct ) +{ + uint8_t* pLastByteAdd, *pLook4Word, *pEndString; + char* pKeyWord; + uint32_t SizeOfKeyWord; + pEndString = 0; + + pKeyWord = SMS_TYPE_STRING; + SizeOfKeyWord = SMS_TYPE_STRING_LENGTH; + + /* First character force to NULL in case not matching found */ + *pSMSStruct->PhoneNumber = 0; + *pSMSStruct->Message = 0; + + /* Interesting information are stored before picture if any */ + /* Moreover picture is not used in this demonstration SW */ + pLastByteAdd = (uint8_t*)(pPayload + PayloadSize); + + pLook4Word = pPayload; + while( memcmp( pLook4Word, pKeyWord, SizeOfKeyWord ) && (pLook4Word < pLastByteAdd) ) + { + pLook4Word++; + } + + /* Retrieve phone number */ + if( pLook4Word != pLastByteAdd ) + { + pLook4Word += SizeOfKeyWord; + pEndString = pLook4Word; + while( memcmp( pEndString, URI_FIRST_DATA_END, URI_FIRST_DATA_END_LENGTH ) && (pEndString < pLastByteAdd) ) + { + pEndString++; + } + if( pEndString != pLastByteAdd ) + { + memcpy( pSMSStruct->PhoneNumber, pLook4Word, pEndString-pLook4Word ); + /* add end of string character */ + pSMSStruct->PhoneNumber[pEndString-pLook4Word] = 0; + } + } + pEndString += URI_FIRST_DATA_END_LENGTH; + pLook4Word = pEndString; + + /* check if e-mail subject is present */ + if( !memcmp( pLook4Word, MESSAGE_BEGIN_STRING, MESSAGE_BEGIN_STRING_LENGTH ) ) + { + pEndString += MESSAGE_BEGIN_STRING_LENGTH; + /* Retrieve message */ + memcpy( pSMSStruct->Message, pEndString, PayloadSize - (pEndString - pPayload) ); + /* add end of string character */ + pSMSStruct->Message[PayloadSize-(pEndString-pPayload)] = 0; + } +} + +/** + * @brief This function read the SMS and store data in a structure. + * @param pRecordStruct : Pointer on the record structure. + * @param pSMSStruct : pointer on the structure to fill. + */ +static void NDEF_ReadURI_SMS( sRecordInfo_t *pRecordStruct, sSMSInfo *pSMSStruct ) +{ + uint8_t* pPayload; + uint32_t PayloadSize; + + PayloadSize = pRecordStruct->PayloadLength; + + /* Read record header */ + pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd); + + if( pRecordStruct->NDEF_Type == URI_SMS_TYPE ) + NDEF_FillSMSStruct( pPayload , PayloadSize, pSMSStruct ); + +} + +/** + * @} + */ + +/** @defgroup libSMS_Public_Functions + * @{ + * @brief This file is used to manage SMS (stored or loaded in tag) + */ + +/** + * @brief This function read NDEF and retrieve SMS information if any. + * @param pRecordStruct : Pointer on the record structure. + * @param pSMSStruct : pointer on the structure to fill. + * @retval NDEF_OK : SMS information from NDEF have been retrieve. + * @retval NDEF_ERROR : Not able to retrieve SMS information. + */ +uint16_t NDEF_ReadSMS( sRecordInfo_t *pRecordStruct, sSMSInfo *pSMSStruct ) +{ + uint16_t status = NDEF_ERROR; + sRecordInfo_t *pSPRecordStruct; + uint32_t PayloadSize, RecordPosition; + uint8_t* pData; + + if( pRecordStruct->NDEF_Type == URI_SMS_TYPE ) + { + NDEF_ReadURI_SMS( pRecordStruct, pSMSStruct ); + status = NDEF_OK; + } + else if( pRecordStruct->NDEF_Type == SMARTPOSTER_TYPE ) + { + for( RecordPosition = 0; RecordPosition < pRecordStruct->NbOfRecordInSPPayload; RecordPosition++ ) + { + pSPRecordStruct = pRecordStruct->SPRecordStructAdd[RecordPosition]; + if( pSPRecordStruct->NDEF_Type == URI_SMS_TYPE ) + { + NDEF_ReadURI_SMS( pSPRecordStruct, pSMSStruct ); + status = NDEF_OK; + } + if( pSPRecordStruct->NDEF_Type == TEXT_TYPE ) + { + PayloadSize = pSPRecordStruct->PayloadLength; + + /* The instruction content the UTF-8 language code that is not used here */ + pData = (uint8_t*)pSPRecordStruct->PayloadBufferAdd; + PayloadSize -= *pData + 1; /* remove not usefull data */ + pData += *pData + 1; /* set pointer on usefull data */ + + memcpy( pSMSStruct->Information, pData, PayloadSize ); + /* add end of string character */ + pSMSStruct->Information[PayloadSize] = 0; + } + } + } + + return status; +} + +/** + * @brief This function write the NDEF file with the SMS data given in the structure. + * @param pSMSStruct : pointer on structure that contain the SMS information. + * @retval NDEF_OK : NDEF file data written in the tag. + * @retval NDEF_ERROR : not able to store NDEF in tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write. + */ +uint16_t NDEF_WriteSMS( sSMSInfo *pSMSStruct, I2C* mi2cChannel ) +{ + uint16_t status = NDEF_ERROR, Offset = 0; + + NDEF_PrepareSMSMessage( pSMSStruct, NDEF_Buffer, &Offset ); + + status = NfcTag_WriteNDEF( Offset , NDEF_Buffer, mi2cChannel ); + + return status; +} + +/** + * @brief This function write the NDEF file with the SMS data given in the structure. + * @param pSMSStruct : pointer on structure that contain the SMS information. + * @param pNDEFMessage : pointer on the NDEF message. + * @param size : to store the size of the NDEF message generated. + */ +void NDEF_PrepareSMSMessage( sSMSInfo *pSMSStruct, uint8_t *pNDEFMessage, uint16_t *size ) +{ + uint16_t Offset = 0; + uint32_t smsSize = 0; + uint32_t infoSize= 0; + uint32_t totalSize = 0; + + /* SMS is an URI but can be included in a smart poster to add text to give instruction to user for instance */ + + /* SMS (smart poster) Record Header */ +/************************************/ +/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */ +/*----------------------------------*/ +/* MB ME CF SR IL TNF */ /* <---- CF=0, IL=0 and SR=1 TNF=1 NFC Forum Well-known type*/ +/*----------------------------------*/ +/* TYPE LENGTH */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 3 */ /* <---- Used only if SR=0 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 2 */ /* <---- Used only if SR=0 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 1 */ /* <---- Used only if SR=0 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 0 */ +/*----------------------------------*/ +/* ID LENGTH */ /* <---- Not Used */ +/*----------------------------------*/ +/* TYPE */ +/*----------------------------------*/ +/* ID */ /* <---- Not Used */ +/************************************/ + + /* SMS : 1+sms:+tel+1+body=+message */ + smsSize = 1 + SMS_TYPE_STRING_LENGTH + strlen(pSMSStruct->PhoneNumber) + URI_FIRST_DATA_END_LENGTH + + MESSAGE_BEGIN_STRING_LENGTH + strlen(pSMSStruct->Message); + + /* Check if a Smart poster is needed */ + if( pSMSStruct->Information[0] != '\0' ) + { + /* Info : 1+2+info */ + infoSize = 1 + ISO_ENGLISH_CODE_STRING_LENGTH + strlen(pSMSStruct->Information); + /* Total */ + totalSize = 4 + smsSize + 4 + infoSize; + if( smsSize > 255 ) totalSize += 3; /* Normal Email size */ + if( infoSize > 255 ) totalSize += 3; /* Normal Info size */ + + /* SmartPoster header */ + if( totalSize > 255 ) + { + pNDEFMessage[Offset++] = 0xC1; + pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (totalSize & 0xFF000000) >> 24; + pNDEFMessage[Offset++] = (totalSize & 0x00FF0000) >> 16; + pNDEFMessage[Offset++] = (totalSize & 0x0000FF00) >> 8; + pNDEFMessage[Offset++] = totalSize & 0x000000FF; + } + else + { + pNDEFMessage[Offset++] = 0xD1; + pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (uint8_t)totalSize; + } + memcpy( &pNDEFMessage[Offset], SMART_POSTER_TYPE_STRING, SMART_POSTER_TYPE_STRING_LENGTH ); + Offset += SMART_POSTER_TYPE_STRING_LENGTH; + } + + /* SMS header */ + pNDEFMessage[Offset] = 0x81; + if( smsSize < 256 ) pNDEFMessage[Offset] |= 0x10; // Set the SR bit + if( pSMSStruct->Information[0] == '\0' ) pNDEFMessage[Offset] |= 0x40; // Set the ME bit + Offset++; + + pNDEFMessage[Offset++] = URI_TYPE_STRING_LENGTH; + if( smsSize > 255 ) + { + pNDEFMessage[Offset++] = (smsSize & 0xFF000000) >> 24; + pNDEFMessage[Offset++] = (smsSize & 0x00FF0000) >> 16; + pNDEFMessage[Offset++] = (smsSize & 0x0000FF00) >> 8; + pNDEFMessage[Offset++] = smsSize & 0x000000FF; + } + else + { + pNDEFMessage[Offset++] = (uint8_t)smsSize; + } + memcpy( &pNDEFMessage[Offset], URI_TYPE_STRING, URI_TYPE_STRING_LENGTH ); + Offset += URI_TYPE_STRING_LENGTH; + + /* SMS payload */ + pNDEFMessage[Offset++] = URI_ID_0x00; + memcpy( &pNDEFMessage[Offset], SMS_TYPE_STRING, SMS_TYPE_STRING_LENGTH ); + Offset += SMS_TYPE_STRING_LENGTH; + memcpy( &pNDEFMessage[Offset], pSMSStruct->PhoneNumber, strlen(pSMSStruct->PhoneNumber) ); + Offset += strlen( pSMSStruct->PhoneNumber ); + memcpy( &pNDEFMessage[Offset], URI_FIRST_DATA_END, URI_FIRST_DATA_END_LENGTH ); + Offset += URI_FIRST_DATA_END_LENGTH; + + memcpy( &pNDEFMessage[Offset], MESSAGE_BEGIN_STRING, MESSAGE_BEGIN_STRING_LENGTH ); + Offset += MESSAGE_BEGIN_STRING_LENGTH; + memcpy( &pNDEFMessage[Offset], pSMSStruct->Message, strlen(pSMSStruct->Message) ); + Offset += strlen( pSMSStruct->Message ); + + /* Information header */ + if( pSMSStruct->Information[0] != '\0' ) + { + if( infoSize > 255 ) + { + pNDEFMessage[Offset++] = 0x41; + pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (infoSize & 0xFF000000) >> 24; + pNDEFMessage[Offset++] = (infoSize & 0x00FF0000) >> 16; + pNDEFMessage[Offset++] = (infoSize & 0x0000FF00) >> 8; + pNDEFMessage[Offset++] = infoSize & 0x000000FF; + } + else + { + pNDEFMessage[Offset++] = 0x51; + pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (uint8_t)infoSize; + } + + memcpy( &pNDEFMessage[Offset], TEXT_TYPE_STRING, TEXT_TYPE_STRING_LENGTH ); + Offset += TEXT_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = ISO_ENGLISH_CODE_STRING_LENGTH; /* UTF-8 with x byte language code */ + memcpy( &pNDEFMessage[Offset], ISO_ENGLISH_CODE_STRING, ISO_ENGLISH_CODE_STRING_LENGTH ); + Offset += ISO_ENGLISH_CODE_STRING_LENGTH; + + /* Information payload */ + memcpy( &pNDEFMessage[Offset], pSMSStruct->Information, strlen(pSMSStruct->Information) ); + Offset += strlen( pSMSStruct->Information ); + } + + *size = (uint16_t)(Offset); +} + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_SMS.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_SMS.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,53 @@ +/** + ****************************************************************************** + * @file lib_NDEF_SMS.h + * @author MMY Application Team + * @version $Revision: 2475 $ + * @date $Date: 2016-06-24 12:11:59 +0200 (Fri, 24 Jun 2016) $ + * @brief This file help to manage SMS NDEF file. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_NDEF_SMS_H +#define __LIB_NDEF_SMS_H + + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" + + +typedef struct +{ + char PhoneNumber[16]; + char Message[400]; + char Information[400]; +}sSMSInfo; + +uint16_t NDEF_ReadSMS( sRecordInfo_t *pRecordStruct, sSMSInfo *pSMSStruct ); +uint16_t NDEF_WriteSMS( sSMSInfo *pSMSStruct, I2C* mi2cChannel ); +void NDEF_PrepareSMSMessage( sSMSInfo *pSMSStruct, uint8_t *pNDEFMessage, uint16_t *size ); + + +#endif /* __LIB_NDEF_SMS_H */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Text.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Text.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,175 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Text.h + * @author MMY Application Team + * @version $Revision: 3210 $ + * @date $Date: 2016-12-05 15:37:48 +0100 (Mon, 05 Dec 2016) $ + * @brief This file help to manage Text NDEF file. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF_Text.h" + +/** @addtogroup NFC_libraries + * @{ + * @brief <b>This is the library used to manage the content of the TAG (data) + * But also the specific feature of the tag, for instance + * password, gpo... </b> + */ + + +/** @addtogroup libNFC_FORUM + * @{ + * @brief This part of the library manage data which follow NFC forum organisation. + */ + +/** + * @brief This buffer contains the data send/received by TAG + */ +extern uint8_t NDEF_Buffer []; + +/** + * @} + */ + +/** @defgroup libEmail_Public_Functions + * @{ + * @brief This file is used to manage Email (stored or loaded in tag) + */ + +/** + * @brief This function write the text in the TAG. + * @param text : text to write. + * @retval NDEF_OK : NDEF file data written in the tag. + * @retval NDEF_ERROR : not able to store NDEF in tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write. + */ +uint16_t NDEF_WriteText( char *text, I2C * mi2cChannel ) +{ + uint16_t status = NDEF_ERROR; + uint32_t textSize, Offset = 0; + + + /* TEXT : 1+en+message */ + textSize = 3 + strlen(text); + + /* TEXT header */ + NDEF_Buffer[Offset] = 0xD1; + if( textSize < 256 ) NDEF_Buffer[Offset] |= 0x10; // Set the SR bit + Offset++; + + NDEF_Buffer[Offset++] = TEXT_TYPE_STRING_LENGTH; + if( textSize > 255 ) + { + NDEF_Buffer[Offset++] = (textSize & 0xFF000000) >> 24; + NDEF_Buffer[Offset++] = (textSize & 0x00FF0000) >> 16; + NDEF_Buffer[Offset++] = (textSize & 0x0000FF00) >> 8; + NDEF_Buffer[Offset++] = textSize & 0x000000FF; + } + else + { + NDEF_Buffer[Offset++] = (uint8_t)textSize; + } + memcpy( &NDEF_Buffer[Offset], TEXT_TYPE_STRING, TEXT_TYPE_STRING_LENGTH ); + Offset += TEXT_TYPE_STRING_LENGTH; + + /* TEXT payload */ + NDEF_Buffer[Offset++] = ISO_ENGLISH_CODE_STRING_LENGTH; + memcpy( &NDEF_Buffer[Offset], ISO_ENGLISH_CODE_STRING, ISO_ENGLISH_CODE_STRING_LENGTH ); + Offset += ISO_ENGLISH_CODE_STRING_LENGTH; + + memcpy( &NDEF_Buffer[Offset], text, strlen(text) ); + Offset += strlen(text); + + status = NfcTag_WriteNDEF( Offset , NDEF_Buffer, mi2cChannel ); + + return status; +} + + +/** + * @brief This function the Text information in a record if any. + * @param pRecordStruct Pointer on a NDEF record structure. + * @param pText A pointer on a text information structure, used to return the text & its metadata. + * @retval NDEF_OK Text information has been retrieved. + * @retval NDEF_ERROR The record is not a Text record. + * @retval NDEF_ERROR_MEMORY_INTERNAL Language code or Text length is too big for the buffers. + */ +uint16_t NDEF_ReadText( sRecordInfo_t *pRecordStruct, NDEF_Text_info_t *pText ) +{ + uint16_t status = NDEF_ERROR; + + if( pRecordStruct->NDEF_Type == TEXT_TYPE ) + { + /* Get the text metadata (status byte (encoding & language code length) + language code) */ + NDEF_Text_metadata_t *text_record_info = (NDEF_Text_metadata_t *)pRecordStruct->PayloadBufferAdd; + + uint32_t text_length = pRecordStruct->PayloadLength /* record length */ + - text_record_info->language_length /* minus language code length */ + - sizeof(uint8_t); /* minus the status byte length */ + + if((text_record_info->language_length >= NDEF_TEXT_LANGUAGE_CODE_MAX_LENGTH) || + (text_length >= NDEF_TEXT_MAX_LENGTH)) + { + /* One of the text info structure buffer is too small */ + return NDEF_ERROR_MEMORY_INTERNAL; + } + + /* Retrieve the encoding */ + pText->encoding = (NDEF_Text_encoding_t)text_record_info->encoding; + + /* Save the language code string (adding null char at the end) */ + memcpy(&pText->language_code,text_record_info->language,text_record_info->language_length); + pText->language_code[text_record_info->language_length] = '\0'; + + /* Copy the text string itself (adding null char at the end) */ + memcpy(&pText->text, text_record_info->language + text_record_info->language_length,text_length); + pText->text[text_length] = '\0'; + + status = NDEF_OK; + } + else + { + /* Not a text record, exit in error */ + status = NDEF_ERROR; + } + + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Text.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Text.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,70 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Text.h + * @author MMY Application Team + * @version $Revision: 3210 $ + * @date $Date: 2016-12-05 15:37:48 +0100 (Mon, 05 Dec 2016) $ + * @brief This file help to manage Text NDEF file. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_NDEF_TEXT_H +#define __LIB_NDEF_TEXT_H + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" + +/** @brief NDEF Text buffer length. */ +#define NDEF_TEXT_MAX_LENGTH 40 +/** @brief NDEF Language code buffer length. */ +#define NDEF_TEXT_LANGUAGE_CODE_MAX_LENGTH 10 + +/** @brief NDEF Text encoding possible values. */ +typedef enum { + NDEF_TEXT_UTF8 = 0, + NDEF_TEXT_UTF16 = 1 +} NDEF_Text_encoding_t; + +/** @brief This structure is used to handle information from a NDEF Text record. */ +typedef struct { + NDEF_Text_encoding_t encoding; /**< metadata: UTF-8 / UTF-16. */ + char language_code[NDEF_TEXT_LANGUAGE_CODE_MAX_LENGTH]; /**< metadata: Language code as specified by IANA. */ + char text[NDEF_TEXT_MAX_LENGTH]; /**< The text itself. */ +} NDEF_Text_info_t; + + +/** @brief This structure is used to parse the raw data from a text record and access its metadata. */ +typedef struct { + uint8_t language_length:4; /**< Language code length. */ + uint8_t rfu:3; /**< reserved for futur usage */ + uint8_t encoding:1; /**< UTF-8 (0) or UTF-16 (1) encoding. */ + char language[1]; /**< IANA language code. */ +} NDEF_Text_metadata_t; + +uint16_t NDEF_WriteText( char *text, I2C * mi2cChannel ); +uint16_t NDEF_ReadText( sRecordInfo_t *pRecordStruct, NDEF_Text_info_t *pText ); + + +#endif /* __LIB_NDEF_TEXT_H */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_URI.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_URI.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,538 @@ +/** + ****************************************************************************** + * @file lib_NDEF_URI.c + * @author MMY Application Team + * @version $Revision: 2702 $ + * @date $Date: 2016-07-13 18:45:05 +0200 (Wed, 13 Jul 2016) $ + * @brief This file help to manage NDEF file that represent URI. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF_URI.h" + +/** @addtogroup NFC_libraries + * @{ + * @brief <b>This is the library used to manage the content of the TAG (data) + * But also the specific feature of the tag, for instance + * password, gpo... </b> + */ + + +/** @addtogroup libNFC_FORUM + * @{ + * @brief This part of the library manage data which follow NFC forum organisation. + */ + +/** + * @brief This buffer contains the data send/received by TAG + */ +extern uint8_t NDEF_Buffer []; + +/** @defgroup libURI_Private_Functions + * @{ + */ + +static void NDEF_Parse_WellKnowType( sRecordInfo_t *pRecordStruct, sURI_Info* pURI ); + +/** + * @brief This function read the URI information and store data in a structure. + * @param pRecordStruct : Pointer on the record structure. + * @param pURI : pointer on the structure to fill. + */ +static void NDEF_Parse_WellKnowType( sRecordInfo_t *pRecordStruct, sURI_Info* pURI ) +{ + uint32_t PayloadSize; + uint8_t Offset; + uint8_t* pPayload; + + pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd); + + switch( *pPayload ) + { + case URI_ID_0x01: + memcpy( pURI->protocol, URI_ID_0x01_STRING, strlen(URI_ID_0x01_STRING) ); + Offset = strlen( URI_ID_0x01_STRING ); + break; + + case URI_ID_0x02: + memcpy( pURI->protocol, URI_ID_0x02_STRING, strlen(URI_ID_0x02_STRING) ); + Offset = strlen( URI_ID_0x02_STRING ); + break; + case URI_ID_0x03: + memcpy( pURI->protocol, URI_ID_0x03_STRING, strlen(URI_ID_0x03_STRING) ); + Offset = strlen( URI_ID_0x03_STRING ); + break; + + case URI_ID_0x04: + memcpy( pURI->protocol, URI_ID_0x04_STRING, strlen(URI_ID_0x04_STRING) ); + Offset = strlen( URI_ID_0x04_STRING ); + break; + + case URI_ID_0x05: + memcpy( pURI->protocol, URI_ID_0x05_STRING, strlen(URI_ID_0x05_STRING) ); + Offset = strlen( URI_ID_0x05_STRING ); + break; + + case URI_ID_0x06: + memcpy( pURI->protocol, URI_ID_0x06_STRING, strlen(URI_ID_0x06_STRING) ); + Offset = strlen( URI_ID_0x06_STRING ); + break; + + case URI_ID_0x07: + memcpy( pURI->protocol, URI_ID_0x07_STRING, strlen(URI_ID_0x07_STRING) ); + Offset = strlen( URI_ID_0x07_STRING ); + break; + + case URI_ID_0x08: + memcpy( pURI->protocol, URI_ID_0x08_STRING, strlen(URI_ID_0x08_STRING) ); + Offset = strlen( URI_ID_0x08_STRING ); + break; + + case URI_ID_0x09: + memcpy( pURI->protocol, URI_ID_0x09_STRING, strlen(URI_ID_0x09_STRING) ); + Offset = strlen( URI_ID_0x09_STRING ); + break; + + case URI_ID_0x0A: + memcpy( pURI->protocol, URI_ID_0x0A_STRING, strlen(URI_ID_0x0A_STRING) ); + Offset = strlen( URI_ID_0x0A_STRING ); + break; + + case URI_ID_0x0B: + memcpy( pURI->protocol, URI_ID_0x0B_STRING, strlen(URI_ID_0x0B_STRING) ); + Offset = strlen( URI_ID_0x0B_STRING ); + break; + + case URI_ID_0x0C: + memcpy( pURI->protocol, URI_ID_0x0C_STRING, strlen(URI_ID_0x0C_STRING) ); + Offset = strlen( URI_ID_0x0C_STRING ); + break; + + case URI_ID_0x0D: + memcpy( pURI->protocol, URI_ID_0x0D_STRING, strlen(URI_ID_0x0D_STRING) ); + Offset = strlen( URI_ID_0x0D_STRING ); + break; + + case URI_ID_0x0E: + memcpy( pURI->protocol, URI_ID_0x0E_STRING, strlen(URI_ID_0x0E_STRING) ); + Offset = strlen( URI_ID_0x0E_STRING ); + break; + + case URI_ID_0x0F: + memcpy( pURI->protocol, URI_ID_0x0F_STRING, strlen(URI_ID_0x0F_STRING) ); + Offset = strlen( URI_ID_0x0F_STRING ); + break; + + case URI_ID_0x10: + memcpy( pURI->protocol, URI_ID_0x10_STRING, strlen(URI_ID_0x10_STRING) ); + Offset = strlen( URI_ID_0x10_STRING ); + break; + + case URI_ID_0x11: + memcpy( pURI->protocol, URI_ID_0x11_STRING, strlen(URI_ID_0x11_STRING) ); + Offset = strlen( URI_ID_0x11_STRING ); + break; + + case URI_ID_0x12: + memcpy( pURI->protocol, URI_ID_0x12_STRING, strlen(URI_ID_0x12_STRING) ); + Offset = strlen( URI_ID_0x12_STRING ); + break; + + case URI_ID_0x13: + memcpy( pURI->protocol, URI_ID_0x13_STRING, strlen(URI_ID_0x13_STRING) ); + Offset = strlen( URI_ID_0x13_STRING ); + break; + + case URI_ID_0x14: + memcpy( pURI->protocol, URI_ID_0x14_STRING, strlen(URI_ID_0x14_STRING) ); + Offset = strlen( URI_ID_0x14_STRING ); + break; + + case URI_ID_0x15: + memcpy( pURI->protocol, URI_ID_0x15_STRING, strlen(URI_ID_0x15_STRING) ); + Offset = strlen( URI_ID_0x15_STRING ); + break; + + case URI_ID_0x16: + memcpy( pURI->protocol, URI_ID_0x16_STRING, strlen(URI_ID_0x16_STRING) ); + Offset = strlen( URI_ID_0x16_STRING ); + break; + + case URI_ID_0x17: + memcpy( pURI->protocol, URI_ID_0x17_STRING, strlen(URI_ID_0x17_STRING) ); + Offset = strlen( URI_ID_0x17_STRING ); + break; + + case URI_ID_0x18: + memcpy( pURI->protocol, URI_ID_0x18_STRING, strlen(URI_ID_0x18_STRING) ); + Offset = strlen( URI_ID_0x18_STRING ); + break; + + case URI_ID_0x19: + memcpy( pURI->protocol, URI_ID_0x19_STRING, strlen(URI_ID_0x19_STRING) ); + Offset = strlen( URI_ID_0x19_STRING ); + break; + + case URI_ID_0x1A: + memcpy( pURI->protocol, URI_ID_0x1A_STRING, strlen(URI_ID_0x1A_STRING) ); + Offset = strlen( URI_ID_0x1A_STRING ); + break; + + case URI_ID_0x1B: + memcpy( pURI->protocol, URI_ID_0x1B_STRING, strlen(URI_ID_0x1B_STRING) ); + Offset = strlen( URI_ID_0x1B_STRING ); + break; + + case URI_ID_0x1C: + memcpy( pURI->protocol, URI_ID_0x1C_STRING, strlen(URI_ID_0x1C_STRING) ); + Offset = strlen( URI_ID_0x1C_STRING ); + break; + + case URI_ID_0x1D: + memcpy( pURI->protocol, URI_ID_0x1D_STRING, strlen(URI_ID_0x1D_STRING) ); + Offset = strlen( URI_ID_0x1D_STRING ); + break; + + case URI_ID_0x1E: + memcpy( pURI->protocol, URI_ID_0x1E_STRING, strlen(URI_ID_0x1E_STRING) ); + Offset = strlen( URI_ID_0x1E_STRING ); + break; + + case URI_ID_0x1F: + memcpy( pURI->protocol, URI_ID_0x1F_STRING, strlen(URI_ID_0x1F_STRING) ); + Offset = strlen( URI_ID_0x1F_STRING ); + break; + + case URI_ID_0x20: + memcpy( pURI->protocol, URI_ID_0x20_STRING, strlen(URI_ID_0x20_STRING) ); + Offset = strlen( URI_ID_0x20_STRING ); + break; + + case URI_ID_0x21: + memcpy( pURI->protocol, URI_ID_0x21_STRING, strlen(URI_ID_0x21_STRING) ); + Offset = strlen( URI_ID_0x21_STRING ); + break; + + case URI_ID_0x22: + memcpy( pURI->protocol, URI_ID_0x22_STRING, strlen(URI_ID_0x22_STRING) ); + Offset = strlen( URI_ID_0x22_STRING ); + break; + + case URI_ID_0x23: + memcpy( pURI->protocol, URI_ID_0x23_STRING, strlen(URI_ID_0x23_STRING) ); + Offset = strlen( URI_ID_0x23_STRING ); + break; + default: + Offset = 0; + /* Should not happened */ + break; + } + /* add end of string character */ + pURI->protocol[Offset] = '\0'; + + pPayload++; /* go after well know byte */ + + PayloadSize = pRecordStruct->PayloadLength; + + PayloadSize = PayloadSize - 1; /* remove well know byte */ + + memcpy( pURI->URI_Message, pPayload, PayloadSize ); + /* add end of string character */ + pURI->URI_Message[PayloadSize] = '\0'; + +} + +/** + * @} + */ + +/** @defgroup libURI_Public_Functions + * @{ + * @brief This file is used to manage URI (stored or loaded in tag) + */ + +/** + * @brief This function read NDEF and retrieve URI information if any. + * @param pRecordStruct : Pointer on the record structure. + * @param pURI : pointer on the structure to fill. + * @retval NDEF_OK : URI information from NDEF have been retrieved. + * @retval NDEF_ERROR : Not able to retrieve URI information. + */ +uint16_t NDEF_ReadURI( sRecordInfo_t *pRecordStruct, sURI_Info *pURI ) +{ + uint16_t status = NDEF_ERROR; + sRecordInfo_t *pSPRecordStruct; + uint32_t PayloadSize, RecordPosition; + uint8_t* pData; + + if( pRecordStruct->NDEF_Type == WELL_KNOWN_ABRIDGED_URI_TYPE ) + { + NDEF_Parse_WellKnowType( pRecordStruct, pURI ); + status = NDEF_OK; + } + else if( pRecordStruct->NDEF_Type == SMARTPOSTER_TYPE ) + { + for( RecordPosition = 0; RecordPosition < pRecordStruct->NbOfRecordInSPPayload; RecordPosition++ ) + { + pSPRecordStruct = pRecordStruct->SPRecordStructAdd[RecordPosition]; + if( pSPRecordStruct->NDEF_Type == WELL_KNOWN_ABRIDGED_URI_TYPE ) + { + NDEF_Parse_WellKnowType( pSPRecordStruct, pURI ); + status = NDEF_OK; + } + if( pSPRecordStruct->NDEF_Type == TEXT_TYPE ) + { + PayloadSize = pSPRecordStruct->PayloadLength; + + /* The instruction content the UTF-8 language code that is not used here */ + pData = (uint8_t*)pSPRecordStruct->PayloadBufferAdd; + PayloadSize -= *pData + 1; /* remove not usefull data */ + pData += *pData + 1; + + memcpy( pURI->Information, pData, PayloadSize ); + } + } + } + else + { + status = NDEF_ERROR; + } + + return status; +} + +/** + * @brief This function prepare the NDEF message with the URI data given in the structure. + * @param pURI : pointer on structure that contain the URI information. + * @param pNDEFMessage : pointer on the NDEF message. + * @param size : to store the size of the NDEF message generated. + */ +void NDEF_PrepareURIMessage( sURI_Info *pURI, uint8_t *pNDEFMessage, uint16_t *size ) +{ + uint32_t uriSize, totalSize, Offset = 0; + uint32_t infoSize = 0; + char type; + + /* An URI can be included in a smart poster to add text to give instruction to user for instance */ + + /* URI (smart poster) Record Header */ +/************************************/ +/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */ +/*----------------------------------*/ +/* MB ME CF SR IL TNF */ /* <---- CF=0, IL=0 and SR=1 TNF=1 NFC Forum Well-known type*/ +/*----------------------------------*/ +/* TYPE LENGTH */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 3 */ /* <---- Used only if SR=0 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 2 */ /* <---- Used only if SR=0 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 1 */ /* <---- Used only if SR=0 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 0 */ +/*----------------------------------*/ +/* ID LENGTH */ /* <---- Not Used */ +/*----------------------------------*/ +/* TYPE */ +/*----------------------------------*/ +/* ID */ /* <---- Not Used */ +/************************************/ + + /* We need to know the URI type in order to define if an abreviation is available */ + type = getUriType( pURI->protocol ); + + /* URI : 1+URI for abreviate protocol*/ + if( type != URI_ID_0x00 ) + uriSize = 1 + strlen(pURI->URI_Message); + else /*: 1+protocol+URI else*/ + uriSize = 1 + strlen(pURI->protocol) + strlen(pURI->URI_Message); + + /* Check if a Smart poster is needed */ + if( pURI->Information[0] != '\0' ) + { + /* Info : 1+2+info */ + infoSize = 1 + ISO_ENGLISH_CODE_STRING_LENGTH + strlen(pURI->Information); + /* Total */ + totalSize = 4 + uriSize + 4 + infoSize; + if( uriSize > 255 ) totalSize += 3; /* Normal URI size */ + if( infoSize > 255 ) totalSize += 3; /* Normal Info size */ + + /* SmartPoster header */ + if( totalSize > 255 ) + { + pNDEFMessage[Offset++] = 0xC1; + pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (totalSize & 0xFF000000) >> 24; + pNDEFMessage[Offset++] = (totalSize & 0x00FF0000) >> 16; + pNDEFMessage[Offset++] = (totalSize & 0x0000FF00) >> 8; + pNDEFMessage[Offset++] = totalSize & 0x000000FF; + } + else + { + pNDEFMessage[Offset++] = 0xD1; + pNDEFMessage[Offset++] = SMART_POSTER_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (uint8_t)totalSize; + } + memcpy( &pNDEFMessage[Offset], SMART_POSTER_TYPE_STRING, SMART_POSTER_TYPE_STRING_LENGTH ); + Offset += SMART_POSTER_TYPE_STRING_LENGTH; + } + + /* URI header */ + pNDEFMessage[Offset] = 0x81; + if( uriSize < 256 ) pNDEFMessage[Offset] |= 0x10; // Set the SR bit + if( pURI->Information[0] == '\0' ) pNDEFMessage[Offset] |= 0x40; // Set the ME bit + Offset++; + + pNDEFMessage[Offset++] = URI_TYPE_STRING_LENGTH; + if( uriSize > 255 ) + { + pNDEFMessage[Offset++] = (uriSize & 0xFF000000) >> 24; + pNDEFMessage[Offset++] = (uriSize & 0x00FF0000) >> 16; + pNDEFMessage[Offset++] = (uriSize & 0x0000FF00) >> 8; + pNDEFMessage[Offset++] = uriSize & 0x000000FF; + } + else + { + pNDEFMessage[Offset++] = (uint8_t)uriSize; + } + memcpy( &pNDEFMessage[Offset], URI_TYPE_STRING, URI_TYPE_STRING_LENGTH ); + Offset += URI_TYPE_STRING_LENGTH; + + pNDEFMessage[Offset++] = type; + if( type == URI_ID_0x00 ) // No abreviation + { + memcpy( &pNDEFMessage[Offset], pURI->protocol, strlen(pURI->protocol) ); + Offset += strlen(pURI->protocol); + } + + memcpy( &pNDEFMessage[Offset], pURI->URI_Message, strlen(pURI->URI_Message) ); + Offset += strlen(pURI->URI_Message); + + /* Information header */ + if( pURI->Information[0] != '\0' ) + { + if( infoSize > 255 ) + { + pNDEFMessage[Offset++] = 0x41; + pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (infoSize & 0xFF000000) >> 24; + pNDEFMessage[Offset++] = (infoSize & 0x00FF0000) >> 16; + pNDEFMessage[Offset++] = (infoSize & 0x0000FF00) >> 8; + pNDEFMessage[Offset++] = infoSize & 0x000000FF; + } + else + { + pNDEFMessage[Offset++] = 0x51; + pNDEFMessage[Offset++] = TEXT_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = (uint8_t)infoSize; + } + + memcpy( &pNDEFMessage[Offset], TEXT_TYPE_STRING, TEXT_TYPE_STRING_LENGTH ); + Offset+=TEXT_TYPE_STRING_LENGTH; + pNDEFMessage[Offset++] = ISO_ENGLISH_CODE_STRING_LENGTH; /* UTF-8 with x byte language code */ + memcpy( &pNDEFMessage[Offset], ISO_ENGLISH_CODE_STRING, ISO_ENGLISH_CODE_STRING_LENGTH ); + Offset += ISO_ENGLISH_CODE_STRING_LENGTH; + + /* Information payload */ + memcpy( &pNDEFMessage[Offset], pURI->Information, strlen(pURI->Information) ); + Offset += strlen(pURI->Information); + } + + *size = Offset; + +} +/** + * @brief This function write the NDEF file with the URI data given in the structure. + * @param pURI : pointer on structure that contain the URI information. + * @retval NDEF_OK : NDEF file data written in the tag. + * @retval NDEF_ERROR : not able to store NDEF in tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL : Cannot write to tag. + * @retval NDEF_ERROR_NOT_FORMATED : CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG : Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED : Tag locked, cannot be write. + */ +uint16_t NDEF_WriteURI( sURI_Info *pURI, I2C* mi2cChannel ) +{ + uint16_t status = NDEF_ERROR, Offset = 0; + + NDEF_PrepareURIMessage( pURI, NDEF_Buffer, &Offset ); + + + status = NfcTag_WriteNDEF( Offset , NDEF_Buffer, mi2cChannel ); + + return status; +} + +char getUriType( char *protocol ) +{ + if( !memcmp( protocol, URI_ID_0x01_STRING, strlen(URI_ID_0x01_STRING) ) ) return URI_ID_0x01; + else if( !memcmp( protocol, URI_ID_0x02_STRING, strlen(URI_ID_0x02_STRING) ) ) return URI_ID_0x02; + else if( !memcmp( protocol, URI_ID_0x03_STRING, strlen(URI_ID_0x03_STRING) ) ) return URI_ID_0x03; + else if( !memcmp( protocol, URI_ID_0x04_STRING, strlen(URI_ID_0x04_STRING) ) ) return URI_ID_0x04; + else if( !memcmp( protocol, URI_ID_0x05_STRING, strlen(URI_ID_0x05_STRING) ) ) return URI_ID_0x05; + else if( !memcmp( protocol, URI_ID_0x06_STRING, strlen(URI_ID_0x06_STRING) ) ) return URI_ID_0x06; + else if( !memcmp( protocol, URI_ID_0x07_STRING, strlen(URI_ID_0x07_STRING) ) ) return URI_ID_0x07; + else if( !memcmp( protocol, URI_ID_0x08_STRING, strlen(URI_ID_0x08_STRING) ) ) return URI_ID_0x08; + else if( !memcmp( protocol, URI_ID_0x09_STRING, strlen(URI_ID_0x09_STRING) ) ) return URI_ID_0x09; + else if( !memcmp( protocol, URI_ID_0x0A_STRING, strlen(URI_ID_0x0A_STRING) ) ) return URI_ID_0x0A; + else if( !memcmp( protocol, URI_ID_0x0B_STRING, strlen(URI_ID_0x0B_STRING) ) ) return URI_ID_0x0B; + else if( !memcmp( protocol, URI_ID_0x0C_STRING, strlen(URI_ID_0x0C_STRING) ) ) return URI_ID_0x0C; + else if( !memcmp( protocol, URI_ID_0x0D_STRING, strlen(URI_ID_0x0D_STRING) ) ) return URI_ID_0x0D; + else if( !memcmp( protocol, URI_ID_0x0E_STRING, strlen(URI_ID_0x0E_STRING) ) ) return URI_ID_0x0E; + else if( !memcmp( protocol, URI_ID_0x0F_STRING, strlen(URI_ID_0x0F_STRING) ) ) return URI_ID_0x0F; + else if( !memcmp( protocol, URI_ID_0x10_STRING, strlen(URI_ID_0x10_STRING) ) ) return URI_ID_0x10; + else if( !memcmp( protocol, URI_ID_0x11_STRING, strlen(URI_ID_0x11_STRING) ) ) return URI_ID_0x11; + else if( !memcmp( protocol, URI_ID_0x12_STRING, strlen(URI_ID_0x12_STRING) ) ) return URI_ID_0x12; + else if( !memcmp( protocol, URI_ID_0x13_STRING, strlen(URI_ID_0x13_STRING) ) ) return URI_ID_0x13; + else if( !memcmp( protocol, URI_ID_0x14_STRING, strlen(URI_ID_0x14_STRING) ) ) return URI_ID_0x14; + else if( !memcmp( protocol, URI_ID_0x15_STRING, strlen(URI_ID_0x15_STRING) ) ) return URI_ID_0x15; + else if( !memcmp( protocol, URI_ID_0x16_STRING, strlen(URI_ID_0x16_STRING) ) ) return URI_ID_0x16; + else if( !memcmp( protocol, URI_ID_0x17_STRING, strlen(URI_ID_0x17_STRING) ) ) return URI_ID_0x17; + else if( !memcmp( protocol, URI_ID_0x18_STRING, strlen(URI_ID_0x18_STRING) ) ) return URI_ID_0x18; + else if( !memcmp( protocol, URI_ID_0x19_STRING, strlen(URI_ID_0x19_STRING) ) ) return URI_ID_0x19; + else if( !memcmp( protocol, URI_ID_0x1A_STRING, strlen(URI_ID_0x1A_STRING) ) ) return URI_ID_0x1A; + else if( !memcmp( protocol, URI_ID_0x1B_STRING, strlen(URI_ID_0x1B_STRING) ) ) return URI_ID_0x1B; + else if( !memcmp( protocol, URI_ID_0x1C_STRING, strlen(URI_ID_0x1C_STRING) ) ) return URI_ID_0x1C; + else if( !memcmp( protocol, URI_ID_0x1D_STRING, strlen(URI_ID_0x1D_STRING) ) ) return URI_ID_0x1D; + else if( !memcmp( protocol, URI_ID_0x1E_STRING, strlen(URI_ID_0x1E_STRING) ) ) return URI_ID_0x1E; + else if( !memcmp( protocol, URI_ID_0x1F_STRING, strlen(URI_ID_0x1F_STRING) ) ) return URI_ID_0x1F; + else if( !memcmp( protocol, URI_ID_0x20_STRING, strlen(URI_ID_0x20_STRING) ) ) return URI_ID_0x20; + else if( !memcmp( protocol, URI_ID_0x21_STRING, strlen(URI_ID_0x21_STRING) ) ) return URI_ID_0x21; + else if( !memcmp( protocol, URI_ID_0x22_STRING, strlen(URI_ID_0x22_STRING) ) ) return URI_ID_0x22; + else if( !memcmp( protocol, URI_ID_0x23_STRING, strlen(URI_ID_0x23_STRING) ) ) return URI_ID_0x23; + else return URI_ID_0x00; // No abreviation for this protocol +} + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_URI.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_URI.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,57 @@ +/** + ****************************************************************************** + * @file lib_NDEF_URI.h + * @author MMY Application Team + * @version $Revision: 2475 $ + * @date $Date: 2016-06-24 12:11:59 +0200 (Fri, 24 Jun 2016) $ + * @brief This file help to manage URI NDEF file. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_NDEF_URI_H +#define __LIB_NDEF_URI_H + + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" + +typedef struct +{ +// char protocol[80]; +// char URI_Message[400]; +// char Information[400]; + char protocol[20]; + char URI_Message[100]; + char Information[20]; +}sURI_Info; + +uint16_t NDEF_ReadURI(sRecordInfo_t *pRecordStruct, sURI_Info *pURI); +uint16_t NDEF_WriteURI(sURI_Info *pURI, I2C* mi2cChannel); + +void NDEF_PrepareURIMessage( sURI_Info *pURI, uint8_t *pNDEFMessage, uint16_t *size ); +char getUriType( char *protocol ); + + +#endif /* __LIB_NDEF_URI_H */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Vcard.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Vcard.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,620 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Vcard.c + * @author MMY Application Team + * @version $Revision: 3210 $ + * @date $Date: 2016-12-05 15:37:48 +0100 (Mon, 05 Dec 2016) $ + * @brief This file help to manage NDEF file that represent Vcard. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF_Vcard.h" + + +/** @addtogroup lib_NDEF_Vcard + * @ingroup libNDEF + * @{ + * @brief This part of the library manage the data which follow NFC forum organisation. + */ + +/* This buffer contains the data sent/received by TAG */ +extern uint8_t NDEF_Buffer []; + +static void NDEF_FillVcardStruct( uint8_t* pPayload, uint32_t PayloadSize, char* pKeyWord, uint32_t SizeOfKeyWord, uint8_t* pString ); +static void NDEF_ExtractVcard( sRecordInfo_t *pRecordStruct, sVcardInfo *pVcardStruct ); + +/** + * @brief This function extracts a Vcard particular property from a vCard. + * @param pPayload Pointer on the vCard payload data of the vCard record. + * @param PayloadSize Number of bytes in the vCard payload. + * @param pKeyWord Pointer on the vCard property keyword to look for. + * @param SizeOfKeyWord Number of bytes of the vCard property keyword we are looking for. + * @param pString Pointer on a string used to return the vCard property read. + */ +static void NDEF_FillVcardStruct( uint8_t* pPayload, uint32_t PayloadSize, char* pKeyWord, uint32_t SizeOfKeyWord, uint8_t* pString ) +{ + uint8_t* pLastByteAdd, *pLook4Word, *pEndString; + + /* First character force to NULL in case not matching found */ + *pString = 0; + + /* Interresting information are stored before picture if any */ + /* Moreover picture is not used in this demonstration SW */ + pLastByteAdd = pPayload; + while( memcmp( pLastByteAdd, JPEG, JPEG_STRING_SIZE ) && (pLastByteAdd < (pPayload + PayloadSize)) ) + { + pLastByteAdd++; + } + + pLook4Word = pPayload; + while( memcmp( pLook4Word, pKeyWord, SizeOfKeyWord ) && (pLook4Word < pLastByteAdd) ) + { + pLook4Word++; + } + + /* Word found */ + if( pLook4Word != pLastByteAdd ) + { + pLook4Word += SizeOfKeyWord; + pEndString = pLook4Word; + while( memcmp( pEndString, LIMIT, LIMIT_STRING_SIZE ) && (pEndString < pLastByteAdd) ) + { + pEndString++; + } + if( pEndString != pLastByteAdd ) + { + memcpy( pString, pLook4Word, pEndString-pLook4Word ); + /* add end of string character */ + pString += pEndString - pLook4Word; + *pString = '\0'; + } + } +} + +/** + * @brief This function reads a Vcard record and stores data in a `sVcardInfo` structure. + * @param pRecordStruct Pointer on the vCard record structure. + * @param pVcardStruct Pointer on the `sCardInfo` structure to fill. + */ +static void NDEF_ExtractVcard( sRecordInfo_t *pRecordStruct, sVcardInfo *pVcardStruct ) +{ + uint32_t PayloadSize; + uint8_t* pPayload; + + + PayloadSize = pRecordStruct->PayloadLength; + + /* Read record header */ + pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd); + + NDEF_FillVcardStruct( pPayload, PayloadSize, VERSION, VERSION_STRING_SIZE, (uint8_t*)(pVcardStruct->Version) ); + if( !memcmp( pVcardStruct->Version, VCARD_VERSION_2_1, VCARD_VERSION_2_1_SIZE ) ) + { + NDEF_FillVcardStruct( pPayload, PayloadSize, FIRSTNAME, FIRSTNAME_STRING_SIZE, (uint8_t*)(pVcardStruct->FirstName) ); + NDEF_FillVcardStruct( pPayload, PayloadSize, TITLE, TITLE_STRING_SIZE, (uint8_t*)(pVcardStruct->Title) ); + NDEF_FillVcardStruct( pPayload, PayloadSize, ORG, ORG_STRING_SIZE, (uint8_t*)(pVcardStruct->Org) ); + NDEF_FillVcardStruct( pPayload, PayloadSize, HOME_ADDRESS, HOME_ADDRESS_STRING_SIZE, (uint8_t*)(pVcardStruct->HomeAddress) ); + NDEF_FillVcardStruct( pPayload, PayloadSize, GEN_ADDRESS, strlen(GEN_ADDRESS), (uint8_t*)(pVcardStruct->Address) ); + NDEF_FillVcardStruct( pPayload, PayloadSize, WORK_ADDRESS, WORK_ADDRESS_STRING_SIZE, (uint8_t*)(pVcardStruct->WorkAddress) ); + NDEF_FillVcardStruct( pPayload, PayloadSize, HOME_TEL, HOME_TEL_STRING_SIZE, (uint8_t*)(pVcardStruct->HomeTel) ); + NDEF_FillVcardStruct( pPayload, PayloadSize, WORK_TEL, WORK_TEL_STRING_SIZE, (uint8_t*)(pVcardStruct->WorkTel) ); + NDEF_FillVcardStruct( pPayload, PayloadSize, CELL_TEL, CELL_TEL_STRING_SIZE, (uint8_t*)(pVcardStruct->CellTel) ); + NDEF_FillVcardStruct( pPayload, PayloadSize, HOME_EMAIL, HOME_EMAIL_STRING_SIZE, (uint8_t*)(pVcardStruct->HomeEmail) ); + NDEF_FillVcardStruct( pPayload, PayloadSize, GEN_EMAIL, strlen(GEN_EMAIL), (uint8_t*)(pVcardStruct->Email) ); + NDEF_FillVcardStruct( pPayload, PayloadSize, WORK_EMAIL, WORK_EMAIL_STRING_SIZE, (uint8_t*)(pVcardStruct->WorkEmail) ); + } + else if( !memcmp( pVcardStruct->Version, VCARD_VERSION_3_0, VCARD_VERSION_3_0_SIZE ) ) + { + /* need to be implemented */ + } + else + { + /* maybe new version but not supported in this sw */ + } + +} + +/** + * @brief This function reads a Vcard record and stores data in a `sVcardInfo` structure. + * @param pRecordStruct Pointer on the vCard record structure. + * @param pVcardStruct Pointer on the `sCardInfo` structure to fill. + * @retval NDEF_OK The Vcard information has been retrieved. + * @retval NDEF_ERROR Not able to retrieve the Vcard information. + */ +uint16_t NDEF_ReadVcard( sRecordInfo_t *pRecordStruct, sVcardInfo *pVcardStruct ) +{ + uint16_t status = NDEF_ERROR; + + if( pRecordStruct->NDEF_Type == VCARD_TYPE ) + { + NDEF_ExtractVcard( pRecordStruct, pVcardStruct ); + status = NDEF_OK; + } + + return status; +} + +/** + * @brief This function writes a NDEF message to the NFC tag with the Vcard data given in a `sVcardInfo` structure. + * @param pVcardStruct Pointer on a `sVcardInfo` structure containing the Vcard information. + * @retval NDEF_OK NDEF file data written in the tag. + * @retval NDEF_ERROR Not able to store the NDEF in tag. + * @retval NDEF_ERROR_MEMORY_INTERNAL Cannot write to tag. + * @retval NDEF_ERROR_NOT_FORMATED CCFile data not supported or not present. + * @retval NDEF_ERROR_MEMORY_TAG Size not compatible with memory. + * @retval NDEF_ERROR_LOCKED Tag locked, cannot be write. + */ +uint16_t NDEF_WriteVcard( sVcardInfo *pVcardStruct, I2C* mi2cChannel ) +{ + uint16_t status = NDEF_ERROR, Offset = 0; + + NDEF_PrepareVcardMessage( pVcardStruct, NDEF_Buffer, &Offset ); + + status = NfcTag_WriteNDEF( Offset , NDEF_Buffer, mi2cChannel ); + + return status; +} + +/** + * @brief This function computes the size of a Vcard record from the data given in the `sVcardInfo` structure. + * @param pVcardStruct Pointer on a `sVcardInfo` structure containing the Vcard information. + * @return vCard record data size in bytes (excluding record metadata). + */ +uint32_t NDEF_GetVcardLength( sVcardInfo *pVcardStruct) +{ + + uint32_t PayloadSize = 0; + + /* "BEGIN:VCARD\r\n" */ + PayloadSize += BEGIN_STRING_SIZE; + PayloadSize += VCARD_STRING_SIZE; + PayloadSize += LIMIT_STRING_SIZE; + + /* "VERSION:2.1\r\n" */ + PayloadSize += VERSION_STRING_SIZE; + PayloadSize += VCARD_VERSION_2_1_SIZE; + PayloadSize += LIMIT_STRING_SIZE; + + /* "N:\r\n" */ + if(*pVcardStruct->Name != '\0') + { + PayloadSize += VCARD_NAME_STRING_SIZE; + PayloadSize += strlen( pVcardStruct->Name ); + PayloadSize += LIMIT_STRING_SIZE; + } + /* "FN:\r\n" */ + if(*pVcardStruct->FirstName != '\0') + { + PayloadSize += FIRSTNAME_STRING_SIZE; + PayloadSize += strlen( pVcardStruct->FirstName ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->Title != '\0') + { + /* "TITLE:\r\n" */ + PayloadSize += TITLE_STRING_SIZE; + PayloadSize += strlen( pVcardStruct->Title ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->Org != '\0') + { + /* "ORG:\r\n" */ + PayloadSize += ORG_STRING_SIZE; + PayloadSize += strlen( pVcardStruct->Org ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->Url != '\0') + { + /* "URL:\r\n" */ + PayloadSize += URL_STRING_SIZE; + PayloadSize += strlen( pVcardStruct->Url ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->HomeAddress != '\0') + { + /* "ADR;HOME:\r\n" */ + PayloadSize += HOME_ADDRESS_STRING_SIZE; + PayloadSize += strlen( pVcardStruct->HomeAddress ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->WorkAddress != '\0') + { + /* "ADR;WORK:\r\n" */ + PayloadSize += WORK_ADDRESS_STRING_SIZE; + PayloadSize += strlen( pVcardStruct->WorkAddress ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->HomeTel != '\0') + { + /* "TEL;HOME:\r\n" */ + PayloadSize += HOME_TEL_STRING_SIZE; + PayloadSize += strlen( pVcardStruct->HomeTel ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->WorkTel != '\0') + { + /* "TEL;WORK:\r\n" */ + PayloadSize += WORK_TEL_STRING_SIZE; + PayloadSize += strlen( pVcardStruct->WorkTel ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->CellTel != '\0') + { + /* "TEL;CELL:\r\n" */ + PayloadSize += CELL_TEL_STRING_SIZE; + PayloadSize += strlen( pVcardStruct->CellTel ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->HomeEmail != '\0') + { + /* "EMAIL;HOME:\r\n" */ + PayloadSize += HOME_EMAIL_STRING_SIZE; + PayloadSize += strlen( pVcardStruct->HomeEmail ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->WorkEmail != '\0') + { + /* "EMAIL;WORK:\r\n" */ + PayloadSize += WORK_EMAIL_STRING_SIZE; + PayloadSize += strlen( pVcardStruct->WorkEmail ); + PayloadSize += LIMIT_STRING_SIZE; + } + /* "END:VCARD\r\n" */ + PayloadSize += END_STRING_SIZE; + PayloadSize += VCARD_STRING_SIZE; + /* PayloadSize += LIMIT_STRING_SIZE;*/ + + return PayloadSize; + +} + +/** + * @brief This function write the NDEF file with the Vcard data given in the structure. + * @param pVcardStruct : pointer on structure that contain the Vcard information. + * @param pNDEFMessage : pointer on the NDEF message. + * @param size : to store the size of the NDEF message generated. + */ +void NDEF_PrepareVcardMessage( sVcardInfo *pVcardStruct, uint8_t *pNDEFMessage, uint16_t *size ) +{ + + uint32_t PayloadSize = 0; + + /* Vcard Record Header */ +/************************************/ +/* 7 | 6 | 5 | 4 | 3 | 2 1 0 */ +/*----------------------------------*/ +/* MB ME CF SR IL TNF */ /* <---- CF=0, IL=0 and SR=0 TNF=2 NFC Forum Media type*/ +/*----------------------------------*/ +/* TYPE LENGTH */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 3 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 2 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 1 */ +/*----------------------------------*/ +/* PAYLOAD LENGTH 0 */ +/*----------------------------------*/ +/* ID LENGTH */ /* <---- Not Used */ +/*----------------------------------*/ +/* TYPE */ +/*----------------------------------*/ +/* ID */ /* <---- Not Used */ +/************************************/ + + /* As we don't have embedded a jpeg encoder/decoder in this firmware */ + /* We have made the choice to manage only string content of the vCard */ + /* For demonstration purpose in order to fill the 8kB of the M24SR */ + /* We have embedded a NDEF vCard in the STM32 to be able to fill M24SR */ + + /* fill record header */ + uint32_t length = NDEF_GetVcardLength(pVcardStruct); + if(length >= 0xFF) + { + pNDEFMessage[0] = 0xC2; /* Record Flag */ + pNDEFMessage[1] = XVCARD_TYPE_STRING_LENGTH; + pNDEFMessage[5] = length & 0xff; + pNDEFMessage[4] = (length>>8) & 0xff; + pNDEFMessage[3] = (length>>16) & 0xff; + pNDEFMessage[2] = length>>24; + memcpy( &pNDEFMessage[6], XVCARD_TYPE_STRING, XVCARD_TYPE_STRING_LENGTH ); + + /* Payload is positionned in the NDEF after record header */ + PayloadSize = 6 + XVCARD_TYPE_STRING_LENGTH; + } else { + pNDEFMessage[0] = 0xD2; /* Record Flag */ + pNDEFMessage[1] = XVCARD_TYPE_STRING_LENGTH; + pNDEFMessage[2] = length; + memcpy( &pNDEFMessage[3], XVCARD_TYPE_STRING, XVCARD_TYPE_STRING_LENGTH ); + + /* Payload is positionned in the NDEF after record header */ + PayloadSize = 3 + XVCARD_TYPE_STRING_LENGTH; + } + + /* "BEGIN:VCARD\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], BEGIN, BEGIN_STRING_SIZE ); + PayloadSize += BEGIN_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], VCARD,VCARD_STRING_SIZE ); + PayloadSize += VCARD_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + + /* "VERSION:2.1\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], VERSION, VERSION_STRING_SIZE ); + PayloadSize += VERSION_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], VCARD_VERSION_2_1, VCARD_VERSION_2_1_SIZE ); + PayloadSize += VCARD_VERSION_2_1_SIZE; + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + + /* "N:\r\n" */ + if(*pVcardStruct->Name != '\0') + { + memcpy( &pNDEFMessage[PayloadSize], VCARD_NAME, VCARD_NAME_STRING_SIZE ); + PayloadSize += VCARD_NAME_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->Name, strlen(pVcardStruct->Name) ); + PayloadSize += strlen( pVcardStruct->Name ); + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + } + /* "FN:\r\n" */ + if(*pVcardStruct->FirstName != '\0') + { + memcpy( &pNDEFMessage[PayloadSize], FIRSTNAME, FIRSTNAME_STRING_SIZE ); + PayloadSize += FIRSTNAME_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->FirstName, strlen(pVcardStruct->FirstName) ); + PayloadSize += strlen( pVcardStruct->FirstName ); + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->HomeTel != '\0') + { + + /* "TEL;HOME:\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], HOME_TEL, HOME_TEL_STRING_SIZE ); + PayloadSize += HOME_TEL_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->HomeTel, strlen(pVcardStruct->HomeTel) ); + PayloadSize += strlen( pVcardStruct->HomeTel ); + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->WorkTel != '\0') + { + + /* "TEL;WORK:\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], WORK_TEL, WORK_TEL_STRING_SIZE ); + PayloadSize += WORK_TEL_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->WorkTel, strlen(pVcardStruct->WorkTel) ); + PayloadSize += strlen( pVcardStruct->WorkTel ); + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->CellTel != '\0') + { + + /* "TEL;CELL:\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], CELL_TEL, CELL_TEL_STRING_SIZE ); + PayloadSize += CELL_TEL_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->CellTel, strlen(pVcardStruct->CellTel) ); + PayloadSize += strlen( pVcardStruct->CellTel ); + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->HomeEmail != '\0') + { + + /* "EMAIL;HOME:\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], HOME_EMAIL, HOME_EMAIL_STRING_SIZE ); + PayloadSize += HOME_EMAIL_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->HomeEmail, strlen(pVcardStruct->HomeEmail) ); + PayloadSize += strlen( pVcardStruct->HomeEmail ); + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->WorkEmail != '\0') + { + + /* "EMAIL;WORK:\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], WORK_EMAIL, WORK_EMAIL_STRING_SIZE ); + PayloadSize += WORK_EMAIL_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->WorkEmail, strlen(pVcardStruct->WorkEmail) ); + PayloadSize += strlen( pVcardStruct->WorkEmail ); + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->HomeAddress != '\0') + { + + /* "ADR;HOME:\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], HOME_ADDRESS, HOME_ADDRESS_STRING_SIZE ); + PayloadSize += HOME_ADDRESS_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->HomeAddress, strlen(pVcardStruct->HomeAddress) ); + PayloadSize += strlen( pVcardStruct->HomeAddress ); + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->WorkAddress != '\0') + { + + /* "ADR;WORK:\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], WORK_ADDRESS, WORK_ADDRESS_STRING_SIZE ); + PayloadSize += WORK_ADDRESS_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->WorkAddress, strlen(pVcardStruct->WorkAddress) ); + PayloadSize += strlen( pVcardStruct->WorkAddress ); + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->Org != '\0') + { + + /* "ORG:\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], ORG, ORG_STRING_SIZE ); + PayloadSize += ORG_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->Org, strlen(pVcardStruct->Org) ); + PayloadSize += strlen( pVcardStruct->Org ); + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->Title != '\0') + { + /* "TITLE:\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], TITLE, TITLE_STRING_SIZE ); + PayloadSize += TITLE_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->Title, strlen(pVcardStruct->Title) ); + PayloadSize += strlen( pVcardStruct->Title ); + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + } + if(*pVcardStruct->Url != '\0') + { + /* "URL:\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], URL, URL_STRING_SIZE ); + PayloadSize += URL_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], pVcardStruct->Url, strlen(pVcardStruct->Url) ); + PayloadSize += strlen( pVcardStruct->Url ); + memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); + PayloadSize += LIMIT_STRING_SIZE; + } + + /* "END:VCARD\r\n" */ + memcpy( &pNDEFMessage[PayloadSize], END, END_STRING_SIZE ); + PayloadSize += END_STRING_SIZE; + memcpy( &pNDEFMessage[PayloadSize], VCARD, VCARD_STRING_SIZE ); + PayloadSize += VCARD_STRING_SIZE; +// memcpy( &pNDEFMessage[PayloadSize], LIMIT, LIMIT_STRING_SIZE ); +// PayloadSize += LIMIT_STRING_SIZE; + + *size = (uint16_t)(PayloadSize); /* Must not count the 2 byte that represent the NDEF size */ +/* + PayloadSize -= 6 + VCARD_TYPE_STRING_LENGTH; + + pNDEFMessage[2] = (PayloadSize & 0xFF000000) >> 24; + pNDEFMessage[3] = (PayloadSize & 0x00FF0000) >> 16; + pNDEFMessage[4] = (PayloadSize & 0x0000FF00) >> 8; + pNDEFMessage[5] = PayloadSize & 0x000000FF; + */ +} + + +/** + * @brief This function extracts binary data from a base64 representation. + * @param input64 : pointer on the input data in base64. + * @param binary : returned binary data. + * @return Updated pointer on the input64 buffer (normal increment is 4 base64 char for 3 bytes of binary data, but special char are ignored) +*/ +static uint8_t* from_base64(uint8_t *input64, uint32_t* binary) +{ + /* Read 4 base64 character & translate them into 3 bytes binary */ + *binary = 0; + uint8_t base64_6bits; + int i = 0; + while(i<4) + { + + if((*input64 >= 'A') && (*input64 <= 'Z')) + { + base64_6bits = *(input64++) - 'A'; + } else if ((*input64 >= 'a') && (*input64 <= 'z')) + { + base64_6bits = *(input64++) - 'a' + 26; + } else if ((*input64 >= '0') && (*input64 <= '9')) { + base64_6bits = *(input64++) - '0' + 52; + } else if (*input64 == '+') + { + base64_6bits = 62; + input64++; + } else if (*input64 == '/') + { + base64_6bits = 63; + input64++; + } else if (*input64 == '=') { + base64_6bits = 0; + input64++; + } else { + input64++; + continue; + } + + *binary |= base64_6bits << (6*(3-i)); + i++; + } + *binary = ((*binary & 0xFF0000)>>16) | ((*binary & 0xFF)<<16) | (*binary & 0xFF00); + return input64; +} + + +/** + * @brief This function return the picture stored in a VCARD. + * @param pPayload : pointer on the payload data of the NDEF message. + * @param PayloadSize : number of data in the payload. + * @param pPict : Pointer on the dpicture buffer (must be big enough to contain the picture - warning: no check is done in the function). + */ +int NDEF_getVcardPicture( uint8_t* pPayload, uint32_t PayloadSize, uint8_t* pPict ) +{ + uint8_t* pSrcPict; + + + /* Let's find the picture */ + pSrcPict = pPayload; + while( memcmp( pSrcPict, JPEG, JPEG_STRING_SIZE ) && (pSrcPict < (pPayload + PayloadSize)) ) + { + pSrcPict++; + } + while( (*pSrcPict != ':') && (pSrcPict < (pPayload + PayloadSize)) ) + { + pSrcPict++; + } + /* Picture start at next char */ + pSrcPict++; + + + /* Word found */ + while( memcmp( pSrcPict, LIMIT, LIMIT_STRING_SIZE ) && (pSrcPict < (pPayload + PayloadSize) ) ) + { + uint32_t binary24; + pSrcPict = from_base64(pSrcPict, &binary24); + /* copy the 3 bytes read from the base64 data */ + memcpy( pPict, &binary24, 3); + pPict += 3; + /* Ignore any line breaks */ + while (*pSrcPict == 0x0A) + { + pSrcPict++; + } + } + + if(pSrcPict >= (pPayload + PayloadSize)) + { + /* problem when parsing the picture */ + return 1; + } else { + /* picture found */ + return 0; + } +} + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Vcard.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Vcard.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,119 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Vcard.h + * @author MMY Application Team + * @version $Revision: 2892 $ + * @date $Date: 2016-09-19 11:03:26 +0200 (Mon, 19 Sep 2016) $ + * @brief This file help to manage Vcard NDEF file. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_NDEF_VCARD_H +#define __LIB_NDEF_VCARD_H + + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" + + +#define VCARD_VERSION_2_1 "2.1" +#define VCARD_VERSION_2_1_SIZE 3 + +#define VCARD_VERSION_3_0 "3.0" +#define VCARD_VERSION_3_0_SIZE 3 + + +#define BEGIN "BEGIN:" +#define VCARD "VCARD" +#define VERSION "VERSION:" +#define VCARD_NAME "N:" + // TODO: rename FIRSTNAME into FORMATTEDNAME +#define FIRSTNAME "FN:" +#define HOME_TEL "TEL;HOME:" +#define WORK_TEL "TEL;WORK:" +#define CELL_TEL "TEL;CELL:" +#define HOME_EMAIL "EMAIL;HOME:" +#define WORK_EMAIL "EMAIL;WORK:" +#define GEN_EMAIL "EMAIL:" +#define HOME_ADDRESS "ADR;HOME:" +#define WORK_ADDRESS "ADR;WORK:" +#define GEN_ADDRESS "ADR:" +#define TITLE "TITLE:" +#define ORG "ORG:" +#define URL "URL:" +#define END "END:" +#define JPEG "JPEG" + +#define LIMIT "\r\n" + +#define BEGIN_STRING_SIZE 6 +#define VCARD_STRING_SIZE 5 +#define VERSION_STRING_SIZE 8 +#define VCARD_NAME_STRING_SIZE 2 + // TODO: rename FIRSTNAME into FORMATTEDNAME +#define FIRSTNAME_STRING_SIZE 3 +#define HOME_TEL_STRING_SIZE 9 +#define WORK_TEL_STRING_SIZE 9 +#define CELL_TEL_STRING_SIZE 9 +#define HOME_EMAIL_STRING_SIZE 11 +#define WORK_EMAIL_STRING_SIZE 11 +#define HOME_ADDRESS_STRING_SIZE 9 +#define WORK_ADDRESS_STRING_SIZE 9 +#define TITLE_STRING_SIZE 6 +#define ORG_STRING_SIZE 4 +#define URL_STRING_SIZE 4 +#define END_STRING_SIZE 4 +#define JPEG_STRING_SIZE 4 + +#define LIMIT_STRING_SIZE 2 + +typedef struct +{ + char Version [10]; + char Name[80]; + // TODO: rename FirstName into FormattedName + char FirstName[80]; + char Title[80]; + char Org[80]; + char HomeAddress[80]; + char WorkAddress[80]; + char Address[80]; + char HomeTel[40]; + char WorkTel[40]; + char CellTel[40]; + char HomeEmail[80]; + char WorkEmail[80]; + char Email[80]; + char Url[80]; +}sVcardInfo; + +uint16_t NDEF_ReadVcard( sRecordInfo_t *pRecordStruct, sVcardInfo *pVcardStruct ); +uint16_t NDEF_WriteVcard( sVcardInfo *pVcardStruct, I2C* mi2cChannel ); +void NDEF_PrepareVcardMessage( sVcardInfo *pVcardStruct, uint8_t *pNDEFMessage, uint16_t *size ); +int NDEF_getVcardPicture( uint8_t* pPayload, uint32_t PayloadSize, uint8_t* pPict ); + + +#endif /* __LIB_NDEF_VCARD_H */ + + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Wifi.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Wifi.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,367 @@ +/** + ****************************************************************************** + * @file lib_NDEF_Wifi.c + * @author Central LAB + * @version V1.0.0 + * @date 7-October-2015 + * @ingroup LibNDEF_Wifi + * @brief This file helps to manage a NDEF message representing a Wifi Token. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF_Wifi.h" +#define ATTRIBUTE_ID_SSID_LSB 0X10 +#define ATTRIBUTE_ID_SSID_MSB 0X45 + + +#define ATTRIBUTE_ID_NETWORK_LSB 0X10 +#define ATTRIBUTE_ID_NETWORK_MSB 0X27 + + +/** @addtogroup lib_NDEF_Wifi Wifi OOB library (WPS) + * @ingroup libNDEF + * @brief This module is used to manage a Wifi Out-Of-Band NDEF message, to start a communication based on Wifi. + * @details The Wifi OOB format is described by the Wifi Protected Setup specification. + * It consists in a list of data elements formated as type-length-value. + * This module allows to build, write & read such data embedded in a NDEF message. + * @section Wifi_Library_Usage Wifi NDEF library usage + * @subsection Write_Wifi_OOB How to write a Wifi OOB + * The Wifi OOB written in a NDEF record by this module has the following structure: + * - Version + * - Credential + - Network index + - SSID + - Authentication Type + - Encryption Type + - Network Key + - MAC Address + - Vendor Extension + - Network Key Shareable + - Vendor Extension + - Version2 + + To write a Wifi OOB, the user must: + 1. Instanciate & initialize a `sWifiTokenInfo` structure, such as: + + sWifiTokenInfo wps_oob = {.NetworkSSID = "MY_SSID", + .AuthenticationType = NDEF_WIFI_AUTHENTICATION_NONE, + .EncryptionType = NDEF_WIFI_ENCRYPTION_NONE, + .NetworkKey = "01234567"}; + @note + 1. `AuthenticationType` & `EncryptionType` fields must respectively be values from enums: `Ndef_Wifi_Authentication_t` & `Ndef_Wifi_Encryption_t`. + 2. If the `Network key` is set to an empty string, the library sets it to `00000000`.\n + Even if 0-length Network Key is supposed to be supported, smartphones dont necessarily accept it. + + 2. Call the `NDEF_WriteWifiToken` function on a pointer on the previous struct instance: + + NDEF_WriteWifiToken(&wps_oob); + * @subsection Read_Wifi_OOB How to read a Wifi OOB + * 1. Read the 1st record of the NDEF message: + * + * sRecordInfo_t rRecord; + * NDEF_ReadNDEF(NDEF_Buffer); + * NDEF_IdentifyBuffer(rRecord,NDEF_Buffer); + * 2. Decode the Wifi OOB: + * + * sWifiTokenInfo wps; + * NDEF_ReadWifiToken(&record, &wps); + * @note + * Only the `NetworkSSID` & `NetworkKey` are extracted from the Wifi OOB, other fields of the `sWifiTokenInfo` structure are left un-initialized. + * @{ + */ + +/* This buffer contains the data send/received by the TAG */ +extern uint8_t NDEF_Buffer [NDEF_MAX_SIZE]; + + +static void NDEF_FillWifiTokenStruct( uint8_t* pPayload, uint32_t PayloadSize, sWifiTokenInfo *pWifiTokenStruct); +static void NDEF_Read_WifiToken ( struct sRecordInfo *pRecordStruct, sWifiTokenInfo *pWifiTokenStruct ); + +/** + * @brief This function fills a WifiToken structure with information from the NDEF message. + * @param pPayload Pointer on the payload data of the NDEF message. + * @param PayloadSize number of data in the payload. + * @param pWifiTokenStruct pointer on the structure to fill. + * @retval NONE + */ +static void NDEF_FillWifiTokenStruct( uint8_t* pPayload, uint32_t PayloadSize, sWifiTokenInfo *pWifiTokenStruct) +{ + uint8_t* pLastByteAdd,data1,data2,*temp,*temp_br ; + uint16_t SSIDLen,NetWorkKeyLen; + uint8_t *dbg,dbg1; + + + pLastByteAdd = (uint8_t*)(pPayload + PayloadSize); + pPayload--; + + while(pPayload++ != pLastByteAdd) + { + uint8_t attribute = *pPayload; + temp_br = pPayload; + switch(attribute) + { + + case ATTRIBUTE_ID_SSID_LSB: + temp = pPayload; + dbg = temp; + dbg1 = *++dbg; + if(dbg1 == ATTRIBUTE_ID_SSID_MSB ) + { + data1 = *++dbg; + data2 = *++dbg; + SSIDLen = data1; + SSIDLen = SSIDLen << 8; + SSIDLen |= data2; + pPayload += 4; + memcpy( pWifiTokenStruct->NetworkSSID, pPayload, SSIDLen); + /* add end of string charactere */ + pWifiTokenStruct->NetworkSSID[SSIDLen] = '\0'; + pPayload += SSIDLen - 1; + } + else if(dbg1 == ATTRIBUTE_ID_NETWORK_MSB ) + { + data1 = *++dbg; + data2 = *++dbg; + NetWorkKeyLen = data1; + NetWorkKeyLen = NetWorkKeyLen << 8; + NetWorkKeyLen |= data2; + pPayload += 4; + memcpy( pWifiTokenStruct->NetworkKey, pPayload, NetWorkKeyLen); + /* add end of string charactere */ + pWifiTokenStruct->NetworkKey[NetWorkKeyLen] = '\0'; + pPayload += NetWorkKeyLen -1; + } + else + { + pPayload = temp_br; + } + + break; + + default : + ; + } + } + +} + +/** + * @brief This fonction reads the WifiToken and store data in a structure. + * @param pRecordStruct Pointer on the record structure. + * @param pWifiTokenStruct Pointer on the structure to fill. + * @retval NONE + */ +static void NDEF_Read_WifiToken ( struct sRecordInfo *pRecordStruct, sWifiTokenInfo *pWifiTokenStruct ) +{ + uint8_t* pPayload; + uint32_t PayloadSize; + + PayloadSize = pRecordStruct->PayloadLength; + + /* Read record header */ + pPayload = (uint8_t*)(pRecordStruct->PayloadBufferAdd); + + if( pRecordStruct->NDEF_Type == URI_WIFITOKEN_TYPE) + NDEF_FillWifiTokenStruct(pPayload , PayloadSize, pWifiTokenStruct); + +} + + +/** + * @brief This fonction reads a NDEF record and retrieves a WifiToken information if any. + * @param pRecordStruct Pointer on the record structure. + * @param pWifiTokenStruct Pointer on a `sWifiTokenInfo` structure to fill with the WifiToken information. + * @retval NDEF_OK WifiToken information from NDEF have been retrieved. + * @retval NDEF_ERROR Not able to retrieve the WifiToken information. + */ +uint16_t NDEF_ReadWifiToken(struct sRecordInfo *pRecordStruct, sWifiTokenInfo *pWifiTokenStruct) +{ + uint16_t status = NDEF_ERROR; + + if( pRecordStruct->NDEF_Type == URI_WIFITOKEN_TYPE ) + { + NDEF_Read_WifiToken(pRecordStruct, pWifiTokenStruct ); + status = NDEF_OK; + } + + return status; +} + + +/** + * @brief This fonction writes a NDEF message built with the WifiToken data given in the structure. + * @param pWifiTokenStruct Pointer on the structure containing the WifiToken information. + * @retval NDEF_OK The NDEF message has been successfully written. + * @retval NDEF_ERROR Not able to store the NDEF message inside the tag. + */ +uint16_t NDEF_WriteWifiToken ( sWifiTokenInfo *pWifiTokenStruct, I2C* mi2cChannel ) +{ + uint16_t status = NDEF_ERROR; + uint8_t* pPayload,initStage = 0; + uint16_t DataSize; + uint32_t PayloadSize,SSIDSize,SSIDKeySize; + + if(pWifiTokenStruct->NetworkKey[0] == '\0') + { + /* Empty network key is not supported by Phones */ + strcpy(pWifiTokenStruct->NetworkKey, NDEF_WIFI_DEFAULT_NETWORK_KEY); + } + + uint8_t configToken1[] = {0x10,0x4A, /* Attribute ID : Version*/ + 0x00,0x01, /* Attribute ID Length*/ + 0x10, /* Version 1.0*/ + 0x10,0x0E, /* Attribute ID Credential*/ + 0x00,0x48, /* Attribute ID Length*/ + 0x10,0x26, /* Attribute ID : Network Index*/ + 0x00,0x01, /* Attribute Length*/ + 0x01, /* Index */ + 0x10,0x45, /* Attribute ID :SSID*/ + + }; + + /* Fill SSID length + SSID between configToken1 and configToken3*/ + + uint8_t configToken3[] = {0x10,0x03, /* Attribute ID :Authentication Type*/ + 0x00,0x02, /* Attribute Length*/ + 0x00,0x01, /* Attribute Type : Open*/ + 0x10,0x0F, /* Attribute ID : Encryption Type*/ + 0x00,0x02, /* Attribute Length*/ + 0x00,0x01, /* Encryption Type : None*/ + 0x10,0x27}; /* Attribute ID : Network Key */ + + + /*Fill SSID KEY Length and SSID Key between configToken3 and configToken5*/ + + uint8_t configToken5[] = {0x10,0x20, /* Attribute ID : MAC Address */ + 0x00,0x06, /* Attribute Length*/ + 0, /*MAC-ADDRESS*/ + 0, /*MAC-ADDRESS*/ + 0, /*MAC-ADDRESS*/ + 0, /*MAC-ADDRESS*/ + 0, /*MAC-ADDRESS*/ + 0, /*MAC-ADDRESS*/ + 0x10,0x49, /* Attribute ID : Vendor Extension */ + 0x00,0x06, /* Attribute Length*/ + 0x00,0x37,0x2A, /* Vendor ID:WFA*/ + 0x02, /* Subelement ID:Network Key Shareable*/ + 0x01, /* Subelement Length*/ + 0x01, /*Network Key Shareable : TRUE*/ + 0x10,0x49, /* Attribute ID : Vendor Extension */ + 0x00,0x06,/* Attribute Length*/ + 0x00,0x37,0x2A,/* Vendor ID:WFA*/ + 0x00, /* Subelement ID:Version2*/ + 0x01, /* Subelement Length:1*/ + 0x20 /* Version2*/ + }; + + + /* Set size of the tokens */ + const uint32_t CONFIG_TOKEN_1 = sizeof(configToken1); + const uint32_t CONFIG_TOKEN_3 = sizeof(configToken3); + const uint32_t CONFIG_TOKEN_5 = sizeof(configToken5); + + /* Update Token3 for Autentication & Encryption Types, their default value is coded in token3 */ + configToken3[CONFIG_TOKEN_3_AUTHENTICATION_TYPE_INDEX] = pWifiTokenStruct->AuthenticationType & 0xFF; + configToken3[CONFIG_TOKEN_3_ENCRYPTION_TYPE_INDEX] = pWifiTokenStruct->EncryptionType & 0xFF; + + /* fill Wifi record header */ + NDEF_Buffer[FIRST_RECORD_OFFSET] = 0xD2; /* Record Flag */ + NDEF_Buffer[FIRST_RECORD_OFFSET+1] = WIFITOKEN_TYPE_STRING_LENGTH; + NDEF_Buffer[FIRST_RECORD_OFFSET+2] = 76; /* needs to be autocalculated - done at the end */ + + memcpy(&NDEF_Buffer[FIRST_RECORD_OFFSET+3], WIFITOKEN_TYPE_STRING, WIFITOKEN_TYPE_STRING_LENGTH); + + pPayload = &NDEF_Buffer[FIRST_RECORD_OFFSET+3+WIFITOKEN_TYPE_STRING_LENGTH]; + PayloadSize = 0; + + /* Compute credential length */ + + uint16_t credential_length = 5 + // Network index + 4 + // SSID type + length + strlen(pWifiTokenStruct->NetworkSSID) + // SSID + CONFIG_TOKEN_3 + + 2 + // Network key length + strlen(pWifiTokenStruct->NetworkKey) + // Network KEY + CONFIG_TOKEN_5; + + /* update credential length */ + configToken1[CONFIG_TOKEN_1_CREDENTIAL_LENGTH_INDEX + 1] = credential_length & 0xff; + configToken1[CONFIG_TOKEN_1_CREDENTIAL_LENGTH_INDEX] = credential_length>>8; + + + for(initStage=0;initStage<CONFIG_TOKEN_1;initStage++) + { + *pPayload =configToken1[initStage]; + pPayload++; + } + + /*Fill SSID length and SSID value*/ + SSIDSize = strlen(pWifiTokenStruct->NetworkSSID); + *pPayload = 0x00; pPayload++; + *pPayload = SSIDSize & 0x000000FF; pPayload++; + + strcpy((char*)pPayload,pWifiTokenStruct->NetworkSSID); + pPayload = pPayload + strlen(pWifiTokenStruct->NetworkSSID); + + for(initStage=0;initStage<CONFIG_TOKEN_3;initStage++) + { + *pPayload =configToken3[initStage]; + pPayload++; + } + + /* Fill the SSIDKey length and SSIDKey value */ + SSIDKeySize = strlen(pWifiTokenStruct->NetworkKey); + *pPayload = 0x00; pPayload++; + *pPayload = SSIDKeySize & 0x000000FF; pPayload++; + + memcpy((char*)pPayload,pWifiTokenStruct->NetworkKey,SSIDKeySize); + pPayload = pPayload + SSIDKeySize; + + for(initStage=0;initStage<CONFIG_TOKEN_5;initStage++) + { + *pPayload =configToken5[initStage]; + pPayload++; + } + + PayloadSize += CONFIG_TOKEN_1 + CONFIG_TOKEN_3 + CONFIG_TOKEN_5 + SSIDSize + SSIDKeySize + 4 ; // +4 is for SSID & Key length fields + + NDEF_Buffer[FIRST_RECORD_OFFSET+2] = (PayloadSize & 0x000000FF); + + DataSize = PayloadSize + 3 + WIFITOKEN_TYPE_STRING_LENGTH; + + /* Write NDEF */ + status = NDEF_WriteNDEF(DataSize , NDEF_Buffer, mi2cChannel); + + return status; +} + + +/** + * @} + */ + + + +/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/ + +
diff -r 000000000000 -r de13951f30f6 lib_NDEF_Wifi.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_NDEF_Wifi.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,110 @@ +/** + ****************************************************************************** + * @file lib_NDEF_WifiToken.h + * @author Central LAB + * @version V1.0.0 + * @date 7-October-2015 + * @brief This file helps to manage the NDEF message representing a Wifi Token. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_NDEF_WIFIT_H +#define __LIB_NDEF_WIFIT_H + + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" + +/** @addtogroup lib_NDEF_Wifi Wifi OOB library (WPS) + * @ingroup libNDEF + * @{ + */ + + +/* Exported types ------------------------------------------------------------*/ +/** @brief This index points to the position of the credential length value in Token1. + * Its value may require to be updated if the token1 is modified. + */ +#define CONFIG_TOKEN_1_CREDENTIAL_LENGTH_INDEX 7 + +/** @brief This index points to the position of the Authentication type value in Token3. + * Its value may require to be updated if the token3 is modified. + */ +#define CONFIG_TOKEN_3_AUTHENTICATION_TYPE_INDEX ((uint32_t)5) +/** @brief This index points to the position of the Encryption type value in Token3. + * Its value may require to be updated if the token3 is modified. + */ +#define CONFIG_TOKEN_3_ENCRYPTION_TYPE_INDEX ((uint32_t)11) + +/** @brief MIME type for the Wifi OOB token. + */ +#define WIFITOKEN_TYPE_STRING "application/vnd.wfa.wsc" +/** @brief Length of the MIME type for the Wifi OOB token. + */ +#define WIFITOKEN_TYPE_STRING_LENGTH ((uint32_t)23) + +/** + * @brief Network key to be used when the Authentication is set to None. + * Althought WPS defines a 0 length network key in such case, + * with tested phones a 8 digit value is required. + */ +#define NDEF_WIFI_DEFAULT_NETWORK_KEY "00000000" + +typedef enum { + NDEF_WIFI_ENCRYPTION_NONE = 0x0000, /**< WPS No Encryption (set to 0 for Android native support / should be 1) */ + NDEF_WIFI_ENCRYPTION_WEP = 0x0002, /**< WPS Encryption based on WEP */ + NDEF_WIFI_ENCRYPTION_TKIP = 0x0003, /**< WPS Encryption based on TKIP */ + NDEF_WIFI_ENCRYPTION_AES = 0x0004 /**< WPS Encryption based on AES */ +} Ndef_Wifi_Encryption_t; + +typedef enum { + NDEF_WIFI_AUTHENTICATION_NONE = 0x0000, /**< WPS No Authentication (set to 0 for Android native support / should be 1) */ + NDEF_WIFI_AUTHENTICATION_WPAPSK = 0x0002, /**< WPS Authentication based on WPAPSK */ + NDEF_WIFI_AUTHENTICATION_SHARED = 0x0003, /**< WPS Authentication based on ?? */ + NDEF_WIFI_AUTHENTICATION_WPA = 0x0004, /**< WPS Authentication based on WPA */ + NDEF_WIFI_AUTHENTICATION_WPA2 = 0x0005, /**< WPS Authentication based on WPA2 */ + NDEF_WIFI_AUTHENTICATION_WPA2PSK = 0x0006 /**< WPS Authentication based on WPA2PSK */ +} Ndef_Wifi_Authentication_t; + +/** + * @brief WifiToken structure, to store Network SSID, Authentication Type, Encryption Type and Network Key. + */ +typedef struct +{ + char NetworkSSID[32]; /**< Store the Network SSID. */ + Ndef_Wifi_Authentication_t AuthenticationType; /**< Store the Authentication type to be used. */ + Ndef_Wifi_Encryption_t EncryptionType; /**< Store the Encryption to be used. */ + char NetworkKey[32]; /**< Store the Network Key. */ +}sWifiTokenInfo; + + +uint16_t NDEF_ReadWifiToken(struct sRecordInfo *pRecordStruct, sWifiTokenInfo *pWifiTokenStruct); +uint16_t NDEF_WriteWifiToken( sWifiTokenInfo *pWifiTokenStruct, I2C* mi2cChannel ); + +/** + * @} + */ + +#endif /* __LIB_NDEF_WIFIT_H */ + +/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 lib_wrapper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib_wrapper.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,49 @@ +/** + ****************************************************************************** + * @file lib_wrapper.h + * @author MMY Application Team + * @version $Revision: 2702 $ + * @date $Date: 2016-07-13 18:45:05 +0200 (Wed, 13 Jul 2016) $ + * @brief This file help to have upper layer independent from HW + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LIB_WRAPPER_H +#define __LIB_WRAPPER_H + +/* Includes ------------------------------------------------------------------*/ +#include "NDEFcommon.h" +#include "mbed.h" + + + + +uint16_t NfcTag_ReadNDEF( uint8_t* pData, I2C* mi2cChannel ); +uint16_t NfcTag_WriteNDEF(uint16_t Length, uint8_t* pData, I2C* mi2cChannel ); +uint16_t NfcTag_WriteProprietary(uint16_t Length, uint8_t* pData, I2C* mi2cChannel ); +uint16_t NfcTag_GetLength(uint16_t* Length, I2C* mi2cChannel); + +#endif /* __LIB_WRAPPER_H */ + + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 tagtype5_wrapper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tagtype5_wrapper.cpp Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,517 @@ +/** + ****************************************************************************** + * @file tagtype5_wrapper.c + * @author MMY Application Team + * @version $Revision: 3210 $ + * @date $Date: 2016-12-05 15:37:48 +0100 (Mon, 05 Dec 2016) $ + * @brief This file provides an abstraction layer to the libNDEF for the NFC Forum Type5 Tag. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "tagtype5_wrapper.h" +#include "BSP/x_nucleo_nfc04a1_nfctag.h" + +//void printDbg(char *str); +//char tmp[40]; +/* +typedef enum +{ + NFCTAG_OK = 0, + NFCTAG_ERROR = 1, + NFCTAG_BUSY = 2, + NFCTAG_TIMEOUT = 3, + NFCTAG_NACK = 4 +} NFCTAG_StatusTypeDef; +*/ +/** @addtogroup Tag_Type_5 Type 5 Tag library + * @ingroup libNFC_FORUM + * @{ + * @brief This module provides an abstraction layer to the NDEF library for the NFC Forum Type5 Tag. + * @details These functions manage the specificities of the Type5 Tag accesses.\n + * The NFC Forum defines specific Capability Containers for the Type5 Tags. + * The Capability Container provides basic information on how a tag can be accessed. + * Depending on the memory size of the tag, 2 different CC will be used: + * 1. 4-bytes Capability Container (Memory Size < 16kbits): + * |Byte0 |Byte1 |Byte2 |Byte3 | + * |:------------:|:---------------------------:|:-----------:|:--------------:| + * | Magic Number | Version & Access Conditions | Memory Size | NFC Type 5 Tag | + * 2. 8-bytes Capability Container (Memory Size > 16kbits): + * |Byte0 |Byte1 |Byte2|Byte3 |Byte4|Byte5|Byte6 |Byte7 | + * |:------------:|:---------------------------:|:---:|:--------------:|:---:|:---:|:---------:|:---------:| + * | Magic Number | Version & Access Conditions | 00h | NFC Type 5 Tag |RFU |RFU |Memory Size|Memory Size| + * @section Type5_Tag_Usage How to write a Type5 Tag Capability Container + * 1. Initialize the Capacity Container structure with the Tag compliant values: + - Example for a 4kbits memory tag: + + CCFileStruct.MagicNumber = NFCT5_MAGICNUMBER_E1_CCFILE; + CCFileStruct.Version = NFCT5_VERSION_V1_0; + CCFileStruct.MemorySize = 0x40; + CCFileStruct.TT5Tag = 0x0; + + - Example for a 64kbits memory tag: + + CCFileStruct.MagicNumber = NFCT5_MAGICNUMBER_E2_CCFILE; + CCFileStruct.Version = NFCT5_VERSION_V1_0; + CCFileStruct.MemorySize = NFCT5_EXTENDED_CCFILE; + CCFileStruct.ExtMemorySize = 0x400; + CCFileStruct.TT5Tag = 0x1; + + 2. Call the `NfcType5_TT5Init` function to write the Capability Container to the Tag: + + NfcType5_TT5Init(); + + */ + +/** @brief Capability Container structure instance (global). */ +sCCFileInfo CCFileStruct; + +/** + * @brief This function reads the data stored in the NDEF message. + * @param pData Pointer on the buffer used to store the read data. + * @retval NDEF_ERROR_MEMORY_INTERNAL The buffer is too small for the NDEF message. + * @retval NDEF_ERROR_NOT_FORMATED No Capability Container detected. + * @retval NDEF_ERROR Error when reading the NDEF message. + * @retval NDEF_OK NDEF message successfully read. + */ +uint16_t NfcTag_ReadNDEF( uint8_t* pData, I2C* mi2cChannel ) +{ + uint16_t status = NDEF_ERROR; + TT5_TLV_t tlv; + uint8_t tlv_size = 0; + uint16_t DataLength; + + /* Detect NDEF message in memory */ + status = NfcType5_NDEFDetection( mi2cChannel ); + if( status != NDEF_OK ) + { + return status; + } + + /* Read TL of Type 5 */ + status = BSP_NFCTAG_ReadData( (uint8_t*)&tlv, CCFileStruct.NDEF_offset, sizeof(TT5_TLV_t), mi2cChannel ); + if( status != NDEF_OK ) + { + return status; + } + + /* Check if L is on 3 or 1 byte and update length in buffer */ + if( tlv.Length == NFCT5_3_BYTES_L_TLV ) + { + tlv_size = 4; + DataLength = ((tlv.Length16 >> 8)&0xff) | ((tlv.Length16&0xff)<<8); + } + else + { + tlv_size = 2; + DataLength = tlv.Length; + } + /* If too many data to write return error */ + if( DataLength > NDEF_MAX_SIZE ) + { + return NDEF_ERROR_MEMORY_INTERNAL; + } + + /* Check CC file is in the correct mode to proceed */ + if( CCFileStruct.State == TT5_INITIALIZED ) + { + return NDEF_ERROR; + } + + if( DataLength > 0 ) + { + /* Read NDEF */ + if( BSP_NFCTAG_ReadData( (pData), CCFileStruct.NDEF_offset + tlv_size, DataLength, mi2cChannel ) != NFCTAG_OK ) + { + return NDEF_ERROR; + } + } + + return NDEF_OK; +} +uint32_t BSP_NFCTAG_GetByteSize( I2C* mi2cChannel ); + +/** + * @brief This function writes data in the NFC Tag. + * @param Type Type of the data: NDEF or Proprietary + * @param Length Number of bytes to write. + * @param pData Pointer on the buffer to copy. + * @retval NDEF_ERROR_MEMORY_INTERNAL Memory size is too small for the data. + * @retval NDEF_ERROR_NOT_FORMATED No Capability Container detected. + * @retval NDEF_ERROR Error when writing the Tag. + * @retval NDEF_OK The data has been successfully written. + */ +uint16_t NfcTag_WriteData(uint8_t Type, uint16_t Length , uint8_t *pData, I2C* mi2cChannel ) +{ + TT5_TLV_t tlv; + uint8_t tlv_size; + uint32_t offset; + uint8_t NfcT5_Terminator = NFCT5_TERMINATOR_TLV; + + uint32_t max_length = BSP_NFCTAG_GetByteSize( mi2cChannel) /* Memory size */ + - ((Length >= 0xFF) ? 4 : 2) /* - TLV length */ + - sizeof(NfcT5_Terminator) /* - Terminator TLV */ + - CCFileStruct.NDEF_offset; /* - CCfile length */ + + /* If too many data to write return error */ + if( Length > max_length ) + { + return NDEF_ERROR_MEMORY_TAG; + } + + /* Detect NDEF message in memory */ + if( NfcType5_NDEFDetection( mi2cChannel ) != NDEF_OK ) + { + return NDEF_ERROR; + } + + /* Prepare TLV */ + tlv.Type = Type; + if(Length >= 0xFF) + { + tlv.Length = NFCT5_3_BYTES_L_TLV; + tlv.Length16 = ((Length&0xff)<<8) | ((Length>>8)&0xff) ; + tlv_size = 4; + + } else { + tlv.Length = Length; + tlv_size = 2; + } + + + offset = CCFileStruct.NDEF_offset; + /* Start write TLV to EEPROM */ + if(BSP_NFCTAG_WriteData( (uint8_t*)&tlv, offset, tlv_size, mi2cChannel )!= NFCTAG_OK) + return NDEF_ERROR; + offset += tlv_size; + + BSP_NFCTAG_WriteData( pData , offset, 4, mi2cChannel ); + + + + /* Continue write TLV data to EEPROM */ + if(BSP_NFCTAG_WriteData( pData , offset, Length, mi2cChannel ) != NFCTAG_OK ) + return NDEF_ERROR; + offset +=Length; + + + /* Write Terminator TLV */ + if(BSP_NFCTAG_WriteData( &NfcT5_Terminator, offset, sizeof(NfcT5_Terminator), mi2cChannel ) != NFCTAG_OK) + return NDEF_ERROR; + + return NDEF_OK; + +} + +/** + * @brief This function writes a NDEF message in the NFC Tag. + * @param Length Number of bytes to write. + * @param pData Pointer on the buffer to copy. + * @retval NDEF_ERROR_MEMORY_INTERNAL Memory size is too small for the data. + * @retval NDEF_ERROR_NOT_FORMATED No Capability Container detected. + * @retval NDEF_ERROR Error when writing the Tag. + * @retval NDEF_OK The data has been successfully written. + */ +uint16_t NfcTag_WriteNDEF(uint16_t Length , uint8_t *pData, I2C* mi2cChannel ) +{ + return NfcTag_WriteData(NFCT5_NDEF_MSG_TLV,Length,pData, mi2cChannel); +} + +/** + * @brief This function writes a Proprietary message to the NFC Tag. + * @param Length Number of byte to write. + * @param pData Pointer on the buffer to copy. + * @retval NDEF_ERROR_MEMORY_INTERNAL Memory size is too small for the data. + * @retval NDEF_ERROR_NOT_FORMATED No Capability Container detected. + * @retval NDEF_ERROR Error when writing the Tag. + * @retval NDEF_OK The data has been successfully written. + */ +uint16_t NfcTag_WriteProprietary(uint16_t Length , uint8_t *pData, I2C* mi2cChannel ) +{ + return NfcTag_WriteData(NFCT5_PROPRIETARY_TLV,Length,pData, mi2cChannel); +} + + +/** + * @brief This functions writes the Capability Container in the NFC Tag. + * @param pCCBuffer Pointer on the buffer containnig the Capability Container. + * @retval NDEF_ERROR Error when writing the Tag. + * @retval NDEF_OK The CC has been successfully written. + */ +uint16_t NfcType5_WriteCCFile( const uint8_t * const pCCBuffer, I2C* mi2cChannel ) +{ + NFCTAG_StatusTypeDef ret_value; + + /* Write first block of CCFile */ + ret_value = BSP_NFCTAG_WriteData( pCCBuffer, 0x00, 0x4, mi2cChannel ); + + /* If extended memory writes the next 4 bytes */ + if( (pCCBuffer[2] == 0x00) && (ret_value == NFCTAG_OK) ) + { + ret_value = BSP_NFCTAG_WriteData( pCCBuffer + 4, 0x04, 4, mi2cChannel ); + } + + if( ret_value != NFCTAG_OK ) + { + return NDEF_ERROR; + } + + return NDEF_OK; +} + +/** + * @brief This functions reads the Capability Container from the NFC Tag. + * @param pCCBuffer Pointer on the buffer used to store the CC. + * @retval NDEF_ERROR Error when reading the Tag. + * @retval NDEF_OK The CC has been successfully read. + */ +uint16_t NfcType5_ReadCCFile( uint8_t * const pCCBuffer, I2C* mi2cChannel ) +{ + NFCTAG_StatusTypeDef ret_value; + + /* Read 4 bytes of CC File */ + ret_value = BSP_NFCTAG_ReadData( pCCBuffer, 0x00, 4, mi2cChannel ); + + /* If extended memory reads the next 4 bytes */ + if( (pCCBuffer[2] == 0x00) && (ret_value == NFCTAG_OK) ) + { + ret_value = BSP_NFCTAG_ReadData( pCCBuffer + 4, 0x04, 4, mi2cChannel ); + } + + if( ret_value != NFCTAG_OK ) + { + return NDEF_ERROR; + } + + return NDEF_OK; +} + +/** + * @brief This function initializes the Capability Container and an empty NDEF message in a NFC Tag. + * @details The Capability Container content is defined by the global variable `CCFileStruct`. + * @retval NDEF_ERROR The Tag has not been initialized. + * @retval NDEF_OK The Tag has been successfully initialized. + */ +uint16_t NfcType5_TT5Init( I2C* mi2cChannel ) +{ + NFCTAG_StatusTypeDef ret_value = NFCTAG_OK; + uint16_t status; + uint8_t accbuffer[8]; + uint8_t cdata; + + /* Prepare buffer to update CCFile */ + accbuffer[0] = CCFileStruct.MagicNumber; + accbuffer[1] = CCFileStruct.Version; + accbuffer[2] = CCFileStruct.MemorySize; + accbuffer[3] = CCFileStruct.TT5Tag; + CCFileStruct.NDEF_offset = 0x04; + + /* If extended memory prepare the length bytes */ + if( CCFileStruct.MemorySize == NFCT5_EXTENDED_CCFILE ) + { + accbuffer[6] = (uint8_t)(CCFileStruct.ExtMemorySize >> 8); + accbuffer[7] = (uint8_t)(CCFileStruct.ExtMemorySize & 0xFF); + CCFileStruct.NDEF_offset = 0x08; + } + + /* Update CCFile */ + status = NfcType5_WriteCCFile( accbuffer, mi2cChannel ); + + + if( status != NDEF_OK ) + { + return status; + } + + /* Update NDEF TLV for INITIALIZED state */ + /* Update T */ + cdata = NFCT5_NDEF_MSG_TLV; + ret_value = BSP_NFCTAG_WriteData( &cdata, CCFileStruct.NDEF_offset, 1, mi2cChannel ); + if( ret_value != NFCTAG_OK ) + { + return NDEF_ERROR; + } + + /* Update L */ + cdata = 0x00; + ret_value = BSP_NFCTAG_WriteData( &cdata, (CCFileStruct.NDEF_offset + 1), 1, mi2cChannel ); + if( ret_value != NFCTAG_OK ) + { + return NDEF_ERROR; + } + + return NDEF_OK; +} + +/** + * @brief This function detects a NDEF message in a Type 5 Tag. + * @details It first detects the Capability Container and then look for the NDEF TLV. + * The `CCfileStruct` global variable is updated accordingly with what is detected. + * @retval NDEF_OK NDEF message Tag Type 5 detected. + * @retval NDEF_ERROR_NOT_FORMATED Device is not a NFC Tag Type 5 Tag. + */ +uint16_t NfcType5_NDEFDetection( I2C* mi2cChannel ) +{ + uint8_t acc_buffer[8]; + TT5_TLV_t tlv_detect; + uint16_t status; + uint32_t memory_size; + + CCFileStruct.State = TT5_NO_NDEF; + + /* Read CCFile */ + status = NfcType5_ReadCCFile( acc_buffer, mi2cChannel ); + + if( status != NDEF_OK ) + { + return status; + } + + /* Check Byte 0 is equal to magic number */ + if( ( acc_buffer[0] != NFCT5_MAGICNUMBER_E1_CCFILE ) && ( acc_buffer[0] != NFCT5_MAGICNUMBER_E2_CCFILE ) ) + { + return NDEF_ERROR_NOT_FORMATED; + } + /* Check Version number */ + else if( ( (acc_buffer[1]&0xFC) != 0x40 ) ) + { + return NDEF_ERROR_NOT_FORMATED; + } + + /* Check if CCFile is on 4 Bytes or 8 Bytes */ + if( acc_buffer[2] == 0x00 ) + { + /* Update CCFIle structure */ + CCFileStruct.MemorySize = 0x0; + CCFileStruct.ExtMemorySize = (uint16_t)acc_buffer[6]; + CCFileStruct.ExtMemorySize = ( CCFileStruct.ExtMemorySize << 8 ) | acc_buffer[7]; + memory_size = CCFileStruct.ExtMemorySize; + CCFileStruct.NDEF_offset = 8; + } + else + { + /* Update CCFIle structure */ + CCFileStruct.MemorySize = acc_buffer[2]; + CCFileStruct.ExtMemorySize = 0x0; + memory_size = CCFileStruct.MemorySize; + CCFileStruct.NDEF_offset = 4; + } + + /* Update CCFIle structure */ + CCFileStruct.MagicNumber = (TT5_MagicNumber_t)acc_buffer[0]; + CCFileStruct.Version = acc_buffer[1]; + CCFileStruct.TT5Tag = acc_buffer[3]; + + /* Search for position of NDEF TLV in memory and tag status */ + while( ( BSP_NFCTAG_ReadData( (uint8_t *)&tlv_detect, CCFileStruct.NDEF_offset, sizeof(TT5_TLV_t), mi2cChannel ) == NFCTAG_OK ) && ( CCFileStruct.NDEF_offset < memory_size ) ) + { + /* Detect first NDEF Message in memory */ + if( tlv_detect.Type == NFCT5_NDEF_MSG_TLV ) + { + if( tlv_detect.Length == 0x00 ) + { + CCFileStruct.State = TT5_INITIALIZED; + } + else + { + if( CCFileStruct.Version & 0x3 ) + { + CCFileStruct.State = TT5_READ; + } + else + { + CCFileStruct.State = TT5_READ_WRITE; + } + } + return NDEF_OK; + } + /* If Proprietary NDEF jump to end of proprietary message */ + else if( tlv_detect.Type == NFCT5_PROPRIETARY_TLV ) + { + if( tlv_detect.Length == NFCT5_3_BYTES_L_TLV ) + { + CCFileStruct.NDEF_offset = CCFileStruct.NDEF_offset + tlv_detect.Length16; + continue; + } + else + { + CCFileStruct.NDEF_offset = CCFileStruct.NDEF_offset + tlv_detect.Length; + continue; + } + } + /* if Terminator no NDEF detected */ + else if( tlv_detect.Type == NFCT5_TERMINATOR_TLV ) + { + return NDEF_ERROR_NOT_FORMATED; + } + + CCFileStruct.NDEF_offset++; + } + + return NDEF_ERROR_NOT_FORMATED; +} + + + +/** + * @brief This function reads and return the size of the NDEF message in the NFC tag. + * @param Length Pointer on the NDEF size to be returned. + * @retval NDEF_ERROR_NOT_FORMATED Device is not a NFC Tag Type 5 Tag. + * @retval NDEF_ERROR The NDEF message size has not been read. + * @retval NDEF_OK The NDEF message size has been retrieved. + */ +uint16_t NfcTag_GetLength(uint16_t* Length, I2C* mi2cChannel) +{ + + uint16_t status = NDEF_ERROR; + TT5_TLV_t tlv; + + /* Detect NDEF message in memory */ + status = NfcType5_NDEFDetection( mi2cChannel ); + if( status != NDEF_OK ) + { + return status; + } + + /* Read TL of Type 5 */ + status = BSP_NFCTAG_ReadData( (uint8_t*)&tlv, CCFileStruct.NDEF_offset, sizeof(TT5_TLV_t), mi2cChannel ); + if( status != NFCTAG_OK ) + { + return NDEF_ERROR; + } + + if(tlv.Length != NFCT5_3_BYTES_L_TLV) + { + *Length = tlv.Length; + } else { + *Length = ((tlv.Length16 >> 8)&0xff) | ((tlv.Length16 & 0xff) << 8); + } + + return NDEF_OK; + +} + + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r de13951f30f6 tagtype5_wrapper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tagtype5_wrapper.h Thu Nov 14 10:34:11 2019 +0000 @@ -0,0 +1,126 @@ +/** + ****************************************************************************** + * @file tagtype5_wrapper.h + * @author MMY Application Team + * @version $Revision: 3310 $ + * @date $Date: 2017-01-13 11:22:18 +0100 (Fri, 13 Jan 2017) $ + * @brief This file provides an abstraction layer to the libNDEF for the NFC Forum Type5 Tag. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> + * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (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.st.com/myliberty + * + * 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, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __TAGTYPE5_WRAPPER_H +#define __TAGTYPE5_WRAPPER_H + +/* Includes ------------------------------------------------------------------*/ +#include "lib_NDEF.h" + +/** @addtogroup Tag_Type_5 + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** + * @brief Tag Type 5 State enumeration definition. + */ +typedef enum +{ + TT5_NO_NDEF = 0, /**< No data detected in the tag. */ + TT5_INITIALIZED, /**< Capability container detected. */ + TT5_READ_WRITE, /**< Read-Write data detected. */ + TT5_READ /**< Read-Only data message detected. */ +} TT5_State; + +/** @brief Type5 Tag Capability Container Magic numbers as defined by the NFC Forum. */ +typedef enum { + NFCT5_MAGICNUMBER_E1_CCFILE = 0xE1, /**< Complete data area can be read by 1-byte block adrdess commands. */ + NFCT5_MAGICNUMBER_E2_CCFILE = 0xE2 /**< Last part of the data area can be only read by 2-bytes block address commands.\n + The first 256 blocks can be read by 1-byte block address commands. */ +} TT5_MagicNumber_t; + +/** + * @brief Type5 Tag Capability Container structure. + */ +typedef struct +{ + TT5_MagicNumber_t MagicNumber; /**< CCfile[0]: Magic Number should be E1h or E2h (for extended API) */ + uint8_t Version; /**< CCfile[1]: Capability container version (b7-b4) and access conditions (b3-b0) */ + uint8_t MemorySize; /**< CCfile[2]: Memory size, expressed in 8 bytes blocks, set to 0 if tag size is greater than 16kbits. */ + uint8_t TT5Tag; /**< CCfile[3]: Additionnal information on the Type5 Tag:\n + b0: supports `read multiple block` commands\n + b1: RFU\n + b2: RFU\n + b3: supports `lock block` commands\n + b4: requires the `special frame` format + */ + uint8_t rsved1; /**< RFU */ + uint8_t rsved2; /**< RFU */ + uint16_t ExtMemorySize; /**< CCfile[6],CCfile[7]: Memory size, expressed in 8 bytes blocks, when tag size is greater than 16kbits. */ + TT5_State State; /**< Indicates if a NDEF message is present. */ + uint32_t NDEF_offset; /**< Indicates the address of a NDEF message in the tag. */ +}sCCFileInfo; + +/** @brief Type5 Tag Type-Length-Value structure as defined by the NFC Forum */ +typedef struct +{ + uint8_t Type; /**< NFC Forum message Type */ + uint8_t Length; /**< Message length if lesser than 255 bytes */ + uint16_t Length16; /**< Message length if greater than or equal to 255 bytes */ +} TT5_TLV_t; + + +/* Exported constants --------------------------------------------------------*/ +/** @brief Memory size value indicating that this is a 8-bytes Capability Container */ +#define NFCT5_EXTENDED_CCFILE 0x00 +/** @brief Capability container version 1.0 */ +#define NFCT5_VERSION_V1_0 0x40 +/** @brief Read access condition mask for the Capability Container byte1 */ +#define NFCT5_READ_ACCESS 0x0C +/** @brief Write access condition mask for the Capability Container byte1 */ +#define NFCT5_WRITE_ACCESS 0x03 + +/** @brief Type5 Tag NDEF message TLV-Type. */ +#define NFCT5_NDEF_MSG_TLV ((uint8_t) 0x03) +/** @brief Type5 Tag Proprietary message TLV-Type. */ +#define NFCT5_PROPRIETARY_TLV ((uint8_t) 0xFD) +/** @brief Type5 Tag Terminator TLV-Type. */ +#define NFCT5_TERMINATOR_TLV ((uint8_t) 0xFE) +/** @brief TLV-Length indicating a 4-bytes TLV (Length coded on 2 bytes). */ +#define NFCT5_3_BYTES_L_TLV ((uint8_t) 0xFF) + +/* Exported macro ------------------------------------------------------------*/ +/* External variables --------------------------------------------------------*/ +extern sCCFileInfo CCFileStruct; + +/* Exported functions ------------------------------------------------------- */ +uint16_t NfcType5_WriteCCFile( const uint8_t * const pCCBuffer, I2C* mi2cChannel ); +uint16_t NfcType5_ReadCCFile( uint8_t * const pCCBuffer, I2C* mi2cChannel ); +uint16_t NfcType5_TT5Init( I2C* mi2cChannel ); +uint16_t NfcType5_NDEFDetection( I2C* mi2cChannel ); + + +#endif /* __TAGTYPE5_WRAPPER_H */ + +/* @} + */ + +/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/