diff --git a/Makefile b/Makefile index 2403747..cb70940 100644 --- a/Makefile +++ b/Makefile @@ -1,24 +1,12 @@ PREFIX?=/usr/local INCLUDEDIR?=$(PREFIX)/include/android -PKGCONFIGDIR?=$(PREFIX)/lib/pkgconfig all: @echo "Use '$(MAKE) install' to install" install: mkdir -p $(DESTDIR)/$(INCLUDEDIR) - mkdir -p $(DESTDIR)/$(PKGCONFIGDIR) - cp android-config.h android-version.h $(DESTDIR)/$(INCLUDEDIR) - cp android-headers.pc $(DESTDIR)/$(PKGCONFIGDIR) - sed -i -e s:prefix=/usr:prefix=$(PREFIX):g $(DESTDIR)/$(PKGCONFIGDIR)/android-headers.pc - cp -r android $(DESTDIR)/$(INCLUDEDIR) - cp -r cutils $(DESTDIR)/$(INCLUDEDIR) - cp -r hardware $(DESTDIR)/$(INCLUDEDIR) - cp -r hardware_legacy $(DESTDIR)/$(INCLUDEDIR) - cp -r linux $(DESTDIR)/$(INCLUDEDIR) - cp -r log $(DESTDIR)/$(INCLUDEDIR) - cp -r nativebase $(DESTDIR)/$(INCLUDEDIR) - cp -r ndk $(DESTDIR)/$(INCLUDEDIR) - cp -r private $(DESTDIR)/$(INCLUDEDIR) - cp -r sync $(DESTDIR)/$(INCLUDEDIR) - cp -r system $(DESTDIR)/$(INCLUDEDIR) - cp -r vndk $(DESTDIR)/$(INCLUDEDIR) + cp -r * $(DESTDIR)/$(INCLUDEDIR) + rm -f $(DESTDIR)/$(INCLUDEDIR)/Makefile + rm -f $(DESTDIR)/$(INCLUDEDIR)/android-headers.pc.in + mkdir -p $(DESTDIR)/$(PREFIX)/lib/pkgconfig + sed -e 's;@prefix@;$(PREFIX)/;g; s;@includedir@;$(INCLUDEDIR);g' android-headers.pc.in > $(DESTDIR)/$(PREFIX)/lib/pkgconfig/android-headers.pc diff --git a/android-config.h b/android-config.h index 235a224..85c6214 100644 --- a/android-config.h +++ b/android-config.h @@ -21,4 +21,6 @@ #include +/* CONFIG GOES HERE */ + #endif diff --git a/android-headers.pc.in b/android-headers.pc.in new file mode 100644 index 0000000..fb757f3 --- /dev/null +++ b/android-headers.pc.in @@ -0,0 +1,4 @@ +Name: android-headers +Description: Provides the headers for the droid system +Version: 9.0.0 +Cflags: -I@includedir@ diff --git a/git-revisions.txt b/git-revisions.txt new file mode 100644 index 0000000..3483a75 --- /dev/null +++ b/git-revisions.txt @@ -0,0 +1,148 @@ +================================================ +bionic @ Tue Apr 20 21:48:56 CEST 2021 +================================================ ++ cd 9.0 ++ repo status bionic + +... A new version of repo (2.12) is available. +... You should upgrade soon: + cp /media/herrie/HaliumDisk/9.0/.repo/repo/repo /home/herrie/bin/repo + +project bionic/ (*** NO BRANCH ***) +prior sync failed; rebase still in progress ++ cd 9.0/bionic +./extract-headersnew.sh: 329: cd: can't cd to 9.0/bionic ++ git show-ref --head +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ++ git remote -v +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). + + +================================================ +hardware/libhardware @ Tue Apr 20 21:48:56 CEST 2021 +================================================ ++ cd 9.0 ++ repo status hardware/libhardware + +... A new version of repo (2.12) is available. +... You should upgrade soon: + cp /media/herrie/HaliumDisk/9.0/.repo/repo/repo /home/herrie/bin/repo + +nothing to commit (working directory clean) ++ cd 9.0/hardware/libhardware +./extract-headersnew.sh: 329: cd: can't cd to 9.0/hardware/libhardware ++ git show-ref --head +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ++ git remote -v +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). + + +================================================ +hardware/libhardware_legacy @ Tue Apr 20 21:48:56 CEST 2021 +================================================ ++ cd 9.0 ++ repo status hardware/libhardware_legacy + +... A new version of repo (2.12) is available. +... You should upgrade soon: + cp /media/herrie/HaliumDisk/9.0/.repo/repo/repo /home/herrie/bin/repo + +nothing to commit (working directory clean) ++ cd 9.0/hardware/libhardware_legacy +./extract-headersnew.sh: 329: cd: can't cd to 9.0/hardware/libhardware_legacy ++ git show-ref --head +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ++ git remote -v +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). + + +================================================ +system/core @ Tue Apr 20 21:48:56 CEST 2021 +================================================ ++ cd 9.0 ++ repo status system/core + +... A new version of repo (2.12) is available. +... You should upgrade soon: + cp /media/herrie/HaliumDisk/9.0/.repo/repo/repo /home/herrie/bin/repo + +nothing to commit (working directory clean) ++ cd 9.0/system/core +./extract-headersnew.sh: 329: cd: can't cd to 9.0/system/core ++ git show-ref --head +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ++ git remote -v +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). + + +================================================ +system/media @ Tue Apr 20 21:48:56 CEST 2021 +================================================ ++ cd 9.0 ++ repo status system/media + +... A new version of repo (2.12) is available. +... You should upgrade soon: + cp /media/herrie/HaliumDisk/9.0/.repo/repo/repo /home/herrie/bin/repo + +nothing to commit (working directory clean) ++ cd 9.0/system/media +./extract-headersnew.sh: 329: cd: can't cd to 9.0/system/media ++ git show-ref --head +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ++ git remote -v +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). + + +================================================ +external/kernel-headers @ Tue Apr 20 21:48:56 CEST 2021 +================================================ ++ cd 9.0 ++ repo status external/kernel-headers + +... A new version of repo (2.12) is available. +... You should upgrade soon: + cp /media/herrie/HaliumDisk/9.0/.repo/repo/repo /home/herrie/bin/repo + +nothing to commit (working directory clean) ++ cd 9.0/external/kernel-headers +./extract-headersnew.sh: 329: cd: can't cd to 9.0/external/kernel-headers ++ git show-ref --head +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ++ git remote -v +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). + + +================================================ +external/libnfc-nxp @ Tue Apr 20 21:48:56 CEST 2021 +================================================ ++ cd 9.0 ++ repo status external/libnfc-nxp + +... A new version of repo (2.12) is available. +... You should upgrade soon: + cp /media/herrie/HaliumDisk/9.0/.repo/repo/repo /home/herrie/bin/repo + +nothing to commit (working directory clean) ++ cd 9.0/external/libnfc-nxp +./extract-headersnew.sh: 329: cd: can't cd to 9.0/external/libnfc-nxp ++ git show-ref --head +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ++ git remote -v +fatal: not a git repository (or any parent up to mount point /media/herrie) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). + + diff --git a/hardware/audio.h b/hardware/audio.h index 10a8789..9034816 100644 --- a/hardware/audio.h +++ b/hardware/audio.h @@ -30,6 +30,12 @@ #include #include +#ifdef __ARM_PCS_VFP +#define FP_ATTRIB __attribute__((pcs("aapcs"))) +#else +#define FP_ATTRIB +#endif + __BEGIN_DECLS /** @@ -250,7 +256,7 @@ struct audio_stream_out { * This method might produce multiple PCM outputs or hardware accelerated * codecs, such as MP3 or AAC. */ - int (*set_volume)(struct audio_stream_out *stream, float left, float right); + int (*set_volume)(struct audio_stream_out *stream, float left, float right) FP_ATTRIB; /** * Write audio buffer to driver. Returns number of bytes written, or a @@ -434,7 +440,7 @@ struct audio_stream_in { /** set the input gain for the audio driver. This method is for * for future use */ - int (*set_gain)(struct audio_stream_in *stream, float gain); + int (*set_gain)(struct audio_stream_in *stream, float gain) FP_ATTRIB; /** Read audio buffer in from audio driver. Returns number of bytes read, or a * negative status_t. If at least one frame was read prior to the error, @@ -649,14 +655,14 @@ struct audio_hw_device { int (*init_check)(const struct audio_hw_device *dev); /** set the audio volume of a voice call. Range is between 0.0 and 1.0 */ - int (*set_voice_volume)(struct audio_hw_device *dev, float volume); + int (*set_voice_volume)(struct audio_hw_device *dev, float volume) FP_ATTRIB; /** * set the audio volume for all audio activities other than voice call. * Range between 0.0 and 1.0. If any value other than 0 is returned, * the software mixer will emulate this capability. */ - int (*set_master_volume)(struct audio_hw_device *dev, float volume); + int (*set_master_volume)(struct audio_hw_device *dev, float volume) FP_ATTRIB; /** * Get the current master volume value for the HAL, if the HAL supports @@ -665,7 +671,7 @@ struct audio_hw_device { * the initial master volume across all HALs. HALs which do not support * this method may leave it set to NULL. */ - int (*get_master_volume)(struct audio_hw_device *dev, float *volume); + int (*get_master_volume)(struct audio_hw_device *dev, float *volume) FP_ATTRIB; /** * set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode diff --git a/hardware/audio_amplifier.h b/hardware/audio_amplifier.h new file mode 100644 index 0000000..26e58a1 --- /dev/null +++ b/hardware/audio_amplifier.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2015, The CyanogenMod Project + * + * 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. + */ + +#ifndef CM_AUDIO_AMPLIFIER_INTERFACE_H +#define CM_AUDIO_AMPLIFIER_INTERFACE_H + +#include +#include +#include + +#include +#include + +#include + +__BEGIN_DECLS + +#define AMPLIFIER_HARDWARE_MODULE_ID "audio_amplifier" + +#define AMPLIFIER_HARDWARE_INTERFACE "audio_amplifier_hw_if" + +#define AMPLIFIER_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) + +#define AMPLIFIER_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0) +#define AMPLIFIER_DEVICE_API_VERSION_2_0 HARDWARE_DEVICE_API_VERSION(2, 0) +#define AMPLIFIER_DEVICE_API_VERSION_2_1 HARDWARE_DEVICE_API_VERSION(2, 1) +#define AMPLIFIER_DEVICE_API_VERSION_CURRENT AMPLIFIER_DEVICE_API_VERSION_2_1 + +struct str_parms; + +typedef struct amplifier_device { + /** + * Common methods of the amplifier device. This *must* be the first member + * of amplifier_device as users of this structure will cast a hw_device_t + * to amplifier_device pointer in contexts where it's known + * the hw_device_t references a amplifier_device. + */ + struct hw_device_t common; + + /** + * Notify amplifier device of current input devices + * + * This function should handle only input devices. + */ + int (*set_input_devices)(struct amplifier_device *device, uint32_t devices); + + /** + * Notify amplifier device of current output devices + * + * This function should handle only output devices. + */ + int (*set_output_devices)(struct amplifier_device *device, uint32_t devices); + + /** + * Notify amplifier device of output device enable/disable + * + * This function should handle only output devices. + */ + int (*enable_output_devices)(struct amplifier_device *device, + uint32_t devices, bool enable); + + /** + * Notify amplifier device of input device enable/disable + * + * This function should handle only input devices. + */ + int (*enable_input_devices)(struct amplifier_device *device, + uint32_t devices, bool enable); + + /** + * Notify amplifier device about current audio mode + */ + int (*set_mode)(struct amplifier_device *device, audio_mode_t mode); + + /** + * Notify amplifier device that an output stream has started + */ + int (*output_stream_start)(struct amplifier_device *device, + struct audio_stream_out *stream, bool offload); + + /** + * Notify amplifier device that an input stream has started + */ + int (*input_stream_start)(struct amplifier_device *device, + struct audio_stream_in *stream); + + /** + * Notify amplifier device that an output stream has stopped + */ + int (*output_stream_standby)(struct amplifier_device *device, + struct audio_stream_out *stream); + + /** + * Notify amplifier device that an input stream has stopped + */ + int (*input_stream_standby)(struct amplifier_device *device, + struct audio_stream_in *stream); + + /** + * set/get audio device parameters. + */ + int (*set_parameters)(struct amplifier_device *device, + struct str_parms *parms); + + /** + * set/get output stream parameters. + */ + int (*out_set_parameters)(struct amplifier_device *device, + struct str_parms *parms); + + /** + * set/get input stream parameters. + */ + int (*in_set_parameters)(struct amplifier_device *device, + struct str_parms *parms); +} amplifier_device_t; + +typedef struct amplifier_module { + /** + * Common methods of the amplifier module. This *must* be the first member + * of amplifier_module as users of this structure will cast a hw_module_t + * to amplifier_module pointer in contexts where it's known + * the hw_module_t references a amplifier_module. + */ + struct hw_module_t common; +} amplifier_module_t; + +/** convenience API for opening and closing a supported device */ + +static inline int amplifier_device_open(const struct hw_module_t *module, + struct amplifier_device **device) +{ + return module->methods->open(module, AMPLIFIER_HARDWARE_INTERFACE, + (struct hw_device_t **) device); +} + +static inline int amplifier_device_close(struct amplifier_device *device) +{ + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // CM_AUDIO_AMPLIFIER_INTERFACE_H diff --git a/hardware/bluetooth.h b/hardware/bluetooth.h index 3bcbeed..40ccc60 100644 --- a/hardware/bluetooth.h +++ b/hardware/bluetooth.h @@ -27,16 +27,7 @@ __BEGIN_DECLS -/** -* The Bluetooth Hardware Module ID -*/ - #define BLUETOOTH_INTERFACE_STRING "bluetoothInterface" -#define BT_HARDWARE_MODULE_ID "bluetooth" -#define BT_STACK_MODULE_ID "bluetooth" -#define BT_STACK_TEST_MODULE_ID "bluetooth_test" -#define bluetooth_module_t "bluetooth_test" - /** Bluetooth profile interface IDs */ diff --git a/hardware/display_defs.h b/hardware/display_defs.h new file mode 100644 index 0000000..0ec356f --- /dev/null +++ b/hardware/display_defs.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_INCLUDE_DISPLAY_DEFS_H +#define ANDROID_INCLUDE_DISPLAY_DEFS_H + +#include +#include + +#include + +__BEGIN_DECLS + +/* Will need to update below enums if hwcomposer_defs.h is updated */ + +/* Extended events for hwc_methods::eventControl() */ +enum { + HWC_EVENT_ORIENTATION = HWC_EVENT_VSYNC + 1 +}; + + +/* Extended hwc_layer_t::compositionType values */ +enum { + /* this layer will be handled in the HWC, using a blit engine */ + HWC_BLIT = 0xFF +}; + +/* Extended hwc_layer_t::flags values + * Flags are set by SurfaceFlinger and read by the HAL + */ +enum { + /* + * HWC_SCREENSHOT_ANIMATOR_LAYER is set by surfaceflinger to indicate + * that this layer is a screenshot animating layer. HWC uses this + * info to disable rotation animation on External Display + */ + HWC_SCREENSHOT_ANIMATOR_LAYER = 0x00000004 +}; + +/* This enum represents different types of 3D mode supported. This definition + * is maintained by HWC and exposed to its clients. + */ +enum { + HWC_S3DMODE_NONE = 0, + HWC_S3DMODE_LR, + HWC_S3DMODE_RL, + HWC_S3DMODE_TB, + HWC_S3DMODE_FP, + HWC_S3DMODE_MAX, +}; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_DISPLAY_DEFS_H*/ diff --git a/hardware/gps.h b/hardware/gps.h index 4e108b3..e461aa1 100644 --- a/hardware/gps.h +++ b/hardware/gps.h @@ -28,6 +28,12 @@ #include "gnss-base.h" +#ifdef __ARM_PCS_VFP +#define FP_ATTRIB __attribute__((pcs("aapcs"))) +#else +#define FP_ATTRIB +#endif + __BEGIN_DECLS /* @@ -631,7 +637,7 @@ typedef struct { * ID). Latitude and longitude are measured in degrees expected accuracy is * measured in meters */ - int (*inject_location)(double latitude, double longitude, float accuracy); + int (*inject_location)(double latitude, double longitude, float accuracy) FP_ATTRIB; /** * Specifies that the next call to start will not use the @@ -1200,7 +1206,7 @@ typedef struct { */ void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude, double radius_meters, int last_transition, int monitor_transitions, - int notification_responsiveness_ms, int unknown_timer_ms); + int notification_responsiveness_ms, int unknown_timer_ms) FP_ATTRIB; /** * Pause monitoring a particular geofence. diff --git a/hardware/hwcomposer_defs.h b/hardware/hwcomposer_defs.h index 9f22f86..fd373e3 100644 --- a/hardware/hwcomposer_defs.h +++ b/hardware/hwcomposer_defs.h @@ -261,19 +261,10 @@ enum { enum { HWC_DISPLAY_PRIMARY = 0, HWC_DISPLAY_EXTERNAL = 1, // HDMI, DP, etc. + HWC_DISPLAY_VIRTUAL = 2, - HWC_DISPLAY_EXTERNAL_2 = 2, - HWC_DISPLAY_EXTERNAL_3 = 3, - HWC_DISPLAY_EXTERNAL_4 = 4, - - HWC_DISPLAY_BUILTIN_2 = 5, - HWC_DISPLAY_BUILTIN_3 = 6, - HWC_DISPLAY_BUILTIN_4 = 7, - - HWC_DISPLAY_VIRTUAL = 8, - - HWC_NUM_PHYSICAL_DISPLAY_TYPES = 8, - HWC_NUM_DISPLAY_TYPES = 9, + HWC_NUM_PHYSICAL_DISPLAY_TYPES = 2, + HWC_NUM_DISPLAY_TYPES = 3, }; enum { diff --git a/libnfc-nxp/nfc_custom_config_example.h b/libnfc-nxp/nfc_custom_config_example.h new file mode 100644 index 0000000..d400bcc --- /dev/null +++ b/libnfc-nxp/nfc_custom_config_example.h @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/** +* \file nfc_custom_config.h +* \brief HAL Custom Configurations +* +* +* \note This is the configuration header file of the HAL 4.0. custom configurable +* parameters of the HAL 4.0 are provided in this file +* +* Project: NFC-FRI-1.1 / HAL4.0 +* +* $Date: Fri Jun 11 16:44:31 2010 $ +* $Author: ing04880 $ +* $Revision: 1.11 $ +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + + +/*@{*/ +#ifndef NFC_CUSTOM_CONFIG_H +#define NFC_CUSTOM_CONFIG_H +/*@}*/ + + +/** +* \name Hal +* +* File: \ref nfc_custom_config.h +* +*/ + + +/* + ***************************************************************** + ********************** CUSTOM MACROS ************************** + ***************************************************************** + */ + +/**< Max number of remote devices supported*/ +#define MAX_REMOTE_DEVICES 0x10 + + +/**< Default Session ID for Initialisation */ +#define DEFAULT_SESSION "NXP-NFC2" + +/** Resolution value for the timer, here the + timer resolution is 100 milliseconds */ +#define TIMER_RESOLUTION 100U + +/**< Defines connection time out value for LLC timer, + 500 is in milliseconds */ +#define LINK_CONNECTION_TIMEOUT 500U + +/**< Defines guard time out value for LLC timer, + 250 is in milliseconds */ +#define LINK_GUARD_TIMEOUT 250U + +/**< Macro to Enable SMX Feature During + * Initialisation */ + + +/* PLEASE NOTE: This Macro should be only enabled if there is a SMART_MX + * Chip attached to the PN544. + */ +/* #define NXP_HAL_ENABLE_SMX */ + + + +/* PLEASE NOTE: Kindly change the DEFAULT_SESSION Macro for each of the + * configuration change done for the below Macros + */ + +/**< External Clock Request Configuration for the NFC Device, + 0x00U -> No Clock Request, + 0x01U -> Clock Request through CLKREQ pin (GPIO pin 2), + 0x02U -> Clock Request through NXP_EVT_CLK_REQUEST Event, + */ +#define NXP_DEFAULT_CLK_REQUEST 0x00U + +/**< External Input Clock Setting for the NFC Device, + 0x00U -> No Input Clock Required (Use the Xtal), + 0x01U -> 13 MHZ, + 0x02U -> 19.2 MHZ, + 0x03U -> 26 MHZ, + 0x04U -> 38.4 MHZ, + 0x05U -> Custom (Set the Custome Clock Registry), + */ +#define NXP_DEFAULT_INPUT_CLK 0x00U + + + +#define NFC_DEV_HWCONF_DEFAULT 0xBCU + +/**< TX LDO Configuration + 0x00 -> 00b 3.0 V, + 0x01 -> 01b 3.0 V, + 0x02 -> 10b 2.7 V, + 0x03 -> 11b 3.3 V, + + */ +#define NXP_DEFAULT_TX_LDO 0x00U + + +/**< External Clock Request Configuration for the NFC Device, + 0x00U -> No Power Request, + 0x01U -> Power Request through CLKREQ pin (GPIO pin 2), + 0x02U -> Power Request through PWR_REQUEST (GPIO Pin 3), + */ +#define NXP_UICC_PWR_REQUEST 0x00U + +/**< UICC Bit Rate Configuration + 0x02U -> 212Kbits/Sec + 0x04U -> 424Kbits/Sec + 0x08U -> 828Kbits/Sec + */ + +#define NXP_UICC_BIT_RATE 0x08U + +/**< Indicates PN544 Power Modes Configuration for the NFC Device, + 0x00U -> PN544 stays in active bat mode + (except when generating RF field) + 0x01U -> PN544 goes in standby when possible otherwise + stays in active bat mode + 0x02U -> PN544 goes in idle mode as soon as it can + (otherwise it is in active bat except when generating RF field) + 0x03U -> PN544 goes in standby when possible otherwise goes in idle mode + as soon as it can (otherwise it is in active bat except when + generating RF field) + */ + +#define NXP_SYSTEM_PWR_STATUS 0x01U + + +/**< System Event Notification + 0x01 Overcurrent + 0x02 PMUVCC Switch + 0x04 External RF Field + 0x08 Memory Violation + 0x10 Temperature Overheat + */ + +#define NXP_SYSTEM_EVT_INFO 0x10U + +/**< NFCIP Active Mode Configuration + 0x01 106 kbps + 0x02 212 kbps + 0x04 424 kbps + */ + +#define NXP_NFCIP_ACTIVE_DEFAULT 0x01U + + + +/* Reset the Default values of Host Link Timers */ +/* Macro to Enable the Host Side Link Timeout Configuration + * 0x00 ----> Default Pre-defined Configuration; + * 0x01 ----> Update only the Host Link Guard Timeout Configuration; + * 0x03 ----> Update Both the Host Link Guard Timeout + and ACK Timeout Configuration; + */ +#define HOST_LINK_TIMEOUT 0x00U + + +#define NXP_NFC_LINK_GRD_CFG_DEFAULT 0x0032U + + +#define NXP_NFC_LINK_ACK_CFG_DEFAULT 0x0005U + + +/* Macro to Enable the Interface Character Timeout Configuration + * 0x00 ----> Default Pre-defined Configuration; + * 0x01 ----> Update the IFC Timeout Default Configuration; + */ +#define NXP_NFC_IFC_TIMEOUT 0x00 + + +#define NXP_NFC_IFC_CONFIG_DEFAULT 0x203AU + + +#define NXP_NFCIP_PSL_BRS_DEFAULT 0x00U + + +#endif /* NFC_CUSTOM_CONFIG_H */ diff --git a/libnfc-nxp/nfc_osal_deferred_call.h b/libnfc-nxp/nfc_osal_deferred_call.h new file mode 100644 index 0000000..08396dc --- /dev/null +++ b/libnfc-nxp/nfc_osal_deferred_call.h @@ -0,0 +1,32 @@ +#ifndef __NFC_OSAL_DEFERRED_CALL_H_ +#define __NFC_OSAL_DEFERRED_CALL_H_ + +/** + * \ingroup grp_osal_nfc + *\brief Deferred call declaration. + * This type of API is called from ClientApplication ( main thread) to notify + * specific callback. + */ +typedef pphLibNfc_DeferredCallback_t nfc_osal_def_call_t; + +/** + * \ingroup grp_osal_nfc + *\brief Deferred message specific info declaration. + * This type information packed as WPARAM when \ref PHOSALNFC_MESSAGE_BASE type + *windows message is posted to main thread. + */ +typedef phLibNfc_DeferredCall_t nfc_osal_def_call_msg_t; + +/** + * \ingroup grp_osal_nfc + *\brief Deferred call declaration. + * This Deferred call post message of type \ref PH_OSALNFC_TIMER_MSG along with + * timer specific details.ain thread,which is responsible for timer callback notification + * consumes of this message and notifies respctive timer callback. + *\note: This API packs upper timer specific callback notification information and post + *ref\PHOSALNFC_MESSAGE_BASE to main thread via windows post messaging mechanism. + */ + +void nfc_osal_deferred_call(nfc_osal_def_call_t func, void *param); + +#endif \ No newline at end of file diff --git a/libnfc-nxp/phDal4Nfc.h b/libnfc-nxp/phDal4Nfc.h new file mode 100644 index 0000000..3cbb585 --- /dev/null +++ b/libnfc-nxp/phDal4Nfc.h @@ -0,0 +1,619 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/*! + +* \file phDal4Nfc.h +* \brief Common DAL for the upper layer. +* +* Project: NFC-FRI-1.1 +* +* $Date: Tue Nov 10 13:56:45 2009 $ +* $Author: ing07299 $ +* $Revision: 1.38 $ +* $Aliases: NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +#ifndef PHDAL4NFC_H +#define PHDAL4NFC_H + +/** +* \name DAl4 NFC +* +* File: \ref phDal4Nfc.h +* +*/ +/*@{*/ +#define PH_DAL4NFC_FILEREVISION "$Revision: 1.38 $" /**< \ingroup grp_file_attributes */ +#define PH_DAL4NFC_FILEALIASES "$Aliases: NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" + /**< \ingroup grp_file_attributes */ +/*@}*/ +/*************************** Includes *******************************/ +/** \defgroup grp_nfc_dal DAL Component + * + * + * + */ +#include +/**< Basic type definitions */ +#include +/**< Generic Interface Layer Function Definitions */ +#include +/*********************** End of includes ****************************/ + +/***************************** Macros *******************************/ + /**< Used for messaging by DAL as well as Upper Layers */ +#define PH_DAL4NFC_MESSAGE_BASE PH_LIBNFC_DEFERREDCALL_MSG + +/************************ End of macros *****************************/ + + +/********************* Structures and enums *************************/ + +/** + * \ingroup grp_nfc_dal + * + * DAL context : This contains the information of the upper layer callback + * and hardware reference. + */ +typedef struct phDal4Nfc_SContext +{ + phNfcIF_sCallBack_t cb_if; /**1.Exports DAL interfaces and DAL layer context to upper layer. + *Exported DAL interfaces are : + *

.phDal4Nfc_Shutdown + *

.phDal4Nfc_Write + *

.phDal4Nfc_Read + *

.phDal4Nfc_ReadWait + *

.phDal4Nfc_ReadWaitCancel + *

phDal4Nfc_Unregister + *

.Registeres upper layer callbacks and upper layer context with DAL layer. + *For details refer to \ref phNfcIF_sReference_t. + *Registration details are valid unless upper layer calls \ref phDal4Nfc_Unregister() + or \ref phDal4Nfc_Shutdown called. + + * \param[in,out] psRefer holds DAL exported interface references once registration + * sucessful.This also contains transmit and receive buffer + * references. + * + * \param[in] if_cb Contains upper layer callback reference details, which are used + * by DAL layer during callback notification. + * These callbacks gets registered with DAL layer. + * + + * \param[out] psIFConf Currently this parameter not used.This parameter to be other than NULL. + * + * + * \retval NFCSTATUS_SUCCESS Operation is successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * + *\msc + *ClientApp,UpperLayer,phDal4Nfc; + *ClientApp=>phDal4Nfc [label="phDal4Nfc_Config()",URL="\ref phDal4Nfc_Config"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_Register()",URL="\ref phDal4Nfc_Register"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_Config()",URL="\ref phDal4Nfc_Config"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_Register()",URL="\ref phDal4Nfc_Register"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_Unregister()",URL="\ref phDal4Nfc_Unregister"]; + *UpperLayer<
. Initialize parameters for HW Interface. + *

. Initializing read and writer threads. + *

. Initializing read and write task specific events and event specific configurations. + *

. Initializing DAL layer specific details. + * + * \param[in] pContext DAL context provided by the upper layer. + * The DAL context will be exported to the + * upper layer via upper layer registration interface. + * \param[in] pHwRef information of the hardware + * + * \retval NFCSTATUS_SUCCESS DAL initialization successful. + * \retval NFCSTATUS_INVALID_DEVICE The device is not enumerated or the + * Hardware Reference points to a device + * which does not exist. Alternatively, + * also already open devices produce this + * error. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function + * is invalid. + * + *\msc + *ClientApp,UpperLayer,phDal4Nfc; + *ClientApp=>phDal4Nfc [label="phDal4Nfc_Config()",URL="\ref phDal4Nfc_Config"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_Register()",URL="\ref phDal4Nfc_Register"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_Init()",URL="\ref phDal4Nfc_Init"]; + *UpperLayer<
.Releases all the resources.( context,memory resources,read/write buffers). + *

.closes COMxx port which is used during DAL session. + *

.Terminates Reader and writer tasks. + * + * \param[in] pContext DAL context is provided by the upper layer. + * The DAL context earlier was given to the + * upper layer through the + * \ref \e phDal4Nfc_Register() function + * \param[in] pHwRef hardware reference context. + * + * \retval NFCSTATUS_SUCCESS DAL shutdown successful + * \retval NFCSTATUS_FAILED DAL shutdown failed(example.unable to + * suspend thread, close HW Interface etc.) + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function + * is invalid. + * + *\msc + *ClientApp,UpperLayer,phDal4Nfc; + *ClientApp=>phDal4Nfc [label="phDal4Nfc_Config()",URL="\ref phDal4Nfc_Config"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_Register()",URL="\ref phDal4Nfc_Register"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_Init()",URL="\ref phDal4Nfc_Init"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_Shutdown()",URL="\ref phDal4Nfc_Shutdown"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_Write()",URL="\ref phDal4Nfc_Write()"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_DeferredCall()",URL="\ref phDal4Nfc_DeferredCall()"]; + *ClientApp=>phDal4Nfc [label="phDal4Nfc_DeferredCb()",URL="\ref phDal4Nfc_DeferredCb()"]; + *phDal4Nfc=>UpperLayer [label="send_complete",URL="\ref phDal4Nfc_DeferredCb()"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_Write()",URL="\ref phDal4Nfc_Write()"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_DeferredCall()",URL="\ref phDal4Nfc_DeferredCall()"]; + *ClientApp=>phDal4Nfc [label="phDal4Nfc_DeferredCb()",URL="\ref phDal4Nfc_DeferredCb()"]; + *phDal4Nfc=>UpperLayer [label="send_complete",URL="\ref phDal4Nfc_DeferredCb()"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_Read()",URL="\ref phDal4Nfc_Read()"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_DeferredCall()",URL="\ref phDal4Nfc_DeferredCall()"]; + *ClientApp=>phDal4Nfc [label="phDal4Nfc_DeferredCb()",URL="\ref phDal4Nfc_DeferredCb()"]; + *phDal4Nfc=>UpperLayer [label="receive_complete",URL="\ref phDal4Nfc_DeferredCb()"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_Write()",URL="\ref phDal4Nfc_Write()"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_DeferredCall()",URL="\ref phDal4Nfc_DeferredCall()"]; + *ClientApp=>phDal4Nfc [label="phDal4Nfc_DeferredCb()",URL="\ref phDal4Nfc_DeferredCb()"]; + *phDal4Nfc=>UpperLayer [label="send_complete",URL="\ref phDal4Nfc_DeferredCb()"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_ReadWait()",URL="\ref phDal4Nfc_ReadWait()"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_DeferredCall()",URL="\ref phDal4Nfc_DeferredCall()"]; + *ClientApp=>phDal4Nfc [label="phDal4Nfc_DeferredCb()",URL="\ref phDal4Nfc_DeferredCb()"]; + *phDal4Nfc=>UpperLayer [label="receive_complete",URL="\ref phDal4Nfc_DeferredCb()"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_Write()",URL="\ref phDal4Nfc_Write()"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_DeferredCall()",URL="\ref phDal4Nfc_DeferredCall()"]; + *ClientApp=>phDal4Nfc [label="phDal4Nfc_DeferredCb()",URL="\ref Call phDal4Nfc_DeferredCb()"]; + *phDal4Nfc=>UpperLayer [label="send_complete",URL="\ref phDal4Nfc_DeferredCb()"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_ReadWait()",URL="\ref phDal4Nfc_ReadWait()"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_ReadWaitCancel()",URL="\ref phDal4Nfc_ReadWaitCancel()"]; + **UpperLayer<phDal4Nfc [label="phDal4Nfc_Config()",URL="\ref phDal4Nfc_Config"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_Config()",URL="\ref phDal4Nfc_Config"]; + *ClientApp<phDal4Nfc [label="phDal4Nfc_Register()",URL="\ref phDal4Nfc_Register"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_Init()",URL="\ref phDal4Nfc_Init"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_Shutdown()",URL="\ref phDal4Nfc_Shutdown"]; + *UpperLayer<phDal4Nfc [label="phDal4Nfc_ConfigRelease()",URL="\ref phDal4Nfc_ConfigRelease"]; + *ClientApp< +#else + +#ifdef _DAL_4_NFC_C +#define _ext_ +#else +#define _ext_ extern +#endif + +typedef pphLibNfc_DeferredCallback_t pphDal4Nfc_Deferred_Call_t; + +typedef phLibNfc_DeferredCall_t phDal4Nfc_DeferredCall_Msg_t; + +#ifndef WIN32 + +#ifdef USE_MQ_MESSAGE_QUEUE +#include +#define MQ_NAME_IDENTIFIER "/nfc_queue" + +_ext_ const struct mq_attr MQ_QUEUE_ATTRIBUTES +#ifdef _DAL_4_NFC_C + = { 0, /* flags */ + 10, /* max number of messages on queue */ + sizeof(phDal4Nfc_DeferredCall_Msg_t), /* max message size in bytes */ + 0 /* number of messages currently in the queue */ + } +#endif +; +#endif + +#endif + +void phDal4Nfc_DeferredCall(pphDal4Nfc_Deferred_Call_t func, void *param); +#endif +#endif + + diff --git a/libnfc-nxp/phDal4Nfc_messageQueueLib.h b/libnfc-nxp/phDal4Nfc_messageQueueLib.h new file mode 100644 index 0000000..b13823b --- /dev/null +++ b/libnfc-nxp/phDal4Nfc_messageQueueLib.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phDalNfc_messageQueueLib.h + * \brief DAL independant message queue implementation for android (can be used under linux too) + * + * Project: Trusted NFC Linux Lignt + * + * $Date: 13 aug 2009 + * $Author: Jonathan roux + * $Revision: 1.0 $ + * + */ +#ifndef PHDAL4NFC_MESSAGEQUEUE_H +#define PHDAL4NFC_MESSAGEQUEUE_H + +#ifndef WIN32 +#ifdef ANDROID +#include +#else +#include +#endif + +typedef struct phDal4Nfc_Message_Wrapper +{ + long mtype; + phLibNfc_Message_t msg; +} phDal4Nfc_Message_Wrapper_t; + +intptr_t phDal4Nfc_msgget(key_t key, int msgflg); +int phDal4Nfc_msgctl(intptr_t msqid, int cmd, void *buf); +int phDal4Nfc_msgsnd(intptr_t msqid, void * msgp, size_t msgsz, int msgflg); +int phDal4Nfc_msgrcv(intptr_t msqid, void * msgp, size_t msgsz, long msgtyp, int msgflg); +#endif + +#endif /* PHDAL4NFC_MESSAGEQUEUE_H */ diff --git a/libnfc-nxp/phDbgTrace.h b/libnfc-nxp/phDbgTrace.h new file mode 100644 index 0000000..b0890cb --- /dev/null +++ b/libnfc-nxp/phDbgTrace.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/** + * \file phDbgTrace.h + * Project: NFC-FRI-1.1 / HAL4.0 + * + * $Date: Tue Apr 28 11:48:33 2009 $ + * $Author: ing08203 $ + * $Revision: 1.17 $ + * $Aliases: NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +/*@{*/ +#ifndef PHDBGTRACE_H +#define PHDBGTRACE_H +/*@}*/ + +#include + + +#ifdef PHDBG_TRACES +#define MAX_TRACE_BUFFER 300 + +#ifndef PHDBG_TRACES_LEVEL_0 +#ifndef PHDBG_TRACES_LEVEL_1 +#ifndef PHDBG_TRACES_LEVEL_2 +#define PHDBG_TRACES_LEVEL_0 +#endif +#endif +#endif + + extern char phOsalNfc_DbgTraceBuffer[]; + + #ifdef PHDBG_TRACES_LEVEL_0 + + /*indicates an error that causes a program to abort.*/ + #define PHDBG_FATAL_ERROR(Str) {\ + snprintf(phOsalNfc_DbgTraceBuffer,MAX_TRACE_BUFFER, \ + "FATAL ERROR in Module :%s\n",__FILE__);\ + phOsalNfc_DbgString(phOsalNfc_DbgTraceBuffer);\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "In Function:%s\n",__FUNCTION__ ); \ + phOsalNfc_DbgString (phOsalNfc_DbgTraceBuffer);\ + } + + #define PHDBG_CRITICAL_ERROR(Str) {\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "CRITICAL ERROR in Module :%s\n",__FILE__);\ + phOsalNfc_DbgString(phOsalNfc_DbgTraceBuffer);\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "In Function:%s\n",__FUNCTION__ ); \ + phOsalNfc_DbgString (phOsalNfc_DbgTraceBuffer);\ + } + #define PHDBG_WARNING(Str) + #define PHDBG_INFO(Str) + #endif /*End of PHDBG_TRACES_LEVEL_0 */ + + #ifdef PHDBG_TRACES_LEVEL_1 + + /*indicates an error that causes a program to abort.*/ + #define PHDBG_FATAL_ERROR(Str) {\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "FATAL ERROR in Module :%s\n",__FILE__);\ + phOsalNfc_DbgString(phOsalNfc_DbgTraceBuffer);\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "In Function:%s\n",__FUNCTION__ ); \ + phOsalNfc_DbgString (phOsalNfc_DbgTraceBuffer);\ + } + + #define PHDBG_CRITICAL_ERROR(Str) {\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "CRITICAL ERROR in Module :%s\n",__FILE__);\ + phOsalNfc_DbgString(phOsalNfc_DbgTraceBuffer);\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "In Function:%s\n",__FUNCTION__ ); \ + phOsalNfc_DbgString (phOsalNfc_DbgTraceBuffer);\ + } + /*Normally this macro shall be used indicate system state that might cause problems in future.*/ + #define PHDBG_WARNING(Str) {\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "WARNING :%s\n",__FILE__);\ + phOsalNfc_DbgString(phOsalNfc_DbgTraceBuffer);\ + phOsalNfc_DbgString (Str);\ + phOsalNfc_DbgString ("\n");\ + } + #define PHDBG_INFO(Str) + #endif /*End of PHDBG_TRACES_LEVEL_1 */ + + #ifdef PHDBG_TRACES_LEVEL_2 + + /*indicates an error that causes a program to abort.*/ + #define PHDBG_FATAL_ERROR(Str) {\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "FATAL ERROR in Module :%s\n",__FILE__);\ + phOsalNfc_DbgString(phOsalNfc_DbgTraceBuffer);\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "In Function:%s\n",__FUNCTION__ ); \ + phOsalNfc_DbgString (phOsalNfc_DbgTraceBuffer);\ + } + + #define PHDBG_CRITICAL_ERROR(Str) {\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "CRITICAL ERROR in Module :%s\n",__FILE__);\ + phOsalNfc_DbgString(phOsalNfc_DbgTraceBuffer);\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "In Function:%s\n",__FUNCTION__ ); \ + phOsalNfc_DbgString (phOsalNfc_DbgTraceBuffer);\ + } + /*Normally this macro shall be used indicate system state that might cause problems in future.*/ + #define PHDBG_WARNING(Str) {\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "WARNING :%s\n",__FILE__);\ + phOsalNfc_DbgString(phOsalNfc_DbgTraceBuffer);\ + phOsalNfc_DbgString (Str);\ + phOsalNfc_DbgString ("\n");\ + } + + #define PHDBG_INFO(Str) {\ + snprintf(phOsalNfc_DbgTraceBuffer, MAX_TRACE_BUFFER, \ + "DBG INFO :%s\n",__FILE__);\ + phOsalNfc_DbgString(phOsalNfc_DbgTraceBuffer);\ + phOsalNfc_DbgString (Str);\ + phOsalNfc_DbgString ("\n");\ + } + + + +#endif /*End of PHDBG_TRACES_LEVEL_2 */ +#else +#define PHDBG_FATAL_ERROR(Str) +#define PHDBG_CRITICAL_ERROR(Str) +#define PHDBG_WARNING(Str) +#define PHDBG_INFO(Str) + + +#endif /*end of DEBUG trace*/ +#endif /* end of PHDBGTRACE_H */ diff --git a/libnfc-nxp/phDnldNfc.c b/libnfc-nxp/phDnldNfc.c new file mode 100644 index 0000000..c0b4b4c --- /dev/null +++ b/libnfc-nxp/phDnldNfc.c @@ -0,0 +1,3832 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phDnldNfc.c * +* \brief Download Mgmt Interface Source for the Firmware Download. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Tue Jun 28 14:25:44 2011 $ * +* $Author: ing04880 $ * +* $Revision: 1.33 $ * +* $Aliases: $ +* * +* =========================================================================== * +*/ + + +/* +################################################################################ +***************************** Header File Inclusion **************************** +################################################################################ +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* +################################################################################ +****************************** Macro Definitions ******************************* +################################################################################ +*/ + +#ifndef STATIC +#define STATIC static +#endif + +#if defined (DNLD_SUMMARY) && !defined (DNLD_TRACE) +#define DNLD_TRACE +#endif + +/* #if defined(PHDBG_INFO) && defined (PHDBG_CRITICAL_ERROR) */ +#if defined(DNLD_TRACE) +extern char phOsalNfc_DbgTraceBuffer[]; + +#define MAX_TRACE_BUFFER 0x0410 +#define Trace_buffer phOsalNfc_DbgTraceBuffer +/* #define DNLD_PRINT( str ) phOsalNfc_DbgTrace(str) */ +#define DNLD_PRINT( str ) phOsalNfc_DbgString(str) +#define DNLD_DEBUG(str, arg) \ + { \ + snprintf(Trace_buffer,MAX_TRACE_BUFFER,str,arg); \ + phOsalNfc_DbgString(Trace_buffer); \ + } +#define DNLD_PRINT_BUFFER(msg,buf,len) \ + { \ + snprintf(Trace_buffer,MAX_TRACE_BUFFER,"\n\t %s:",msg); \ + phOsalNfc_DbgString(Trace_buffer); \ + phOsalNfc_DbgTrace(buf,len); \ + phOsalNfc_DbgString("\r"); \ + } +#else +#define DNLD_PRINT( str ) +#define DNLD_DEBUG(str, arg) +#define DNLD_PRINT_BUFFER(msg,buf,len) +#endif + +#define DO_DELAY(period) usleep(period) + +/* delay after SW reset cmd in ms, required on uart for XTAL stability */ +#define PHDNLD_DNLD_DELAY 5000 +//#define PHDNLD_MAX_PACKET 0x0200U /* Max Total Packet Size is 512 */ +#define PHDNLD_MAX_PACKET 32U /* Max Total Packet Size is 512 */ +#define PHDNLD_DATA_SIZE ((PHDNLD_MAX_PACKET)- 8U) /* 0x01F8U */ + /* Max Data Size is 504 */ +#define PHDNLD_MIN_PACKET 0x03U /* Minimum Packet Size is 3*/ + +#define DNLD_DEFAULT_RESPONSE_TIMEOUT 0x4000U + +#define NXP_FW_MIN_TX_RX_LEN 0x0AU + + +#if defined( NXP_FW_MAX_TX_RX_LEN ) && \ + ( NXP_FW_MAX_TX_RX_LEN > NXP_FW_MIN_TX_RX_LEN ) + +#define PHDNLD_FW_TX_RX_LEN NXP_FW_MAX_TX_RX_LEN + +#elif !defined( NXP_FW_MAX_TX_RX_LEN ) + +/* To specify the Maximum TX/RX Len */ +#define NXP_FW_MAX_TX_RX_LEN 0x200 +#define PHDNLD_FW_TX_RX_LEN NXP_FW_MAX_TX_RX_LEN + +#else + +#define PHDNLD_FW_TX_RX_LEN NXP_FW_MIN_TX_RX_LEN + +#endif + +#define PHDNLD_FRAME_LEN_SIZE 0x02U +#define PHDNLD_ADDR_SIZE 0x03U +#define PHDNLD_DATA_LEN_SIZE 0x02U +#define PHDNLD_FRAME_DATA_OFFSET 0x03U + +#define DNLD_SM_UNLOCK_MASK 0x01U +#define DNLD_TRIM_MASK 0x02U +#define DNLD_RESET_MASK 0x04U +#define DNLD_VERIFY_MASK 0x08U +#define DNLD_CRITICAL_MASK 0x10U + + +#define NXP_NFC_IMAG_FW_MAX 0x05U + +#define PHDNLD_FW_PATCH_SEC 0x5FU + +#define PHDNLD_PAGE_SIZE 0x80U /* Page Size Configured for 64 Bytes */ + +#define FW_MAX_SECTION 0x15U /* Max Number of Sections */ + +#define DNLD_CRC16_SIZE 0x02U + +#define DNLD_CRC32_SIZE 0x04U + +#define DNLD_CFG_PG_ADDR 0x00008000U +#define DNLD_FW_CODE_ADDR 0x00800000U +#define DNLD_PATCH_CODE_ADDR 0x00018800U +#define DNLD_PATCH_TABLE_ADDR 0x00008200U + + +/* Raw Command to pass the Data in Download Mode */ +#define PHDNLD_CMD_RAW 0x00U +/* Command to Reset the Device in Download Mode */ +#define PHDNLD_CMD_RESET 0x01U +/* Command to Read from the Address specified in Download Mode */ +#define PHDNLD_CMD_READ 0x07U +#define PHDNLD_CMD_READ_LEN 0x0005U +/* Command to write to the Address specified in Download Mode */ +#define PHDNLD_CMD_WRITE 0x08U +#define PHDNLD_CMD_SEC_WRITE 0x0CU +#define PHDNLD_CMD_WRITE_MIN_LEN 0x0005U +#define PHDNLD_CMD_WRITE_MAX_LEN PHDNLD_DATA_SIZE +/* Command to verify the data written */ +#define PHDNLD_CMD_CHECK 0x06U +#define PHDNLD_CMD_CHECK_LEN 0x0007U + +/* Command to Lock the */ +#define PHDNLD_CMD_LOCK 0x40U +#define PHDNLD_CMD_LOCK_LEN 0x0002U + + +/* Command to set the Host Interface properties */ +#define PHDNLD_CMD_SET_HIF 0x09U + +/* Command to Activate the Patches Updated */ +#define PHDNLD_CMD_ACTIVATE_PATCH 0x0AU + +/* Command to verify the Integrity of the data written */ +#define PHDNLD_CMD_CHECK_INTEGRITY 0x0BU + +/* Command to verify the Integrity of the data written */ +#define PHDNLD_CMD_ENCAPSULATE 0x0DU + +#define CHECK_INTEGRITY_RESP_CRC16_LEN 0x03U +#define CHECK_INTEGRITY_RESP_CRC32_LEN 0x05U +#define CHECK_INTEGRITY_RESP_COMP_LEN 0x10U + + +/* Success Response to a Command Sent in the Download Mode */ +#define PHDNLD_RESP_SUCCESS 0x00U +/* Timeout Response to a Command Sent in the Download Mode */ +#define PHDNLD_RESP_TIMEOUT 0x01U +/* CRC Error Response to a Command Sent in the Download Mode */ +#define PHDNLD_RESP_CRC_ERROR 0x02U +/* Access Denied Response to a Command Sent in the Download Mode */ +#define PHDNLD_RESP_ACCESS_DENIED 0x08U +/* PROTOCOL Error Response to a Command Sent in the Download Mode */ +#define PHDNLD_RESP_PROTOCOL_ERROR 0x0BU +/* Invalid parameter Response to a Command Sent in the Download Mode */ +#define PHDNLD_RESP_INVALID_PARAMETER 0x11U +/* Command Not Supported Response to a Command Sent in the Download Mode */ +#define PHDNLD_RESP_CMD_NOT_SUPPORTED 0x13U +/* Length parameter error Response to a Command Sent in the Download Mode */ +#define PHDNLD_RESP_INVALID_LENGTH 0x18U +/* Checksum Error Response to a Command Sent in the Download Mode */ +#define PHDNLD_RESP_CHKSUM_ERROR 0x19U +/* Version already uptodate Response to a Command Sent in the Download Mode */ +#define PHDNLD_RESP_VERSION_UPTODATE 0x1DU +/* Memory operation error during the processing of + the Command Frame in the Download Mode */ +#define PHDNLD_RESP_MEMORY_UPDATE_ERROR 0x20U +/* The Chaining of the Command Frame was Successful in the Download Mode */ +#define PHDNLD_RESP_CHAINING_SUCCESS 0x21U +/* The Command is not allowed anymore in the Download Mode */ +#define PHDNLD_RESP_CMD_NOT_ALLOWED 0xE0U +/* The Error during the Chaining the Command Frame in the Download Mode */ +#define PHDNLD_RESP_CHAINING_ERROR 0xE6U +/* Write Error Response to a Command Sent in the Download Mode */ +#define PHDNLD_RESP_WRITE_ERROR 0x74U + +#define PNDNLD_WORD_LEN 0x04U + +#define NXP_MAX_DNLD_RETRY 0x02U + +#define NXP_MAX_SECTION_WRITE 0x05U + +#define NXP_PATCH_VER_INDEX 0x05U + + +/* +################################################################################ +******************** Enumeration and Structure Definition ********************** +################################################################################ +*/ + +typedef enum phDnldNfc_eSeqType{ + DNLD_SEQ_RESET = 0x00U, + DNLD_SEQ_INIT, + DNLD_SEQ_RAW, + DNLD_SEQ_LOCK, + DNLD_SEQ_UNLOCK, + DNLD_SEQ_UPDATE, + DNLD_SEQ_ROLLBACK, + DNLD_SEQ_COMPLETE +} phDnldNfc_eSeqType_t; + +typedef enum phDnldNfc_eState +{ + phDnld_Reset_State = 0x00, + phDnld_Unlock_State, + phDnld_Upgrade_State, + phDnld_Verify_State, + phDnld_Complete_State, + phDnld_Invalid_State +}phDnldNfc_eState_t; + + +typedef enum phDnldNfc_eSeq +{ + phDnld_Reset_Seq = 0x00, + phDnld_Activate_Patch, + phDnld_Deactivate_Patch, + phDnld_Update_Patch, + phDnld_Update_Patchtable, + phDnld_Lock_System, + phDnld_Unlock_System, + phDnld_Upgrade_Section, + phDnld_Verify_Integrity, + phDnld_Verify_Section, + phDnld_Complete_Seq, + phDnld_Raw_Upgrade, + phDnld_Invalid_Seq +}phDnldNfc_eSeq_t; + +typedef enum phDnldNfc_eChkCrc{ + CHK_INTEGRITY_CONFIG_PAGE_CRC = 0x00U, + CHK_INTEGRITY_PATCH_TABLE_CRC = 0x01U, + CHK_INTEGRITY_FLASH_CODE_CRC = 0x02U, + CHK_INTEGRITY_PATCH_CODE_CRC = 0x03U, + CHK_INTEGRITY_COMPLETE_CRC = 0xFFU +} phDnldNfc_eChkCrc_t; + + + +typedef struct hw_comp_tbl +{ + uint8_t hw_version[3]; + uint8_t compatibility; +}hw_comp_tbl_t; + + +typedef struct img_data_hdr +{ + /* Image Identification */ + uint32_t img_id; + /* Offset of the Data from the header */ + uint8_t img_data_offset; + /* Number of fimware images available in the img_data */ + uint8_t no_of_fw_img; + /* Fimware image Padding in the img_data */ + uint8_t fw_img_pad[2]; + /* HW Compatiblity table for the set of the Hardwares */ + hw_comp_tbl_t comp_tbl; + /* This data consists of the firmware images required to download */ +}img_data_hdr_t; + + +typedef struct fw_data_hdr +{ + /* The data offset from the firmware header. + * Just in case if in future we require to + * add some more information. + */ + uint8_t fw_hdr_len; + /* Total size of all the sections which needs to be updated */ + uint8_t no_of_sections; + uint8_t hw_comp_no; + uint8_t fw_patch; + uint32_t fw_version; +}fw_data_hdr_t; + + + + /* This data consists all the sections that needs to be downloaded */ +typedef struct section_hdr +{ + uint8_t section_hdr_len; + uint8_t section_mem_type; + uint8_t section_checksum; + uint8_t section_conf; + uint32_t section_address; + uint32_t section_length; +}section_hdr_t; + +typedef struct section_info +{ + section_hdr_t *p_sec_hdr; + uint8_t *p_trim_data; + /* The section data consist of the Firmware binary required + * to be loaded to the particular address. + */ + uint8_t *p_sec_data; + /* The Section checksum to verify the integrity of the section + * data. + */ + uint8_t *p_sec_chksum; + /** \internal Index used to refer and process the + * Firmware Section Data */ + volatile uint32_t section_offset; + + /** \internal Section Read Sequence */ + volatile uint8_t section_read; + + /** \internal Section Write Sequence */ + volatile uint8_t section_write; + + /** \internal TRIM Write Sequence */ + volatile uint8_t trim_write; + + volatile uint8_t sec_verify_retry; + +}section_info_t; + + +typedef struct phDnldNfc_sParam +{ + uint8_t data_addr[PHDNLD_ADDR_SIZE]; + uint8_t data_len[PHDNLD_DATA_LEN_SIZE]; + uint8_t data_packet[PHDNLD_DATA_SIZE]; +}phDnldNfc_sParam_t; + +typedef struct phDnldNfc_sDataHdr +{ + uint8_t frame_type; + uint8_t frame_length[PHDNLD_FRAME_LEN_SIZE]; +}phDnldNfc_sData_Hdr_t; + +typedef struct phDnldNfc_sRawHdr +{ + uint8_t frame_type; + uint8_t frame_length[PHDNLD_FRAME_LEN_SIZE]; +}phDnldNfc_sRawHdr_t; + +typedef struct phDnldNfc_sRawDataHdr +{ + uint8_t data_addr[PHDNLD_ADDR_SIZE]; + uint8_t data_len[PHDNLD_DATA_LEN_SIZE]; +}phDnldNfc_sRawDataHdr_t; + +typedef struct phDnldNfc_sChkCrc16_Resp +{ + uint8_t Chk_status; + uint8_t Chk_Crc16[2]; + +}phDnldNfc_sChkCrc16_Resp_t; + +typedef struct phDnldNfc_sChkCrc32_Resp +{ + uint8_t Chk_status; + uint8_t Chk_Crc32[4]; + +}phDnldNfc_sChkCrc32_Resp_t; + + +typedef struct phDnldNfc_sChkCrcComplete +{ + phDnldNfc_sChkCrc16_Resp_t config_page; + phDnldNfc_sChkCrc16_Resp_t patch_table; + phDnldNfc_sChkCrc32_Resp_t flash_code; + phDnldNfc_sChkCrc32_Resp_t patch_code; +}phDnldNfc_sChkCrcComplete_t; + +typedef struct phDnldNfc_sData +{ + uint8_t frame_type; + uint8_t frame_length[PHDNLD_FRAME_LEN_SIZE]; + union param + { + phDnldNfc_sParam_t data_param; + uint8_t response_data[PHDNLD_MAX_PACKET]; + uint8_t cmd_param; + }param_info; +}phDnldNfc_sData_t; + +#ifdef NXP_NFC_MULTIPLE_FW + +typedef struct phDnldNfc_sFwImageInfo +{ + /** \internal Data Pointer to the Firmware header section of the Firmware */ + fw_data_hdr_t *p_fw_hdr; + /** \internal Buffer pointer to store the Firmware Section Data */ + section_info_t *p_fw_sec; + /** \internal Buffer pointer to store the Firmware Raw Data */ + uint8_t *p_fw_raw; +}phDnldNfc_sFwImageInfo_t; + +#endif /* #ifdef NXP_NFC_MULTIPLE_FW */ + + +typedef struct phDnldNfc_TxInfo +{ + uint8_t *transmit_frame; + + uint16_t tx_offset; + + /** \internal Remaining amount of data to be sent */ + uint16_t tx_len; + + uint16_t tx_total; + + /** \internal Chain information for the data to be sent */ + uint8_t tx_chain; + +}phDnldNfc_TxInfo_t; + + +typedef struct phDnldNfc_RxInfo +{ + /** \internal Total length of the received buffer */ + uint16_t rx_total; + /** \internal Chain information of the received buffer */ + uint16_t rx_chain; + /** \internal Remaining Data information to be read to complete the + * Data Information. + */ + uint16_t rx_remain; + + /** \internal Buffer to Send the Raw Data Frame */ + uint8_t raw_buffer_data[PHDNLD_MAX_PACKET + + PHDNLD_PAGE_SIZE]; +}phDnldNfc_RxInfo_t; + + +typedef struct phDnldNfc_sContext +{ + /** \internal Structure to store the lower interface operations */ + phNfc_sLowerIF_t lower_interface; + + phNfc_sData_t *p_fw_version; + + /** \internal Pointer to the Hardware Reference Sturcture */ + phHal_sHwReference_t *p_hw_ref; + + /** \internal Pointer to the upper layer notification callback function */ + pphNfcIF_Notification_CB_t p_upper_notify; + /** \internal Pointer to the upper layer context */ + void *p_upper_context; + + /** \internal Timer ID for the Download Abort */ + uint32_t timer_id; + /** \internal Internal Download for the Download Abort */ + uint32_t dnld_timeout; + /** \internal Data Pointer to the Image header section of the Firmware */ + img_data_hdr_t *p_img_hdr; + +#ifdef NXP_NFC_MULTIPLE_FW + /** \internal Data Pointer to the Firmware Image Information */ + phDnldNfc_sFwImageInfo_t *p_img_info; +#endif /* #ifdef NXP_NFC_MULTIPLE_FW */ + + /** \internal Data Pointer to the Firmware header section of the Firmware */ + fw_data_hdr_t *p_fw_hdr; + /** \internal Buffer pointer to store the Firmware Data */ + section_info_t *p_fw_sec; + /** \internal Buffer pointer to store the Firmware Raw Data */ + uint8_t *p_fw_raw; + + /** \internal Previous Download Size */ + uint32_t prev_dnld_size; + + /** \internal Single Data Block to download the Firmware */ + uint8_t dnld_data[PHDNLD_MAX_PACKET + + PHDNLD_PAGE_SIZE]; + /** \internal Index used to refer and process the Download Data */ + volatile uint32_t dnld_index; + + /** \internal Response Data to process the response */ + phDnldNfc_sData_t dnld_resp; + + /** \internal Previously downloaded data stored + * to compare the written data */ + phNfc_sData_t dnld_store; + + /** \internal Previously downloaded trimmed data stored + * to compare the written data */ + phNfc_sData_t trim_store; + + uint8_t *p_resp_buffer; + + phDnldNfc_sChkCrcComplete_t chk_integrity_crc; + + phDnldNfc_eChkCrc_t chk_integrity_param; + +#define NXP_FW_SW_VMID_TRIM +#ifdef NXP_FW_SW_VMID_TRIM + +#define NXP_FW_VMID_TRIM_CHK_ADDR 0x0000813DU +#define NXP_FW_VMID_CARD_MODE_ADDR 0x00009931U +#define NXP_FW_VMID_RD_MODE_ADDR 0x00009981U + + uint8_t vmid_trim_update; +#endif /* #ifdef NXP_FW_SW_VMID_TRIM */ + + uint8_t cur_frame_info; + + uint8_t raw_mode_upgrade; + + uint8_t *p_patch_table_crc; + + uint8_t *p_flash_code_crc; + + uint8_t *p_patch_code_crc; + + uint16_t resp_length; + + /** \internal Current FW Section in Process */ + volatile uint8_t section_index; + + /** \internal Previous Command sent */ + volatile uint8_t prev_cmd; + + uint8_t dnld_retry; + + /** \internal Current Download State */ + volatile uint8_t cur_dnld_state; + /** \internal Next Download State */ + volatile uint8_t next_dnld_state; + + /** \internal Current step in Download Sequence */ + volatile uint8_t cur_dnld_seq; + /** \internal Next step in Download Sequence */ + volatile uint8_t next_dnld_seq; + + /* \internal Data Transmit information */ + phDnldNfc_TxInfo_t tx_info; + + /* \internal Data Receive information */ + phDnldNfc_RxInfo_t rx_info; + + +}phDnldNfc_sContext_t; + + +/* +################################################################################ +******************** Global and Static Variables Definition ******************** +################################################################################ +*/ + +#ifndef NFC_TIMER_CONTEXT +static phDnldNfc_sContext_t *gpphDnldContext = NULL; +#endif + +#ifdef NXP_FW_DNLD_CHECK_PHASE + +#define NXP_FW_DNLD_COMPLETE_PHASE 0x00U +#define NXP_FW_DNLD_SYSTEM_PHASE 0x01U +#define NXP_FW_DNLD_CFG_PHASE 0x02U +#define NXP_FW_DNLD_DATA_PHASE 0x03U +#define NXP_FW_DNLD_RAW_PHASE 0x04U +#define NXP_FW_DNLD_INVALID_PHASE 0xFFU + +static uint8_t gphDnldPhase = NXP_FW_DNLD_COMPLETE_PHASE; + +#endif /* #ifdef NXP_FW_DNLD_CHECK_PHASE */ + +/**/ + +/* +*************************** Static Function Declaration ************************** +*/ + +STATIC +NFCSTATUS +phDnldNfc_Send_Command( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + uint8_t cmd, + void *params, + uint16_t param_length + ); + +static +NFCSTATUS +phDnldNfc_Process_FW( + phDnldNfc_sContext_t *psDnldContext, + phHal_sHwReference_t *pHwRef +#ifdef NXP_FW_PARAM + , + uint8_t *nxp_nfc_fw, + uint32_t fw_length +#endif + ); + +STATIC +void +phDnldNfc_Send_Complete ( + void *psContext, + void *pHwRef, + phNfc_sTransactionInfo_t *pInfo + ); + +STATIC +void +phDnldNfc_Receive_Complete ( + void *psContext, + void *pHwRef, + phNfc_sTransactionInfo_t *pInfo + ); + +STATIC +NFCSTATUS +phDnldNfc_Process_Response( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + void *pdata, + uint16_t length + ); + + +static +NFCSTATUS +phDnldNfc_Resume( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + void *pdata, + uint16_t length + ); + +static +NFCSTATUS +phDnldNfc_Resume_Write( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef + ); + +static +NFCSTATUS +phDnldNfc_Process_Write( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + section_info_t *p_sec_info, + uint32_t *p_sec_offset + ); + +static +NFCSTATUS +phDnldNfc_Sequence( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + void *pdata, + uint16_t length + ); + +static +NFCSTATUS +phDnldNfc_Upgrade_Sequence( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + void *pdata, + uint16_t length + ); + +STATIC +NFCSTATUS +phDnldNfc_Receive( + void *psContext, + void *pHwRef, + uint8_t *pdata, + uint16_t length + ); + + +STATIC +NFCSTATUS +phDnldNfc_Send ( + void *psContext, + void *pHwRef, + uint8_t *pdata, + uint16_t length + ); + +STATIC +NFCSTATUS +phDnldNfc_Set_Seq( + phDnldNfc_sContext_t *psDnldContext, + phDnldNfc_eSeqType_t seq_type + ); + +static +void +phDnldNfc_Notify( + pphNfcIF_Notification_CB_t p_upper_notify, + void *p_upper_context, + void *pHwRef, + uint8_t type, + void *pInfo + ); + +STATIC +NFCSTATUS +phDnldNfc_Allocate_Resource ( + void **ppBuffer, + uint16_t size + ); + +STATIC +void +phDnldNfc_Release_Resources ( + phDnldNfc_sContext_t **ppsDnldContext + ); + +STATIC +void +phDnldNfc_Release_Lower( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef + ); + + +static +NFCSTATUS +phDnldNfc_Read( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + section_info_t *p_sec_info + ); + +STATIC +void +phDnldNfc_Abort ( + uint32_t abort_id +#ifdef NFC_TIMER_CONTEXT + , void *dnld_cntxt +#endif + ); + + +#ifdef DNLD_CRC_CALC + +static +void +phDnldNfc_UpdateCrc16( + uint8_t crcByte, + uint16_t *pCrc +); + +STATIC +uint16_t +phDnldNfc_ComputeCrc16( + uint8_t *pData, + uint16_t length +); + + +/* +*************************** Function Definitions ************************** +*/ +#define CRC32_POLYNOMIAL 0xEDB88320L + +static uint32_t CRC32Table[0x100]; + +void BuildCRCTable() +{ + unsigned long crc; + uint8_t i = 0, j = 0; + + for ( i = 0; i <= 0xFF ; i++ ) + { + crc = i; + for ( j = 8 ; j> 0; j-- ) + { + if ( crc & 1 ) + { + crc = ( crc>> 1 ) ^ CRC32_POLYNOMIAL; + } + else + { + crc>>= 1; + } + } + CRC32Table[ i ] = crc; + } +} + +/* +* This routine calculates the CRC for a block of data using the +* table lookup method. It accepts an original value for the crc, +* and returns the updated value. +*/ + +uint32_t CalculateCRC32( void *buffer , uint32_t count, uint32_t crc ) +{ + uint8_t *p; + uint32_t temp1; + uint32_t temp2; + + p = (uint8_t *) buffer; + while ( count-- != 0 ) { + temp1 = ( crc>> 8 ) & 0x00FFFFFFL; + temp2 = CRC32Table[ ( (int) crc ^ *p++ ) & 0xff ]; + crc = temp1 ^ temp2; + } + return( crc ); +} + + +static +void +phDnldNfc_UpdateCrc16( + uint8_t crcByte, + uint16_t *pCrc +) +{ + crcByte = (crcByte ^ (uint8_t)((*pCrc) & 0x00FF)); + crcByte = (crcByte ^ (uint8_t)(crcByte << 4)); + *pCrc = (*pCrc >> 8) ^ ((uint16_t)crcByte << 8) ^ + ((uint16_t)crcByte << 3) ^ + ((uint16_t)crcByte >> 4); +} + + +STATIC +uint16_t +phDnldNfc_ComputeCrc16( + uint8_t *pData, + uint16_t length +) +{ + uint8_t crc_byte = 0; + uint16_t index = 0; + uint16_t crc = 0; + +#ifdef CRC_A + crc = 0x6363; /* ITU-V.41 */ +#else + crc = 0xFFFF; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ +#endif /* #ifdef CRC_A */ + + do + { + crc_byte = pData[index]; + phDnldNfc_UpdateCrc16(crc_byte, &crc); + index++; + } while (index < length); + +#ifndef INVERT_CRC + crc = ~crc; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ +#endif /* #ifndef INVERT_CRC */ + +/* *pCrc1 = (uint8_t) (crc & BYTE_MASK); + *pCrc2 = (uint8_t) ((crc >> 8) & BYTE_MASK); */ + return crc ; +} + +#endif /* #ifdef DNLD_CRC_CALC */ + + +/*! + * \brief Allocation of the Download Interface resources. + * + * This function releases and frees all the resources used by Download Mode + * Feature. + */ + +STATIC +NFCSTATUS +phDnldNfc_Allocate_Resource ( + void **ppBuffer, + uint16_t size + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + *ppBuffer = (void *) phOsalNfc_GetMemory(size); + if( *ppBuffer != NULL ) + { + (void )memset(((void *)*ppBuffer), 0, + size); + } + else + { + *ppBuffer = NULL; + status = PHNFCSTVAL(CID_NFC_DNLD, + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + return status; +} + + +/*! + * \brief Release of the Download Interface resources. + * + * This function releases and frees all the resources used by Download layer. + */ + +STATIC +void +phDnldNfc_Release_Resources ( + phDnldNfc_sContext_t **ppsDnldContext + ) +{ + + if(NULL != (*ppsDnldContext)->p_resp_buffer) + { + phOsalNfc_FreeMemory((*ppsDnldContext)->p_resp_buffer); + (*ppsDnldContext)->p_resp_buffer = NULL; + } + if(NULL != (*ppsDnldContext)->dnld_store.buffer) + { + phOsalNfc_FreeMemory((*ppsDnldContext)->dnld_store.buffer); + (*ppsDnldContext)->dnld_store.buffer = NULL; + (*ppsDnldContext)->dnld_store.length = 0; + } + if(NULL != (*ppsDnldContext)->trim_store.buffer) + { + phOsalNfc_FreeMemory((*ppsDnldContext)->trim_store.buffer); + (*ppsDnldContext)->trim_store.buffer = NULL; + (*ppsDnldContext)->trim_store.length = 0; + } + if(NULL != (*ppsDnldContext)->p_fw_sec) + { + phOsalNfc_FreeMemory((*ppsDnldContext)->p_fw_sec); + (*ppsDnldContext)->p_fw_sec = NULL; + } + if ( NXP_INVALID_TIMER_ID != (*ppsDnldContext)->timer_id ) + { + phOsalNfc_Timer_Stop((*ppsDnldContext)->timer_id ); + phOsalNfc_Timer_Delete((*ppsDnldContext)->timer_id ); + (*ppsDnldContext)->timer_id = NXP_INVALID_TIMER_ID; + } + + phOsalNfc_FreeMemory((*ppsDnldContext)); + (*ppsDnldContext) = NULL; + + return ; +} + + +STATIC +void +phDnldNfc_Release_Lower( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef + ) +{ + phNfc_sLowerIF_t *plower_if = + &(psDnldContext->lower_interface); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + PHNFC_UNUSED_VARIABLE(status); + + if(NULL != plower_if->release) + { +#ifdef DNLD_LOWER_RELEASE + status = plower_if->release((void *)plower_if->pcontext, + (void *)pHwRef); +#else + PHNFC_UNUSED_VARIABLE(pHwRef); + +#endif + (void)memset((void *)plower_if, + 0, sizeof(phNfc_sLowerIF_t)); + DNLD_DEBUG(" FW_DNLD: Releasing the Lower Layer Resources: Status = %02X\n" + ,status); + } + + return; +} + + + +static +void +phDnldNfc_Notify( + pphNfcIF_Notification_CB_t p_upper_notify, + void *p_upper_context, + void *pHwRef, + uint8_t type, + void *pInfo + ) +{ + if( ( NULL != p_upper_notify) ) + { + /* Notify the to the Upper Layer */ + (p_upper_notify)(p_upper_context, pHwRef, type, pInfo); + } +} + + +STATIC +NFCSTATUS +phDnldNfc_Set_Seq( + phDnldNfc_sContext_t *psDnldContext, + phDnldNfc_eSeqType_t seq_type + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t prev_temp_state = 0; + static uint8_t prev_temp_seq = + (uint8_t) phDnld_Activate_Patch; + + switch(seq_type) + { + case DNLD_SEQ_RESET: + case DNLD_SEQ_INIT: + { + psDnldContext->cur_dnld_state = + (uint8_t) phDnld_Reset_State; + psDnldContext->next_dnld_state = + (uint8_t)phDnld_Upgrade_State; + psDnldContext->cur_dnld_seq = + (uint8_t)phDnld_Upgrade_Section; + psDnldContext->next_dnld_seq = + psDnldContext->cur_dnld_seq; + break; + } + case DNLD_SEQ_RAW: + { + psDnldContext->cur_dnld_state = + (uint8_t) phDnld_Reset_State; + psDnldContext->next_dnld_state = + (uint8_t)phDnld_Upgrade_State; + psDnldContext->cur_dnld_seq = + (uint8_t)phDnld_Raw_Upgrade; + psDnldContext->next_dnld_seq = + psDnldContext->cur_dnld_seq; + break; + } + case DNLD_SEQ_UNLOCK: + { + psDnldContext->cur_dnld_state = + (uint8_t) phDnld_Reset_State; + +#ifdef NXP_FW_DNLD_CHECK_PHASE + if( NXP_FW_DNLD_SYSTEM_PHASE < gphDnldPhase ) + { + psDnldContext->next_dnld_state = + (uint8_t)phDnld_Upgrade_State; + psDnldContext->cur_dnld_seq = + (uint8_t)phDnld_Upgrade_Section; + } + else +#endif /* NXP_FW_DNLD_CHECK_PHASE */ + { + psDnldContext->next_dnld_state = + (uint8_t) phDnld_Unlock_State; + psDnldContext->cur_dnld_seq = + (uint8_t) phDnld_Activate_Patch; + } + psDnldContext->next_dnld_seq = + psDnldContext->cur_dnld_seq; + break; + } + case DNLD_SEQ_LOCK: + { + psDnldContext->cur_dnld_state = + (uint8_t) phDnld_Reset_State; + psDnldContext->next_dnld_state = + (uint8_t) phDnld_Reset_State; + psDnldContext->cur_dnld_seq = + (uint8_t) phDnld_Lock_System; + psDnldContext->next_dnld_seq = + psDnldContext->cur_dnld_seq; + break; + } + case DNLD_SEQ_UPDATE: + { + prev_temp_state = (uint8_t) psDnldContext->cur_dnld_state; + psDnldContext->cur_dnld_state = + psDnldContext->next_dnld_state; + /* psDnldContext->next_dnld_state = + (uint8_t)phDnld_Invalid_State ; */ + prev_temp_seq = (uint8_t) psDnldContext->cur_dnld_seq; + psDnldContext->cur_dnld_seq = + psDnldContext->next_dnld_seq; + break; + } + case DNLD_SEQ_ROLLBACK: + { + psDnldContext->cur_dnld_seq = (uint8_t) prev_temp_seq; + psDnldContext->next_dnld_seq = + (uint8_t)phDnld_Invalid_Seq ; + prev_temp_seq = 0; + + psDnldContext->cur_dnld_state = (uint8_t) prev_temp_state; + /* psDnldContext->next_dnld_state = + (uint8_t)phDnld_Invalid_State ; */ + prev_temp_state = 0; + break; + } + case DNLD_SEQ_COMPLETE: + { + psDnldContext->cur_dnld_state = + (uint8_t) phDnld_Reset_State; + psDnldContext->next_dnld_state = + (uint8_t) phDnld_Verify_State; + psDnldContext->cur_dnld_seq = + (uint8_t) phDnld_Verify_Integrity; + psDnldContext->next_dnld_seq = + psDnldContext->cur_dnld_seq ; + break; + } + default: + { + break; + } + } + + return status; +} + + + +/*! + * \brief Sends the data the corresponding peripheral device. + * + * This function sends the Download data to the connected NFC Pheripheral device + */ + + + STATIC + NFCSTATUS + phDnldNfc_Send ( + void *psContext, + void *pHwRef, + uint8_t *pdata, + uint16_t length + ) +{ + phDnldNfc_sContext_t *psDnldContext= (phDnldNfc_sContext_t *)psContext; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + phNfc_sLowerIF_t *plower_if = &(psDnldContext->lower_interface); + + if( (NULL != plower_if) + && (NULL != plower_if->send) + ) + { +#ifndef DNLD_SUMMARY + DNLD_PRINT_BUFFER("Send Buffer",pdata,length); +#endif + status = plower_if->send((void *)plower_if->pcontext, + (void *)pHwRef, pdata, length); + +#if defined(FW_DOWNLOAD_TIMER) && \ + (FW_DOWNLOAD_TIMER == 2) + if ( + (NFCSTATUS_PENDING == status) + && ( NXP_INVALID_TIMER_ID != psDnldContext->timer_id ) + ) + { + psDnldContext->dnld_timeout = NXP_DNLD_COMPLETE_TIMEOUT; + + if ( psDnldContext->dnld_timeout + < DNLD_DEFAULT_RESPONSE_TIMEOUT) + { + psDnldContext->dnld_timeout + = DNLD_DEFAULT_RESPONSE_TIMEOUT; + } + /* Start the Download Timer */ + phOsalNfc_Timer_Start( psDnldContext->timer_id, + psDnldContext->dnld_timeout, + (ppCallBck_t) phDnldNfc_Abort +#ifdef NFC_TIMER_CONTEXT + , (void *) psDnldContext +#endif + ); + + DNLD_DEBUG(" DNLD : Timer %X Started ", psDnldContext->timer_id); + DNLD_DEBUG(" \t\t With %U Timeout \n", psDnldContext->dnld_timeout); + } + +#endif /* (NXP_NFC_DNLD_TIMER == 1) */ + } + + return status; +} + + +/*! + * \brief Receives the Download Mode Response from the corresponding peripheral device. + * + * This function receives the Download Command Response to the connected NFC + * Pheripheral device. + */ + +STATIC +NFCSTATUS +phDnldNfc_Receive( + void *psContext, + void *pHwRef, + uint8_t *pdata, + uint16_t length + ) +{ + phDnldNfc_sContext_t *psDnldContext= (phDnldNfc_sContext_t *)psContext; + phNfc_sLowerIF_t *plower_if = NULL ; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if(NULL == psDnldContext ) + { + status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } + else + { + plower_if = &(psDnldContext->lower_interface); + + if( (NULL != plower_if) + && (NULL != plower_if->receive) + ) + { + status = plower_if->receive((void *)plower_if->pcontext, + (void *)pHwRef, pdata, length); + } + } + return status; +} + + +static +NFCSTATUS +phDnldNfc_Read( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + section_info_t *p_sec_info + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phDnldNfc_sData_t *p_dnld_data = + (phDnldNfc_sData_t *)psDnldContext->dnld_data; + phDnldNfc_sParam_t *p_data_param = + &p_dnld_data->param_info.data_param; + uint32_t read_addr = (p_sec_info->p_sec_hdr->section_address + + p_sec_info->section_offset); + static unsigned sec_type = 0; + uint8_t i = 0; + uint16_t read_size = 0 ; + + sec_type = (unsigned int)p_sec_info->p_sec_hdr->section_mem_type; + + if( ( FALSE == p_sec_info->section_read ) + && ((sec_type & DNLD_TRIM_MASK)) + && (FALSE == p_sec_info->trim_write) ) + { + read_size = (uint16_t) p_sec_info->p_sec_hdr->section_length; + DNLD_DEBUG(" FW_DNLD: Section Read = %X \n", read_size); + } + else + { + if (( FALSE == p_sec_info->section_read ) + && ((sec_type & DNLD_VERIFY_MASK)) + ) + { + read_size = (uint16_t)(psDnldContext->prev_dnld_size ); + DNLD_DEBUG(" FW_DNLD: Section Read = %X \n", read_size); + } + else if( ( TRUE == p_sec_info->section_read ) + && ( TRUE == p_sec_info->section_write ) + ) + { + /*Already Read the Data Hence Ignore the Read */ + DNLD_DEBUG(" FW_DNLD: Already Read, Read Ignored, read_size = %X \n", read_size); + } + else + { + /* Ignore the Read */ + DNLD_DEBUG(" FW_DNLD: Section Read Status = %X \n", p_sec_info->section_read); + DNLD_DEBUG(" FW_DNLD: Section Write Status = %X \n", p_sec_info->section_write); + DNLD_DEBUG(" FW_DNLD: No Read Required, Read_size = %X \n", read_size); + } + } + + if (read_size != 0) + { + + read_size = (uint16_t)((PHDNLD_DATA_SIZE >= read_size)? + read_size: PHDNLD_DATA_SIZE); + + p_dnld_data->frame_length[i] = (uint8_t)0; + /* Update the LSB of the Data and the Address Parameter*/ + p_data_param->data_addr[i] = (uint8_t)((read_addr >> + (BYTE_SIZE + BYTE_SIZE)) & BYTE_MASK); + p_data_param->data_len[i] = (uint8_t)((read_size >> + BYTE_SIZE) & BYTE_MASK); + i++; + + p_dnld_data->frame_length[i] = (uint8_t) + ( PHDNLD_CMD_READ_LEN & BYTE_MASK); + /* Update the 2nd byte of the Data and the Address Parameter*/ + p_data_param->data_addr[i] = (uint8_t)((read_addr >> + BYTE_SIZE) & BYTE_MASK); + p_data_param->data_len[i] = (uint8_t) (read_size & BYTE_MASK); + i++; + + /* Update the 3rd byte of the the Address Parameter*/ + p_data_param->data_addr[i] = (uint8_t)(read_addr & BYTE_MASK); + + status = phDnldNfc_Send_Command( psDnldContext, pHwRef, + PHDNLD_CMD_READ, NULL , 0 ); + + if ( NFCSTATUS_PENDING == status ) + { + p_sec_info->section_read = TRUE ; + psDnldContext->next_dnld_state = phDnld_Upgrade_State; + DNLD_DEBUG(" FW_DNLD: Memory Read at Address %X : ", read_addr); + DNLD_DEBUG(" of Size %X \n", read_size); + } + + } + return status; +} + + + +static +NFCSTATUS +phDnldNfc_Process_Write( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + section_info_t *p_sec_info, + uint32_t *p_sec_offset + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phDnldNfc_sData_t *p_dnld_data = + (phDnldNfc_sData_t *)psDnldContext->dnld_data; + phDnldNfc_sParam_t *dnld_data = + &p_dnld_data->param_info.data_param; + uint8_t *p_sm_trim_data = (uint8_t *)psDnldContext-> + dnld_resp.param_info.response_data; + uint32_t dnld_addr = 0; +#ifdef NXP_FW_SW_VMID_TRIM + uint32_t trim_addr = 0; +#endif /* #ifdef NXP_FW_SW_VMID_TRIM */ + static unsigned sec_type = 0; + uint8_t i = 0; + uint16_t dnld_size = 0; + int cmp_val = 0x00; + + + sec_type = (unsigned int)p_sec_info->p_sec_hdr->section_mem_type; + + status = phDnldNfc_Read(psDnldContext, pHwRef, p_sec_info); + if( NFCSTATUS_PENDING != status ) + { + if( (TRUE == p_sec_info->trim_write) + && (TRUE == p_sec_info->section_read) + && ((sec_type & DNLD_VERIFY_MASK)) + ) + { + if(NULL != psDnldContext->trim_store.buffer) + { + uint32_t trim_cmp_size = psDnldContext->prev_dnld_size; + + if( p_sec_info->p_sec_hdr->section_address + < (DNLD_CFG_PG_ADDR + PHDNLD_PAGE_SIZE) ) + { + trim_cmp_size = trim_cmp_size - 2; + } + + /* Below Comparison fails due to the checksum */ + cmp_val = phOsalNfc_MemCompare( + psDnldContext->trim_store.buffer, + &psDnldContext->dnld_resp. + param_info.response_data[0] + ,trim_cmp_size); + DNLD_DEBUG(" FW_DNLD: %X Bytes Trim Write Complete ", + psDnldContext->prev_dnld_size); + DNLD_DEBUG(" Comparison Status %X\n", cmp_val); + } + p_sec_info->trim_write = FALSE; + DNLD_DEBUG(" FW_DNLD: TRIMMED %X Bytes Write Complete\n", psDnldContext->prev_dnld_size); + } + else + { + if((NULL != psDnldContext->dnld_store.buffer) + && ((sec_type & DNLD_VERIFY_MASK)) + && (TRUE == p_sec_info->section_write) + && (TRUE == p_sec_info->section_read) + ) + { + cmp_val = phOsalNfc_MemCompare( + psDnldContext->dnld_store.buffer, + &psDnldContext->dnld_resp. + param_info.response_data[0] + ,psDnldContext->dnld_store.length); + p_sec_info->section_read = FALSE; + p_sec_info->section_write = FALSE; + DNLD_DEBUG(" FW_DNLD: %X Bytes Write Complete ", + psDnldContext->dnld_store.length); + DNLD_DEBUG(" Comparison Status %X\n", cmp_val); + } + else + { + if(( TRUE == p_sec_info->section_write) + && ( FALSE == p_sec_info->section_read) + ) + { + p_sec_info->section_write = FALSE; + } + } + /* p_sec_info->section_read = FALSE; */ + } + + if (( 0 == psDnldContext->dnld_retry ) + && (0 == cmp_val) + ) + { + p_sec_info->sec_verify_retry = 0; + p_sec_info->section_offset = p_sec_info->section_offset + + psDnldContext->prev_dnld_size; + psDnldContext->prev_dnld_size = 0; + DNLD_DEBUG(" FW_DNLD: Memory Write Retry - %X \n", + psDnldContext->dnld_retry); + } + else + { + p_sec_info->sec_verify_retry++; + DNLD_DEBUG(" FW_DNLD: Memory Verification Failed, Retry = %X \n", + p_sec_info->sec_verify_retry); + } + + if( p_sec_info->sec_verify_retry < NXP_MAX_SECTION_WRITE ) + { + + dnld_addr = (p_sec_info->p_sec_hdr->section_address + *p_sec_offset); + dnld_size = (uint16_t)(p_sec_info->p_sec_hdr->section_length + - *p_sec_offset); + } + else + { + status = NFCSTATUS_FAILED; + DNLD_DEBUG(" FW_DNLD: Memory Verification - Maximum Limit, Retry = %X \n", + p_sec_info->sec_verify_retry); + } + } + + + if (dnld_size != 0) + { + + dnld_size = (uint16_t)((PHDNLD_DATA_SIZE >= dnld_size)? + dnld_size: PHDNLD_DATA_SIZE); + + /* Update the LSB of the Data and the Address Parameter*/ + dnld_data->data_addr[i] = (uint8_t)((dnld_addr >> + (BYTE_SIZE + BYTE_SIZE)) & BYTE_MASK); + dnld_data->data_len[i] = (uint8_t)((dnld_size >> BYTE_SIZE) + & BYTE_MASK); + p_dnld_data->frame_length[i] = (uint8_t) + (((dnld_size + PHDNLD_CMD_WRITE_MIN_LEN) >> BYTE_SIZE) + & BYTE_MASK); + i++; + /* Update the 2nd byte of the Data and the Address Parameter*/ + dnld_data->data_addr[i] = (uint8_t)((dnld_addr >> BYTE_SIZE) + & BYTE_MASK); + dnld_data->data_len[i] = (uint8_t) (dnld_size & BYTE_MASK); + p_dnld_data->frame_length[i] = (uint8_t) ((dnld_size + + PHDNLD_CMD_WRITE_MIN_LEN) & BYTE_MASK); + i++; + /* Update the 3rd byte of the the Address Parameter*/ + dnld_data->data_addr[i] = (uint8_t)(dnld_addr & BYTE_MASK); + + (void)memcpy( dnld_data->data_packet, + (p_sec_info->p_sec_data + *p_sec_offset), dnld_size ); + + if( ((sec_type & DNLD_TRIM_MASK)) + && (p_sec_info->sec_verify_retry != 0) + && (NULL != psDnldContext->trim_store.buffer) + ) + { + (void)memcpy( dnld_data->data_packet, + psDnldContext->trim_store.buffer, dnld_size ); + } + else if(((sec_type & DNLD_TRIM_MASK)) + && ( TRUE == p_sec_info->section_read ) + ) + { + for(i = 0; i < *(p_sec_info->p_trim_data);i++) + { + +#ifdef NXP_FW_SW_VMID_TRIM + +/* +if(bit 0 of 0x813D is equal to 1) then + + Do not overwrite 0x9931 / 0x9981 during download + +else + + @0x9931 = 0x79 // card Mode + @0x9981 = 0x79 // Reader Mode +*/ + trim_addr = p_sec_info->p_sec_hdr->section_address + + p_sec_info->p_trim_data[i+1]; + if (NXP_FW_VMID_TRIM_CHK_ADDR == trim_addr) + { + psDnldContext->vmid_trim_update = + p_sm_trim_data[p_sec_info->p_trim_data[i+1]] ; + } + + if((NXP_FW_VMID_CARD_MODE_ADDR == trim_addr) + || (NXP_FW_VMID_RD_MODE_ADDR == trim_addr)) + { + if (TRUE == psDnldContext->vmid_trim_update) + { + dnld_data->data_packet[p_sec_info->p_trim_data[i+1]] = + p_sm_trim_data[p_sec_info->p_trim_data[i+1]] ; + } + } + else + +#endif + { + dnld_data->data_packet[p_sec_info->p_trim_data[i+1]] = + p_sm_trim_data[p_sec_info->p_trim_data[i+1]] ; + } + } + if(NULL != psDnldContext->trim_store.buffer) + { + phOsalNfc_FreeMemory(psDnldContext->trim_store.buffer); + psDnldContext->trim_store.buffer = NULL; + psDnldContext->trim_store.length = 0; + } +#if 1 + (void) + phDnldNfc_Allocate_Resource((void **) + &(psDnldContext->trim_store.buffer),dnld_size); +#else + psDnldContext->trim_store.buffer = + (uint8_t *) phOsalNfc_GetMemory(dnld_size); +#endif + + if(NULL != psDnldContext->trim_store.buffer) + { + (void )memset((void *)psDnldContext->trim_store.buffer,0, + dnld_size); + (void)memcpy( psDnldContext->trim_store.buffer, + dnld_data->data_packet, dnld_size ); + psDnldContext->trim_store.length = dnld_size; + DNLD_DEBUG(" FW_DNLD: Write with Trimming at Address %X ", dnld_addr ); + DNLD_DEBUG(" of Size %X and ", dnld_size ); + DNLD_DEBUG(" with %X Trimming Values \n", *(p_sec_info->p_trim_data) ); + + } + } + else + { + if(NULL != psDnldContext->dnld_store.buffer) + { + phOsalNfc_FreeMemory(psDnldContext->dnld_store.buffer); + psDnldContext->dnld_store.buffer = NULL; + psDnldContext->dnld_store.length = 0; + } +#if 1 + (void) + phDnldNfc_Allocate_Resource((void **) + &(psDnldContext->dnld_store.buffer),dnld_size); +#else + psDnldContext->dnld_store.buffer = + (uint8_t *) phOsalNfc_GetMemory(dnld_size); +#endif + if(NULL != psDnldContext->dnld_store.buffer) + { + (void )memset((void *)psDnldContext->dnld_store.buffer,0, + dnld_size); + (void)memcpy( psDnldContext->dnld_store.buffer, + dnld_data->data_packet, dnld_size ); + psDnldContext->dnld_store.length = dnld_size; + DNLD_DEBUG(" FW_DNLD: Memory Write at Address %X ", dnld_addr ); + DNLD_DEBUG(" of Size %X ", dnld_size ); + } + } + + if(PHDNLD_FW_PATCH_SEC != psDnldContext->p_fw_hdr->fw_patch) + { + status = phDnldNfc_Send_Command( psDnldContext, pHwRef, + PHDNLD_CMD_WRITE, NULL , 0 ); + } + else + { + status = phDnldNfc_Send_Command( psDnldContext, pHwRef, + PHDNLD_CMD_SEC_WRITE, NULL , 0 ); + } + + DNLD_DEBUG(" FW_DNLD: Memory Write Status = %X \n", status); + if ( NFCSTATUS_PENDING == status ) + { + psDnldContext->prev_dnld_size = dnld_size; + cmp_val = 0x00; + if((sec_type & DNLD_TRIM_MASK)) + { + p_sec_info->trim_write = TRUE; + DNLD_DEBUG(" FW_DNLD: Bytes Downloaded (Trimming Values) = %X Bytes \n", + dnld_size); + } + else + { + p_sec_info->section_write = TRUE; + DNLD_DEBUG(" FW_DNLD: Bytes Downloaded = %X : ", + (*p_sec_offset + dnld_size)); + DNLD_DEBUG(" Bytes Remaining = %X \n", + (p_sec_info->p_sec_hdr->section_length - + (*p_sec_offset + dnld_size))); + } + + p_sec_info->section_read = FALSE; + } + } + return status; +} + + + +static +NFCSTATUS +phDnldNfc_Resume_Write( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t sec_index = psDnldContext->section_index; + section_info_t *p_sec_info = (psDnldContext->p_fw_sec + sec_index); + + while((sec_index < psDnldContext->p_fw_hdr->no_of_sections) + && (NFCSTATUS_SUCCESS == status ) + ) + { + + status = phDnldNfc_Process_Write(psDnldContext, pHwRef, + p_sec_info, (uint32_t *)&(p_sec_info->section_offset)); + if (NFCSTATUS_SUCCESS == status) + { + unsigned sec_type = 0; + sec_type = (unsigned int)p_sec_info->p_sec_hdr->section_mem_type; + + p_sec_info->section_offset = 0; + p_sec_info->section_read = FALSE; + p_sec_info->section_write = FALSE; + p_sec_info->trim_write = FALSE; + + DNLD_DEBUG(" FW_DNLD: Section %02X Download Complete\n", sec_index); + if((sec_type & DNLD_RESET_MASK)) + { + DNLD_DEBUG(" FW_DNLD: Reset After Section %02X Download \n", sec_index); + status = phDnldNfc_Send_Command( psDnldContext, pHwRef, + PHDNLD_CMD_RESET , NULL, 0 ); + } + DNLD_PRINT("*******************************************\n\n"); + + sec_index++; + +#ifdef NXP_FW_DNLD_CHECK_PHASE + if( p_sec_info->p_sec_hdr->section_address + < (DNLD_CFG_PG_ADDR + PHDNLD_PAGE_SIZE) ) + { + gphDnldPhase = NXP_FW_DNLD_DATA_PHASE; + + } + + p_sec_info = (psDnldContext->p_fw_sec + sec_index); + + if( (sec_index < psDnldContext->p_fw_hdr->no_of_sections) + && ( p_sec_info->p_sec_hdr->section_address + < (DNLD_CFG_PG_ADDR + PHDNLD_PAGE_SIZE) ) + ) + { + if( NXP_FW_DNLD_CFG_PHASE >= gphDnldPhase ) + { + gphDnldPhase = NXP_FW_DNLD_CFG_PHASE; + } + else + { + sec_index++; + p_sec_info = (psDnldContext->p_fw_sec + sec_index); + } + } +#else + p_sec_info = (psDnldContext->p_fw_sec + sec_index); +#endif /* #ifdef NXP_FW_DNLD_CHECK_PHASE */ + + psDnldContext->section_index = sec_index; + /* psDnldContext->next_dnld_state = (uint8_t) phDnld_Upgrade_State; */ + } + } + if (NFCSTATUS_PENDING == status) + { + psDnldContext->next_dnld_state = (uint8_t) phDnld_Upgrade_State; + } + else if (NFCSTATUS_SUCCESS == status) + { + /* Reset the PN544 Device */ + psDnldContext->next_dnld_state = (uint8_t) phDnld_Complete_State; + } + else + { + + } + return status; +} + + +#define NXP_DNLD_SM_UNLOCK_ADDR 0x008002U + +#if !defined (ES_HW_VER) +#define ES_HW_VER 32 +#endif + +#if (ES_HW_VER <= 30) +#define NXP_DNLD_PATCH_ADDR 0x01AFFFU +#else +#define NXP_DNLD_PATCH_ADDR 0x01A1E0U +#endif + +#if (ES_HW_VER <= 30) +#define NXP_DNLD_PATCH_TABLE_ADDR 0x008107U +#else +#define NXP_DNLD_PATCH_TABLE_ADDR 0x00825AU +#endif + + +static +NFCSTATUS +phDnldNfc_Sequence( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + void *pdata, + uint16_t length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint32_t dnld_addr = 0; + phDnldNfc_sData_t *p_dnld_data = + (phDnldNfc_sData_t *)psDnldContext->dnld_data; + phDnldNfc_sParam_t *p_data_param = + & p_dnld_data->param_info.data_param; + uint8_t *p_data = NULL; + static uint32_t patch_size = 0; + +#if (ES_HW_VER == 32) + + static uint8_t patch_table[] = {0xA0, 0xA1, 0xE0, 0x80, 0xA9, 0x6C }; + static uint8_t patch_data[] = {0xA5, 0xD0, 0xFE, 0xA5, 0xD0, 0xFD, 0xA5, + 0xD0, 0xFC, 0xA5, 0x02, 0x80, 0xA9, 0x75}; + +#elif (ES_HW_VER == 31) + + static uint8_t patch_table[] = {0xA0, 0xAF, 0xE0, 0x80, 0x78, 0x84 }; + static uint8_t patch_data[] = {0xA5, 0xD0, 0xFE, 0xA5, 0xD0, 0xFD, 0xA5, + 0xD0, 0xFC, 0xD0, 0xE0, 0xA5, 0x02, 0x80, 0x78, 0x8D}; + +#elif (ES_HW_VER == 30) + + static uint8_t patch_table[] = {0x80, 0x91, 0x51, 0xA0, 0xAF, + 0xFF, 0x80, 0x91, 0x5A}; + static uint8_t patch_data[] = {0x22}; + +#endif + + static uint8_t unlock_data[] = {0x00, 0x00}; + static uint8_t lock_data[] = {0x0C, 0x00}; + + uint8_t i = 0; + + PHNFC_UNUSED_VARIABLE(pdata); + PHNFC_UNUSED_VARIABLE(length); + switch(psDnldContext->cur_dnld_seq) + { + case phDnld_Reset_Seq: + { + status = phDnldNfc_Send_Command( psDnldContext, pHwRef, + PHDNLD_CMD_RESET , NULL , 0 ); + /* status = (NFCSTATUS_PENDING == status)? NFCSTATUS_SUCCESS: + status; */ + DNLD_DEBUG(" FW_DNLD: Reset Seq.. Status = %X \n", status); + + break; + } + case phDnld_Activate_Patch: + { + uint8_t patch_activate = 0x01; + psDnldContext->next_dnld_seq = + (uint8_t)phDnld_Update_Patch; +#ifdef NXP_FW_DNLD_CHECK_PHASE + gphDnldPhase = NXP_FW_DNLD_SYSTEM_PHASE; +#endif /* NXP_FW_DNLD_CHECK_PHASE */ + + status = phDnldNfc_Send_Command( psDnldContext, pHwRef, + PHDNLD_CMD_ACTIVATE_PATCH , &patch_activate, sizeof(patch_activate) ); + DNLD_PRINT(" FW_DNLD: Activate the Patch Update .... \n"); + break; + } + case phDnld_Deactivate_Patch: + { + uint8_t patch_activate = 0x00; + + psDnldContext->next_dnld_state = + (uint8_t)phDnld_Reset_State; + + status = phDnldNfc_Send_Command( psDnldContext, pHwRef, + PHDNLD_CMD_ACTIVATE_PATCH , &patch_activate, sizeof(patch_activate) ); + DNLD_PRINT(" FW_DNLD: Deactivate the Patch Update .... \n"); + break; + } + case phDnld_Update_Patch: + { + dnld_addr = NXP_DNLD_PATCH_ADDR; + patch_size = sizeof(patch_data) ; + p_data = patch_data; + psDnldContext->next_dnld_seq = + (uint8_t)phDnld_Update_Patchtable; + DNLD_PRINT(" FW_DNLD: Patch Update Seq.... \n"); + break; + } + case phDnld_Update_Patchtable: + { + dnld_addr = NXP_DNLD_PATCH_TABLE_ADDR; + patch_size = sizeof(patch_table) ; + p_data = patch_table; + + psDnldContext->next_dnld_state = + (uint8_t)phDnld_Reset_State; + + DNLD_PRINT(" FW_DNLD: Patch Table Update Seq.... \n"); + break; + } + case phDnld_Unlock_System: + { + dnld_addr = NXP_DNLD_SM_UNLOCK_ADDR; + patch_size = sizeof(unlock_data) ; + p_data = unlock_data; +#define NXP_FW_PATCH_DISABLE +#ifdef NXP_FW_PATCH_DISABLE + psDnldContext->next_dnld_seq = + (uint8_t)phDnld_Deactivate_Patch; +#else + psDnldContext->next_dnld_state = + (uint8_t)phDnld_Reset_State; +#endif + + DNLD_PRINT(" FW_DNLD: System Memory Unlock Seq.... \n"); + break; + } + case phDnld_Lock_System: + { + dnld_addr = NXP_DNLD_SM_UNLOCK_ADDR; + patch_size = sizeof(lock_data) ; + p_data = lock_data; + psDnldContext->next_dnld_state = + (uint8_t) phDnld_Reset_State; + + DNLD_PRINT(" FW_DNLD: System Memory Lock Seq.... \n"); + break; + } + case phDnld_Upgrade_Section: + { + status = phDnldNfc_Resume_Write( + psDnldContext, pHwRef ); + break; + } + case phDnld_Verify_Integrity: + { + psDnldContext->next_dnld_state = + (uint8_t) phDnld_Reset_State; + + status = phDnldNfc_Send_Command( psDnldContext, pHwRef, + PHDNLD_CMD_CHECK_INTEGRITY , NULL, 0 ); + DNLD_PRINT(" FW_DNLD: System Memory Integrity Check Sequence.... \n"); + break; + } + case phDnld_Verify_Section: + { + break; + } + default: + { + break; + } + } + + if( NFCSTATUS_SUCCESS == status) + { + + /* Update the LSB of the Data and the Address Parameter*/ + p_data_param->data_addr[i] = (uint8_t)((dnld_addr >> + (BYTE_SIZE + BYTE_SIZE)) + & BYTE_MASK); + p_data_param->data_len[i] = (uint8_t)((patch_size >> BYTE_SIZE) + & BYTE_MASK); + p_dnld_data->frame_length[i] = (uint8_t) + (((patch_size + PHDNLD_CMD_WRITE_MIN_LEN) >> BYTE_SIZE) + & BYTE_MASK); + i++; + /* Update the 2nd byte of the Data and the Address Parameter*/ + p_data_param->data_addr[i] = (uint8_t)((dnld_addr >> BYTE_SIZE) + & BYTE_MASK); + p_data_param->data_len[i] = (uint8_t) (patch_size & BYTE_MASK); + p_dnld_data->frame_length[i] = (uint8_t) + ((patch_size + PHDNLD_CMD_WRITE_MIN_LEN) + & BYTE_MASK); + i++; + /* Update the 3rd byte of the the Address Parameter*/ + p_data_param->data_addr[i] = (uint8_t)(dnld_addr & BYTE_MASK); + + status = phDnldNfc_Send_Command( psDnldContext, pHwRef, + PHDNLD_CMD_WRITE,(void *)p_data , (uint8_t)patch_size ); + + if (NFCSTATUS_PENDING != status) + { + status = phDnldNfc_Set_Seq(psDnldContext, + DNLD_SEQ_ROLLBACK); + } + } + return status; +} + +#define FRAME_HEADER_LEN 0x03U + + +static +void +phDnldNfc_Tx_Reset(phDnldNfc_sContext_t *psDnldContext) +{ + psDnldContext->tx_info.transmit_frame = NULL; + psDnldContext->tx_info.tx_total = 0x00; + psDnldContext->tx_info.tx_offset = 0x00; + psDnldContext->tx_info.tx_len = 0x00; + psDnldContext->tx_info.tx_chain = FALSE; +} + +STATIC +bool_t +phDnldNfc_Extract_Chunks( + uint8_t *frame_data, + uint16_t frame_offset, + uint16_t frame_length, + uint16_t max_frame , + uint16_t *chunk_length + ); + + +STATIC +bool_t +phDnldNfc_Extract_Chunks( + uint8_t *frame_data, + uint16_t frame_offset, + uint16_t frame_length, + uint16_t max_frame , + uint16_t *chunk_length + ) +{ + bool_t chunk_present = FALSE; + + if( 0 == frame_offset) + { + if( max_frame >= (frame_length + - frame_offset)) + { + *chunk_length = (frame_length - frame_offset); + } + else + { + *chunk_length = max_frame + - FRAME_HEADER_LEN; + chunk_present = TRUE; + } + } + else + { + if( max_frame >= (frame_length + - frame_offset)) + { + *chunk_length = (frame_length - frame_offset); + } + else + { + *chunk_length = max_frame + - FRAME_HEADER_LEN; + chunk_present = TRUE; + } + } + + return chunk_present; +} + + +STATIC +NFCSTATUS +phDnldNfc_Send_Raw( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + uint8_t *raw_frame, + uint16_t frame_offset, + uint16_t frame_length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phDnldNfc_sRawHdr_t *raw_frame_hdr = ( phDnldNfc_sRawHdr_t * ) raw_frame; + + switch(raw_frame_hdr->frame_type) + { + case PHDNLD_CMD_RESET: + { + break; + } + case PHDNLD_CMD_READ: + { + /* TODO: To Update the length and the buffer to receive data */ + break; + } + case PHDNLD_CMD_WRITE: + { + psDnldContext->resp_length = PHDNLD_MIN_PACKET; + + break; + } + case PHDNLD_CMD_SEC_WRITE: + { + uint16_t tx_length = 0x00; + uint16_t frame_offset = + psDnldContext->tx_info.tx_offset; + uint16_t chain = + psDnldContext->tx_info.tx_chain; + + chain = + phDnldNfc_Extract_Chunks( + raw_frame, + frame_offset, + frame_length, + PHDNLD_FW_TX_RX_LEN, + &tx_length + ); + + if( TRUE == chain ) + { + status = phDnldNfc_Send_Command( psDnldContext, + pHwRef, PHDNLD_CMD_ENCAPSULATE, + (raw_frame + frame_offset), + tx_length); + if(NFCSTATUS_PENDING == status) + { + psDnldContext->prev_cmd = raw_frame_hdr->frame_type; + /* TODO: Update for the Chaining */ + psDnldContext->tx_info.tx_offset += tx_length; + psDnldContext->tx_info.tx_chain = chain; + } + } + else if (0 != frame_offset) + { + status = phDnldNfc_Send_Command( psDnldContext, + pHwRef, PHDNLD_CMD_ENCAPSULATE, + (raw_frame + frame_offset), + tx_length); + if(NFCSTATUS_PENDING == status) + { + psDnldContext->prev_cmd = raw_frame_hdr->frame_type; + /* TODO: Update for the Chaining */ + psDnldContext->prev_dnld_size = frame_length; + phDnldNfc_Tx_Reset(psDnldContext); + } + } + else + { + psDnldContext->resp_length = PHDNLD_MIN_PACKET; + } + + break; + } + case PHDNLD_CMD_CHECK: + { + psDnldContext->resp_length = PHDNLD_MIN_PACKET; + break; + } + case PHDNLD_CMD_SET_HIF: + { + psDnldContext->resp_length = PHDNLD_MIN_PACKET; + break; + } + case PHDNLD_CMD_ACTIVATE_PATCH: + { + psDnldContext->resp_length = PHDNLD_MIN_PACKET; + break; + } + case PHDNLD_CMD_CHECK_INTEGRITY: + { + uint8_t integrity_param = + *(raw_frame + FRAME_HEADER_LEN); + switch(integrity_param) + { + case CHK_INTEGRITY_CONFIG_PAGE_CRC: + case CHK_INTEGRITY_PATCH_TABLE_CRC: + { + psDnldContext->resp_length = PHDNLD_MIN_PACKET + + CHECK_INTEGRITY_RESP_CRC16_LEN; + break; + } + case CHK_INTEGRITY_FLASH_CODE_CRC: + case CHK_INTEGRITY_PATCH_CODE_CRC: + { + psDnldContext->resp_length = PHDNLD_MIN_PACKET + + CHECK_INTEGRITY_RESP_CRC32_LEN; + break; + } + case CHK_INTEGRITY_COMPLETE_CRC: + default: + { + psDnldContext->resp_length = PHDNLD_MIN_PACKET + + CHECK_INTEGRITY_RESP_COMP_LEN; + break; + } + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + } + + if (NFCSTATUS_SUCCESS == status) + { + status = phDnldNfc_Send( psDnldContext, pHwRef , + raw_frame, frame_length); + + if(NFCSTATUS_PENDING == status) + { + psDnldContext->prev_cmd = raw_frame_hdr->frame_type; + /* TODO: Update for the Chaining */ + psDnldContext->prev_dnld_size = frame_length; + } + } + + return status; +} + + +static +NFCSTATUS +phDnldNfc_Raw_Write( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint32_t dnld_index = psDnldContext->dnld_index; + uint32_t tx_length = 0; + uint8_t *p_raw_sec_hdr = NULL; + uint8_t dnld_flag = FALSE; + uint8_t skip_frame = FALSE; + + if(NULL != psDnldContext->p_fw_raw) + { + + if( (TRUE != psDnldContext->tx_info.tx_chain) + && (0x00 == psDnldContext->dnld_retry) + ) + { + dnld_index = dnld_index + psDnldContext->prev_dnld_size; + p_raw_sec_hdr = psDnldContext->p_fw_raw + dnld_index; + dnld_index = dnld_index + *p_raw_sec_hdr; + } + else + { + phDnldNfc_sData_Hdr_t *p_dnld_raw = (phDnldNfc_sData_Hdr_t *) + (psDnldContext->p_fw_raw + + psDnldContext->dnld_index); + + tx_length = ((p_dnld_raw->frame_length[0] << BYTE_SIZE) | + p_dnld_raw->frame_length[1]); + + tx_length = tx_length + PHDNLD_MIN_PACKET; + + status = phDnldNfc_Send_Raw( psDnldContext, pHwRef, + (uint8_t *)(p_dnld_raw), + psDnldContext->tx_info.tx_offset, + (uint16_t)tx_length); + } + + +#define PHDNLD_MAJOR_OFFSET 0x04U +#define PHDNLD_MINOR_OFFSET 0x05U +#define PHDNLD_PHASE_OFFSET 0x06U +#define PHDNLD_FRAMETYPE_OFFSET 0x07U + +#define PHDNLD_NO_OPERATION 0x00U +#define PHDNLD_NORMAL_OPERATION 0x10U +#define PHDNLD_ADVANCED_OPERATION 0x20U +#define PHDNLD_SETUP_OPERATION 0x40U +#define PHDNLD_RECOVER_OPERATION 0x80U +#define PHDNLD_COMPLETE_OPERATION 0xF0U + +#define PHDNLD_TERMINATE_TYPE 0x0EU + +#define PHDNLD_MARKER_MASK 0x0FU + + while((NFCSTATUS_SUCCESS == status ) + && (FALSE == dnld_flag) + ) + { + phDnldNfc_sData_Hdr_t *p_dnld_raw = (phDnldNfc_sData_Hdr_t *) + (psDnldContext->p_fw_raw + dnld_index); + uint8_t frame_type = *(p_raw_sec_hdr + PHDNLD_FRAMETYPE_OFFSET); + + tx_length = ((p_dnld_raw->frame_length[0] << BYTE_SIZE) | + p_dnld_raw->frame_length[1]); + + tx_length = tx_length + PHDNLD_MIN_PACKET; + + skip_frame = FALSE; + + if( (0x00 == *(p_raw_sec_hdr + PHDNLD_PHASE_OFFSET)) + || (0xFF == *(p_raw_sec_hdr + PHDNLD_PHASE_OFFSET)) + || !( psDnldContext->raw_mode_upgrade + & (frame_type & (~PHDNLD_MARKER_MASK)) ) + ) + { + dnld_index = dnld_index + tx_length; + p_raw_sec_hdr = psDnldContext->p_fw_raw + dnld_index; + dnld_index = dnld_index + *p_raw_sec_hdr; + skip_frame = TRUE; + } + if (PHDNLD_TERMINATE_TYPE == + (frame_type & PHDNLD_MARKER_MASK)) + { + if(TRUE != skip_frame) + { + psDnldContext->raw_mode_upgrade = + (psDnldContext->raw_mode_upgrade & + ~(frame_type & ~PHDNLD_MARKER_MASK)); + } + + if(PHDNLD_NO_OPERATION == + psDnldContext->raw_mode_upgrade) + { + dnld_flag = TRUE; + } + } + else + { + + } + + if((FALSE == skip_frame) + && (FALSE == dnld_flag) + ) + { + status = phDnldNfc_Send_Raw( psDnldContext, pHwRef, + (uint8_t *)(p_dnld_raw), + psDnldContext->tx_info.tx_offset, + (uint16_t)tx_length); + } + + if( NFCSTATUS_PENDING == status ) + { + psDnldContext->dnld_index = dnld_index; + psDnldContext->cur_frame_info= frame_type; + } + } + } + + return status; +} + +static +NFCSTATUS +phDnldNfc_Upgrade_Sequence( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + void *pdata, + uint16_t length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + PHNFC_UNUSED_VARIABLE(pdata); + PHNFC_UNUSED_VARIABLE(length); + + if(phDnld_Raw_Upgrade == psDnldContext->cur_dnld_seq) + { + status = phDnldNfc_Raw_Write( psDnldContext, pHwRef ); + } + else + { + status = phDnldNfc_Resume_Write( psDnldContext, pHwRef ); + } + + return status; +} + + + +static +NFCSTATUS +phDnldNfc_Resume( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + void *pdata, + uint16_t length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phDnldNfc_eState_t dnld_next_state = (phDnldNfc_eState_t) + psDnldContext->cur_dnld_state; + phNfc_sCompletionInfo_t comp_info = {0,0,0}; + + switch( dnld_next_state ) + { + case phDnld_Reset_State: + { + status = phDnldNfc_Send_Command( psDnldContext, pHwRef, + PHDNLD_CMD_RESET , NULL, 0 ); + switch( psDnldContext->cur_dnld_seq ) + { + case phDnld_Update_Patchtable: + { + psDnldContext->next_dnld_state = + (uint8_t)phDnld_Unlock_State; + psDnldContext->next_dnld_seq = + (uint8_t)phDnld_Unlock_System; + break; + } +#ifdef NXP_FW_PATCH_DISABLE + case phDnld_Deactivate_Patch: +#else + case phDnld_Unlock_System: +#endif + { + psDnldContext->next_dnld_state = + (uint8_t)phDnld_Upgrade_State; + psDnldContext->next_dnld_seq = + (uint8_t)phDnld_Upgrade_Section; +#ifdef NXP_FW_DNLD_CHECK_PHASE + gphDnldPhase = NXP_FW_DNLD_CFG_PHASE; +#endif /* NXP_FW_DNLD_CHECK_PHASE */ + break; + } + case phDnld_Lock_System: + { +#if (NXP_FW_INTEGRITY_CHK >= 0x01) + psDnldContext->next_dnld_state = + (uint8_t)phDnld_Verify_State; + psDnldContext->next_dnld_seq = + (uint8_t)phDnld_Verify_Integrity; +#else + /* (void ) memset( (void *) &psDnldContext->chk_integrity_crc, + 0, sizeof(psDnldContext->chk_integrity_crc)); */ + psDnldContext->next_dnld_state = + (uint8_t) phDnld_Complete_State; +#endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ + break; + } + case phDnld_Verify_Integrity: + { + psDnldContext->next_dnld_state = + (uint8_t) phDnld_Complete_State; + break; + } + default: + { + status = (NFCSTATUS_PENDING == status)? + NFCSTATUS_SUCCESS: status; + break; + } + } + break; + } + case phDnld_Unlock_State: + { + + status = phDnldNfc_Sequence( psDnldContext, pHwRef, + pdata, length); + break; + } + case phDnld_Upgrade_State: + { + status = phDnldNfc_Upgrade_Sequence( psDnldContext, pHwRef, + pdata, length); + if ((NFCSTATUS_SUCCESS == status ) + && (phDnld_Complete_State == psDnldContext->next_dnld_state)) + { +#if 0 + psDnldContext->cur_dnld_seq = + (uint8_t)phDnld_Lock_System; + psDnldContext->next_dnld_seq = + psDnldContext->cur_dnld_seq; +#endif +#if (NXP_FW_INTEGRITY_CHK >= 0x01) + psDnldContext->next_dnld_state = + (uint8_t)phDnld_Verify_State; + psDnldContext->next_dnld_seq = + (uint8_t)phDnld_Verify_Integrity; + psDnldContext->cur_dnld_seq = + psDnldContext->next_dnld_seq; + status = phDnldNfc_Sequence( psDnldContext, + pHwRef, pdata, length); +#else + /* (void ) memset( (void *) &psDnldContext->chk_integrity_crc, + 0, sizeof(psDnldContext->chk_integrity_crc)); */ + psDnldContext->next_dnld_state = + (uint8_t) phDnld_Complete_State; +#endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ + } + break; + } + case phDnld_Verify_State: + { + status = phDnldNfc_Sequence( psDnldContext, + pHwRef, pdata, length); + break; + } + case phDnld_Complete_State: + { + uint8_t integrity_chk = 0xA5; + +#if (NXP_FW_INTEGRITY_CHK >= 0x01) + uint8_t verify_crc = 0x96; + + if ( (NULL != psDnldContext->p_flash_code_crc) + && (NULL != psDnldContext->p_patch_code_crc) + && (NULL != psDnldContext->p_patch_table_crc) + ) + { + uint8_t crc_i = 0; + uint16_t patch_table_crc = 0; + uint32_t flash_code_crc = 0; + uint32_t patch_code_crc = 0; + + for (crc_i = 0; crc_i < DNLD_CRC32_SIZE; crc_i++ ) + { + if (crc_i < DNLD_CRC16_SIZE ) + { + patch_table_crc = patch_table_crc + | psDnldContext->chk_integrity_crc.patch_table.Chk_Crc16[crc_i] + << (crc_i * BYTE_SIZE) ; + } + flash_code_crc = flash_code_crc + | psDnldContext->chk_integrity_crc.flash_code.Chk_Crc32[crc_i] + << (crc_i * BYTE_SIZE) ; + patch_code_crc = patch_code_crc + | psDnldContext->chk_integrity_crc.patch_code.Chk_Crc32[crc_i] + << (crc_i * BYTE_SIZE) ; + } + verify_crc =(uint8_t)( (*((uint32_t *) psDnldContext->p_flash_code_crc)) != + flash_code_crc ); + verify_crc |=(uint8_t)( (*((uint32_t *) psDnldContext->p_patch_code_crc)) != + patch_code_crc ); + verify_crc |=(uint8_t)( (*((uint16_t *) psDnldContext->p_patch_table_crc)) != + patch_table_crc ); + } + else + { + DNLD_PRINT(" FW_DNLD: Flash, Patch code and Patch Table CRC "); + DNLD_PRINT(" Not Available in the Firmware \n"); + } + +#endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ + + integrity_chk = psDnldContext->chk_integrity_crc.config_page.Chk_status + + psDnldContext->chk_integrity_crc.patch_table.Chk_status + + psDnldContext->chk_integrity_crc.flash_code.Chk_status + + psDnldContext->chk_integrity_crc.patch_code.Chk_status; + + if ( ( 0 != integrity_chk ) +#if (NXP_FW_INTEGRITY_CHK >= 0x01) + || ( 0 != verify_crc ) +#endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ + ) + { + status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + break; + } + } + + if (NFCSTATUS_PENDING == status) + { + /* Write/Receive is still pending */ + } + else + { + pphNfcIF_Notification_CB_t p_upper_notify = + psDnldContext->p_upper_notify; + void *p_upper_context = + psDnldContext->p_upper_context; + + DNLD_DEBUG(" FW_DNLD: Resume Termination Status = %X \n", status); + + comp_info.status = status; + + (void) phDal4Nfc_Unregister( + psDnldContext->lower_interface.pcontext, pHwRef); + phDnldNfc_Release_Lower(psDnldContext, pHwRef); + phDnldNfc_Release_Resources(&psDnldContext); +#ifndef NFC_TIMER_CONTEXT + gpphDnldContext = psDnldContext; +#endif + /* Notify the Error/Success Scenario to the upper layer */ + phDnldNfc_Notify( p_upper_notify, p_upper_context, pHwRef, (uint8_t) + ((NFCSTATUS_SUCCESS == comp_info.status )? NFC_IO_SUCCESS: NFC_IO_ERROR), + &comp_info ); + } + return status; +} + +STATIC +NFCSTATUS +phDnldNfc_Process_Response( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + void *pdata, + uint16_t length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phDnldNfc_sData_Hdr_t *resp_data = + (phDnldNfc_sData_Hdr_t *) pdata; + + PHNFC_UNUSED_VARIABLE(pHwRef); + DNLD_DEBUG(" FW_DNLD: Receive Length = %X \n", length ); + if(( psDnldContext->rx_info.rx_total == 0 ) + && (PHDNLD_MIN_PACKET <= length) + ) + { + psDnldContext->rx_info.rx_total = + ((uint16_t)resp_data->frame_length[0] << BYTE_SIZE)| + resp_data->frame_length[1]; + if( psDnldContext->rx_info.rx_total + PHDNLD_MIN_PACKET == length ) + { + + DNLD_DEBUG(" FW_DNLD: Success Memory Read = %X \n", + psDnldContext->rx_info.rx_total); +#ifndef DNLD_SUMMARY + /* DNLD_PRINT_BUFFER("Receive Buffer",pdata,length); */ +#endif + + } + else + { + /* status = phDnldNfc_Receive( psDnldContext, pHwRef, + psDnldContext->p_resp_buffer, + (uint8_t)((psDnldContext->rx_info.rx_total <= PHDNLD_MAX_PACKET)? + psDnldContext->rx_info.rx_total: PHDNLD_MAX_PACKET) ); */ + DNLD_PRINT(" FW_DNLD: Invalid Receive length "); + DNLD_DEBUG(": Length Expected = %X \n", + (psDnldContext->rx_info.rx_total + PHDNLD_MIN_PACKET)); + status = PHNFCSTVAL( CID_NFC_DNLD, + NFCSTATUS_INVALID_RECEIVE_LENGTH ); + } + } + else + { + /*TODO:*/ + psDnldContext->rx_info.rx_total = 0 ; + status = PHNFCSTVAL( CID_NFC_DNLD, + NFCSTATUS_INVALID_RECEIVE_LENGTH ); + } + + return status; +} + + + +STATIC +void +phDnldNfc_Receive_Complete ( + void *psContext, + void *pHwRef, + phNfc_sTransactionInfo_t *pInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS ; + void *pdata = NULL ; + phDnldNfc_sData_Hdr_t *resp_data = NULL; + uint16_t length = 0 ; + phNfc_sCompletionInfo_t comp_info = {0,0,0}; + + DNLD_PRINT("\n FW_DNLD: Receive Response .... "); + if ( (NULL != psContext) + && (NULL != pInfo) + && (NULL != pHwRef) + ) + { + phDnldNfc_sContext_t *psDnldContext = + (phDnldNfc_sContext_t *)psContext; + status = pInfo->status ; + length = pInfo->length ; + pdata = pInfo->buffer; + + if(status != NFCSTATUS_SUCCESS) + { + DNLD_DEBUG(" Failed. Status = %02X\n",status); + /* Handle the Error Scenario */ + } + else if (NULL == pdata) + { + DNLD_DEBUG(" Failed. No data received. pdata = %02X\n",pdata); + /* Handle the Error Scenario */ + status = PHNFCSTVAL( CID_NFC_DNLD, NFCSTATUS_FAILED ); + } + else if ((0 == length) + || (PHDNLD_MIN_PACKET > length )) + { + DNLD_DEBUG(" Receive Response Length = %u .... \n",length); + /* Handle the Error Scenario */ +#ifndef HAL_SW_DNLD_RLEN + status = PHNFCSTVAL( CID_NFC_DNLD, + NFCSTATUS_INVALID_RECEIVE_LENGTH ); +#endif + } + else + { + +#if defined(FW_DOWNLOAD_TIMER) && \ + (FW_DOWNLOAD_TIMER == 2) + if ( NXP_INVALID_TIMER_ID != psDnldContext->timer_id ) + { + phOsalNfc_Timer_Stop( psDnldContext->timer_id ); + } + +#endif + +#ifndef DNLD_SUMMARY + DNLD_PRINT_BUFFER("Receive Buffer",pdata,length); +#endif + DNLD_DEBUG(" Receive Response Length = %X. \n", length); + + resp_data = (phDnldNfc_sData_Hdr_t *) pdata; + + switch(resp_data->frame_type) + { + case PHDNLD_RESP_SUCCESS: + { + uint16_t resp_length = + ((uint16_t)resp_data->frame_length[0] << BYTE_SIZE)| + resp_data->frame_length[1]; + switch ( psDnldContext->prev_cmd ) + { + case PHDNLD_CMD_READ : + { + if( PHDNLD_NO_OPERATION + == psDnldContext->raw_mode_upgrade) + { + status = phDnldNfc_Process_Response( + psDnldContext, pHwRef, pdata , length); + + if (NFCSTATUS_SUCCESS != status) + { + /* psDnldContext->dnld_retry++; */ + psDnldContext->dnld_retry = NXP_MAX_DNLD_RETRY; + /* psDnldContext->dnld_retry < NXP_MAX_DNLD_RETRY */ + } + } + else + { + + } + break; + } + case PHDNLD_CMD_CHECK_INTEGRITY : + { + if( PHDNLD_NO_OPERATION + == psDnldContext->raw_mode_upgrade) + { +#if (NXP_FW_INTEGRITY_CHK >= 0x01) + phDnldNfc_sChkCrcComplete_t *p_dnld_crc_all = + &psDnldContext->chk_integrity_crc; + switch(psDnldContext->chk_integrity_param) + { + case CHK_INTEGRITY_CONFIG_PAGE_CRC: + { + (void)memcpy(&p_dnld_crc_all->config_page, + (((uint8_t *)pdata) + PHDNLD_MIN_PACKET), resp_length); + break; + } + case CHK_INTEGRITY_PATCH_TABLE_CRC: + { + (void)memcpy(&p_dnld_crc_all->patch_table, + (((uint8_t *)pdata) + PHDNLD_MIN_PACKET), resp_length); + break; + } + case CHK_INTEGRITY_FLASH_CODE_CRC: + { + (void)memcpy(&p_dnld_crc_all->flash_code, + (((uint8_t *)pdata) + PHDNLD_MIN_PACKET), resp_length); + break; + } + case CHK_INTEGRITY_PATCH_CODE_CRC: + { + (void)memcpy(&p_dnld_crc_all->patch_code, + (((uint8_t *)pdata) + PHDNLD_MIN_PACKET), resp_length); + break; + } + case CHK_INTEGRITY_COMPLETE_CRC: + { + (void)memcpy(p_dnld_crc_all, + (((uint8_t *)pdata) + PHDNLD_MIN_PACKET), resp_length); + DNLD_DEBUG(" FW_DNLD: Check Integrity Complete Structure Size = %X \n", + sizeof(psDnldContext->chk_integrity_crc)); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_DNLD, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + } +#endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ + } + else + { + psDnldContext->raw_mode_upgrade = + (PHDNLD_SETUP_OPERATION | PHDNLD_ADVANCED_OPERATION); + /* psDnldContext->raw_mode_upgrade = + (psDnldContext->raw_mode_upgrade & + ( psDnldContext->cur_frame_info & ~PHDNLD_MARKER_MASK )); */ + } + break; + } + case PHDNLD_CMD_WRITE: + { + psDnldContext->dnld_retry = 0; + break; + } + case PHDNLD_CMD_SEC_WRITE: + { + psDnldContext->dnld_retry = 0; + break; + } + case PHDNLD_CMD_ACTIVATE_PATCH: + case PHDNLD_CMD_CHECK: + default: + { + if( PHDNLD_NO_OPERATION + == psDnldContext->raw_mode_upgrade) + { + if( ( (PHDNLD_MIN_PACKET > length) + || ( 0 != resp_length) ) + ) + { + psDnldContext->dnld_retry = NXP_MAX_DNLD_RETRY; + status = PHNFCSTVAL( CID_NFC_DNLD, + NFCSTATUS_INVALID_RECEIVE_LENGTH ); + } + else + { + psDnldContext->dnld_retry = 0; + } + } + else + { + psDnldContext->raw_mode_upgrade = + (psDnldContext->raw_mode_upgrade & ~PHDNLD_RECOVER_OPERATION); + } + break; + } + } /* End of the Previous Command Switch Case */ + break; + }/* Case PHDNLD_RESP_SUCCESS*/ + case PHDNLD_RESP_TIMEOUT: + case PHDNLD_RESP_CRC_ERROR: + case PHDNLD_RESP_WRITE_ERROR: + { + if(psDnldContext->dnld_retry < NXP_MAX_DNLD_RETRY ) + { + psDnldContext->dnld_retry++; + } + status = PHNFCSTVAL(CID_NFC_DNLD, + resp_data->frame_type); + break; + } + /* fall through */ + case PHDNLD_RESP_ACCESS_DENIED: + case PHDNLD_RESP_INVALID_PARAMETER: + case PHDNLD_RESP_INVALID_LENGTH: + /* Initial Frame Checksum */ + case PHDNLD_RESP_CHKSUM_ERROR: + case PHDNLD_RESP_MEMORY_UPDATE_ERROR: + { + psDnldContext->dnld_retry = NXP_MAX_DNLD_RETRY; + status = PHNFCSTVAL(CID_NFC_DNLD, + resp_data->frame_type); + break; + } + case PHDNLD_RESP_PROTOCOL_ERROR: + { + if(( PHDNLD_NO_OPERATION + == psDnldContext->raw_mode_upgrade) + || ( PHDNLD_ADVANCED_OPERATION + == psDnldContext->raw_mode_upgrade) + ) + { + psDnldContext->dnld_retry = NXP_MAX_DNLD_RETRY; + status = PHNFCSTVAL(CID_NFC_DNLD, + NFCSTATUS_INVALID_FORMAT); + } + else if( (PHDNLD_NORMAL_OPERATION + & psDnldContext->raw_mode_upgrade) + ) + { + psDnldContext->raw_mode_upgrade = + (psDnldContext->raw_mode_upgrade & ~PHDNLD_NORMAL_OPERATION); + } + else if ( PHDNLD_RECOVER_OPERATION + & psDnldContext->raw_mode_upgrade ) + { + psDnldContext->dnld_retry = NXP_MAX_DNLD_RETRY; + status = PHNFCSTVAL(CID_NFC_DNLD, + NFCSTATUS_INVALID_FORMAT); + } + else + { + psDnldContext->raw_mode_upgrade = + (psDnldContext->raw_mode_upgrade & + ~( psDnldContext->cur_frame_info & ~PHDNLD_MARKER_MASK )); + } + break; + } + case PHDNLD_RESP_VERSION_UPTODATE: + { + /* TODO: to make sure that the Advance Frames are sent to get + * the updated status */ + if ( PHDNLD_ADVANCED_OPERATION + == psDnldContext->raw_mode_upgrade) + { + status = ( CID_NFC_DNLD << BYTE_SIZE ) ; + } + else if ( PHDNLD_NO_OPERATION + != psDnldContext->raw_mode_upgrade) + { + + psDnldContext->raw_mode_upgrade = + (psDnldContext->raw_mode_upgrade & + ~( psDnldContext->cur_frame_info & ~PHDNLD_MARKER_MASK )); + } + else + { + } + break; + } + case PHDNLD_RESP_CMD_NOT_SUPPORTED: + { + + if ( PHDNLD_NO_OPERATION + == psDnldContext->raw_mode_upgrade) + { + status = PHNFCSTVAL(CID_NFC_DNLD, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else if ( PHDNLD_ADVANCED_OPERATION + == psDnldContext->raw_mode_upgrade) + { + status = PHNFCSTVAL(CID_NFC_DNLD, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + } +#if 0 + else if( (PHDNLD_NORMAL_OPERATION + & psDnldContext->raw_mode_upgrade) + ) + { + psDnldContext->raw_mode_upgrade = + (psDnldContext->raw_mode_upgrade & ~PHDNLD_NORMAL_OPERATION); + } + else if ( PHDNLD_SETUP_OPERATION + & psDnldContext->raw_mode_upgrade ) + { + psDnldContext->raw_mode_upgrade = + (psDnldContext->raw_mode_upgrade & ~PHDNLD_SETUP_OPERATION); + } +#endif + else + { + psDnldContext->raw_mode_upgrade = + (psDnldContext->raw_mode_upgrade & + ~( psDnldContext->cur_frame_info & ~PHDNLD_MARKER_MASK )); + } + break; + } + /* The Chaining of the Command Frame + was Successful in the Download Mode */ + case PHDNLD_RESP_CHAINING_SUCCESS: + { + /* TODO: Handle the Corner Case Scenarios + * the updated status */ + psDnldContext->dnld_retry = 0x00; + break; + } +/* The Error during the Chaining the Command Frame in the Download Mode */ + case PHDNLD_RESP_CHAINING_ERROR: + { + /* TODO: Restart the Chunk in Corner Case + * the updated status */ + psDnldContext->dnld_retry++; + phDnldNfc_Tx_Reset(psDnldContext); + break; + } +/* The Command is not allowed anymore in the Download Mode */ + case PHDNLD_RESP_CMD_NOT_ALLOWED: + default: + { + psDnldContext->dnld_retry = NXP_MAX_DNLD_RETRY; + status = PHNFCSTVAL(CID_NFC_DNLD, + NFCSTATUS_NOT_ALLOWED); + break; + } + + } /* End of the Response Frame Type Switch */ + + if (NFCSTATUS_PENDING != status) + { + if ((NFCSTATUS_SUCCESS != status) && + (psDnldContext->dnld_retry >= NXP_MAX_DNLD_RETRY)) + { + pphNfcIF_Notification_CB_t p_upper_notify = + psDnldContext->p_upper_notify; + void *p_upper_context = + psDnldContext->p_upper_context; + + comp_info.status = status; + DNLD_DEBUG(" FW_DNLD: Termination in Receive, Status = %X \n", status); + status = phDal4Nfc_Unregister( + psDnldContext->lower_interface.pcontext, pHwRef); + phDnldNfc_Release_Lower(psDnldContext, pHwRef); + phDnldNfc_Release_Resources(&psDnldContext); +#ifndef NFC_TIMER_CONTEXT + gpphDnldContext = psDnldContext; +#endif + /* Notify the Error/Success Scenario to the upper layer */ + phDnldNfc_Notify( p_upper_notify, p_upper_context, pHwRef, + (uint8_t) NFC_IO_ERROR, &comp_info ); + } + else if ( (NFCSTATUS_SUCCESS != status) && + (NFCSTATUS_SUCCESS == PHNFCSTATUS(status)) + ) + { + pphNfcIF_Notification_CB_t p_upper_notify = + psDnldContext->p_upper_notify; + void *p_upper_context = + psDnldContext->p_upper_context; + + comp_info.status = NFCSTATUS_SUCCESS; + DNLD_DEBUG(" FW_DNLD: Termination in Receive, Status = %X \n", status); + status = phDal4Nfc_Unregister( + psDnldContext->lower_interface.pcontext, pHwRef); + phDnldNfc_Release_Lower(psDnldContext, pHwRef); + phDnldNfc_Release_Resources(&psDnldContext); +#ifndef NFC_TIMER_CONTEXT + gpphDnldContext = psDnldContext; +#endif + /* Notify the Error/Success Scenario to the upper layer */ + phDnldNfc_Notify( p_upper_notify, p_upper_context, pHwRef, + (uint8_t) NFC_IO_SUCCESS, &comp_info ); + + } + else if (NFCSTATUS_FEATURE_NOT_SUPPORTED == PHNFCSTATUS(status)) + { + pphNfcIF_Notification_CB_t p_upper_notify = + psDnldContext->p_upper_notify; + void *p_upper_context = + psDnldContext->p_upper_context; + + comp_info.status = status; + DNLD_DEBUG(" FW_DNLD: Termination in Receive, Status = %X \n", status); + status = phDal4Nfc_Unregister( + psDnldContext->lower_interface.pcontext, pHwRef); + phDnldNfc_Release_Lower(psDnldContext, pHwRef); + phDnldNfc_Release_Resources(&psDnldContext); +#ifndef NFC_TIMER_CONTEXT + gpphDnldContext = psDnldContext; +#endif + /* Notify the Error/Success Scenario to the upper layer */ + phDnldNfc_Notify( p_upper_notify, p_upper_context, pHwRef, + (uint8_t) NFC_IO_SUCCESS, &comp_info ); + + } + else + { + /* DNLD_PRINT(" FW_DNLD: Successful.\n"); */ + psDnldContext->resp_length = /* PHDNLD_MIN_PACKET */ 0 ; + status = phDnldNfc_Set_Seq(psDnldContext, + DNLD_SEQ_UPDATE); + status = phDnldNfc_Resume( psDnldContext, + pHwRef, pdata, length ); + } + } + } /* End of status != Success */ + } +} + + +STATIC +void +phDnldNfc_Send_Complete ( + void *psContext, + void *pHwRef, + phNfc_sTransactionInfo_t *pInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS ; + uint16_t length = 0; + + DNLD_PRINT(" FW_DNLD: Send Data .... "); + if ( (NULL != psContext) + && (NULL != pInfo) + && (NULL != pHwRef) + ) + { + phDnldNfc_sContext_t *psDnldContext = + (phDnldNfc_sContext_t *)psContext; + status = pInfo->status ; + length = pInfo->length ; + if(status != NFCSTATUS_SUCCESS) + { + DNLD_DEBUG(" Failed. Status = %02X\n",status); + /* Handle the Error Scenario */ + } + else + { + DNLD_PRINT(" Successful.\n"); + (void)memset((void *)&psDnldContext->dnld_data, 0, + sizeof(psDnldContext->dnld_data)); + if ((PHDNLD_CMD_SET_HIF != psDnldContext->prev_cmd) + && (PHDNLD_CMD_RESET != psDnldContext->prev_cmd)) + { + psDnldContext->rx_info.rx_total = 0; + status = phDnldNfc_Receive( psDnldContext, pHwRef, + (uint8_t *)(&psDnldContext->dnld_resp), + psDnldContext->resp_length); + } + else + { + psDnldContext->resp_length = 0; + psDnldContext->dnld_retry = 0; + /* clock unstable after SW reset command, especially on UART + * platform because of its sensitivity to clock. Experimentally + * we found clock unstable for 750us. Delay for 5ms to be sure. + */ + if( PHDNLD_CMD_RESET == psDnldContext->prev_cmd ) + { + DO_DELAY(PHDNLD_DNLD_DELAY); + } +#if defined(FW_DOWNLOAD_TIMER) && \ + (FW_DOWNLOAD_TIMER == 2) + + if ( NXP_INVALID_TIMER_ID != psDnldContext->timer_id ) + { + phOsalNfc_Timer_Stop( psDnldContext->timer_id ); + } +#endif + + status = phDnldNfc_Set_Seq(psDnldContext, + DNLD_SEQ_UPDATE); + } + + if(NFCSTATUS_SUCCESS == status ) + { + status = phDnldNfc_Resume( psDnldContext, pHwRef, NULL, length); + } + + } /* End of status != Success */ + + } /* End of Context != NULL */ +} + + + +STATIC +NFCSTATUS +phDnldNfc_Send_Command( + phDnldNfc_sContext_t *psDnldContext, + void *pHwRef, + uint8_t cmd, + void *params, + uint16_t param_length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint16_t tx_length = 0; + uint16_t rx_length = 0; + uint8_t **pp_resp_data = &psDnldContext->p_resp_buffer; + phDnldNfc_sData_t *p_dnld_data = + (phDnldNfc_sData_t *)psDnldContext->dnld_data; + + switch(cmd) + { + case PHDNLD_CMD_RESET: + { + (void)memset((void *)&psDnldContext->dnld_data, 0, + sizeof(psDnldContext->dnld_data)); + break; + } + case PHDNLD_CMD_READ: + { + phDnldNfc_sData_t *p_dnld_data = + (phDnldNfc_sData_t *)psDnldContext->dnld_data; + phDnldNfc_sParam_t *param_info = /* (phDnldNfc_sParam_t *)params */ + &p_dnld_data->param_info.data_param; + tx_length = PHDNLD_CMD_READ_LEN; + if (NULL != *pp_resp_data) + { + phOsalNfc_FreeMemory(*pp_resp_data); + *pp_resp_data = NULL; + } + rx_length = (uint16_t) (((uint16_t)param_info->data_len[0] + << BYTE_SIZE) + param_info->data_len[1]); + + psDnldContext->resp_length = + (( rx_length + PHDNLD_MIN_PACKET )); + (void)phDnldNfc_Allocate_Resource( (void **) pp_resp_data, + rx_length); + break; + } + case PHDNLD_CMD_WRITE: + case PHDNLD_CMD_SEC_WRITE: + { + phDnldNfc_sData_t *p_dnld_data = + (phDnldNfc_sData_t *)psDnldContext->dnld_data; + phDnldNfc_sParam_t *param_info = /* (phDnldNfc_sParam_t *)params */ + &p_dnld_data->param_info.data_param; + tx_length = (uint16_t) (((uint16_t)param_info->data_len[0] + << BYTE_SIZE) + param_info->data_len[1] + + PHDNLD_CMD_WRITE_MIN_LEN ); + + psDnldContext->resp_length = PHDNLD_MIN_PACKET; + if ((0 != param_length) && (NULL != params)) + { + (void)memcpy(param_info->data_packet, params, param_length); + } + break; + } + case PHDNLD_CMD_CHECK: + { + tx_length = PHDNLD_CMD_CHECK_LEN; + psDnldContext->resp_length = PHDNLD_MIN_PACKET; + break; + } + case PHDNLD_CMD_ENCAPSULATE: + { + uint8_t i = 0x00; + if ((0 != param_length) && (NULL != params)) + { + p_dnld_data->frame_type = + PHDNLD_CMD_ENCAPSULATE; + (void)memcpy((void *)( ((uint8_t *)p_dnld_data) + + PHDNLD_FRAME_DATA_OFFSET) + , params, param_length); + tx_length = param_length; + + p_dnld_data->frame_length[i++] = + (uint8_t)(tx_length >> BYTE_SIZE); + p_dnld_data->frame_length[i] = + (uint8_t)( tx_length & BYTE_MASK ); + tx_length += PHDNLD_FRAME_DATA_OFFSET; + + psDnldContext->resp_length = PHDNLD_MIN_PACKET; + + status = phDnldNfc_Send( psDnldContext, pHwRef , + (uint8_t *)p_dnld_data, tx_length); + } + else + { + status = PHNFCSTVAL(CID_NFC_DNLD, + NFCSTATUS_NOT_ALLOWED); + } + break; + } + case PHDNLD_CMD_SET_HIF: + { + tx_length++; + psDnldContext->resp_length = PHDNLD_MIN_PACKET; + break; + } + case PHDNLD_CMD_ACTIVATE_PATCH: + { + psDnldContext->resp_length = PHDNLD_MIN_PACKET; + if ((NULL != params) && ( param_length > 0 )) + { + p_dnld_data->param_info.cmd_param = + (*(uint8_t *)params); + tx_length = param_length; + } + else + { + p_dnld_data->param_info.cmd_param = FALSE; + tx_length++; + } + break; + } + case PHDNLD_CMD_CHECK_INTEGRITY: + { +#if (NXP_FW_INTEGRITY_CHK >= 0x01) + if ((NULL != params) && ( param_length > 0 )) + { + psDnldContext->chk_integrity_param = + (phDnldNfc_eChkCrc_t)(*(uint8_t *)params); + tx_length = param_length; + } + else + { + psDnldContext->chk_integrity_param = CHK_INTEGRITY_COMPLETE_CRC; + tx_length++; + } + p_dnld_data->param_info.cmd_param = + (uint8_t) psDnldContext->chk_integrity_param; + switch(psDnldContext->chk_integrity_param) + { + case CHK_INTEGRITY_CONFIG_PAGE_CRC: + case CHK_INTEGRITY_PATCH_TABLE_CRC: + { + psDnldContext->resp_length = PHDNLD_MIN_PACKET + + CHECK_INTEGRITY_RESP_CRC16_LEN; + break; + } + case CHK_INTEGRITY_FLASH_CODE_CRC: + case CHK_INTEGRITY_PATCH_CODE_CRC: + { + psDnldContext->resp_length = PHDNLD_MIN_PACKET + + CHECK_INTEGRITY_RESP_CRC32_LEN; + break; + } + case CHK_INTEGRITY_COMPLETE_CRC: + default: + { + psDnldContext->resp_length = PHDNLD_MIN_PACKET + + CHECK_INTEGRITY_RESP_COMP_LEN; + break; + } + } +#else + tx_length++; + p_dnld_data->param_info.cmd_param = + (uint8_t) CHK_INTEGRITY_COMPLETE_CRC; + +#endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + } + if (NFCSTATUS_SUCCESS == status) + { + uint8_t i = 0; + + p_dnld_data->frame_type = cmd; + p_dnld_data->frame_length[i++] = + (uint8_t)(tx_length >> BYTE_SIZE); + p_dnld_data->frame_length[i] = + (uint8_t)( tx_length & BYTE_MASK ); + tx_length = tx_length + PHDNLD_MIN_PACKET; + status = phDnldNfc_Send( psDnldContext, pHwRef , + (uint8_t *)p_dnld_data, tx_length); + if(NFCSTATUS_PENDING == status) + { + psDnldContext->prev_cmd = cmd; + + if( PHDNLD_CMD_RESET == cmd ) + DO_DELAY(PHDNLD_DNLD_DELAY); //this seems like its on the wrong thread + } + } + + return status; +} + +static +NFCSTATUS +phDnldNfc_Check_FW( + phHal_sHwReference_t *pHwRef, + fw_data_hdr_t *cur_fw_hdr + ) +{ + NFCSTATUS status = NFCSTATUS_FAILED; + + if ( !pHwRef->device_info.fw_version ) + { + /* Override the Firmware Version Check and upgrade*/; + DNLD_PRINT(" FW_DNLD_CHK: Forceful Upgrade of the Firmware .... Required \n"); + status = NFCSTATUS_SUCCESS; + } + else if ( (pHwRef->device_info.fw_version >> (BYTE_SIZE * 2)) + != ( cur_fw_hdr->fw_version >> (BYTE_SIZE * 2) )) + { + /* Check for the Compatible Romlib Version for the Hardware */ + DNLD_PRINT(" FW_DNLD: IC Hardware Version Mismatch.. \n"); + status = PHNFCSTVAL( CID_NFC_DNLD, NFCSTATUS_NOT_ALLOWED ); + } + else if (( pHwRef->device_info.fw_version < cur_fw_hdr->fw_version ) + ) + { + /* TODO: Firmware Version Check and upgrade*/ + DNLD_PRINT(" FW_DNLD: Older Firmware Upgrading to newerone.... \n"); + status = NFCSTATUS_SUCCESS; + } +#ifdef NXP_FW_CHK_LATEST + else if (( pHwRef->device_info.fw_version > cur_fw_hdr->fw_version ) + ) + { + DNLD_PRINT(" FW_DNLD: Newer than the Stored One .... \n"); + status = PHNFCSTVAL( CID_NFC_DNLD, NFCSTATUS_NOT_ALLOWED ); + } +#endif /* NXP_FW_CHK_LATEST */ + else + { + DNLD_PRINT(" FW_DNLD: Already Updated .... \n"); + status = ( CID_NFC_DNLD << BYTE_SIZE ) ; + } + + return status; + } + + +static +NFCSTATUS +phDnldNfc_Process_FW( + phDnldNfc_sContext_t *psDnldContext, + phHal_sHwReference_t *pHwRef +#ifdef NXP_FW_PARAM + ,uint8_t *nxp_nfc_fw + ,uint32_t nxp_fw_len +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_FAILED; + section_info_t *p_cur_sec = NULL; + static unsigned sec_type; + uint32_t fw_index = 0; +#ifdef NXP_NFC_MULTIPLE_FW + phDnldNfc_sFwImageInfo_t *p_cur_fw = NULL; +#endif /* #ifdef NXP_NFC_MULTIPLE_FW */ + fw_data_hdr_t *cur_fw_hdr = NULL; + uint8_t sec_index = 0; + uint8_t i = 0; + + psDnldContext->p_img_hdr = (img_data_hdr_t *) nxp_nfc_fw; + +#ifdef NXP_NFC_MULTIPLE_FW + + /* TODO: Create a memory of pointers to store all the Firmwares */ + if( (NXP_NFC_IMAG_FW_MAX > psDnldContext->p_img_hdr->no_of_fw_img) + && (0 != psDnldContext->p_img_hdr->no_of_fw_img) + ) + { + ( void )phDnldNfc_Allocate_Resource((void **)&psDnldContext->p_img_info, + (psDnldContext->p_img_hdr->no_of_fw_img * sizeof(phDnldNfc_sFwImageInfo_t))); + + if(NULL != psDnldContext->p_img_info) + { + p_cur_fw = psDnldContext->p_img_info; + } + } +#endif /* #ifdef NXP_NFC_MULTIPLE_FW */ + + fw_index = sizeof (img_data_hdr_t); + + for ( i=0; i < psDnldContext->p_img_hdr->no_of_fw_img; i++ ) + { + + psDnldContext->p_fw_hdr = (fw_data_hdr_t *) ( nxp_nfc_fw + fw_index ); + +#ifdef NXP_NFC_MULTIPLE_FW + if(NULL != p_cur_fw) + { + ( p_cur_fw + i)->p_fw_hdr = psDnldContext->p_fw_hdr; + } +#endif /* #ifdef NXP_NFC_MULTIPLE_FW */ + cur_fw_hdr = psDnldContext->p_fw_hdr; + + fw_index = fw_index + (cur_fw_hdr->fw_hdr_len * PNDNLD_WORD_LEN); + + status = phDnldNfc_Check_FW( pHwRef, cur_fw_hdr); + + } + + if ( ( NFCSTATUS_SUCCESS == status ) +#if defined (NXP_FW_INTEGRITY_VERIFY) + || (NFCSTATUS_SUCCESS == PHNFCSTATUS(status) ) +#endif /* !defined (NXP_FW_INTEGRITY_VERIFY) */ + ) + { + if( (BYTE_MASK > cur_fw_hdr->no_of_sections) + && (0 != cur_fw_hdr->no_of_sections) + ) + { + (void) phDnldNfc_Allocate_Resource((void **)&psDnldContext->p_fw_sec, + (cur_fw_hdr->no_of_sections * sizeof(section_info_t))); + + if(NULL != psDnldContext->p_fw_sec) + { + DNLD_DEBUG(" FW_DNLD: FW Index : %x \n", + fw_index ); + + DNLD_DEBUG(" FW_DNLD: No of Sections : %x \n\n", + cur_fw_hdr->no_of_sections); + + for(sec_index = 0; sec_index + < cur_fw_hdr->no_of_sections; sec_index++ ) + { + p_cur_sec = ((section_info_t *) + (psDnldContext->p_fw_sec + sec_index )); + + p_cur_sec->p_sec_hdr = (section_hdr_t *) + (nxp_nfc_fw + fw_index); + + DNLD_DEBUG(" FW_DNLD: Section %x \n", sec_index); + DNLD_DEBUG(" FW_DNLD: Section Header Len : %x ", + p_cur_sec->p_sec_hdr->section_hdr_len); + DNLD_DEBUG(" Section Address : %x ", + p_cur_sec->p_sec_hdr->section_address); + DNLD_DEBUG(" Section Length : %x ", + p_cur_sec->p_sec_hdr->section_length); + DNLD_DEBUG(" Section Memory Type : %x \n", + p_cur_sec->p_sec_hdr->section_mem_type); + + sec_type = (unsigned int)p_cur_sec->p_sec_hdr->section_mem_type; + + if((sec_type & DNLD_TRIM_MASK)) + { + p_cur_sec->p_trim_data = (uint8_t *) + (nxp_nfc_fw + fw_index + sizeof(section_hdr_t)); + } + else + { + p_cur_sec->p_trim_data = NULL; + } + + if (0 == sec_index) + { + if ((sec_type & DNLD_SM_UNLOCK_MASK)) + { + (void)phDnldNfc_Set_Seq(psDnldContext, + DNLD_SEQ_UNLOCK); + } + else + { + (void)phDnldNfc_Set_Seq(psDnldContext, + DNLD_SEQ_INIT); + } + } + p_cur_sec->section_read = FALSE; + + p_cur_sec->section_offset = 0; + + p_cur_sec->p_sec_data = ((uint8_t *) nxp_nfc_fw) + fw_index + + (p_cur_sec->p_sec_hdr->section_hdr_len * PNDNLD_WORD_LEN); + + fw_index = fw_index + + (p_cur_sec->p_sec_hdr->section_hdr_len * PNDNLD_WORD_LEN) + + p_cur_sec->p_sec_hdr->section_length; + + + if( 0 != p_cur_sec->p_sec_hdr->section_checksum ) + { + DNLD_DEBUG(" FW_DNLD: Section checksum : %x \n", + p_cur_sec->p_sec_hdr->section_checksum ); + + p_cur_sec->p_sec_chksum = ( uint8_t *)(nxp_nfc_fw + fw_index); + + fw_index = fw_index + + p_cur_sec->p_sec_hdr->section_checksum; + } + + DNLD_DEBUG(" FW_DNLD: FW Index : %x \n", fw_index ); + +#if (NXP_FW_INTEGRITY_CHK >= 0x01) + switch( p_cur_sec->p_sec_hdr->section_address ) + { + case DNLD_FW_CODE_ADDR: + { + psDnldContext->p_flash_code_crc = + p_cur_sec->p_sec_data + + p_cur_sec->p_sec_hdr->section_length + - DNLD_CRC32_SIZE; + break; + } + case DNLD_PATCH_CODE_ADDR: + { + psDnldContext->p_patch_code_crc = + p_cur_sec->p_sec_data + + p_cur_sec->p_sec_hdr->section_length + - DNLD_CRC32_SIZE; + break; + } + case DNLD_PATCH_TABLE_ADDR: + { + psDnldContext->p_patch_table_crc = + p_cur_sec->p_sec_data + + p_cur_sec->p_sec_hdr->section_length + - DNLD_CRC16_SIZE; + break; + } + default: + { + break; + } + + } /* End of Address Switch */ +#endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ + } /* End of For Loop */ + } /* End of the Null Check */ + else + { + status = PHNFCSTVAL(CID_NFC_DNLD, + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + else if ( + (0 == cur_fw_hdr->no_of_sections) + && (PHDNLD_FW_PATCH_SEC == cur_fw_hdr->fw_patch) + ) + { + psDnldContext->p_fw_raw = (uint8_t *)(nxp_nfc_fw + fw_index); + + psDnldContext->raw_mode_upgrade = PHDNLD_COMPLETE_OPERATION; + + (void)phDnldNfc_Set_Seq(psDnldContext, + DNLD_SEQ_RAW); + } + else + { + DNLD_PRINT("********* Empty Section and Firmware ******************\n\n"); + } + + DNLD_PRINT("*******************************************\n\n"); + + } + return status; +} + +#if !defined (NXP_FW_INTEGRITY_VERIFY) + +NFCSTATUS +phDnldNfc_Run_Check( + phHal_sHwReference_t *pHwRef +#ifdef NXP_FW_PARAM + ,uint8_t *nxp_nfc_fw + uint32_t fw_length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_FAILED; + uint32_t fw_index = 0; + img_data_hdr_t *p_img_hdr = NULL; + fw_data_hdr_t *p_fw_hdr = NULL; + fw_data_hdr_t *cur_fw_hdr = NULL; + uint8_t i = 0; + + p_img_hdr = (img_data_hdr_t *) nxp_nfc_fw; + + fw_index = sizeof (img_data_hdr_t); + + for ( i=0; i < p_img_hdr->no_of_fw_img; i++ ) + { + p_fw_hdr = (fw_data_hdr_t *) ( nxp_nfc_fw + fw_index ); + /* TODO: Create a memory of pointers to store all the Firmwares */ + cur_fw_hdr = p_fw_hdr; + + fw_index = fw_index + (cur_fw_hdr->fw_hdr_len * PNDNLD_WORD_LEN); + + status = phDnldNfc_Check_FW( pHwRef, cur_fw_hdr); + } + return status; +} + +#endif /* #if !defined (NXP_FW_INTEGRITY_VERIFY) */ + + +STATIC +void +phDnldNfc_Abort ( + uint32_t abort_id +#ifdef NFC_TIMER_CONTEXT + , void *dnld_cntxt +#endif + ) +{ + + phNfc_sCompletionInfo_t comp_info = {0,0,0}; + + phDnldNfc_sContext_t *p_dnld_context = NULL; + +#ifdef NFC_TIMER_CONTEXT + p_dnld_context = (phDnldNfc_sContext_t *)dnld_cntxt; +#else + p_dnld_context = gpphDnldContext; +#endif + + if ( ( NULL != p_dnld_context) + && (abort_id == p_dnld_context->timer_id )) + { + pphNfcIF_Notification_CB_t p_upper_notify = + p_dnld_context->p_upper_notify; + void *p_upper_context = + p_dnld_context->p_upper_context; + phHal_sHwReference_t *pHwRef = p_dnld_context->p_hw_ref; + + (void)phDal4Nfc_Unregister( + p_dnld_context->lower_interface.pcontext, pHwRef ); + phDnldNfc_Release_Lower(p_dnld_context, pHwRef); + phDnldNfc_Release_Resources(&p_dnld_context); +#ifndef NFC_TIMER_CONTEXT + gpphDnldContext = p_dnld_context; +#endif + + /* Notify the Error/Success Scenario to the upper layer */ + DNLD_DEBUG(" FW_DNLD: FW_DNLD Aborted with %x Timer Timeout \n", + abort_id); + comp_info.status = NFCSTATUS_FAILED ; + phDnldNfc_Notify( p_upper_notify, p_upper_context, + pHwRef, (uint8_t) NFC_IO_ERROR, &comp_info ); + } + + return ; +} + + + +NFCSTATUS +phDnldNfc_Upgrade ( + phHal_sHwReference_t *pHwRef, +#ifdef NXP_FW_PARAM + uint8_t type, + uint8_t *nxp_nfc_fw, + uint32_t fw_length, +#endif + pphNfcIF_Notification_CB_t upgrade_complete, + void *context + ) + { + phDnldNfc_sContext_t *psDnldContext = NULL; + phNfcIF_sReference_t dnldReference = { NULL,0,0 }; + phNfcIF_sCallBack_t if_callback = { NULL, NULL, NULL, NULL }; + phNfc_sLowerIF_t *plower_if = NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } + else + { + DNLD_PRINT(" FW_DNLD: Starting the FW Upgrade Sequence .... \n"); + + (void) + phDnldNfc_Allocate_Resource((void **) + &psDnldContext,sizeof(phDnldNfc_sContext_t)); + if(psDnldContext != NULL) + { +#ifndef NFC_TIMER_CONTEXT + gpphDnldContext = psDnldContext; +#endif + psDnldContext->p_hw_ref = pHwRef; + psDnldContext->timer_id = NXP_INVALID_TIMER_ID; + + DNLD_PRINT(" FW_DNLD: Initialisation in Progress.... \n"); + + if_callback.pif_ctxt = psDnldContext ; + if_callback.send_complete = &phDnldNfc_Send_Complete; + if_callback.receive_complete= &phDnldNfc_Receive_Complete; + /* if_callback.notify = &phDnldNfc_Notify_Event; */ + plower_if = dnldReference.plower_if = &(psDnldContext->lower_interface); + status = phDal4Nfc_Register(&dnldReference, if_callback, + NULL); + DNLD_DEBUG(" FW_DNLD: Lower Layer Register, Status = %02X\n",status); + + if( (NFCSTATUS_SUCCESS == status) && (NULL != plower_if->init)) + { + /* psDnldContext->p_config_params = pHwConfig ; */ + status = plower_if->init((void *)plower_if->pcontext, + (void *)pHwRef); + DNLD_DEBUG(" FW_DNLD: Lower Layer Initialisation, Status = %02X\n",status); + } + else + { + /* TODO: Handle Initialisation in the Invalid State */ + } + /* The Lower layer Initialisation successful */ + if (NFCSTATUS_SUCCESS == status) + { + psDnldContext->p_upper_notify = upgrade_complete; + psDnldContext->p_upper_context = context; + + status = phDnldNfc_Process_FW( psDnldContext, pHwRef +#ifdef NXP_FW_PARAM + ,*nxp_nfc_fw , fw_length +#endif + ); + + if (NFCSTATUS_SUCCESS == status) + { + status = phDnldNfc_Send_Command( psDnldContext, pHwRef, + PHDNLD_CMD_RESET , NULL , 0 ); + if (NFCSTATUS_PENDING == status) + { + DNLD_PRINT("\n FW_DNLD: Initial Reset .... \n"); + +#if defined(FW_DOWNLOAD_TIMER) + + psDnldContext->timer_id = phOsalNfc_Timer_Create( ); + +#if (FW_DOWNLOAD_TIMER < 2) + phOsalNfc_Timer_Start( psDnldContext->timer_id, + NXP_DNLD_COMPLETE_TIMEOUT, + (ppCallBck_t) phDnldNfc_Abort +#ifdef NFC_TIMER_CONTEXT + , (void *) psDnldContext +#endif + ); + +#endif /* #if (FW_DOWNLOAD_TIMER < 2) */ + +#endif /* #if defined(FW_DOWNLOAD_TIMER) */ + + } + } + else if (NFCSTATUS_SUCCESS == PHNFCSTATUS(status)) + { +#if defined (NXP_FW_INTEGRITY_VERIFY) + /* + * To check for the integrity if the firmware is already + * Upgraded. + */ + status = phDnldNfc_Send_Command( psDnldContext, pHwRef, + PHDNLD_CMD_RESET , NULL , 0 ); + if (NFCSTATUS_PENDING == status) + { + DNLD_PRINT("\n FW_DNLD: Integrity Reset .... \n"); + (void)phDnldNfc_Set_Seq(psDnldContext, DNLD_SEQ_COMPLETE); + status = PHNFCSTVAL( CID_NFC_DNLD, + NFCSTATUS_PENDING ); +#if defined(FW_DOWNLOAD_TIMER) + psDnldContext->timer_id = phOsalNfc_Timer_Create( ); +#if (FW_DOWNLOAD_TIMER < 2) + phOsalNfc_Timer_Start( psDnldContext->timer_id, + NXP_DNLD_COMPLETE_TIMEOUT, + (ppCallBck_t) phDnldNfc_Abort +#ifdef NFC_TIMER_CONTEXT + , (void *) psDnldContext +#endif + ); + +#endif /* #if (FW_DOWNLOAD_TIMER < 2) */ + +#endif /* #if defined(FW_DOWNLOAD_TIMER) */ + } + +#else + status = NFCSTATUS_SUCCESS; + +#endif /* #if defined (NXP_FW_INTEGRITY_VERIFY) */ + + } + else + { + DNLD_PRINT(" FW_DNLD Initialisation in Failed \n"); + } + } + + if (NFCSTATUS_PENDING != PHNFCSTATUS(status)) + { + (void)phDal4Nfc_Unregister( + psDnldContext->lower_interface.pcontext, pHwRef); + phDnldNfc_Release_Lower(psDnldContext, pHwRef); + phDnldNfc_Release_Resources(&psDnldContext); +#ifndef NFC_TIMER_CONTEXT + gpphDnldContext = psDnldContext; +#endif + } + } /* End of Status Check for Memory */ + else + { + status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INSUFFICIENT_RESOURCES); + + DNLD_PRINT(" FW_DNLD: Memory Allocation of Context Failed\n"); + } + } + + return status; + } diff --git a/libnfc-nxp/phDnldNfc.h b/libnfc-nxp/phDnldNfc.h new file mode 100644 index 0000000..7126413 --- /dev/null +++ b/libnfc-nxp/phDnldNfc.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phDnldNfc.h * +* \brief Download Mgmt Header for the Generic Download Management. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Thu Aug 26 15:39:56 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.7 $ * +* $Aliases: $ +* * +* =========================================================================== * +*/ + + +/*@{*/ + +#ifndef PHDNLDNFC_H +#define PHDNLDNFC_H + +/*@}*/ +/** + * \name Download Mgmt + * + * File: \ref phDnldNfc.h + * + */ +/*@{*/ +#define PH_DNLDNFC_FILEREVISION "$Revision: 1.7 $" /**< \ingroup grp_file_attributes */ +#define PH_DNLDNFC_FILEALIASES "$Aliases: $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +################################################################################ +***************************** Header File Inclusion **************************** +################################################################################ +*/ + +#include +#include + +/* +################################################################################ +****************************** Macro Definitions ******************************* +################################################################################ +*/ + + +/* +################################################################################ +******************** Enumeration and Structure Definition ********************** +################################################################################ +*/ + +#ifndef NXP_FW_PARAM +extern const uint8_t *nxp_nfc_fw; +#endif /* NXP_FW_PARAM */ + + + + +/* +################################################################################ +*********************** Function Prototype Declaration ************************* +################################################################################ +*/ + +/** + * \ingroup grp_hci_nfc + * + * The phDnldNfc_Upgrade function Upgrades the firmware of + * connected NFC Device with the data provided. + * + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] pHalNotify Upper layer Notification function + * pointer. + * \param[in] psContext psContext is the context of + * the Upper Layer. + * + * \retval NFCSTATUS_PENDING Upgrade of Download Layer is in Progress. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + extern + NFCSTATUS + phDnldNfc_Upgrade ( + phHal_sHwReference_t *pHwRef, +#ifdef NXP_FW_PARAM + uint8_t *nxp_nfc_fw, + uint32_t fw_length, +#endif + pphNfcIF_Notification_CB_t upgrade_complete, + void *context + ); + + +#if !defined (NXP_FW_INTEGRITY_VERIFY) + +extern +NFCSTATUS +phDnldNfc_Run_Check( + phHal_sHwReference_t *pHwRef +#ifdef NXP_FW_PARAM + ,uint8_t *nxp_nfc_fw + uint32_t fw_length +#endif + ); +#endif /* #if !defined (NXP_FW_INTEGRITY_VERIFY) */ + + +#endif /* PHDNLDNFC_H */ + + diff --git a/libnfc-nxp/phFriNfc.h b/libnfc-nxp/phFriNfc.h new file mode 100644 index 0000000..3677405 --- /dev/null +++ b/libnfc-nxp/phFriNfc.h @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc.h + * \brief NFC FRI Main Header. + * + * Project: NFC-FRI + * + * $Date: Mon Dec 13 14:14:13 2010 $ + * $Author: ing02260 $ + * $Revision: 1.20 $ + * $Aliases: $ + * + */ + +#ifndef PHFRINFC_H /* */ +#define PHFRINFC_H /* */ +#include +#include + +#define PH_HAL4_ENABLE + +#ifdef PH_HAL4_ENABLE + #include + #define LOCK_BITS_CHECK_ENABLE +#endif + +#define FRINFC_READONLY_NDEF + +#ifdef DISABLE_MIFARE_MAPPING +#define PH_FRINFC_MAP_MIFAREUL_DISABLED +#define PH_FRINFC_MAP_MIFARESTD_DISABLED +#define PH_FRINFC_MAP_DESFIRE_DISABLED +#else +#define PH_NDEF_MIFARE_ULC +#endif + +#ifdef DISABLE_FELICA_MAPPING +#define PH_FRINFC_MAP_FELICA_DISABLED +#endif + +#ifdef DISABLE_JEWEL_MAPPING +#define PH_FRINFC_MAP_TOPAZ_DISABLED +#define PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED +#endif + +#ifdef DISABLE_ISO15693_MAPPING +#define PH_FRINFC_MAP_ISO15693_DISABLED +#endif + + +#ifdef DISABLE_FORMAT +#define PH_FRINFC_FMT_DESFIRE_DISABLED +#define PH_FRINFC_FMT_MIFAREUL_DISABLED +#define PH_FRINFC_FMT_MIFARESTD_DISABLED +#define PH_FRINFC_FMT_ISO15693_DISABLED +#endif /* #ifdef DISABLE_FORMAT */ + +#define PH_FRINFC_FMT_TOPAZ_DISABLED + +/*! + * \name NFC FRI Main Header + * + * File: \ref phFriNfc.h + * + */ +/*@{*/ + +#define PH_FRINFC_FILEREVISION "$Revision: 1.20 $" /**< \ingroup grp_file_attributes */ +#define PH_FRINFC_FILEALIASES "$Aliases: $" /**< \ingroup grp_file_attributes */ + +/*@}*/ + + +/*! + * \ingroup grp_fri_nfc_common + * + * \brief \copydoc page_cb Completion Routine + * + * NFC-FRI components that work in an overlapped style need to provide a function that is compatible + * to this definition.\n\n + * It is \b mandatory to define such a routine for components that interact with other components up or + * down the stack. Moreover, such components shall provide a function within their API to enable the + * setting of the \b Completion \b Routine address and parameters. + * + * \par First Parameter: Context + * Set to the address of the called instance (component instance context structure). For instance, + * a component that needs to give control to a component up the stack needs to call the completion + * routine of the \b upper component. The value to assign to this parameter is the \b address of + * the context structure instance of the called component. Such a structure usually contains all + * variables, data or state information a component member needs for operation. The address of the + * upper instance must be known by the lower (completing) instance. The mechanism to ensure that this + * information is present involves the structure \ref phFriNfc_CplRt_t . See its documentation for + * further information. + * + * \par Second Parameter: Status Value + * The lower layer hands over the completion status via this parameter. The completion + * routine that has been called needs to process the status in a way that is comparable to what + * a regular function return value would require. + * + * \note The prototype of the component's \b Process(ing) functions has to be compatible to this + * function pointer declaration for components interacting with others. In other cases, where + * there is no interaction or asynchronous processing the definition of the \b Process(ing) + * function can be arbitrary, if present at all. + */ + +typedef void (*pphFriNfc_Cr_t)(void*, NFCSTATUS); + + +/*! + * \ingroup grp_fri_nfc_common + * + * \brief Completion Routine structure + * + * This structure finds itself within each component that requires to report completion + * to an upper (calling) component.\n\n + * Depending on the actual implementation (static or dynamic completion information) the stack + * initialisation \b or the calling component needs to inform the initialised \b or called component + * about the completion path. This information is submitted via this structure. + * + */ +typedef struct phFriNfc_CplRt +{ + pphFriNfc_Cr_t CompletionRoutine; /*!< Address of the upper Layer's \b Process(ing) function to call upon completion. + * The stack initialiser (or depending on the implementation: the calling component) + * needs to set this member to the address of the function that needs to be within + * the completion path: A calling component would give its own processing function + * address to the lower layer. + */ + void *Context; /*!< Instance address (context) parameter. + * The stack initialiser (or depending on the implementation: the calling component) + * needs to set this member to the address of the component context structure instance + * within the completion path: A calling component would give its own instance address + * to the lower layer. + */ +} phFriNfc_CplRt_t; + + +#define NFCSTATUS_INVALID_DEVICE_REQUEST (0x10F5) + + +#endif /* __PHFRINFC_H__ */ diff --git a/libnfc-nxp/phFriNfc_DesfireFormat.c b/libnfc-nxp/phFriNfc_DesfireFormat.c new file mode 100644 index 0000000..50cf142 --- /dev/null +++ b/libnfc-nxp/phFriNfc_DesfireFormat.c @@ -0,0 +1,1425 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phFriNfc_DesfireFormat.c +* \brief This component encapsulates different format functinalities , +* for the Type4/Desfire card. +* +* Project: NFC-FRI +* +* $Date: Thu Oct 28 17:44:00 2010 $ +* $Author: ing02260 $ +* $Revision: 1.8 $ +* $Aliases: $ +* +*/ +#include +#include +#include +#include + + +/* Following section details, how to wrap the native DESFire commands in to ISO commands +Following are different native commands are wrapped under the ISO commands : +1. Crate Application +2. Select File +3. Get version +4. Create CC/NDEF File +5. Write data to STD File +In this File above commands are sent using the ISO Wrapper. + +Wrapping the native DESFire APDU's procedure +-------------------------------------------------------------------------------- +CLA INS P1 P2 Lc Data Le +0x90 Cmd 0x00 0x00 Data Len Cmd. Par's 0x00 +-----------------------------------------------------------------------------------*/ + +/****************************** Macro definitions start ********************************/ +/* This settings can be changed, depending on the requirement*/ +#define PH_FRINFC_DESF_PICC_NFC_KEY_SETTING 0x0FU + +#ifdef FRINFC_READONLY_NDEF + + #define READ_ONLY_NDEF_DESFIRE 0xFFU + #define CC_BYTES_SIZE 0x0FU + #define PH_FRINFC_DESF_READ_DATA_CMD 0xBDU + #define NATIVE_WRAPPER_READ_DATA_LC_VALUE 0x07U + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +#ifdef DESFIRE_FMT_EV1 + +#define DESFIRE_CARD_TYPE_EV1 0x01U + +#define DESFIRE_EV1_MAPPING_VERSION 0x20U + +#define DESFIRE_EV1_HW_MAJOR_VERSION 0x01U +#define DESFIRE_EV1_HW_MINOR_VERSION 0x00U +#define DESFIRE_EV1_SW_MAJOR_VERSION 0x01U +#define DESFIRE_EV1_SW_MINOR_VERSION 0x03U + +/* The below values are received for the command GET VERSION */ +#define DESFIRE_TAG_SIZE_IDENTIFIER_2K 0x16U +#define DESFIRE_TAG_SIZE_IDENTIFIER_4K 0x18U +#define DESFIRE_TAG_SIZE_IDENTIFIER_8K 0x1AU + +#define DESFIRE_2K_CARD 2048U +#define DESFIRE_4K_CARD 4096U +#define DESFIRE_8K_CARD 7680U + +#define DESFIRE_EV1_KEY_SETTINGS_2 0x21U + +#define DESFIRE_EV1_FIRST_AID_BYTE 0x01U +#define DESFIRE_EV1_SECOND_AID_BYTE 0x00U +#define DESFIRE_EV1_THIRD_AID_BYTE 0x00U + +#define DESFIRE_EV1_FIRST_ISO_FILE_ID 0x05U +#define DESFIRE_EV1_SECOND_ISO_FILE_ID 0xE1U + +#define DESFIRE_EV1_ISO_APP_DF_NAME {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01} + +#define DESFIRE_EV1_CC_FILE_ID 0x01U +#define DESFIRE_EV1_FIRST_CC_FILE_ID_BYTE 0x03U +#define DESFIRE_EV1_SECOND_CC_FILE_ID_BYTE 0xE1U + +#define DESFIRE_EV1_NDEF_FILE_ID 0x02U +#define DESFIRE_EV1_FIRST_NDEF_FILE_ID_BYTE 0x04U +#define DESFIRE_EV1_SECOND_NDEF_FILE_ID_BYTE 0xE1U + + +#define PH_FRINFC_DESF_STATE_REACTIVATE 0x0FU + +#endif /* #ifdef DESFIRE_FMT_EV1 */ +/****************************** Macro definitions end ********************************/ +/* Helper functions to create app/select app/create data file/read /write from the +CC file and NDEF files */ +static void phFriNfc_Desf_HWrapISONativeCmds(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,uint8_t CmdType); + +/* Gets H/W version details*/ +static NFCSTATUS phFriNfc_Desf_HGetHWVersion(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/* Gets S/W version details*/ +static NFCSTATUS phFriNfc_Desf_HGetSWVersion(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/* Updates the version details to context structure*/ +static NFCSTATUS phFriNfc_Desf_HUpdateVersionDetails(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*Gets UID details*/ +static NFCSTATUS phFriNfc_Desf_HGetUIDDetails(phFriNfc_sNdefSmtCrdFmt_t * NdefSmtCrdFmt); + +/*Creates Application*/ +static NFCSTATUS phFriNfc_Desf_HCreateApp(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/* Selects Application*/ +static NFCSTATUS phFriNfc_Desf_HSelectApp(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*Creates Capability Container File*/ +static NFCSTATUS phFriNfc_Desf_HCreatCCFile(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/* Create NDEF File*/ +static NFCSTATUS phFriNfc_Desf_HCreatNDEFFile(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/* Writes CC Bytes to CC File*/ +static NFCSTATUS phFriNfc_Desf_HWrCCBytes(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/* Writes NDEF data into NDEF File*/ +static NFCSTATUS phFriNfc_Desf_HWrNDEFData(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/* Transceive Cmd initiation*/ +static NFCSTATUS phFriNfc_Desf_HSendTransCmd(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +#ifdef FRINFC_READONLY_NDEF + +#if 0 +static +NFCSTATUS +phFriNfc_Desf_HReadOnlySelectCCFile ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); +#endif /* #if 0 */ + +static +NFCSTATUS +phFriNfc_Desf_HReadOnlyReadCCFile ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +static +NFCSTATUS +phFriNfc_Desf_HReadOnlyWriteCCFile ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +static +NFCSTATUS +phFriNfc_Desf_HReadOnlySelectApp ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +#ifdef DESFIRE_FMT_EV1 + +static +NFCSTATUS +phFriNfc_Desf_HReadOnlySelectAppEV1 ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +#endif /* #ifdef DESFIRE_FMT_EV1 */ + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +void phFriNfc_Desfire_Reset( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + /* This piece of code may not be useful for the current supported DESFire formatting feature*/ + /* Currently, s/w doesn't support authenticating either PICC Master key nor NFC Forum + Application Master key*/ + + /*NdefSmtCrdFmt->AddInfo.Type4Info.PICCMasterKey[] = PH_FRINFC_SMTCRDFMT_DESF_PICC_MASTER_KEY; + NdefSmtCrdFmt->AddInfo.Type4Info.NFCForumMasterkey[] = PH_FRINFC_SMTCRDFMT_DESF_NFCFORUM_APP_KEY;*/ + + /* reset to zero PICC and NFC FORUM master keys*/ + (void)memset((void *)NdefSmtCrdFmt->AddInfo.Type4Info.PICCMasterKey, + 0x00, + 16); + + (void)memset((void *)NdefSmtCrdFmt->AddInfo.Type4Info.NFCForumMasterkey, + 0x00, + 16); + NdefSmtCrdFmt->AddInfo.Type4Info.PrevState = 0; + +} + + +static void phFriNfc_Desf_HWrapISONativeCmds(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt,uint8_t CmdType) +{ + + uint16_t i=0, CmdByte=1; + uint8_t NdefFileBytes[] = PH_FRINFC_DESF_NDEFFILE_BYTES; + uint8_t CCFileBytes[] = PH_FRINFC_DESF_CCFILE_BYTES; + + + /* common elements for all the native commands*/ + + /* Class Byte */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_CLASS_BYTE; + + /* let the place to store the cmd byte type, point to next index*/ + i += 2; + + + /* P1/P2 offsets always set to zero */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_OFFSET_P1; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_OFFSET_P2; + i++; + + switch(CmdType) + { + case PH_FRINFC_DESF_GET_HW_VERSION_CMD : + case PH_FRINFC_DESF_GET_SW_VERSION_CMD : + case PH_FRINFC_DESF_GET_UID_CMD : + { + if (CmdType == PH_FRINFC_DESF_GET_HW_VERSION_CMD ) + { + /* Instruction Cmd code */ + NdefSmtCrdFmt->SendRecvBuf[CmdByte] = PH_FRINFC_DESF_GET_VER_CMD; + } + else + { + /* Instruction Cmd code */ + NdefSmtCrdFmt->SendRecvBuf[CmdByte] = PH_FRINFC_DESF_PICC_ADDI_FRAME_RESP; + } + + /* Lc: Length of wrapped data */ + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + + /* NO Data to send in this cmd*/ + /* we are not suppose to set Le*/ + /* set the length of the buffer*/ + NdefSmtCrdFmt->SendLength = i; + + break; + } + + case PH_FRINFC_DESF_CREATEAPP_CMD: + { +#ifdef DESFIRE_FMT_EV1 + uint8_t df_name[] = DESFIRE_EV1_ISO_APP_DF_NAME; +#endif /* #ifdef DESFIRE_FMT_EV1 */ + + /* Instruction Cmd code */ + NdefSmtCrdFmt->SendRecvBuf[CmdByte] = PH_FRINFC_DESF_CREATE_AID_CMD; + +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* Lc: Length of wrapped data, + here the magic number 2 is for the ISO File ID for the application */ + NdefSmtCrdFmt->SendRecvBuf[i] = (uint8_t)(PH_FRINFC_DESF_NATIVE_CRAPP_WRDT_LEN + + sizeof (df_name) + 2); + i++; + /* NFC FORUM APPLICATION ID*/ + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_FIRST_AID_BYTE; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_SECOND_AID_BYTE; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_THIRD_AID_BYTE; + i++; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + /* Lc: Length of wrapped data */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_CRAPP_WRDT_LEN; + i++; + /* NFC FORUM APPLICATION ID*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_FIRST_AID_BYTE; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_SEC_AID_BYTE; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_THIRD_AID_BYTE; + i++; + } + /* set key settings and number of keys*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_PICC_NFC_KEY_SETTING; + i++; +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* set key settings and number of keys*/ + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_KEY_SETTINGS_2; + i++; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NFCFORUM_APP_NO_OF_KEYS; + i++; + } + +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* ISO File ID */ + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_FIRST_ISO_FILE_ID; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_SECOND_ISO_FILE_ID; + i++; + /* DF file name */ + (void)memcpy ((void *)&NdefSmtCrdFmt->SendRecvBuf[i], + (void *)df_name, sizeof (df_name)); + i = (uint16_t)(i + sizeof (df_name)); + } +#endif /* #ifdef DESFIRE_FMT_EV1 */ + + /* Le bytes*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_LE_BYTE; + i++; + +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* set the length of the buffer*/ + NdefSmtCrdFmt->SendLength = i; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + NdefSmtCrdFmt->SendLength = PH_FRINFC_DESF_CREATEAPP_CMD_SNLEN; + } + break; + } + + case PH_FRINFC_DESF_SELECTAPP_CMD: + { + /* Instruction Cmd code */ + NdefSmtCrdFmt->SendRecvBuf[CmdByte] = PH_FRINFC_DESF_SLECT_APP_CMD; + + /* Lc: Length of wrapped data */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_SLAPP_WRDT_LEN; + i++; + +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* Data*/ + /* set the send buffer to create the application identifier*/ + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_FIRST_AID_BYTE; + i++; + + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_SECOND_AID_BYTE; + i++; + + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_THIRD_AID_BYTE; + i++; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + /* Data*/ + /* set the send buffer to create the application identifier*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_FIRST_AID_BYTE; + i++; + + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_SEC_AID_BYTE; + i++; + + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_THIRD_AID_BYTE; + i++; + } + + /* Le bytes*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_LE_BYTE; + i++; + + /* set the length of the buffer*/ + NdefSmtCrdFmt->SendLength = PH_FRINFC_DESF_SELECTAPP_CMD_SNLEN; + break; + } + + case PH_FRINFC_DESF_CREATECC_CMD: + { + /* Instruction Cmd code */ + NdefSmtCrdFmt->SendRecvBuf[CmdByte] = PH_FRINFC_DESF_CREATE_DATA_FILE_CMD; + +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* Lc: Length of wrapped data, + here the magic number 2 is added as part of the ISO File ID in the packet */ + NdefSmtCrdFmt->SendRecvBuf[i] = (uint8_t) + (PH_FRINFC_DESF_NATIVE_CRCCNDEF_WRDT_LEN + 2); + i++; + /* set cc file id* */ + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_CC_FILE_ID; + i++; + /* ISO File ID */ + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_FIRST_CC_FILE_ID_BYTE; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_SECOND_CC_FILE_ID_BYTE; + i++; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + /* Lc: Length of wrapped data */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_CRCCNDEF_WRDT_LEN; + i++; + /* set cc file id*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_CC_FILE_ID; + i++; + } + + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_COMM_SETTINGS; + i++; + + /* set the Access Rights are set to full read/write, full cntrl*/ + NdefSmtCrdFmt->SendRecvBuf[i] = 0xEE; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0xEE; + i++; + + /* set the file size*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_CC_FILE_SIZE; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + + /* Le bytes*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_LE_BYTE; + i++; +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* set the length of the buffer*/ + NdefSmtCrdFmt->SendLength = i; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + /* set the length of the buffer*/ + NdefSmtCrdFmt->SendLength = PH_FRINFC_DESF_CREATECCNDEF_CMD_SNLEN; + } + break; + } + + case PH_FRINFC_DESF_CREATENDEF_CMD: + { + /* Instruction Cmd code */ + NdefSmtCrdFmt->SendRecvBuf[CmdByte] = PH_FRINFC_DESF_CREATE_DATA_FILE_CMD; + +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* Lc: Length of wrapped data, + here the magic number 2 is added as part of the ISO File ID in the packet */ + NdefSmtCrdFmt->SendRecvBuf[i] = (uint8_t) + (PH_FRINFC_DESF_NATIVE_CRCCNDEF_WRDT_LEN + 2); + i++; + /* set NDEF file id* */ + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_NDEF_FILE_ID; + i++; + /* ISO File ID */ + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_FIRST_NDEF_FILE_ID_BYTE; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_SECOND_NDEF_FILE_ID_BYTE; + i++; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + /* Lc: Length of wrapped data */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_CRCCNDEF_WRDT_LEN; + i++; + + /* set NDEF file id*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NDEF_FILE_ID; + i++; + } + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_COMM_SETTINGS; + i++; + + /* set the r/w access rights.Once Authentication part is fixed, + we will use the constants*/ + NdefSmtCrdFmt->SendRecvBuf[i] = 0xEE; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0xEE; + i++; + + NdefSmtCrdFmt->SendRecvBuf[i]= (uint8_t)NdefSmtCrdFmt->AddInfo.Type4Info.CardSize; + i++; + NdefSmtCrdFmt->SendRecvBuf[i]= (uint8_t) + (NdefSmtCrdFmt->AddInfo.Type4Info.CardSize >> 8); + i++; + NdefSmtCrdFmt->SendRecvBuf[i]= (uint8_t) + (NdefSmtCrdFmt->AddInfo.Type4Info.CardSize >> 16); + i++; + + /* Le bytes*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_LE_BYTE; + i++; + +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* set the length of the buffer*/ + NdefSmtCrdFmt->SendLength = i; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + /* set the length of the buffer*/ + NdefSmtCrdFmt->SendLength = PH_FRINFC_DESF_CREATECCNDEF_CMD_SNLEN; + } + break; + } + + case PH_FRINFC_DESF_WRITECC_CMD: + { + /* Instruction Cmd code */ + NdefSmtCrdFmt->SendRecvBuf[CmdByte] = PH_FRINFC_DESF_WRITE_CMD; + + /* Lc: Length of wrapped data */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_WRCC_WRDT_LEN; + i++; + +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* set the file id*/ + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_CC_FILE_ID; + i++; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + /* set the file id*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_CC_FILE_ID; + i++; + } + + /* set the offset to zero*/ + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + + /* Set the length of data available to write*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_CC_FILE_SIZE; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + CCFileBytes[2] = (uint8_t)DESFIRE_EV1_MAPPING_VERSION; + + /* Length value is updated in the CC as per the card size received from + the GetVersion command */ + CCFileBytes[11] = (uint8_t) + (NdefSmtCrdFmt->AddInfo.Type4Info.CardSize >> 8); + CCFileBytes[12] = (uint8_t) + (NdefSmtCrdFmt->AddInfo.Type4Info.CardSize); + } +#endif /* #ifdef DESFIRE_FMT_EV1 */ + /*set the data to be written to the CC file*/ + (void)memcpy ((void *)&NdefSmtCrdFmt->SendRecvBuf[i], + (void *)CCFileBytes, sizeof (CCFileBytes)); +#ifdef DESFIRE_FMT_EV1 +#else + i++; +#endif /* #ifdef DESFIRE_FMT_EV1 */ + + i = (uint16_t)(i + sizeof (CCFileBytes)); + + /* Le bytes*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_LE_BYTE; + i++; +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + NdefSmtCrdFmt->SendLength = i; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + NdefSmtCrdFmt->SendLength = PH_FRINFC_DESF_WRITECC_CMD_SNLEN; + } + break; + } + + case PH_FRINFC_DESF_WRITENDEF_CMD: + { + /* Instruction Cmd code */ + NdefSmtCrdFmt->SendRecvBuf[CmdByte] = PH_FRINFC_DESF_WRITE_CMD; + + /* Lc: Length of wrapped data */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_WRNDEF_WRDT_LEN; + i++; + +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* set the file id*/ + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_NDEF_FILE_ID; + i++; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + /* set the file id*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NDEF_FILE_ID; + i++; + } + + /* set the offset to zero*/ + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + + /* Set the length of data available to write*/ + NdefSmtCrdFmt->SendRecvBuf[i] = 0x02; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + + /*set the data to be written to the CC file*/ + + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[i], + NdefFileBytes, sizeof (NdefFileBytes)); + i = (uint16_t)(i + sizeof (NdefFileBytes)); + + /* Le bytes*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_LE_BYTE; + i++; + + NdefSmtCrdFmt->SendLength = PH_FRINFC_DESF_WRITENDEF_CMD_SNLEN; + break; + } + + default: + { + break; + } + } +} + +static NFCSTATUS phFriNfc_Desf_HGetHWVersion(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; +#ifdef PH_HAL4_ENABLE + /* Removed uint8_t i=0; */ +#else + uint8_t i=0; +#endif /* #ifdef PH_HAL4_ENABLE */ + + /*set the state*/ + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_GET_HW_VERSION; + + /* Helper routine to wrap the native DESFire cmds*/ + phFriNfc_Desf_HWrapISONativeCmds(NdefSmtCrdFmt,PH_FRINFC_DESF_GET_HW_VERSION_CMD); + + status = phFriNfc_Desf_HSendTransCmd(NdefSmtCrdFmt); + + return ( status); +} + +static NFCSTATUS phFriNfc_Desf_HGetSWVersion(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + + NFCSTATUS status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_FORMAT_ERROR); + + if (NdefSmtCrdFmt->SendRecvBuf[*(NdefSmtCrdFmt->SendRecvLength)- 1] == + PH_FRINFC_DESF_PICC_ADDI_FRAME_RESP) + { + /*set the state*/ + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_GET_SW_VERSION; + + /* Helper routine to wrap the native DESFire cmds*/ + phFriNfc_Desf_HWrapISONativeCmds(NdefSmtCrdFmt,PH_FRINFC_DESF_GET_SW_VERSION_CMD); + + status = phFriNfc_Desf_HSendTransCmd(NdefSmtCrdFmt); + } + return status; +} + +static NFCSTATUS phFriNfc_Desf_HUpdateVersionDetails(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS status = PHNFCSTVAL(CID_NFC_NONE, + NFCSTATUS_SUCCESS); + + if (NdefSmtCrdFmt->SendRecvBuf[*(NdefSmtCrdFmt->SendRecvLength) - + PH_SMTCRDFMT_DESF_VAL1] == PH_FRINFC_DESF_PICC_ADDI_FRAME_RESP) + { + NdefSmtCrdFmt->AddInfo.Type4Info.MajorVersion = NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL3]; + NdefSmtCrdFmt->AddInfo.Type4Info.MinorVersion = NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL4]; + + if ((PH_FRINFC_DESF4_MAJOR_VERSION == NdefSmtCrdFmt->AddInfo.Type4Info.MajorVersion) && + (PH_FRINFC_DESF4_MINOR_VERSION == NdefSmtCrdFmt->AddInfo.Type4Info.MinorVersion)) + { + /* card size of DESFire4 type */ + NdefSmtCrdFmt->AddInfo.Type4Info.CardSize = PH_FRINFC_DESF4_MEMORY_SIZE; + + } +#ifdef DESFIRE_FMT_EV1 + else if ((DESFIRE_EV1_SW_MAJOR_VERSION == NdefSmtCrdFmt->AddInfo.Type4Info.MajorVersion) && + (DESFIRE_EV1_SW_MINOR_VERSION == NdefSmtCrdFmt->AddInfo.Type4Info.MinorVersion)) + { + NdefSmtCrdFmt->CardType = DESFIRE_CARD_TYPE_EV1; + } +#endif /* #ifdef DESFIRE_FMT_EV1 */ + else + { + // need to handle the Desfire8 type cards + // need to use get free memory + status = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); + + } +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + switch (NdefSmtCrdFmt->SendRecvBuf[5]) + { + case DESFIRE_TAG_SIZE_IDENTIFIER_2K: + { + NdefSmtCrdFmt->AddInfo.Type4Info.CardSize = DESFIRE_2K_CARD; + break; + } + + case DESFIRE_TAG_SIZE_IDENTIFIER_4K: + { + NdefSmtCrdFmt->AddInfo.Type4Info.CardSize = DESFIRE_4K_CARD; + break; + } + + case DESFIRE_TAG_SIZE_IDENTIFIER_8K: + { + NdefSmtCrdFmt->AddInfo.Type4Info.CardSize = DESFIRE_8K_CARD; + break; + } + + default: + { + status = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); + break; + } + } + } +#endif /* #ifdef DESFIRE_FMT_EV1 */ + } + + return status; +} + +static NFCSTATUS phFriNfc_Desf_HGetUIDDetails(phFriNfc_sNdefSmtCrdFmt_t * NdefSmtCrdFmt) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + if (NdefSmtCrdFmt->SendRecvBuf[*(NdefSmtCrdFmt->SendRecvLength) - + PH_SMTCRDFMT_DESF_VAL1] == PH_FRINFC_DESF_PICC_ADDI_FRAME_RESP) + { + /*set the state*/ + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_GET_UID; + + /* Helper routine to wrap the native desfire cmds*/ + phFriNfc_Desf_HWrapISONativeCmds(NdefSmtCrdFmt,PH_FRINFC_DESF_GET_UID_CMD); + + status = phFriNfc_Desf_HSendTransCmd(NdefSmtCrdFmt); + } + + return status; + +} + + +static NFCSTATUS phFriNfc_Desf_HCreateApp(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_FORMAT_ERROR); + + if ( (NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL14] == PH_FRINFC_DESF_NAT_WRAP_FIRST_RESP_BYTE) + && (NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL15] == PH_FRINFC_DESF_NAT_WRAP_SEC_RESP_BYTE )) + { + /*set the state*/ + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_CREATE_AID; + + /* Helper routine to wrap the native DESFire cmds*/ + phFriNfc_Desf_HWrapISONativeCmds(NdefSmtCrdFmt,PH_FRINFC_DESF_CREATEAPP_CMD); + + status = phFriNfc_Desf_HSendTransCmd(NdefSmtCrdFmt); + } + return ( status); +} + + +static NFCSTATUS phFriNfc_Desf_HSelectApp(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + + NFCSTATUS status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_FORMAT_ERROR); + + /* check for the response of previous operation, before + issuing the next command*/ + + if ( (NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL0] == PH_FRINFC_DESF_NAT_WRAP_FIRST_RESP_BYTE) && + (NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL1] == PH_FRINFC_DESF_NAT_WRAP_SEC_RESP_BYTE )) + { + /*set the state*/ + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_SELECT_APP; + + /* Helper routine to wrap the native DESFire cmds*/ + phFriNfc_Desf_HWrapISONativeCmds(NdefSmtCrdFmt,PH_FRINFC_DESF_SELECTAPP_CMD); + + status = phFriNfc_Desf_HSendTransCmd(NdefSmtCrdFmt); + } + return ( status); + +} + +static NFCSTATUS phFriNfc_Desf_HCreatCCFile(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_FORMAT_ERROR); + + if ( (NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL0] == PH_FRINFC_DESF_NATIVE_RESP_BYTE1) && + (NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL1] == PH_FRINFC_DESF_NATIVE_RESP_BYTE2 )) + { + /*set the state*/ + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_CREATE_CCFILE; + + /* Helper routine to wrap the native DESFire cmds*/ + phFriNfc_Desf_HWrapISONativeCmds(NdefSmtCrdFmt,PH_FRINFC_DESF_CREATECC_CMD); + + status = phFriNfc_Desf_HSendTransCmd(NdefSmtCrdFmt); + } + return ( status); +} + +static NFCSTATUS phFriNfc_Desf_HCreatNDEFFile(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + + NFCSTATUS status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_FORMAT_ERROR); + + if ( (NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL0] == PH_FRINFC_DESF_NATIVE_RESP_BYTE1) && + (NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL1] == PH_FRINFC_DESF_NATIVE_RESP_BYTE2 )) + { + /*set the state*/ + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_CREATE_NDEFFILE; + + /* Helper routine to wrap the native desfire cmds*/ + phFriNfc_Desf_HWrapISONativeCmds(NdefSmtCrdFmt,PH_FRINFC_DESF_CREATENDEF_CMD); + + status = phFriNfc_Desf_HSendTransCmd(NdefSmtCrdFmt); + + } + + return ( status); + +} + +static NFCSTATUS phFriNfc_Desf_HWrCCBytes(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + + NFCSTATUS result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_FORMAT_ERROR); + if ( (NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL0] == PH_FRINFC_DESF_NATIVE_RESP_BYTE1) && + (NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL1] == PH_FRINFC_DESF_NATIVE_RESP_BYTE2 )) + { + + /*set the state*/ + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_WRITE_CC_FILE; + + /* Helper routine to wrap the native DESFire cmds*/ + phFriNfc_Desf_HWrapISONativeCmds(NdefSmtCrdFmt,PH_FRINFC_DESF_WRITECC_CMD); + + result = phFriNfc_Desf_HSendTransCmd(NdefSmtCrdFmt); + } + return (result); +} + +static NFCSTATUS phFriNfc_Desf_HWrNDEFData(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_FORMAT_ERROR); + + + if ( (NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL0] == PH_FRINFC_DESF_NATIVE_RESP_BYTE1) && + (NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL1] == PH_FRINFC_DESF_NATIVE_RESP_BYTE2 )) + { + /*set the state*/ + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_WRITE_NDEF_FILE; + + /* Helper routine to wrap the native DESFire cmds*/ + phFriNfc_Desf_HWrapISONativeCmds(NdefSmtCrdFmt,PH_FRINFC_DESF_WRITENDEF_CMD); + + Result = phFriNfc_Desf_HSendTransCmd(NdefSmtCrdFmt); + } + return (Result); +} + +static NFCSTATUS phFriNfc_Desf_HSendTransCmd(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* set the command type*/ +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.Iso144434Cmd = phHal_eIso14443_4_Raw; +#else + NdefSmtCrdFmt->Cmd.Iso144434Cmd = phHal_eIso14443_4_CmdListTClCmd; +#endif /* #ifdef PH_HAL4_ENABLE */ + + /* set the Additional Info*/ + NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.NADPresent = 0; + + /*set the completion routines for the desfire card operations*/ + NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = phFriNfc_NdefSmtCrd_Process; + NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = NdefSmtCrdFmt; + + /* set the receive length */ + *NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE; + + + /*Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive(NdefSmtCrdFmt->LowerDevice, + &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo, + NdefSmtCrdFmt->psRemoteDevInfo, + NdefSmtCrdFmt->Cmd, + &NdefSmtCrdFmt->psDepAdditionalInfo, + NdefSmtCrdFmt->SendRecvBuf, + NdefSmtCrdFmt->SendLength, + NdefSmtCrdFmt->SendRecvBuf, + NdefSmtCrdFmt->SendRecvLength); + + return (status); + + +} + +NFCSTATUS phFriNfc_Desfire_Format(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + + NFCSTATUS status = NFCSTATUS_SUCCESS; +#ifdef DESFIRE_FMT_EV1 + NdefSmtCrdFmt->CardType = 0; +#endif /* #ifdef DESFIRE_FMT_EV1 */ + status = phFriNfc_Desf_HGetHWVersion(NdefSmtCrdFmt); + return (status); +} + +#ifdef FRINFC_READONLY_NDEF + +#if 0 +static +NFCSTATUS +phFriNfc_Desf_HReadOnlySelectCCFile ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + return result; +} +#endif /* #if 0 */ + +static +NFCSTATUS +phFriNfc_Desf_HReadOnlyReadCCFile ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint16_t i = 0; + + if ((PH_FRINFC_DESF_NATIVE_RESP_BYTE1 == + NdefSmtCrdFmt->SendRecvBuf[(*NdefSmtCrdFmt->SendRecvLength - 2)]) + && (PH_FRINFC_DESF_NATIVE_RESP_BYTE2 == + NdefSmtCrdFmt->SendRecvBuf[(*NdefSmtCrdFmt->SendRecvLength - 1)])) + { + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_RO_READ_CC_FILE; + + /* Class Byte */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_CLASS_BYTE; + i++; + + /* let the place to store the cmd byte type, point to next index + Instruction Cmd code */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_READ_DATA_CMD; + i++; + + + /* P1/P2 offsets always set to zero */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_OFFSET_P1; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_OFFSET_P2; + i++; + + /* Lc: Length of wrapped data */ + NdefSmtCrdFmt->SendRecvBuf[i] = NATIVE_WRAPPER_READ_DATA_LC_VALUE; + i++; + +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* set the file id*/ + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_CC_FILE_ID; + i++; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + /* set the file id*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_CC_FILE_ID; + i++; + } + + /* set the offset to zero*/ + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + + /* Set the length of data available to read */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_CC_FILE_SIZE; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + + /* Le Value is set 0 */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_LE_BYTE; + i++; + + NdefSmtCrdFmt->SendLength = i; + + result = phFriNfc_Desf_HSendTransCmd (NdefSmtCrdFmt); + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_FORMAT_ERROR); + } + + return result; +} + +static +NFCSTATUS +phFriNfc_Desf_HReadOnlyWriteCCFile ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t read_cc_btyes[CC_BYTES_SIZE] = {0}; + uint16_t i = 0; + + if ((PH_FRINFC_DESF_NATIVE_RESP_BYTE1 == + NdefSmtCrdFmt->SendRecvBuf[(*NdefSmtCrdFmt->SendRecvLength - 2)]) + && (PH_FRINFC_DESF_NATIVE_RESP_BYTE2 == + NdefSmtCrdFmt->SendRecvBuf[(*NdefSmtCrdFmt->SendRecvLength - 1)])) + { + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_RO_UPDATE_CC_FILE; + + memcpy ((void *)read_cc_btyes, (void *)NdefSmtCrdFmt->SendRecvBuf, + sizeof (read_cc_btyes)); + read_cc_btyes[(sizeof (read_cc_btyes) - 1)] = READ_ONLY_NDEF_DESFIRE; + + /* Class Byte */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_CLASS_BYTE; + i++; + + /* let the place to store the cmd byte type, point to next index + Instruction Cmd code */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_WRITE_CMD; + i++; + + + /* P1/P2 offsets always set to zero */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_OFFSET_P1; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_OFFSET_P2; + i++; + + /* Lc: Length of wrapped data */ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_WRCC_WRDT_LEN; + i++; + +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + /* set the file id*/ + NdefSmtCrdFmt->SendRecvBuf[i] = DESFIRE_EV1_CC_FILE_ID; + i++; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + /* set the file id*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_CC_FILE_ID; + i++; + } + + /* set the offset to zero*/ + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + + /* Set the length of data available to write*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_CC_FILE_SIZE; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + NdefSmtCrdFmt->SendRecvBuf[i] = 0x00; + i++; + + /*set the data to be written to the CC file*/ + (void)memcpy ((void *)&NdefSmtCrdFmt->SendRecvBuf[i], + (void *)read_cc_btyes, sizeof (read_cc_btyes)); +#ifdef DESFIRE_FMT_EV1 +#else + i++; +#endif /* #ifdef DESFIRE_FMT_EV1 */ + + i = (uint16_t)(i + sizeof (read_cc_btyes)); + + /* Le bytes*/ + NdefSmtCrdFmt->SendRecvBuf[i] = PH_FRINFC_DESF_NATIVE_LE_BYTE; + i++; +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + NdefSmtCrdFmt->SendLength = i; + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + NdefSmtCrdFmt->SendLength = PH_FRINFC_DESF_WRITECC_CMD_SNLEN; + } + + result = phFriNfc_Desf_HSendTransCmd (NdefSmtCrdFmt); + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_FORMAT_ERROR); + } + + return result; +} + +static +NFCSTATUS +phFriNfc_Desf_HReadOnlySelectApp ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + + NdefSmtCrdFmt->CardType = 0; + + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_RO_SELECT_APP; + + /* Helper routine to wrap the native DESFire cmds */ + phFriNfc_Desf_HWrapISONativeCmds (NdefSmtCrdFmt, PH_FRINFC_DESF_SELECTAPP_CMD); + + result = phFriNfc_Desf_HSendTransCmd (NdefSmtCrdFmt); + + return result; +} + +#ifdef DESFIRE_FMT_EV1 +static +NFCSTATUS +phFriNfc_Desf_HReadOnlySelectAppEV1 ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + + NdefSmtCrdFmt->CardType = DESFIRE_CARD_TYPE_EV1; + + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_RO_SELECT_APP_EV1; + + /* Helper routine to wrap the native DESFire cmds */ + phFriNfc_Desf_HWrapISONativeCmds (NdefSmtCrdFmt, PH_FRINFC_DESF_SELECTAPP_CMD); + + result = phFriNfc_Desf_HSendTransCmd (NdefSmtCrdFmt); + + return result; +} +#endif /* #ifdef DESFIRE_FMT_EV1 */ + +NFCSTATUS +phFriNfc_Desfire_ConvertToReadOnly ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + +#ifdef DESFIRE_FMT_EV1 + result = phFriNfc_Desf_HReadOnlySelectAppEV1 (NdefSmtCrdFmt); +#else + result = phFriNfc_Desf_HReadOnlySelectApp (NdefSmtCrdFmt); +#endif /* #ifdef DESFIRE_FMT_EV1 */ + + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +void phFriNfc_Desf_Process( void *Context, + NFCSTATUS Status) +{ + + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt; + + NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t *)Context; + + if((NFCSTATUS_SUCCESS & PHNFCSTBLOWER) == (Status & PHNFCSTBLOWER)) + { + switch(NdefSmtCrdFmt->State) + { +#ifdef FRINFC_READONLY_NDEF +#ifdef DESFIRE_FMT_EV1 + case PH_FRINFC_DESF_STATE_RO_SELECT_APP_EV1: + { + if ((PH_FRINFC_DESF_NATIVE_RESP_BYTE1 == + NdefSmtCrdFmt->SendRecvBuf[(*NdefSmtCrdFmt->SendRecvLength - 2)]) + && (PH_FRINFC_DESF_NATIVE_RESP_BYTE2 == + NdefSmtCrdFmt->SendRecvBuf[(*NdefSmtCrdFmt->SendRecvLength - 1)])) + { + Status = phFriNfc_Desf_HReadOnlyReadCCFile (NdefSmtCrdFmt); + } + else + { + Status = phFriNfc_Desf_HReadOnlySelectApp (NdefSmtCrdFmt); + } + break; + } +#endif /* #ifdef DESFIRE_FMT_EV1 */ + + case PH_FRINFC_DESF_STATE_RO_SELECT_APP: + { + Status = phFriNfc_Desf_HReadOnlyReadCCFile (NdefSmtCrdFmt); + break; + } + + case PH_FRINFC_DESF_STATE_RO_READ_CC_FILE: + { + Status = phFriNfc_Desf_HReadOnlyWriteCCFile (NdefSmtCrdFmt); + break; + } + + case PH_FRINFC_DESF_STATE_RO_UPDATE_CC_FILE: + { + if ((PH_FRINFC_DESF_NATIVE_RESP_BYTE1 == + NdefSmtCrdFmt->SendRecvBuf[(*NdefSmtCrdFmt->SendRecvLength - 2)]) + && (PH_FRINFC_DESF_NATIVE_RESP_BYTE2 == + NdefSmtCrdFmt->SendRecvBuf[(*NdefSmtCrdFmt->SendRecvLength - 1)])) + { + /* SUCCESSFULL Formatting */ +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + Status = phFriNfc_OvrHal_Reconnect ( + NdefSmtCrdFmt->LowerDevice, + &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo, + NdefSmtCrdFmt->psRemoteDevInfo); + + if (NFCSTATUS_PENDING == Status) + { + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_REACTIVATE; + } + } +#endif /* #ifdef DESFIRE_FMT_EV1 */ + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_FORMAT_ERROR); + } + break; + } + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + case PH_FRINFC_DESF_STATE_GET_HW_VERSION: + { + /* Check and store the h/w and s/w specific details. + Ex: Major/Minor version, memory storage info. */ + + Status = phFriNfc_Desf_HGetSWVersion (NdefSmtCrdFmt); + + break; + } + + case PH_FRINFC_DESF_STATE_GET_SW_VERSION: + { + /* Check and store the h/w and s/w specific details. + Ex: Major/Minor version, memory storage info. */ + + Status = phFriNfc_Desf_HUpdateVersionDetails (NdefSmtCrdFmt); + if ( Status == NFCSTATUS_SUCCESS ) + { + Status = phFriNfc_Desf_HGetUIDDetails (NdefSmtCrdFmt); + } + break; + } + + case PH_FRINFC_DESF_STATE_GET_UID: + { + Status = phFriNfc_Desf_HCreateApp (NdefSmtCrdFmt); + break; + } + + case PH_FRINFC_DESF_STATE_CREATE_AID: + { + Status = phFriNfc_Desf_HSelectApp (NdefSmtCrdFmt); + break; + } + + case PH_FRINFC_DESF_STATE_SELECT_APP: + { + Status = phFriNfc_Desf_HCreatCCFile (NdefSmtCrdFmt); + break; + } + + case PH_FRINFC_DESF_STATE_CREATE_CCFILE: + { + Status = phFriNfc_Desf_HCreatNDEFFile (NdefSmtCrdFmt); + break; + } + + case PH_FRINFC_DESF_STATE_CREATE_NDEFFILE: + { + Status = phFriNfc_Desf_HWrCCBytes (NdefSmtCrdFmt); + break; + } + + case PH_FRINFC_DESF_STATE_WRITE_CC_FILE: + { + Status = phFriNfc_Desf_HWrNDEFData (NdefSmtCrdFmt); + break; + } + + case PH_FRINFC_DESF_STATE_WRITE_NDEF_FILE: + { + if ((PH_FRINFC_DESF_NATIVE_RESP_BYTE1 == + NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL0]) && + (PH_FRINFC_DESF_NATIVE_RESP_BYTE2 == + NdefSmtCrdFmt->SendRecvBuf[PH_SMTCRDFMT_DESF_VAL1])) + { + NdefSmtCrdFmt->CardState = 0; +#ifdef DESFIRE_FMT_EV1 + if (DESFIRE_CARD_TYPE_EV1 == NdefSmtCrdFmt->CardType) + { + Status = phFriNfc_OvrHal_Reconnect ( + NdefSmtCrdFmt->LowerDevice, + &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo, + NdefSmtCrdFmt->psRemoteDevInfo); + + if (NFCSTATUS_PENDING == Status) + { + NdefSmtCrdFmt->State = PH_FRINFC_DESF_STATE_REACTIVATE; + } + } + else +#endif /* #ifdef DESFIRE_FMT_EV1 */ + { + Status = PHNFCSTVAL (CID_NFC_NONE, NFCSTATUS_SUCCESS); + } + } + break; + } + +#ifdef DESFIRE_FMT_EV1 + case PH_FRINFC_DESF_STATE_REACTIVATE: + { + /* Do nothing */ + break; + } +#endif /* #ifdef DESFIRE_FMT_EV1 */ + + default: + { + /*set the invalid state*/ + Status = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + } + /* Handle the all the error cases*/ + if ((NFCSTATUS_PENDING & PHNFCSTBLOWER) != (Status & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_SmtCrdFmt_HCrHandler(NdefSmtCrdFmt,Status); + } + +} + diff --git a/libnfc-nxp/phFriNfc_DesfireFormat.h b/libnfc-nxp/phFriNfc_DesfireFormat.h new file mode 100644 index 0000000..cabb9b0 --- /dev/null +++ b/libnfc-nxp/phFriNfc_DesfireFormat.h @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phFriNfc_DesfireFormat.h +* \brief Type4 Smart card formatting. +* +* Project: NFC-FRI +* +* $Date: Tue Jul 27 08:59:52 2010 $ +* $Author: ing02260 $ +* $Revision: 1.3 $ +* $Aliases: $ +* +*/ + +#ifndef PHFRINFC_DESFIREFORMAT_H +#define PHFRINFC_DESFIREFORMAT_H + + +/*! \ingroup grp_file_attributes +* \name NDEF Smart Card Foramting +* +* File: \ref phFriNfc_DesfireFormat.h +* +*/ +/*@{*/ + +/*@}*/ + + +/* Enum to represent the state variables*/ +enum{ + + PH_FRINFC_DESF_STATE_CREATE_AID = 0, + PH_FRINFC_DESF_STATE_SELECT_APP = 1, + PH_FRINFC_DESF_STATE_CREATE_CCFILE = 2, + PH_FRINFC_DESF_STATE_CREATE_NDEFFILE = 3, + PH_FRINFC_DESF_STATE_WRITE_CC_FILE = 4, + PH_FRINFC_DESF_STATE_WRITE_NDEF_FILE = 5, + PH_FRINFC_DESF_STATE_DISCON = 6, + PH_FRINFC_DESF_STATE_CON = 7, + PH_FRINFC_DESF_STATE_POLL = 8, + PH_FRINFC_DESF_STATE_GET_UID = 9, + PH_FRINFC_DESF_STATE_GET_SW_VERSION = 10, + PH_FRINFC_DESF_STATE_GET_HW_VERSION = 11, +#ifdef FRINFC_READONLY_NDEF + +#ifdef DESFIRE_FMT_EV1 + PH_FRINFC_DESF_STATE_RO_SELECT_APP_EV1 = 100, +#endif /* #ifdef DESFIRE_FMT_EV1 */ + + PH_FRINFC_DESF_STATE_RO_SELECT_APP = 101, + PH_FRINFC_DESF_STATE_RO_SELECT_CC_FILE = 102, + PH_FRINFC_DESF_STATE_RO_READ_CC_FILE = 103, + PH_FRINFC_DESF_STATE_RO_UPDATE_CC_FILE = 104, + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + + /* following are used in the ISO wrapper commands*/ + PH_FRINFC_DESF_CREATEAPP_CMD = 0, + PH_FRINFC_DESF_SELECTAPP_CMD = 1, + PH_FRINFC_DESF_CREATECC_CMD = 2, + PH_FRINFC_DESF_CREATENDEF_CMD = 3, + PH_FRINFC_DESF_WRITECC_CMD = 4, +#ifdef FRINFC_READONLY_NDEF + PH_FRINFC_DESF_WRITECC_CMD_READ_ONLY = 20, +#endif /* #ifdef FRINFC_READONLY_NDEF */ + PH_FRINFC_DESF_WRITENDEF_CMD = 5, + PH_FRINFC_DESF_GET_HW_VERSION_CMD = 6, + PH_FRINFC_DESF_GET_SW_VERSION_CMD = 7, + PH_FRINFC_DESF_GET_UID_CMD = 8, + PH_FRINFC_DESF_WRITENDEF_CMD_SNLEN = 15, + PH_FRINFC_DESF_WRITECC_CMD_SNLEN = 28, + PH_FRINFC_DESF_CREATECCNDEF_CMD_SNLEN = 13, + PH_FRINFC_DESF_SELECTAPP_CMD_SNLEN = 9, + PH_FRINFC_DESF_CREATEAPP_CMD_SNLEN = 11, + PH_FRINFC_DESF_NATIVE_OFFSET_P1 = 0x00, + PH_FRINFC_DESF_NATIVE_OFFSET_P2 = 0x00, + PH_FRINFC_DESF_NATIVE_LE_BYTE = 0x00, + PH_FRINFC_DESF_NATIVE_CRAPP_WRDT_LEN = 5, + PH_FRINFC_DESF_NATIVE_SLAPP_WRDT_LEN = 3, + PH_FRINFC_DESF_NATIVE_CRCCNDEF_WRDT_LEN = 7, + PH_FRINFC_DESF_NATIVE_WRCC_WRDT_LEN = 22, + PH_FRINFC_DESF_NATIVE_WRNDEF_WRDT_LEN = 9 + +}; + + +/* CC File contents*/ + +#define PH_FRINFC_DESF_CCFILE_BYTES {0x00,0x0f,0x10,0x00,0x3B,0x00,0x34,0x04,0x06,0xE1,0x04,0x04,0x00,0x00,0x00 } +#define PH_FRINFC_DESF_NDEFFILE_BYTES {0x00,0x00} +#define PH_FRINFC_DESF_PICC_MASTER_KEY {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } +#define PH_FRINFC_DESF_NFCFORUM_APP_KEY {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } +#define PH_FRINFC_DESF_COMM_SETTINGS 0x00 +#define PH_FRINFC_DESF_CREATE_DATA_FILE_CMD 0xCD +#define PH_FRINFC_DESF_NATIVE_CLASS_BYTE 0x90 + +/* Constant defined to specify the NFC Forum Application ID : 0xEEEE10*/ +/* This is defined in order to support to N/W Byte order style : LSB : : MSB*/ +#define PH_FRINFC_DESF_FIRST_AID_BYTE 0x10 +#define PH_FRINFC_DESF_SEC_AID_BYTE 0xEE +#define PH_FRINFC_DESF_THIRD_AID_BYTE 0xEE + + +/* Create File command constants*/ +#define PH_FRINFC_DESF_CREATE_AID_CMD 0xCA + +/* Specifies the NFC Forum App Number of Keys*/ +#define PH_FRINFC_DESF_NFCFORUM_APP_NO_OF_KEYS 0x01 + +#define PH_FRINFC_DESF_SLECT_APP_CMD 0x5A + +#define PH_FRINFC_DESF_GET_VER_CMD 0x60 + + +#define PH_FRINFC_DESF_NATIVE_RESP_BYTE1 0x91 +#define PH_FRINFC_DESF_NATIVE_RESP_BYTE2 0x00 + +/* Create CC File Commands*/ +#define PH_FRINFC_DESF_CC_FILE_ID 0x03 +#define PH_FRINFC_DESF_CC_FILE_SIZE 0x0F +#define PH_FRINFC_DESF_FIRST_BYTE_CC_ACCESS_RIGHTS 0x00 +#define PH_FRINFC_DESF_SEC_BYTE_CC_ACCESS_RIGHTS 0xE0 + + +/* Create NDEF File Commands*/ +#define PH_FRINFC_DESF_NDEF_FILE_ID 0x04 +#define PH_FRINFC_DESF_NDEF_FILE_SIZE 0x04 +#define PH_FRINFC_DESF_FIRST_BYTE_NDEF_ACCESS_RIGHTS 0xE0 +#define PH_FRINFC_DESF_SEC_BYTE_NDEF_ACCESS_RIGHTS 0xEE + + +/* Write/Read Data commands/constants*/ +#define PH_FRINFC_DESF_WRITE_CMD 0x3D + +/* PICC additional frame response*/ +#define PH_FRINFC_DESF_PICC_ADDI_FRAME_RESP 0xAF + +/* Response for PICC native DESFire wrapper cmd*/ +#define PH_FRINFC_DESF_NAT_WRAP_FIRST_RESP_BYTE 0x91 +#define PH_FRINFC_DESF_NAT_WRAP_SEC_RESP_BYTE 0x00 + +/* DESFire4 Major/Minor versions*/ +#define PH_FRINFC_DESF4_MAJOR_VERSION 0x00 +#define PH_FRINFC_DESF4_MINOR_VERSION 0x06 + +/* DESFire4 memory size*/ +#define PH_FRINFC_DESF4_MEMORY_SIZE 0xEDE + +enum{ + PH_SMTCRDFMT_DESF_VAL0 = 0, + PH_SMTCRDFMT_DESF_VAL1 = 1, + PH_SMTCRDFMT_DESF_VAL2 = 2, + PH_SMTCRDFMT_DESF_VAL3 = 3, + PH_SMTCRDFMT_DESF_VAL4 = 4, + PH_SMTCRDFMT_DESF_VAL14 = 14, + PH_SMTCRDFMT_DESF_VAL15 = 15 +}; + + + +/*! +* \brief \copydoc page_reg Resets the component instance to the initial state and lets the component forget about +* the list of registered items. Moreover, the lower device is set. +* +* \param[in] NdefSmtCrdFmt Pointer to a valid or uninitialized instance of \ref phFriNfc_sNdefSmtCrdFmt_t. +* +* \note This function has to be called at the beginning, after creating an instance of +* \ref phFriNfc_sNdefSmtCrdFmt_t. Use this function to reset the instance of smart card +formatting context variables. +*/ +void phFriNfc_Desfire_Reset(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! +* \ingroup grp_fri_smart_card_formatting +* +* \brief Initiates the card formatting procedure for Remote Smart Card Type. +* +* \copydoc page_ovr The function initiates and formats the DESFire Card.After this +* operation,remote card would be properly initialized and +* Ndef Compliant.Depending upon the different card type, this +* function handles formatting procedure.This function also handles +* the different recovery procedures for different types of the cards. +* For both Format and Recovery Management same API is used. +* +* \param[in] phFriNfc_sNdefSmartCardFmt_t Pointer to a valid instance of the \ref phFriNfc_sNdefSmartCardFmt_t +* structure describing the component context. +* +* \retval NFCSTATUS_SUCCESS Card formatting has been successfully completed. +* \retval NFCSTATUS_PENDING The action has been successfully triggered. +* \retval NFCSTATUS_FORMAT_ERROR Error occured during the formatting procedure. +* \retval NFCSTATUS_INVALID_REMOTE_DEVICE Card Type is unsupported. +* \retval NFCSTATUS_INVALID_DEVICE_REQUEST Command or Operation types are mismatching. +* +*/ +NFCSTATUS phFriNfc_Desfire_Format(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! +* \brief \copydoc page_reg Resets the component instance to the initial state and lets the component forget about +* the list of registered items. Moreover, the lower device is set. +* +* \param[in] NdefSmtCrdFmt Pointer to a valid or uninitialized instance of \ref phFriNfc_sNdefSmtCrdFmt_t. +* +* \note This function has to be called at the beginning, after creating an instance of +* \ref phFriNfc_sNdefSmtCrdFmt_t. Use this function to reset the instance of smart card +formatting context variables. +*/ +void phFriNfc_Desfire_Reset(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +#ifdef FRINFC_READONLY_NDEF +/*! + * \ingroup grp_fri_smart_card_formatting + * + * \brief Initiates the conversion of the already NDEF formatted tag to READ ONLY. + * + * \copydoc page_ovr The function initiates the conversion of the already NDEF formatted + * tag to READ ONLY. After this formation, remote card would be properly Ndef Compliant and READ ONLY. + * Depending upon the different card type, this function handles formatting procedure. + * + * \param[in] phFriNfc_sNdefSmartCardFmt_t Pointer to a valid instance of the \ref phFriNfc_sNdefSmartCardFmt_t + * structure describing the component context. + * + * \retval NFCSTATUS_SUCCESS Card formatting has been successfully completed. + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_FORMAT_ERROR Error occured during the formatting procedure. + * \retval NFCSTATUS_INVALID_REMOTE_DEVICE Card Type is unsupported. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST Command or Operation types are mismatching. + * + */ +NFCSTATUS +phFriNfc_Desfire_ConvertToReadOnly ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/** +*\ingroup grp_fri_smart_card_formatting +* +* \brief Smart card Formatting \b Completion \b Routine or \b Process function +* +* \copydoc page_ovr Completion Routine: This function is called by the lower layer (OVR HAL) +* when an I/O operation has finished. The internal state machine decides +* whether to call into the lower device again or to complete the process +* by calling into the upper layer's completion routine, stored within this +* component's context (\ref phFriNfc_sNdefSmtCrdFmt_t). +* +* The function call scheme is according to \ref grp_interact. No State reset is performed during +* operation. +* +* \param[in] Context The context of the current (not the lower/upper) instance, as set by the lower, +* calling layer, upon its completion. +* \param[in] Status The completion status of the lower layer (to be handled by the implementation of +* the state machine of this function like a regular return value of an internally +* called function). +* +* \note For general information about the completion routine interface please see \ref pphFriNfc_Cr_t . * The Different Status Values are as follows +* +*/ +void phFriNfc_Desf_Process(void *Context, + NFCSTATUS Status); + + +#endif + diff --git a/libnfc-nxp/phFriNfc_DesfireMap.c b/libnfc-nxp/phFriNfc_DesfireMap.c new file mode 100644 index 0000000..2ce46ad --- /dev/null +++ b/libnfc-nxp/phFriNfc_DesfireMap.c @@ -0,0 +1,1830 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phFriNfc_Desfire.c +* \brief This component encapsulates read/write/check ndef/process functionalities, +* for the Desfire Card. +* +* Project: NFC-FRI +* +* $Date: Tue Jul 27 08:58:22 2010 $ +* $Author: ing02260 $ +* $Revision: 1.11 $ +* $Aliases: $ +* +*/ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED + +#include +#include +#include + + +/*! \ingroup grp_file_attributes +* \name NDEF Mapping +* +* File: \ref phFriNfc_Desfire.c +* +*/ +/*@{*/ +#define PHFRINFCNDEFMAP_FILEREVISION "$Revision: 1.11 $" +#define PHFRINFCNDEFMAP_FILEALIASES "$Aliases: $" + +/*@}*/ + +/***************** Start of MACROS ********************/ +#ifdef DESFIRE_EV1 + #define DESFIRE_EV1_P2_OFFSET_VALUE (0x0CU) +#endif /* #ifdef DESFIRE_EV1 */ + +/***************** End of MACROS ********************/ + +/*@}*/ + +/*! + * \name Desfire Mapping - Helper Functions + * + */ +/*@{*/ + +/*! + * \brief \copydoc page_ovr Helper function for Desfire. This function specifies + * the card is a Desfire card or not. + */ +static NFCSTATUS phFriNfc_Desfire_SelectSmartTag( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Desfire. This function is used + * to selct a file in the card. + */ +static NFCSTATUS phFriNfc_Desfire_SelectFile ( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Desfire. This function is to + * read the card. + */ +static NFCSTATUS phFriNfc_Desfire_ReadBinary( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Desfire. This function is to + * write to the card. + */ +static NFCSTATUS phFriNfc_Desfire_UpdateBinary( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Desfire. This function is to + * update the capability container of the card. + */ +static NFCSTATUS phFriNfc_Desfire_Update_SmartTagCapContainer( phFriNfc_NdefMap_t *NdefMap); + + +/* Completion Helper*/ +static void phFriNfc_Desfire_HCrHandler( phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Status); + +/* Calculates the Le Bytes for Read Operation*/ +static uint32_t phFriNfc_Desfire_HGetLeBytes( phFriNfc_NdefMap_t *NdefMap); + +static NFCSTATUS phFriNfc_Desf_HChkAndParseTLV( phFriNfc_NdefMap_t *NdefMap, + uint8_t BuffIndex); + +static NFCSTATUS phFriNfc_Desfire_HSetGet_NLEN( phFriNfc_NdefMap_t *NdefMap); + +static void phFriNfc_Desfire_HProcReadData( phFriNfc_NdefMap_t *NdefMap); + +static void phFriNfc_Desfire_HChkNDEFFileAccessRights( phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Desfire_HSendTransCmd(phFriNfc_NdefMap_t *NdefMap,uint8_t SendRecvLen); + +#ifdef PH_HAL4_ENABLE + +#else + +/* Following are the API's are used to get the version of the desfire card*/ +static NFCSTATUS phFriNfc_Desfire_HGetHWVersion(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Desfire_HGetSWVersion(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Desfire_HGetUIDDetails(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Desfire_HUpdateVersionDetails(const phFriNfc_NdefMap_t *NdefMap); + +#endif /* #ifdef PH_HAL4_ENABLE */ + +#ifdef PH_HAL4_ENABLE + +#else + +static NFCSTATUS phFriNfc_Desfire_HGetHWVersion(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + + /*set the state*/ + NdefMap->State = PH_FRINFC_DESF_STATE_GET_HW_VERSION; + + /* Helper routine to wrap the native desfire cmds*/ + PH_FRINFC_DESF_ISO_NATIVE_WRAPPER(); + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE); + + return (status); +} + +static NFCSTATUS phFriNfc_Desfire_HGetSWVersion(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + if( ( NdefMap->SendRecvBuf[*(NdefMap->SendRecvLength)- 1] == PH_FRINFC_DESF_NATIVE_GETVER_RESP) ) + { + /*set the state*/ + NdefMap->State = PH_FRINFC_DESF_STATE_GET_SW_VERSION; + + /* Helper routine to wrap the native desfire commands*/ + PH_FRINFC_DESF_ISO_NATIVE_WRAPPER(); + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE); + } +#ifdef PH_HAL4_ENABLE + else + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + } +#endif /* #ifdef PH_HAL4_ENABLE */ + return status; +} + +static NFCSTATUS phFriNfc_Desfire_HGetUIDDetails(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + + if( ( NdefMap->SendRecvBuf[*(NdefMap->SendRecvLength)- 1] == PH_FRINFC_DESF_NATIVE_GETVER_RESP) ) + { + /*set the state*/ + NdefMap->State = PH_FRINFC_DESF_STATE_GET_UID; + + /* Helper routine to wrap the native desfire commands*/ + PH_FRINFC_DESF_ISO_NATIVE_WRAPPER(); + + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE); + } +#ifdef PH_HAL4_ENABLE + else + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + } +#endif /* #ifdef PH_HAL4_ENABLE */ + return status; + +} + +static NFCSTATUS phFriNfc_Desfire_HUpdateVersionDetails(const phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + + if( ( NdefMap->SendRecvBuf[*(NdefMap->SendRecvLength)- 1] == 0xAF) ) + { + + status = NFCSTATUS_SUCCESS; + + /* We do not need the following details presently.Retained for future use*/ + #if 0 + NdefMap->AddInfo.Type4Info.MajorVersion = NdefSmtCrdFmt->SendRecvBuf[3]; + NdefMap->AddInfo.Type4Info.MinorVersion = NdefSmtCrdFmt->SendRecvBuf[4]; + if ( ( NdefMap->AddInfo.Type4Info.MajorVersion == 0x00 )&& + ( NdefMap->AddInfo.Type4Info.MinorVersion == 0x06 )) + { + /* card size of DESFire4 type */ + //NdefMap->AddInfo.Type4Info.CardSize = 0xEDE; + + } + else + { + // need to handle the Desfire8 type cards + // need to use get free memory + } + #endif + } + return status; +} + + +#endif /* #ifdef PH_HAL4_ENABLE */ + +/*! +* \brief Initiates Reading of NDEF information from the Desfire Card. +* +* The function initiates the reading of NDEF information from a Remote Device. +* It performs a reset of the state and starts the action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be +* done once the action has been triggered. +*/ + +NFCSTATUS phFriNfc_Desfire_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + NdefMap->ApduBufferSize = *PacketDataLength; + /* To return actual number of bytes read to the caller */ + NdefMap->NumOfBytesRead = PacketDataLength ; + *NdefMap->NumOfBytesRead = 0; + + /* store the offset in to map context*/ + NdefMap->Offset = Offset; + + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (*NdefMap->DataCount == NdefMap->DesfireCapContainer.NdefDataLen)) + { + /* No space on card for Reading : we have already + reached the end of file ! + Offset is set to Continue Operation */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + + /* reset the inter flag*/ + NdefMap->DesfireCapContainer.IsNlenPresentFlag = 0; + NdefMap->DesfireCapContainer.SkipNlenBytesFlag = 0; + + /* Set the desfire read operation */ + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_READ_OP; + + /* Save the packet data buffer address in the context */ + NdefMap->ApduBuffer = PacketData; + + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + +#ifdef DESFIRE_EV1 + /* Select smart tag operation. First step for the read operation. */ + if (PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 == NdefMap->CardType) + { + status = phFriNfc_Desfire_SelectFile(NdefMap); + } + else +#endif /* #ifdef DESFIRE_EV1 */ + { + status = phFriNfc_Desfire_SelectSmartTag(NdefMap); + } + } + + return status; +} + +/*! +* \brief Initiates Writing of NDEF information to the Remote Device. +* +* The function initiates the writing of NDEF information to a Remote Device. +* It performs a reset of the state and starts the action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action +* has been triggered. +*/ + +NFCSTATUS phFriNfc_Desfire_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + NdefMap->ApduBufferSize = *PacketDataLength; + NdefMap->WrNdefPacketLength = PacketDataLength; + + /* Now, let's initialize *NdefMap->WrNdefPacketLength to zero. + In case we get an error, this will be correctly set to "no byte written". + In case there is no error, this will be updated later on, in the _process function. + */ + *NdefMap->WrNdefPacketLength = 0; + + /* we have write access. */ + if( *NdefMap->DataCount >= PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE) + { + /* No space on card for writing : we have already + reached the end of file ! + Offset is set to Continue Operation */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + /* Adapt the nb of bytes that the user would like to write */ + + /*set the defire write operation*/ + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_WRITE_OP; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + NdefMap->Offset = Offset; + + /*Store the packet data buffer*/ + NdefMap->ApduBuffer = PacketData; + +#ifdef DESFIRE_EV1 + if (PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 == NdefMap->CardType) + { + status = phFriNfc_Desfire_SelectFile(NdefMap); + } + else +#endif /* #ifdef DESFIRE_EV1 */ + { + /* Select smart tag operation. First step for the write operation. */ + status = phFriNfc_Desfire_SelectSmartTag (NdefMap); + } + } + return status; +} + +/*! +* \brief Check whether a particular Remote Device is NDEF compliant. +* +* The function checks whether the peer device is NDEF compliant. +* +*/ + +NFCSTATUS phFriNfc_Desfire_ChkNdef( phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + +#ifdef PH_HAL4_ENABLE + +#ifdef DESFIRE_EV1 + /* Reset card type */ + NdefMap->CardType = 0; +#endif /* #ifdef DESFIRE_EV1 */ + /*Set the desfire operation flag*/ + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP; + + /*Call Select Smart tag Functinality*/ + status = phFriNfc_Desfire_SelectSmartTag(NdefMap); +#else + /* Need to get the version details of the card, to + identify the the desfire4card type */ + status = phFriNfc_Desfire_HGetHWVersion(NdefMap); +#endif + + return (status); +} + +static NFCSTATUS phFriNfc_Desf_HChkAndParseTLV(phFriNfc_NdefMap_t *NdefMap, uint8_t BuffIndex) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if((NdefMap->SendRecvBuf[BuffIndex] <= 0x03) || + (NdefMap->SendRecvBuf[BuffIndex] >= 0x06) ) + { + status = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + /* check for the type of TLV*/ + NdefMap->TLVFoundFlag = + ((NdefMap->SendRecvBuf[BuffIndex] == 0x04)? + PH_FRINFC_NDEFMAP_DESF_NDEF_CNTRL_TLV: + PH_FRINFC_NDEFMAP_DESF_PROP_CNTRL_TLV); + + status = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_SUCCESS); + } + return status; +} + +static NFCSTATUS phFriNfc_Desfire_HSetGet_NLEN(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + + if ( PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP == NdefMap->DespOpFlag) + { + + /*Call Select Smart tag Functinality*/ + status = phFriNfc_Desfire_SelectSmartTag(NdefMap); + } + else + { + + /* Get the Data Count and set it to NoOfBytesWritten + Update the NLEN using Transceive cmd*/ + + /*Form the packet for the update binary command*/ + NdefMap->SendRecvBuf[0] = 0x00; + NdefMap->SendRecvBuf[1] = 0xD6; + + /* As we need to set the NLEN @ first 2 bytes of NDEF File*/ + /* set the p1/p2 offsets */ + NdefMap->SendRecvBuf[2] = 0x00; /* p1 */ + NdefMap->SendRecvBuf[3] = 0x00; /* p2 */ + + /* Set only two bytes as NLEN*/ + NdefMap->SendRecvBuf[4] = 0x02; + + /* update NLEN */ + NdefMap->SendRecvBuf[5] = (uint8_t)(*NdefMap->DataCount >> PH_FRINFC_NDEFMAP_DESF_SHL8); + NdefMap->SendRecvBuf[6] = (uint8_t)(*NdefMap->DataCount & (0x00ff)); + + NdefMap->SendLength = 0x07 ; + + /* Change the state to Write */ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_UPDATE_BIN_END; + + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET); + } + return status; +} + +static void phFriNfc_Desfire_HProcReadData(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_PENDING; + uint32_t BufferSize = 0; + uint8_t BufIndex=0; + uint16_t SizeToCpy=0; + + /* Need to check the Actual Ndef Length before copying the data to buffer*/ + /* Only NDEF data should be copied , rest all the data should be ignored*/ + /* Ex : Ndef File Size 50 bytes , but only 5 bytes(NLEN) are relavent to NDEF data*/ + /* component should only copy 5 bytes to user buffer*/ + + /* Data has been read successfully in the TRX buffer. */ + /* copy it to the user buffer. */ + + /* while copying need check the offset if its begin need to skip the first 2 bytes + while copying. If its current no need to skip the first 2 bytes*/ + + if ( NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN ) + { + BufIndex = (uint8_t)(( NdefMap->DesfireCapContainer.IsNlenPresentFlag == 1 )? + 0:PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES); + + /* Update the latest NLEN to context*/ + NdefMap->DesfireCapContainer.NdefDataLen = ((*NdefMap->DataCount == 0)? + ( (((uint16_t)NdefMap->SendRecvBuf[ + PH_FRINFC_NDEFMAP_DESF_CCLEN_BYTE_FIRST_INDEX])<<8)+ \ + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_CCLEN_BYTE_SECOND_INDEX]): + NdefMap->DesfireCapContainer.NdefDataLen); + + /* Decide how many byes to be copied into user buffer: depending upon the actual NDEF + size need to copy the content*/ + if ( (NdefMap->DesfireCapContainer.NdefDataLen) <= (*NdefMap->SendRecvLength - \ + (PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET + BufIndex))) + { + SizeToCpy = NdefMap->DesfireCapContainer.NdefDataLen; + + } + else + { + SizeToCpy = ((*NdefMap->SendRecvLength)-(PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET+BufIndex)); + } + + /* Check do we have Ndef Data len > 0 present in the card.If No Ndef Data + present in the card , set the card state to Initalised and set an Error*/ + if ( NdefMap->DesfireCapContainer.NdefDataLen == 0x00 ) + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED; + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); +#ifdef PH_HAL4_ENABLE +#else + NdefMap->PrevOperation = 0; +#endif /* #ifdef PH_HAL4_ENABLE */ + phFriNfc_Desfire_HCrHandler(NdefMap,Result); + } + else + { + (void)memcpy( (&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex])), + (&(NdefMap->SendRecvBuf[BufIndex])), + (SizeToCpy)); + + /* Increment the Number of Bytes Read, which will be returned to the caller. */ + *NdefMap->NumOfBytesRead = (uint32_t)(*NdefMap->NumOfBytesRead + SizeToCpy); + + /*update the data count*/ + *NdefMap->DataCount = (uint16_t)(*NdefMap->DataCount + SizeToCpy); + + /*update the buffer index of the apdu buffer*/ + NdefMap->ApduBuffIndex = (uint16_t)(NdefMap->ApduBuffIndex + SizeToCpy); + } + } + else + { + (void)memcpy( (&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex])), + (NdefMap->SendRecvBuf),/* to avoid the length of the NDEF File*/ + (*(NdefMap->SendRecvLength)-(PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET))); + + /* Increment the Number of Bytes Read, which will be returned to the caller. */ + *NdefMap->NumOfBytesRead +=( *NdefMap->SendRecvLength - \ + (PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET)); + + /*update the data count*/ + *NdefMap->DataCount += \ + (*NdefMap->SendRecvLength - (PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET)); + + /*update the buffer index of the apdu buffer*/ + NdefMap->ApduBuffIndex += \ + *NdefMap->SendRecvLength - (PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET ); + } + + /* check whether we still have to read some more data. */ + if (*NdefMap->DataCount < NdefMap->DesfireCapContainer.NdefDataLen ) + { + /* we have some bytes to read. */ + + /* Now check, we still have bytes left in the user buffer. */ + BufferSize = NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex; + if(BufferSize != 0) + { + /* Before read need to set the flag to intimate the module to + dont skip the first 2 bytes as we are in mode reading next + continues available bytes, which will not contain the NLEN + information in the begining part that is 2 bytes*/ + NdefMap->DesfireCapContainer.IsNlenPresentFlag = 1; + /* Read Operation is not complete */ + Result = phFriNfc_Desfire_ReadBinary( NdefMap ); + /* handle the error in Transc function*/ + if ( (Result & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER) ) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Result); + } + } + else + { + /* There are some more bytes to read, but + no space in the user buffer */ + Result = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS); + NdefMap->ApduBuffIndex =0; + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Result); + } + } + else + { + if (*NdefMap->DataCount == NdefMap->DesfireCapContainer.NdefDataLen ) + { + /* we have read all the bytes available in the card. */ + Result = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS); +#ifdef PH_HAL4_ENABLE + /* Do nothing */ +#else + NdefMap->PrevOperation = 0; +#endif /* #ifndef PH_HAL4_ENABLE */ + } + else + { + /* The control should not come here. */ + /* we have actually read more byte than available in the card. */ + NdefMap->PrevOperation = 0; +#ifndef PH_HAL4_ENABLE + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_CMD_ABORTED); +#else + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_FAILED); +#endif + } + + + NdefMap->ApduBuffIndex = 0; + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Result); + } +} + + + +/*! +* \brief Completion Routine, Processing function, needed to avoid long blocking. +* \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion +* Routine in order to be able to notify the component that an I/O has finished and data are +* ready to be processed. +* +*/ + +void phFriNfc_Desfire_Process(void *Context, + NFCSTATUS Status) +{ + /*Set the context to Map Module*/ + phFriNfc_NdefMap_t *NdefMap = (phFriNfc_NdefMap_t *)Context; + uint8_t ErrFlag = 0; + uint16_t NLength = 0, + SendRecLen=0; + uint32_t BytesRead = 0; + + + /* Sujatha P: Fix for 0000255/0000257:[gk] MAP:Handling HAL Errors */ + if ( Status == NFCSTATUS_SUCCESS ) + { + switch (NdefMap->State) + { + +#ifdef PH_HAL4_ENABLE +#else + + case PH_FRINFC_DESF_STATE_GET_HW_VERSION : + + /* Check and store the h/w and s/w specific details. + Ex: Major/Minor version, memory storage info. */ + Status = phFriNfc_Desfire_HGetSWVersion(NdefMap); + + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + + break; + + case PH_FRINFC_DESF_STATE_GET_SW_VERSION : + + /* Check and store the h/w and s/w specific details. + Ex: Major/Minor version, memory storage info. */ + + Status = phFriNfc_Desfire_HUpdateVersionDetails(NdefMap); + if ( Status == NFCSTATUS_SUCCESS ) + { + Status = phFriNfc_Desfire_HGetUIDDetails(NdefMap); + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + + break; + + case PH_FRINFC_DESF_STATE_GET_UID : + + /*Set the desfire operation flag*/ + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP; + + /*Call Select Smart tag Functinality*/ + Status = phFriNfc_Desfire_SelectSmartTag(NdefMap); + + break; +#endif /* #ifdef PH_HAL4_ENABLE */ + +#ifdef DESFIRE_EV1 + case PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG_EV1: + { + if(( NdefMap->SendRecvBuf[(*(NdefMap->SendRecvLength) - 2)] == + PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[(*(NdefMap->SendRecvLength) - 1)] == + PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE)) + { + NdefMap->CardType = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1; + + Status = phFriNfc_Desfire_SelectFile(NdefMap); + + /* handle the error in Transc function*/ + if ((Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + else + { + NdefMap->CardType = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD; + /* The card is not the new desfire, so send select smart tag command + of the old desfire */ + Status = phFriNfc_Desfire_SelectSmartTag(NdefMap); + + + } + break; + } +#endif /* #ifdef DESFIRE_EV1 */ + + case PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG: +#ifdef DESFIRE_EV1 + if(( NdefMap->SendRecvBuf[(*(NdefMap->SendRecvLength) - 2)] == + PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[(*(NdefMap->SendRecvLength) - 1)] == + PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE)) +#else + if(( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW1_INDEX] == + PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW2_INDEX] == + PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE)) +#endif /* #ifdef DESFIRE_EV1 */ + { + Status = phFriNfc_Desfire_SelectFile(NdefMap); + + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + else + { + /*Error " Smart Tag Functionality Not Supported"*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_SMART_TAG_FUNC_NOT_SUPPORTED); +#ifdef DESFIRE_EV1 + NdefMap->CardType = 0; +#endif /* #ifdef DESFIRE_EV1 */ + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + + } + + break; + + case PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_FILE : + + if(( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW1_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW2_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE)) + { + /*check for the which operation */ + if( (NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_READ_OP) || + (NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP) || + (NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP )) + { + /* call for read binary operation*/ + Status = phFriNfc_Desfire_ReadBinary(NdefMap); + + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER) ) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + /*its a write Operation*/ + else if(NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_WRITE_OP ) + { + Status = phFriNfc_Desfire_UpdateBinary (NdefMap); + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + else + { + /* unknown/invalid desfire operations*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_REMOTE_DEVICE); + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + else + { + /*return Error " Select File Operation Failed"*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_REMOTE_DEVICE); + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + break; + + case PH_FRINFC_NDEFMAP_DESF_STATE_READ_CAP_CONT: + if( (NdefMap->SendRecvBuf[(*(NdefMap->SendRecvLength)-2)] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[(*(NdefMap->SendRecvLength)-1)] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE)) + { + /* Read successful. */ + /*Update the smart tag capability container*/ + Status = phFriNfc_Desfire_Update_SmartTagCapContainer(NdefMap); + + if ( Status == NFCSTATUS_SUCCESS) + { + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP; +#ifdef DESFIRE_EV1 + if (PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 == NdefMap->CardType) + { + Status = phFriNfc_Desfire_SelectFile(NdefMap); + } + else +#endif /* #ifdef DESFIRE_EV1 */ + { + Status = phFriNfc_Desfire_HSetGet_NLEN(NdefMap); + } + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + } + else + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + + } + + } + else + { + /*return Error " Capability Container Not Found"*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + break; + + case PH_FRINFC_NDEFMAP_DESF_STATE_READ_BIN: + + /* Check how many bytes have been read/returned from the card*/ + BytesRead = phFriNfc_Desfire_HGetLeBytes(NdefMap); + + /* set the send recev len*/ + SendRecLen = *NdefMap->SendRecvLength - (PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET ); + if ( (NdefMap->DesfireCapContainer.SkipNlenBytesFlag == 1) && ((BytesRead == 1) || (BytesRead == 2 ))) + { + BytesRead += PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES; /* to take care of first 2 len bytes*/ + + } + else + { + /* Nothing to process*/ + ; + } + /* Read More Number Of Bytes than Expected*/ + if ( ( BytesRead == SendRecLen ) && + ((NdefMap->SendRecvBuf[(*NdefMap->SendRecvLength-2)] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[(*NdefMap->SendRecvLength-1)] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE))) + + { + /* this is to check the card state in first Read Operation*/ + if ( NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP ) + { + /* check the actual length of the ndef data : NLEN*/ + NLength = ( (((uint16_t)NdefMap->SendRecvBuf[0])<SendRecvBuf[1]); + if (( NLength > PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE )|| + ( NLength == 0xFFFF)) + { + ErrFlag = 1; + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + /* Store the NLEN into the context */ + NdefMap->DesfireCapContainer.NdefDataLen = NLength; + + Status = phFriNfc_MapTool_SetCardState( NdefMap, + NLength); + if ( Status == NFCSTATUS_SUCCESS ) + { + /*Set the card type to Desfire*/ +#ifndef DESFIRE_EV1 + NdefMap->CardType = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD; +#endif /* #ifdef DESFIRE_EV1 */ + /*Set the state to specify True for Ndef Compliant*/ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_CHK_NDEF; + + /*set the data count back to zero*/; + *NdefMap->DataCount = 0; + /*set the apdu buffer index to zero*/ + NdefMap->ApduBuffIndex = 0; + /* Set the Operationg flag to Complete check NDEF Operation*/ + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP; + + } + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + }/* End ofNdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP*/ + } + else if ( NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_READ_OP ) + { + phFriNfc_Desfire_HProcReadData(NdefMap); + } + else + { + /* Invalid Desfire Operation */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + + } + else + { + /*handle the Error case*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_READ_FAILED); + ErrFlag =1; + } + if( ErrFlag == 1) + { + *NdefMap->DataCount = 0; + + /*set the buffer index back to zero*/ + NdefMap->ApduBuffIndex = 0; + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + + break; + + case PH_FRINFC_NDEFMAP_DESF_STATE_UPDATE_BIN_BEGIN: + if( (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW1_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW2_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE)) + { + /* Write operation was successful. */ + /* NdefMap->NumOfBytesWritten have been written on to the card. + Update the DataCount and the ApduBufferIndex */ + *NdefMap->DataCount = (uint16_t)(*NdefMap->DataCount + + NdefMap->NumOfBytesWritten); + NdefMap->ApduBuffIndex = (uint16_t)(NdefMap->ApduBuffIndex + + NdefMap->NumOfBytesWritten); + + /* Update the user-provided buffer size to write */ + *NdefMap->WrNdefPacketLength += NdefMap->NumOfBytesWritten; + + /* Call Upadte Binary function to check if some more bytes are to be written. */ + Status = phFriNfc_Desfire_UpdateBinary( NdefMap ); + } + else + { + /*handle the Error case*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_WRITE_FAILED); + + /*set the buffer index back to zero*/ + NdefMap->ApduBuffIndex = 0; + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } + break; + case PH_FRINFC_NDEFMAP_DESF_STATE_UPDATE_BIN_END : + if((NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW1_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE) && + (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_SW2_INDEX] == PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE)) + { + /* Updating NLEN operation was successful. */ + /* Entire Write Operation is complete*/ + /* Reset the relevant parameters. */ + Status = PHNFCSTVAL(CID_NFC_NONE,\ + NFCSTATUS_SUCCESS); + + /* set the state & Data len into context*/ + NdefMap->CardState = (uint8_t)((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INITIALIZED)? + PH_NDEFMAP_CARD_STATE_READ_WRITE : + NdefMap->CardState); + + NdefMap->DesfireCapContainer.NdefDataLen = (uint16_t)(*NdefMap->WrNdefPacketLength); +#ifdef PH_HAL4_ENABLE + /* Do nothing */ +#else + NdefMap->PrevOperation = 0; +#endif /* #ifndef PH_HAL4_ENABLE */ + + } + else + { + NdefMap->PrevOperation = 0; + /*handle the Error case*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_WRITE_FAILED); + } + + /*set the buffer index back to zero*/ + NdefMap->ApduBuffIndex = 0; + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + break; + + default: + /*define the invalid state*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_DEVICE_REQUEST); + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + break; + } + } + else + { + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,Status); + } +} + + + +/*! +* \brief this shall select the smart tag functinality of the Desfire card. +* +* Only when this command returns command completed it is a Smart Tag +* compatible product. +* +*/ +static +NFCSTATUS phFriNfc_Desfire_SelectSmartTag(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; +#ifdef DESFIRE_EV1 + uint8_t card_type = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1; +#endif /* #ifdef DESFIRE_EV1 */ + + /*form the packet for Select smart tag command*/ + NdefMap->SendRecvBuf[0] = 0x00; /* cls */ + NdefMap->SendRecvBuf[1] = 0xa4; /* ins */ + NdefMap->SendRecvBuf[2] = 0x04; /* p1 */ + NdefMap->SendRecvBuf[3] = 0x00; /* p2 */ + NdefMap->SendRecvBuf[4] = 0x07; /* lc */ + + /* next 7 bytes specify the DF Name*/ + NdefMap->SendRecvBuf[5] = 0xd2; + NdefMap->SendRecvBuf[6] = 0x76; + NdefMap->SendRecvBuf[7] = 0x00; + NdefMap->SendRecvBuf[8] = 0x00; + NdefMap->SendRecvBuf[9] = 0x85; + NdefMap->SendRecvBuf[10] = 0x01; + +#ifdef DESFIRE_EV1 + + switch (NdefMap->DespOpFlag) + { + case PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP: + { + /* First select the smart tag using the new desfire EV1 and increment the + "sel_index" and if it fails then try the old desfire select smart tag + command */ + if (0 == NdefMap->CardType) + { + /* p2 + NdefMap->SendRecvBuf[3] = DESFIRE_EV1_P2_OFFSET_VALUE; */ + NdefMap->SendRecvBuf[11] = 0x01; + /* Le */ + NdefMap->SendRecvBuf[12] = 0x00; + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG_EV1; + card_type = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1; + } + else + { + NdefMap->SendRecvBuf[3] = 0x00; /* p2 */ + NdefMap->SendRecvBuf[11] = 0x00; + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG; + card_type = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD; + } + break; + } + + case PH_FRINFC_NDEFMAP_DESF_READ_OP: + default : + { + if (PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 == NdefMap->CardType) + { + NdefMap->SendRecvBuf[11] = 0x01; + NdefMap->SendRecvBuf[12] = 0x00; + NdefMap->State = (uint8_t)PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG_EV1; + card_type = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1; + } + else + { + NdefMap->SendRecvBuf[11] = 0x00; + NdefMap->State = (uint8_t)PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG; + card_type = PH_FRINFC_NDEFMAP_ISO14443_4A_CARD; + } + break; + } + } + +#else /* #ifdef DESFIRE_EV1 */ + + NdefMap->SendRecvBuf[11] = 0x00; + +#endif /* #ifdef DESFIRE_EV1 */ + + /*Set the Send length*/ + NdefMap->SendLength = PH_FRINFC_NDEFMAP_DESF_CAPDU_SMARTTAG_PKT_SIZE; +#ifdef DESFIRE_EV1 + + if (PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 == card_type) + { + /* Send length is updated for the NEW DESFIRE EV1 */ + NdefMap->SendLength = (uint16_t)(NdefMap->SendLength + 1); + } + +#else + /* Change the state to Select Smart Tag */ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG; +#endif /* #ifdef DESFIRE_EV1 */ + + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET); + + return status; +} + +/*! +* \brief this shall select/access the capability container of the Desfire +* card. +* +* This shall be used to identify, if NDEF data structure do exist on +* the smart tag, we receive command completed status. +* +*/ +static +NFCSTATUS phFriNfc_Desfire_SelectFile (phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + + /* check for the invalid/unknown desfire operations*/ + if ((NdefMap->DespOpFlag != PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP)&& \ + (NdefMap->DespOpFlag != PH_FRINFC_NDEFMAP_DESF_READ_OP)&&\ + ( NdefMap->DespOpFlag != PH_FRINFC_NDEFMAP_DESF_WRITE_OP) && + ( NdefMap->DespOpFlag != PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP)) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_REMOTE_DEVICE); + } + else + { + + /* Set the command*/ + //NdefMap->Cmd.Iso144434Cmd = phHal_eIso14443_4_CmdListTClCmd; + + /* Form the packet for select file command either for the + Check Ndef/Read/Write functionalities*/ + NdefMap->SendRecvBuf[0] = 0x00; /* cls */ + NdefMap->SendRecvBuf[1] = 0xa4; /* ins */ + NdefMap->SendRecvBuf[2] = 0x00; /* p1 */ + NdefMap->SendRecvBuf[3] = 0x00; /* p2 */ + NdefMap->SendRecvBuf[4] = 0x02; /* lc */ + +#ifdef DESFIRE_EV1 + if (PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 == NdefMap->CardType) + { + NdefMap->SendRecvBuf[3] = DESFIRE_EV1_P2_OFFSET_VALUE; /* p2 */ + } +#endif /* #ifdef DESFIRE_EV1 */ + + if (NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP) + + { + /* cap container file identifier*/ + NdefMap->SendRecvBuf[5] = 0xe1; + NdefMap->SendRecvBuf[6] = 0x03; + } + /* Mantis entry 0394 fixed */ + else + { + NdefMap->SendRecvBuf[5] = (uint8_t)((NdefMap->DesfireCapContainer.NdefMsgFid) >> PH_FRINFC_NDEFMAP_DESF_SHL8); + NdefMap->SendRecvBuf[6] = (uint8_t)((NdefMap->DesfireCapContainer.NdefMsgFid) & (0x00ff)); + } + /*Set the Send length*/ + NdefMap->SendLength = PH_FRINFC_NDEFMAP_DESF_CAPDU_SELECT_FILE_PKT_SIZE; + + /* Change the state to Select File */ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_FILE; + + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET); + + } + + return status; + +} + +/*! +* \brief this shall read the data from Desfire card. +* +* This is used in two cases namely Reading the Capability container +* data( le == 0 ) and reading the file data.Maximum bytes to be read during +* a single read binary is known after the reading the data from the capability +* conatainer. +* +*/ +static +NFCSTATUS phFriNfc_Desfire_ReadBinary(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint32_t BytesToRead = 0; + uint8_t BufIndex=0,OperFlag=0; + uint16_t DataCnt=0; + + /* to read the capability container data*/ + if (NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP ) + { + /*specifies capability container shall be read*/ + NdefMap->SendRecvBuf[0] = 0x00; + NdefMap->SendRecvBuf[1] = 0xb0; + NdefMap->SendRecvBuf[2] = 0x00; /* p1 */ + NdefMap->SendRecvBuf[3] = 0x00; /* p2 */ + NdefMap->SendRecvBuf[4] = 0x0F; /* le */ + + NdefMap->SendLength = PH_FRINFC_NDEFMAP_DESF_CAPDU_READ_BIN_PKT_SIZE; + + /* Change the state to Cap Container Read */ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_READ_CAP_CONT; + + /* set the send receive buffer length*/ + OperFlag = 1; + } + /*desfire file read operation*/ + else + { + NdefMap->SendRecvBuf[0] = 0x00; + NdefMap->SendRecvBuf[1] = 0xb0; + + /*TBD the NLEN bytes*/ + if( *NdefMap->DataCount == 0 ) + { + /* first read */ + /* set the offset p1 and p2*/ + NdefMap->SendRecvBuf[2] = 0; + NdefMap->SendRecvBuf[3] = 0; + } + else + { + /* as the p1 of the 8bit is 0, p1 and p2 are used to store the + ofset value*/ + DataCnt = *NdefMap->DataCount; + DataCnt += PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES; + NdefMap->SendRecvBuf[2] = (uint8_t)((DataCnt)>> PH_FRINFC_NDEFMAP_DESF_SHL8); + NdefMap->SendRecvBuf[3] = (uint8_t)((DataCnt)& (0x00ff)); + } + /* calculate the Le Byte*/ + BytesToRead = phFriNfc_Desfire_HGetLeBytes(NdefMap); + + if ( NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN ) + { + /* BufIndex represents the 2 NLEN bytes and decides about the presence of + 2 bytes NLEN data*/ + + BufIndex = (uint8_t)(( NdefMap->DesfireCapContainer.SkipNlenBytesFlag == 1 ) ? + PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES:0); + + if( ((BytesToRead == 1) || (BytesToRead == 2)) && (NdefMap->DesfireCapContainer.SkipNlenBytesFlag == 1)) + { + BytesToRead += BufIndex; + } + } + + /* set the Le byte*/ + /* This following code is true for get nlen and current offset set*/ + NdefMap->SendRecvBuf[4]=(uint8_t) BytesToRead ; + + /* Change the state to Read */ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_READ_BIN; + + /*set the send length*/ + NdefMap->SendLength = PH_FRINFC_NDEFMAP_DESF_CAPDU_READ_BIN_PKT_SIZE; + OperFlag = 2; + } + + if (OperFlag == 1 ) + { + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE); + } + else + { + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,(uint8_t)(BytesToRead +PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET)); + } + return (status); +} + +/*! +* \brief this shall write the data to Desfire card. +* Maximum bytes to be written during a single update binary +* is known after the reading the data from the capability +* conatainer. +* +* le filed specifes , how many bytes of data to be written to the +* Card. +* +*/ +static +NFCSTATUS phFriNfc_Desfire_UpdateBinary(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + uint16_t noOfBytesToWrite = 0, DataCnt=0, + index=0; + + /* Do we have space in the file to write? */ + if ( (*NdefMap->DataCount < PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE) && + (NdefMap->ApduBuffIndex < NdefMap->ApduBufferSize)) + { + /* Yes, we have some bytes to write */ + /* Check and set the card memory size , if user sent bytes are more than the + card memory size*/ + if( (uint16_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >\ + (uint16_t)(PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE - *NdefMap->DataCount)) + { + NdefMap->ApduBufferSize =( (PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE) - (*NdefMap->DataCount + NdefMap->ApduBuffIndex)); + } + + /* Now, we have space in the card to write the data, */ + /*Form the packet for the update binary command*/ + NdefMap->SendRecvBuf[0] = 0x00; + NdefMap->SendRecvBuf[1] = 0xD6; + + if( *NdefMap->DataCount == 0) + { + /* set the p1/p2 offsets */ + NdefMap->SendRecvBuf[2] = 0x00; /* p1 */ + NdefMap->SendRecvBuf[3] = 0x00; /* p2 */ + NdefMap->DesfireCapContainer.SkipNlenBytesFlag = 0; + } + else + { + /* as the p1 of the 8bit is 0, p1 and p2 are used to store the + ofset value*/ + /* This sets card offset in a card for a write operation. + 2 is + added as first 2 offsets represents the size of the NDEF Len present + in the file*/ + + DataCnt = *NdefMap->DataCount; + DataCnt += PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES; + NdefMap->SendRecvBuf[2] = (uint8_t)((DataCnt)>> PH_FRINFC_NDEFMAP_DESF_SHL8); + NdefMap->SendRecvBuf[3] = (uint8_t)((DataCnt)& (0x00ff)); + /* No need to attach 2 NLEN bytes at the begining. + as we have already attached in the first write operation.*/ + NdefMap->DesfireCapContainer.SkipNlenBytesFlag = 1; + + } + + /* Calculate the bytes to write */ + if( (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >= (uint32_t)( NdefMap->DesfireCapContainer.MaxCmdSize )) + + { + noOfBytesToWrite = ( ( NdefMap->DesfireCapContainer.SkipNlenBytesFlag == 1) ? + NdefMap->DesfireCapContainer.MaxCmdSize : + (NdefMap->DesfireCapContainer.MaxCmdSize - PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES)); + } + else + { + /* Read only till the available buffer space */ + noOfBytesToWrite = (uint16_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + } + + if ( NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN ) + { + if ( NdefMap->DesfireCapContainer.SkipNlenBytesFlag == 1 ) + { + index = 5; + /* To Specify the NDEF data len written : updated at the of write cycle*/ + NdefMap->SendRecvBuf[4] = (uint8_t)noOfBytesToWrite; + } + else + { + /* Leave space to update NLEN */ + NdefMap->SendRecvBuf[5] = 0x00; + NdefMap->SendRecvBuf[6] = 0x00; + index =7; + /* To Specify the NDEF data len written : updated at the of write cycle*/ + NdefMap->SendRecvBuf[4] = (uint8_t)noOfBytesToWrite + PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES; + } + + /* copy the data to SendRecvBuf from the apdu buffer*/ + (void)memcpy( &NdefMap->SendRecvBuf[index], + &NdefMap->ApduBuffer[NdefMap->ApduBuffIndex], + noOfBytesToWrite); + NdefMap->SendLength = (noOfBytesToWrite + index); + } + else + { + NdefMap->SendRecvBuf[4] = (uint8_t)noOfBytesToWrite; + + /* copy the data to SendRecvBuf from the apdu buffer*/ + (void)memcpy( &NdefMap->SendRecvBuf[5], + &NdefMap->ApduBuffer[NdefMap->ApduBuffIndex], + noOfBytesToWrite); + NdefMap->SendLength = (noOfBytesToWrite + 5); + } + + /* Store the number of bytes being written in the context structure, so that + the parameters can be updated, after a successful write operation. */ + NdefMap->NumOfBytesWritten = noOfBytesToWrite; + + /* Change the state to Write */ + NdefMap->State = PH_FRINFC_NDEFMAP_DESF_STATE_UPDATE_BIN_BEGIN; + + status = phFriNfc_Desfire_HSendTransCmd(NdefMap,PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET); + + } /* if(NdefMap->ApduBuffIndex < NdefMap->ApduBufferSize) */ + else + { + if ( (*NdefMap->DataCount == PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE) || + (NdefMap->ApduBuffIndex == NdefMap->ApduBufferSize)) + { + /* The NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_SET_LEN_OP is not + required, because the DespOpFlag shall be WRITE_OP + */ + /* Update the NLEN Bytes*/ +#ifdef PH_HAL4_ENABLE + /* Do nothing */ +#else + NdefMap->DespOpFlag = PH_FRINFC_NDEFMAP_DESF_SET_LEN_OP; +#endif /* #ifdef PH_HAL4_ENABLE */ + status = phFriNfc_Desfire_HSetGet_NLEN(NdefMap); + } + else + { + /* The control should not come here. + wrong internal calculation. + we have actually written more than the space available + in the card ! */ +#ifndef PH_HAL4_ENABLE + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_CMD_ABORTED); +#else + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_FAILED); +#endif + /* Reset the relevant parameters. */ + NdefMap->ApduBuffIndex = 0; + NdefMap->PrevOperation = 0; + + /* call respective CR */ + phFriNfc_Desfire_HCrHandler(NdefMap,status); + } + + } + /* if(*NdefMap->DataCount < PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE) */ + + return status; +} + + +static void phFriNfc_Desfire_HChkNDEFFileAccessRights(phFriNfc_NdefMap_t *NdefMap) +{ + if ( (NdefMap->DesfireCapContainer.ReadAccess == 0x00) && + (NdefMap->DesfireCapContainer.WriteAccess == 0x00 )) + { + /* Set the card state to Read/write State*/ + /* This state can be either INITIALISED or READWRITE. but default + is INITIALISED */ + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE; + + } + else if((NdefMap->DesfireCapContainer.ReadAccess == 0x00) && + (NdefMap->DesfireCapContainer.WriteAccess == 0xFF )) + { + /* Set the card state to Read Only State*/ + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY; + } + else + { + /* Set the card state to invalid State*/ + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } +} + +/*! +* \brief this shall update the Desfire capability container structure. +* +* This function shall store version,maximum Ndef data structure size, +* Read Access permissions, Write Access permissions , Maximum data size +* that can be sent using a single Update Binary, maximum data size that +* can be read from the Desfire using a singlr read binary. +* These vaues shall be stored and used during the read/update binary +* operations. +* +*/ +static +NFCSTATUS phFriNfc_Desfire_Update_SmartTagCapContainer(phFriNfc_NdefMap_t *NdefMap) +{ + uint16_t CapContSize = 0, + /* this is initalised 2 because CCLEN includes the field size bytes i.e 2bytes*/ + CCLen= 0; + uint8_t ErrFlag = 0; + + NFCSTATUS status= NFCSTATUS_SUCCESS; + + /*Check the Size of Cap Container */ + CapContSize = ( (((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_CCLEN_BYTE_FIRST_INDEX])<<8)+ \ + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_CCLEN_BYTE_SECOND_INDEX]); + + CCLen += 2; + + if ( (CapContSize < 0x0f) || (CapContSize == 0xffff)) + { + ErrFlag =1; + } + else + { + /*Version : Smart Tag Spec version */ + /* check for the validity of Major and Minor Version numbers*/ + status = phFriNfc_MapTool_ChkSpcVer ( NdefMap, + PH_FRINFC_NDEFMAP_DESF_VER_INDEX); + if ( status != NFCSTATUS_SUCCESS ) + { + ErrFlag =1; + } + else + { + CCLen += 1; + + /*Get Response APDU data size + to check the integration s/w response size*/ +#ifdef PH_HAL4_ENABLE + { + uint16_t max_rsp_size = + ((((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLE_BYTE_FIRST_INDEX]) << 8)\ + + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLE_BYTE_SECOND_INDEX]); + NdefMap->DesfireCapContainer.MaxRespSize = + ((max_rsp_size > PHHAL_MAX_DATASIZE)? + (PHHAL_MAX_DATASIZE) : max_rsp_size); + } +#else + NdefMap->DesfireCapContainer.MaxRespSize = + ((((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLE_BYTE_FIRST_INDEX]) << 8)\ + +NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLE_BYTE_SECOND_INDEX]); +#endif /* #ifdef PH_HAL4_ENABLE */ + + /*Get Command APDU data size*/ +#ifdef PH_HAL4_ENABLE + { + uint16_t max_cmd_size = + ((((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLC_BYTE_FIRST_INDEX])<<8)\ + + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLC_BYTE_SECOND_INDEX]); + + NdefMap->DesfireCapContainer.MaxCmdSize = + ((max_cmd_size > PHHAL_MAX_DATASIZE)? + (PHHAL_MAX_DATASIZE): max_cmd_size); + } +#else + NdefMap->DesfireCapContainer.MaxCmdSize = + ((((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLC_BYTE_FIRST_INDEX])<<8)\ + +NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_MLC_BYTE_SECOND_INDEX]); +#endif /* #ifdef PH_HAL4_ENABLE */ + /* Check for the Validity of Cmd & Resp Size*/ + /* check the Validity of the Cmd Size*/ + if( (NdefMap->DesfireCapContainer.MaxRespSize < 0x0f) || + ( NdefMap->DesfireCapContainer.MaxCmdSize == 0x00)) + { + ErrFlag=1; + + } + else + { + CCLen += 4; + + /* Check and Parse the TLV structure */ + /* In future this chk can be extended to Propritery TLV */ + //status = phFriNfc_ChkAndParseTLV(NdefMap); + status = phFriNfc_Desf_HChkAndParseTLV(NdefMap,PH_FRINFC_NDEFMAP_DESF_TLV_INDEX); + if ( (status == NFCSTATUS_SUCCESS) && (NdefMap->TLVFoundFlag == PH_FRINFC_NDEFMAP_DESF_NDEF_CNTRL_TLV)) + { + CCLen += 1; + + /* check the TLV length*/ + if ( (( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_TLV_LEN_INDEX]) > 0x00 ) && + (( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_TLV_LEN_INDEX]) <= 0xFE )&& + (( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_TLV_LEN_INDEX]) == 0x06 )) + { + CCLen +=1; + /* store the contents in to the container structure*/ + NdefMap->DesfireCapContainer.NdefMsgFid = ( (((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_NDEF_FILEID_BYTE_FIRST_INDEX])<SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_NDEF_FILEID_BYTE_SECOND_INDEX]); + + CCLen +=2; + + /* Invalid Msg File Id : User Can't Have read/write Opeartion*/ + if ( (NdefMap->DesfireCapContainer.NdefMsgFid == 0xFFFF) || + (NdefMap->DesfireCapContainer.NdefMsgFid == 0xE102) || + (NdefMap->DesfireCapContainer.NdefMsgFid == 0xE103) || + (NdefMap->DesfireCapContainer.NdefMsgFid == 0x3F00) || + (NdefMap->DesfireCapContainer.NdefMsgFid == 0x3FFF ) ) + { + + ErrFlag=1; + } + else + { + /*Get Ndef Size*/ + NdefMap->DesfireCapContainer.NdefFileSize = + ((((uint16_t)NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_NDEF_FILESZ_BYTE_FIRST_INDEX])<<8) + | (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_NDEF_FILESZ_BYTE_SECOND_INDEX] & 0x00ff)); + + + /*Check Ndef Size*/ + /* TBD : Do we need to minus 2 bytes of size it self?*/ + if ( ((NdefMap->DesfireCapContainer.NdefFileSize -2) <= 0x0004 ) || + ((NdefMap->DesfireCapContainer.NdefFileSize -2) == 0xFFFD ) ) + { + ErrFlag=1; + } + else + { + CCLen +=2; + + /*Ndef File Read Access*/ + NdefMap->DesfireCapContainer.ReadAccess = NdefMap->\ + SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_NDEF_FILERD_ACCESS_INDEX] ; + + /*Ndef File Write Access*/ + NdefMap->DesfireCapContainer.WriteAccess = NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_DESF_NDEF_FILEWR_ACCESS_INDEX]; + + CCLen +=2; + + phFriNfc_Desfire_HChkNDEFFileAccessRights(NdefMap); + } + } + } + else + { + + /* TLV Lenth is of two byte value + TBD: As the length of TLV is fixed for 6 bytes. We need not + handle the 2 byte value*/ + + + } + } + else + { + if ( NdefMap->TLVFoundFlag == PH_FRINFC_NDEFMAP_DESF_PROP_CNTRL_TLV ) + { + /*TBD: To Handle The Proprietery TLV*/ + } + else + { + /*Invalid T found case*/ + ErrFlag =1; + } + } + /* check for the entire LENGTH Validity + CCLEN + TLV L value == CCLEN*/ + if ( CapContSize < CCLen ) + { + ErrFlag=1; + } + + }/* if NdefMap->DesfireCapContainer.MaxRespSize < 0x0f */ + }/* Chkeck Map Version*/ + }/* CC size invalid*/ + if( ErrFlag == 1 ) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + return ( status ); +} + +static uint32_t phFriNfc_Desfire_HGetLeBytes(phFriNfc_NdefMap_t *NdefMap) +{ + /*Represents the LE byte*/ + uint16_t BytesToRead =0; + + if ( NdefMap->DespOpFlag == PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP ) + { + BytesToRead = PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES; + NdefMap->DesfireCapContainer.SkipNlenBytesFlag =0; + } + else + { + + /* Calculate Le bytes : No of bytes to read*/ + /* Check for User Apdu Buffer Size and Msg Size of Desfire Capability container */ + if((NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >= NdefMap->DesfireCapContainer.MaxRespSize) + { + /* We have enough buffer space to read the whole capability container + size bytes + Now, check do we have NdefMap->DesfireCapContainer.MaxRespSize to read ? */ + + BytesToRead = (((NdefMap->DesfireCapContainer.NdefDataLen - *NdefMap->DataCount) >= + NdefMap->DesfireCapContainer.MaxRespSize) ? + NdefMap->DesfireCapContainer.MaxRespSize : + (NdefMap->DesfireCapContainer.NdefDataLen - + *NdefMap->DataCount)); + } + else + { + /* Read only till the available buffer space */ + BytesToRead = (uint16_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + if(BytesToRead >= (uint16_t)(NdefMap->DesfireCapContainer.NdefDataLen - *NdefMap->DataCount)) + { + BytesToRead = (NdefMap->DesfireCapContainer.NdefDataLen - *NdefMap->DataCount); + } + } + + NdefMap->DesfireCapContainer.SkipNlenBytesFlag = + (uint8_t)(((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN )&&( *NdefMap->DataCount == 0 )) ? + 1 : 0); + + } + return (BytesToRead); +} + + + +/*! +* \brief this shall notify the integration software with respective +* success/error status along with the completion routines. +* +* This routine is called from the desfire process function. +* +*/ + +static void phFriNfc_Desfire_HCrHandler( phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Status) +{ + /* set the state back to the Reset_Init state*/ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; + + switch(NdefMap->DespOpFlag) + { + /* check which routine has the problem and set the CR*/ + case PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP : + /* set the completion routine*/ + NdefMap->CompletionRoutine[PH_FRINFC_NDEFMAP_CR_CHK_NDEF].\ + CompletionRoutine(NdefMap->CompletionRoutine->Context,\ + Status); + break; + + case PH_FRINFC_NDEFMAP_DESF_READ_OP : + /* set the completion routine*/ + NdefMap->CompletionRoutine[PH_FRINFC_NDEFMAP_CR_RD_NDEF].\ + CompletionRoutine(NdefMap->CompletionRoutine->Context,\ + Status); + break; + + case PH_FRINFC_NDEFMAP_DESF_WRITE_OP : + /* set the completion routine*/ + NdefMap->CompletionRoutine[PH_FRINFC_NDEFMAP_CR_WR_NDEF].\ + CompletionRoutine(NdefMap->CompletionRoutine->Context,\ + Status); + break; + + default : + /* set the completion routine*/ + NdefMap->CompletionRoutine[PH_FRINFC_NDEFMAP_CR_INVALID_OPE].\ + CompletionRoutine(NdefMap->CompletionRoutine->Context,\ + Status); + break; + + } +} + +static NFCSTATUS phFriNfc_Desfire_HSendTransCmd(phFriNfc_NdefMap_t *NdefMap,uint8_t SendRecvLen) +{ + + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* set the command type*/ +#ifndef PH_HAL4_ENABLE + NdefMap->Cmd.Iso144434Cmd = phHal_eIso14443_4_CmdListTClCmd; +#else + NdefMap->Cmd.Iso144434Cmd = phHal_eIso14443_4_Raw; +#endif + + /* set the Additional Info*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + + /*set the completion routines for the desfire card operations*/ + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_Desfire_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + /* set the receive length */ + *NdefMap->SendRecvLength = ((uint16_t)(SendRecvLen)); + + + /*Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive(NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + + return (status); + + +} + + +#ifdef UNIT_TEST +#include +#endif + +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ diff --git a/libnfc-nxp/phFriNfc_DesfireMap.h b/libnfc-nxp/phFriNfc_DesfireMap.h new file mode 100644 index 0000000..0432ab5 --- /dev/null +++ b/libnfc-nxp/phFriNfc_DesfireMap.h @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* + * \file phFriNfc_Desfire.h + * \brief NFC Ndef Mapping For Desfire Smart Card. + * + * Project: NFC-FRI + * + * $Date: Tue Jul 27 08:58:21 2010 $ + * $Author: ing02260 $ + * $Revision: 1.5 $ + * $Aliases: $ + * + */ + +#ifndef PHFRINFC_DESFIREMAP_H +#define PHFRINFC_DESFIREMAP_H + +#include +#ifdef PH_HAL4_ENABLE +#include +#else +#include +#endif +#include +#include +#include + + + +/*! + * \name Desfire - Standard constants + * + */ +/*@{*/ +#define PH_FRINFC_NDEFMAP_DESF_READ_OP 2 /*!< Desfire Operation Flag is Read */ +#define PH_FRINFC_NDEFMAP_DESF_WRITE_OP 3 /*!< Desfire Operation Flag is Write */ +#define PH_FRINFC_NDEFMAP_DESF_NDEF_CHK_OP 4 /*!< Desfire Operation Flag is Check Ndef */ +#define PH_FRINFC_NDEFMAP_DESF_GET_LEN_OP 5 +#define PH_FRINFC_NDEFMAP_DESF_SET_LEN_OP 6 +#define PH_FRINFC_NDEFMAP_DESF_RESP_OFFSET 2 /*!< Two Status Flag at the end of the + Receive buffer*/ +#define PH_FRINFC_NDEFMAP_DESF_CAPDU_SMARTTAG_PKT_SIZE 12 /*!< Send Length for Smart Tag function*/ +#define PH_FRINFC_NDEFMAP_DESF_CAPDU_SELECT_FILE_PKT_SIZE 7 /*!< Send Length for Select File function */ +#define PH_FRINFC_NDEFMAP_DESF_CAPDU_READ_BIN_PKT_SIZE 5 /*!< Send Length for Reading a Packet */ + +/*! + * \name NDEF Mapping - states of the Finite State machine + * + */ +/*@{*/ +#ifdef DESFIRE_EV1 + #define PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG_EV1 4 /*!< Selection of Smart Tag is going on for Desfire EV1 */ +#endif /* #ifdef DESFIRE_EV1 */ +#define PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_SMART_TAG 5 /*!< Selection of Smart Tag is going on */ +#define PH_FRINFC_NDEFMAP_DESF_STATE_SELECT_FILE 6 /*!< Selecting a file to read/write */ +#define PH_FRINFC_NDEFMAP_DESF_STATE_READ_CAP_CONT 7 /*!< Reading a capability container */ +#define PH_FRINFC_NDEFMAP_DESF_STATE_READ_BIN 8 /*!< Reading from the card */ +#define PH_FRINFC_NDEFMAP_DESF_STATE_UPDATE_BIN_BEGIN 60 /*!< Writing to the card */ +#define PH_FRINFC_NDEFMAP_DESF_STATE_UPDATE_BIN_END 61 /*!< Writing to the card */ + +#define PH_FRINFC_NDEFMAP_DESF_STATE_CHK_NDEF 10 /*!< Check Ndef is in progress */ +#define PH_FRINFC_NDEFMAP_DESF_TLV_INDEX 7 /*!< Specifies the index of TLV Structure */ +#define PH_FRINFC_NDEFMAP_DESF_NDEF_CNTRL_TLV 0x04 /*!< Specifies the NDEF File Cntrl TLV */ +#define PH_FRINFC_NDEFMAP_DESF_PROP_CNTRL_TLV 0x05 /*!< Specifies the Propreitary File Cntrl TLV */ + +/* Following Constants are used to navigate the Capability Container(CC)*/ + +/*!< Following two indexes represents the CCLEN in CC*/ +#define PH_FRINFC_NDEFMAP_DESF_CCLEN_BYTE_FIRST_INDEX 0 +#define PH_FRINFC_NDEFMAP_DESF_CCLEN_BYTE_SECOND_INDEX 1 + +/*!< Specifies the index of the Mapping Version in CC */ +#define PH_FRINFC_NDEFMAP_DESF_VER_INDEX 2 + +/*!< Following two indexes represents the MLe bytes in CC*/ +#define PH_FRINFC_NDEFMAP_DESF_MLE_BYTE_FIRST_INDEX 3 +#define PH_FRINFC_NDEFMAP_DESF_MLE_BYTE_SECOND_INDEX 4 + +/*!< Following two indexes represents the MLc bytes in CC*/ +#define PH_FRINFC_NDEFMAP_DESF_MLC_BYTE_FIRST_INDEX 5 +#define PH_FRINFC_NDEFMAP_DESF_MLC_BYTE_SECOND_INDEX 6 + +/*!< Specifies the index of the TLV in CC */ +#define PH_FRINFC_NDEFMAP_DESF_TLV_INDEX 7 + +/*!< Specifies the index of the TLV length in CC */ +#define PH_FRINFC_NDEFMAP_DESF_TLV_LEN_INDEX 8 + +/*!< Following two indexes represents the NDEF file identifier in CC*/ +#define PH_FRINFC_NDEFMAP_DESF_NDEF_FILEID_BYTE_FIRST_INDEX 9 +#define PH_FRINFC_NDEFMAP_DESF_NDEF_FILEID_BYTE_SECOND_INDEX 10 + +/*!< Following two indexes represents the NDEF file size in CC */ +#define PH_FRINFC_NDEFMAP_DESF_NDEF_FILESZ_BYTE_FIRST_INDEX 11 +#define PH_FRINFC_NDEFMAP_DESF_NDEF_FILESZ_BYTE_SECOND_INDEX 12 + +/*!< Specifies the index of the NDEF file READ access byte in CC */ +#define PH_FRINFC_NDEFMAP_DESF_NDEF_FILERD_ACCESS_INDEX 13 + +/*!< Specifies the index of the NDEF file WRITE access byte in CC */ +#define PH_FRINFC_NDEFMAP_DESF_NDEF_FILEWR_ACCESS_INDEX 14 + + +/* Macros to find Maximum NDEF File Size*/ +#define PH_NFCFRI_NDEFMAP_DESF_NDEF_FILE_SIZE (NdefMap->DesfireCapContainer.NdefFileSize - 2) +/* Specifies the size of the NLEN Bytes*/ +#define PH_FRINFC_NDEFMAP_DESF_NLEN_SIZE_IN_BYTES 2 + + +/* Following constants are used with buffer index's*/ +#define PH_FRINFC_NDEFMAP_DESF_SW1_INDEX 0 +#define PH_FRINFC_NDEFMAP_DESF_SW2_INDEX 1 + + +/* Following constants are used for SW1 SW2 status codes*/ +#define PH_FRINFC_NDEFMAP_DESF_RAPDU_SW1_BYTE 0x90 +#define PH_FRINFC_NDEFMAP_DESF_RAPDU_SW2_BYTE 0x00 + + +/* Following constatnts for shift bytes*/ +#define PH_FRINFC_NDEFMAP_DESF_SHL8 8 + + +#define PH_FRINFC_DESF_GET_VER_CMD 0x60 +#define PH_FRINFC_DESF_NATIVE_CLASS_BYTE 0x90 +#define PH_FRINFC_DESF_NATIVE_OFFSET_P1 0x00 +#define PH_FRINFC_DESF_NATIVE_OFFSET_P2 0x00 +#define PH_FRINFC_DESF_NATIVE_GETVER_RESP 0xAF +/*! +* \name NDEF Mapping - states of the Finite State machine +* +*/ +/*@{*/ + +typedef enum +{ + PH_FRINFC_DESF_STATE_GET_UID, + PH_FRINFC_DESF_STATE_GET_SW_VERSION, + PH_FRINFC_DESF_STATE_GET_HW_VERSION + +}phFriNfc_eMapDesfireState; + +typedef enum +{ + PH_FRINFC_DESF_IDX_0, + PH_FRINFC_DESF_IDX_1, + PH_FRINFC_DESF_IDX_2, + PH_FRINFC_DESF_IDX_3, + PH_FRINFC_DESF_IDX_4, + PH_FRINFC_DESF_IDX_5 + +}phFriNfc_eMapDesfireId; + +#define PH_FRINFC_DESF_ISO_NATIVE_WRAPPER() \ + do \ +{\ + NdefMap->SendRecvBuf[PH_FRINFC_DESF_IDX_0] = PH_FRINFC_DESF_NATIVE_CLASS_BYTE;\ + NdefMap->SendRecvBuf[PH_FRINFC_DESF_IDX_2] = PH_FRINFC_DESF_NATIVE_OFFSET_P1;\ + NdefMap->SendRecvBuf[PH_FRINFC_DESF_IDX_3] = PH_FRINFC_DESF_NATIVE_OFFSET_P2;\ + switch(NdefMap->State)\ +{\ + case PH_FRINFC_DESF_STATE_GET_HW_VERSION :\ + case PH_FRINFC_DESF_STATE_GET_SW_VERSION :\ + case PH_FRINFC_DESF_STATE_GET_UID :\ + if ( NdefMap->State == PH_FRINFC_DESF_STATE_GET_HW_VERSION )\ +{\ + NdefMap->SendRecvBuf[PH_FRINFC_DESF_IDX_1] = PH_FRINFC_DESF_GET_VER_CMD;\ +}\ + else\ +{\ + NdefMap->SendRecvBuf[PH_FRINFC_DESF_IDX_1] = 0xAF;\ +}\ + NdefMap->SendRecvBuf[PH_FRINFC_DESF_IDX_4] = 0x00;\ + NdefMap->SendLength = PH_FRINFC_DESF_IDX_5;\ + break;\ + default :\ + break;\ +}\ +} while(0)\ + + + + + +/*! + * \brief \copydoc page_ovr Initiates Reading of NDEF information from the Remote Device. + * + * The function initiates the reading of NDEF information from a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that receives the NDEF Packet. + * + * \param[in,out] PacketDataLength Pointer to a variable receiving the length of the NDEF packet. + * + * \param[in] Offset Indicates whether the read operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start reading from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start reading + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED No Space in the File to read. + * \retval NFCSTATUS_MORE_INFORMATION There are more bytes to read in the card. + * \retval NFCSTATUS_SUCCESS Last Byte of the card read. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_Desfire_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + +/*! + * \brief \copydoc page_ovr Initiates Writing of NDEF information to the Remote Device. + * + * The function initiates the writing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that holds the prepared NDEF Packet. + * + * \param[in,out] PacketDataLength Variable specifying the length of the prepared NDEF packet. + * + * \param[in] Offset Indicates whether the write operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start writing from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start writing + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED Last byte is written to the card after this + * no further writing is possible. + * \retval NFCSTATUS_SUCCESS Buffer provided by the user is completely written + * into the card. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_Desfire_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + +/*! + * \brief \copydoc page_ovr Check whether a particulat Remote Device is NDEF compliant. + * + * The function checks whether the peer device is NDEF compliant. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_Desfire_ChkNdef( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_cb Completion Routine, Processing function, needed to avoid long blocking. + * + * The function call scheme is according to \ref grp_interact. No State reset is performed during operation. + * + * \copydoc pphFriNfc_Cr_t + * + * \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion + * Routine in order to be able to notify the component that an I/O has finished and data are + * ready to be processed. + * + */ + +void phFriNfc_Desfire_Process( void *Context, + NFCSTATUS Status); + + +#endif /* PHFRINFC_DESFIREMAP_H */ + diff --git a/libnfc-nxp/phFriNfc_FelicaMap.c b/libnfc-nxp/phFriNfc_FelicaMap.c new file mode 100644 index 0000000..c45f335 --- /dev/null +++ b/libnfc-nxp/phFriNfc_FelicaMap.c @@ -0,0 +1,3065 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc_FelicaMap.c + * \brief This component encapsulates read/write/check ndef/process functionalities, + * for the Felica Smart Card. + * + * Project: NFC-FRI + * + * $Date: Thu May 6 14:01:35 2010 $ + * $Author: ing07385 $ + * $Revision: 1.10 $ + * $Aliases: NFC_FRI1.1_WK1017_R34_4,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED + +#include +#include +#include +#include + + +/*! \ingroup grp_file_attributes + * \name NDEF Mapping + * + * File: \ref phFriNfc_FelicaMap.c + * + */ +/*@{*/ + +#define PHFRINFCNDEFMAP_FILEREVISION "$Revision: 1.10 $" +#define PHFRINFCNDEFMAP_FILEALIASES "$Aliases: NFC_FRI1.1_WK1017_R34_4,NFC_FRI1.1_WK1023_R35_1 $" + +/*@}*/ + +/* Helpers for Read and updating the attribute informations*/ +static NFCSTATUS phFriNfc_Felica_HRdAttrInfo(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Felica_HUpdateAttrInfo(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Felica_HCalCheckSum(const uint8_t *TempBuffer, + uint8_t StartIndex, + uint8_t EndIndex, + uint16_t RecvChkSum); + +/* Helpers for Poll Related Operations*/ +static NFCSTATUS phFriNfc_Felica_HPollCard( phFriNfc_NdefMap_t *NdefMap, + const uint8_t sysCode[], + uint8_t state); + +static NFCSTATUS phFriNfc_Felica_HUpdateManufIdDetails(const phFriNfc_NdefMap_t *NdefMap); + +/*Helpers for Reading Operations*/ +static NFCSTATUS phFriNfc_Felica_HReadData(phFriNfc_NdefMap_t *NdefMap,uint8_t offset); +static uint16_t phFriNfc_Felica_HGetMaximumBlksToRead(const phFriNfc_NdefMap_t *NdefMap,uint8_t NbcOrNmaxb ); +static void phFriNfc_Felica_HAfterRead_CopyDataToBuff(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Felica_HSetTransceiveForRead(phFriNfc_NdefMap_t *NdefMap,uint16_t TrxLen,uint8_t Offset); +static uint16_t phFriNfc_Felica_HSetTrxLen(phFriNfc_NdefMap_t *NdefMap,uint16_t Nbc); +static NFCSTATUS phFriNfc_Felica_HChkApduBuff_Size( phFriNfc_NdefMap_t *NdefMap); + +/* Helpers for Writing Operations*/ +static NFCSTATUS phFriNfc_Felica_HChkAttrBlkForWrOp(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Felica_HChkAttrBlkForRdOp(phFriNfc_NdefMap_t *NdefMap, + uint32_t NdefLen); +static NFCSTATUS phFriNfc_Felica_HUpdateAttrBlkForWrOp(phFriNfc_NdefMap_t *NdefMap,uint8_t isStarted); +static NFCSTATUS phFriNfc_Felica_HUpdateData(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_Felica_HWriteDataBlk(phFriNfc_NdefMap_t *NdefMap); + +/* Write Empty NDEF Message*/ +static NFCSTATUS phFriNfc_Felica_HWrEmptyMsg(phFriNfc_NdefMap_t *NdefMap); + +/*Helpers for common checks*/ +static NFCSTATUS phFriNfc_Felica_HCheckManufId(const phFriNfc_NdefMap_t *NdefMap); +static void phFriNfc_Felica_HCrHandler(phFriNfc_NdefMap_t *NdefMap, + uint8_t CrIndex, + NFCSTATUS Status); + +static void phFriNfc_Felica_HInitInternalBuf(uint8_t *Buffer); + +static int phFriNfc_Felica_MemCompare ( void *s1, void *s2, unsigned int n ); + +/*! + * \brief returns maximum number of blocks can be read from the Felica Smart Card. + * + * The function is useful in reading of NDEF information from a felica tag. + */ + +static uint16_t phFriNfc_Felica_HGetMaximumBlksToRead(const phFriNfc_NdefMap_t *NdefMap, uint8_t NbcOrNmaxb ) +{ + uint16_t BlksToRead=0; + uint32_t DataLen = 0; + /* This part of the code is useful if we take account of Nbc blks reading*/ + if ( NbcOrNmaxb == PH_NFCFRI_NDEFMAP_FELI_NBC ) + { + PH_NFCFRI_NDEFMAP_FELI_CAL_LEN_BYTES(NdefMap->FelicaAttrInfo.LenBytes[0], + NdefMap->FelicaAttrInfo.LenBytes[1], + NdefMap->FelicaAttrInfo.LenBytes[2], + DataLen); + /* Calculate Nbc*/ + BlksToRead = (uint16_t) ( ((DataLen % 16) == 0) ? (DataLen >> 4) : ((DataLen >> 4) +1) ); + + + } + else if ( NbcOrNmaxb == PH_NFCFRI_NDEFMAP_FELI_NMAXB) + { + BlksToRead = NdefMap->FelicaAttrInfo.Nmaxb; + } + else + { + /* WARNING !!! code should not reach this point*/ + ; + } + return (BlksToRead); +} + +/*! + * \brief Initiates Reading of NDEF information from the Felica Card. + * + * The function initiates the reading of NDEF information from a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfcNdefMap_Process has to be + * done once the action has been triggered. + */ + +NFCSTATUS phFriNfc_Felica_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + uint32_t Nbc = 0; + + NdefMap->ApduBufferSize = *PacketDataLength; + /*Store the packet data buffer*/ + NdefMap->ApduBuffer = PacketData; + + NdefMap->NumOfBytesRead = PacketDataLength ; + *NdefMap->NumOfBytesRead = 0; + NdefMap->ApduBuffIndex = 0; + + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + NdefMap->Felica.Offset = Offset; + + if( ( Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN )||( NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE)) + { + NdefMap->Felica.CurBlockNo = 0; + NdefMap->Felica.OpFlag = PH_FRINFC_NDEFMAP_FELI_RD_ATTR_RD_OP; + NdefMap->Felica.IntermediateCpyFlag = FALSE; + NdefMap->Felica.IntermediateCpyLen = 0; + NdefMap->Felica.Rd_NoBytesToCopy = 0; + NdefMap->Felica.EofCardReachedFlag= FALSE ; + NdefMap->Felica.LastBlkReachedFlag = FALSE; + NdefMap->Felica.CurrBytesRead = 0; + + phFriNfc_Felica_HInitInternalBuf(NdefMap->Felica.Rd_BytesToCopyBuff); + + /* send request to read attribute information*/ + status = phFriNfc_Felica_HRdAttrInfo(NdefMap); + /* handle the error in Transc function*/ + if ( (status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_CHK_NDEF,status); + } + } + else + { + Nbc = phFriNfc_Felica_HGetMaximumBlksToRead(NdefMap,PH_NFCFRI_NDEFMAP_FELI_NBC); + + /* Offset = Current, but the read has reached the End of NBC Blocks */ + if(( ( Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && (NdefMap->Felica.CurBlockNo == Nbc)) && + (NdefMap->Felica.EofCardReachedFlag == FELICA_RD_WR_EOF_CARD_REACHED )) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + + NdefMap->Felica.CurrBytesRead = ((NdefMap->Felica.CurBlockNo * 16)- NdefMap->Felica.Rd_NoBytesToCopy); + status = phFriNfc_Felica_HReadData(NdefMap,NdefMap->Felica.Offset); + + } + } + return (status); +} + +/*Read Operation Related Helper Routines*/ + +/*! + * \brief Used in Read Opearation.Sets the Trx Buffer Len calls Transc Cmd. + * After a successful read operation, function does checks the user buffer size + * sets the status flags. +*/ + +static NFCSTATUS phFriNfc_Felica_HReadData(phFriNfc_NdefMap_t *NdefMap,uint8_t offset) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint16_t Nbc=0,TranscLen=0; + + Nbc = phFriNfc_Felica_HGetMaximumBlksToRead(NdefMap,PH_NFCFRI_NDEFMAP_FELI_NBC); + if( ( (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) > 0) && (NdefMap->Felica.CurBlockNo < Nbc )) + { + /* if data is present in the internal buffer*/ + if (NdefMap->Felica.Rd_NoBytesToCopy > 0 ) + { + /* copy data to external buffer*/ + phFriNfc_Felica_HAfterRead_CopyDataToBuff(NdefMap); + /*Check the size of user buffer*/ + status = phFriNfc_Felica_HChkApduBuff_Size(NdefMap); + if ( (status != NFCSTATUS_SUCCESS) && (NdefMap->Felica.IntermediateRdFlag == TRUE )) + { + /* set the transc len and call transc cmd*/ + TranscLen = phFriNfc_Felica_HSetTrxLen(NdefMap,Nbc); + status= phFriNfc_Felica_HSetTransceiveForRead(NdefMap,TranscLen,offset); + } + else + { + /* Nothing to be done , if IntermediateRdFlag is set to zero*/ + ; + } + } + else + { + /* set the transc len and call transc cmd*/ + TranscLen = phFriNfc_Felica_HSetTrxLen(NdefMap,Nbc); + status= phFriNfc_Felica_HSetTransceiveForRead(NdefMap,TranscLen,offset); + } + } + else + { + /* Chk the Buffer size*/ + status = phFriNfc_Felica_HChkApduBuff_Size(NdefMap); + if ( (status != NFCSTATUS_SUCCESS) && (NdefMap->Felica.IntermediateRdFlag == TRUE )) + { + TranscLen = phFriNfc_Felica_HSetTrxLen(NdefMap,Nbc); + status= phFriNfc_Felica_HSetTransceiveForRead(NdefMap,TranscLen,offset); + } + } + return (status); +} + +/*! + * \brief Used in Read Opearation.Sets the Trx Buffer Len. + */ + +static uint16_t phFriNfc_Felica_HSetTrxLen(phFriNfc_NdefMap_t *NdefMap,uint16_t Nbc) +{ + uint16_t TranscLen = 0,BlocksToRead=0; + + if( ( (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)% 16) == 0) + { + BlocksToRead = (uint16_t)( (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)/16 ); + } + else + { + BlocksToRead = (uint16_t)(((NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)/16) +1); + } + if ( (BlocksToRead > Nbc) ||( (BlocksToRead) > ( Nbc - NdefMap->Felica.CurBlockNo)) ) + { + BlocksToRead = Nbc - NdefMap->Felica.CurBlockNo; + } + + + if ( BlocksToRead >= NdefMap->FelicaAttrInfo.Nbr) + { + if( NdefMap->FelicaAttrInfo.Nbr < Nbc ) + { + TranscLen = NdefMap->FelicaAttrInfo.Nbr*16; + } + else + { + TranscLen = Nbc*16; + NdefMap->Felica.LastBlkReachedFlag =1; + } + } + else + { + if (BlocksToRead <= Nbc ) + { + if ( ( BlocksToRead * 16) == ((Nbc *16) - (NdefMap->Felica.CurBlockNo * 16))) + { + NdefMap->Felica.LastBlkReachedFlag =1; + + } + TranscLen = BlocksToRead*16; + + } + else + { + TranscLen = Nbc*16; + } + } + /* As Cur Blk changes, to remember the exact len what we had set + in the begining of each read operation*/ + NdefMap->Felica.TrxLen = TranscLen; + return (TranscLen); +} + +/*! + * \brief Used in Read Opearation.After a successful read operation, + * Copies the data to user buffer. + */ + +static void phFriNfc_Felica_HAfterRead_CopyDataToBuff(phFriNfc_NdefMap_t *NdefMap) +{ + uint8_t ResetFlag = FALSE, ExtrBytesToCpy = FALSE; + uint16_t Nbc=0; + uint32_t DataLen=0; + + Nbc = phFriNfc_Felica_HGetMaximumBlksToRead(NdefMap,PH_NFCFRI_NDEFMAP_FELI_NBC ); + + PH_NFCFRI_NDEFMAP_FELI_CAL_LEN_BYTES(NdefMap->FelicaAttrInfo.LenBytes[0], + NdefMap->FelicaAttrInfo.LenBytes[1], + NdefMap->FelicaAttrInfo.LenBytes[2], + DataLen); + /* Internal Buffer has some old read bytes to cpy to user buffer*/ + if( NdefMap->Felica.Rd_NoBytesToCopy > 0 ) + { + if ( (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) < NdefMap->Felica.Rd_NoBytesToCopy ) + { + NdefMap->Felica.Rd_NoBytesToCopy -= (uint8_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + + if (NdefMap->Felica.IntermediateCpyFlag == TRUE ) + { + /*Copy data from the internal buffer to user buffer*/ + (void)memcpy( (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (&(NdefMap->Felica.Rd_BytesToCopyBuff[NdefMap->Felica.IntermediateCpyLen])), + (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)); + + + + /* Store number of bytes copied frm internal buffer to User Buffer */ + NdefMap->Felica.IntermediateCpyLen += (uint8_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + NdefMap->Felica.IntermediateCpyFlag = 1; + + /* check do we reach len bytes any chance*/ + PH_NFCFRI_NDEFMAP_FELI_CAL_LEN_BYTES(NdefMap->FelicaAttrInfo.LenBytes[0], + NdefMap->FelicaAttrInfo.LenBytes[1], + NdefMap->FelicaAttrInfo.LenBytes[2], + DataLen); + /* Internal buffer has zero bytes for copy operation*/ + if ( NdefMap->Felica.Rd_NoBytesToCopy == 0) + { + NdefMap->Felica.EofCardReachedFlag =FELICA_RD_WR_EOF_CARD_REACHED; + } + } + else + { + /*Copy data from the internal buffer to apdu buffer*/ + (void)memcpy( (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + NdefMap->Felica.Rd_BytesToCopyBuff, + (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)); + } + NdefMap->ApduBuffIndex += (uint8_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + + } + else if ( (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) == NdefMap->Felica.Rd_NoBytesToCopy ) + { + if ( NdefMap->Felica.IntermediateCpyFlag == TRUE ) + { + /*Copy data internal buff to apdubuffer*/ + (void)memcpy( (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (&(NdefMap->Felica.Rd_BytesToCopyBuff[NdefMap->Felica.IntermediateCpyLen])), + NdefMap->Felica.Rd_NoBytesToCopy); + } + else + { + /*Copy data internal buff to apdubuffer*/ + (void)memcpy( (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + NdefMap->Felica.Rd_BytesToCopyBuff, + NdefMap->Felica.Rd_NoBytesToCopy); + } + + /*increment the index,internal buffer len*/ + NdefMap->ApduBuffIndex += NdefMap->Felica.Rd_NoBytesToCopy; + NdefMap->Felica.Rd_NoBytesToCopy -= (uint8_t)(NdefMap->ApduBuffIndex); + + /* To reset the parameters*/ + ResetFlag = TRUE; + } + else + { + /* Extra Bytes to Copy from internal buffer to external buffer*/ + if ( NdefMap->Felica.IntermediateCpyFlag == TRUE ) + { + /*Copy data internal buff to apdubuffer*/ + (void)memcpy( (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (&(NdefMap->Felica.Rd_BytesToCopyBuff[NdefMap->Felica.IntermediateCpyLen])), + NdefMap->Felica.Rd_NoBytesToCopy); + } + else + { + /*Copy data internal buff to apdubuffer*/ + (void)memcpy( (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + NdefMap->Felica.Rd_BytesToCopyBuff, + NdefMap->Felica.Rd_NoBytesToCopy); + } + /*increment the index*/ + NdefMap->ApduBuffIndex += NdefMap->Felica.Rd_NoBytesToCopy; + + /* To reset the parameters*/ + ResetFlag = TRUE; + } + }/*End of Internal Buffer has some old read bytes to cpy to user buffer*/ + else + { + /* check if last block is reached*/ + if ( ((NdefMap->Felica.LastBlkReachedFlag == 1) && (( NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >= 16)) ) + { + /* greater than 16 but less than the data len size*/ + if (( NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >= DataLen) + { + NdefMap->Felica.CurrBytesRead = (uint16_t)((DataLen) - (NdefMap->Felica.CurrBytesRead + + NdefMap->ApduBuffIndex)); + + (void)memcpy( (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (&(NdefMap->SendRecvBuf[13])), + NdefMap->Felica.CurrBytesRead); + + NdefMap->ApduBuffIndex += NdefMap->Felica.CurrBytesRead; + if ( NdefMap->ApduBuffIndex == DataLen) + { + ResetFlag = TRUE; + } + } + else + { + /* need to check exact no. of bytes to copy to buffer*/ + if( ( (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) <= NdefMap->Felica.TrxLen )|| + ((NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) <= DataLen )) + { + + ExtrBytesToCpy = TRUE; + } + else + { + NdefMap->Felica.Rd_NoBytesToCopy = (uint8_t)(16-(( Nbc * 16) - (DataLen))); + + if ( NdefMap->Felica.Rd_NoBytesToCopy > (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)) + { + /*Reduce already copied bytes from the internal buffer*/ + NdefMap->Felica.Rd_NoBytesToCopy -= (uint8_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + ExtrBytesToCpy = TRUE; + } + else + { + ExtrBytesToCpy = FALSE; + } + } + if ( ExtrBytesToCpy == TRUE ) + { + NdefMap->Felica.CurrBytesRead = (uint16_t)((DataLen)- (NdefMap->Felica.CurrBytesRead + + NdefMap->ApduBuffIndex)); + + if(NdefMap->Felica.CurrBytesRead < + (uint16_t)(NdefMap->ApduBufferSize - + NdefMap->ApduBuffIndex)) + { + (void)memcpy( (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (&(NdefMap->SendRecvBuf[13])), + NdefMap->Felica.CurrBytesRead); + } + else + { + (void)memcpy( (&( NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (&( NdefMap->SendRecvBuf[13])), + (uint16_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)); + } + + if ( NdefMap->Felica.LastBlkReachedFlag == 1 ) + { + NdefMap->Felica.Rd_NoBytesToCopy = + (uint8_t)((NdefMap->Felica.CurrBytesRead > + (uint16_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex))? + (NdefMap->Felica.CurrBytesRead - + (uint16_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)): + 0); + + ResetFlag = ((NdefMap->Felica.Rd_NoBytesToCopy == 0)?TRUE:FALSE); + + } + else + { + NdefMap->Felica.Rd_NoBytesToCopy = (uint8_t)( NdefMap->Felica.TrxLen - (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)); + } + + /* Copy remained bytes back into internal buffer*/ + (void)memcpy( NdefMap->Felica.Rd_BytesToCopyBuff, + (&(NdefMap->SendRecvBuf[PH_NFCFRI_NDEFMAP_FELI_RESP_HEADER_LEN+(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)])), + NdefMap->Felica.Rd_NoBytesToCopy); + + /* set the intermediate flag : This flag remembers that there are still X no. bytes remained in + Internal Buffer Ex: User has given only one byte buffer,needs to cpy one byte at a time*/ + NdefMap->Felica.IntermediateCpyFlag = TRUE; + + NdefMap->ApduBuffIndex += ((NdefMap->Felica.CurrBytesRead < + (uint16_t)(NdefMap->ApduBufferSize - + NdefMap->ApduBuffIndex))? + NdefMap->Felica.CurrBytesRead: + (uint16_t)(NdefMap->ApduBufferSize - + NdefMap->ApduBuffIndex)); + } + else + { + /*Copy data from the internal buffer to user buffer*/ + (void)memcpy( (&( NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (&( NdefMap->SendRecvBuf[13])), + NdefMap->Felica.Rd_NoBytesToCopy); + + NdefMap->ApduBuffIndex += NdefMap->Felica.Rd_NoBytesToCopy; + ResetFlag = TRUE; + + } + } + + } + else + { + if ((NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) < NdefMap->Felica.TrxLen ) + { + /* Calculate exactly remained bytes to copy to internal buffer and set it*/ + if ( NdefMap->Felica.LastBlkReachedFlag == 1) + { + NdefMap->Felica.Rd_NoBytesToCopy = (uint8_t)(16-(( Nbc * 16) - DataLen)); + + if ( NdefMap->Felica.Rd_NoBytesToCopy > (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)) + { + /*Reduce already copied bytes from the internal buffer*/ + NdefMap->Felica.Rd_NoBytesToCopy -= (uint8_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + ExtrBytesToCpy = TRUE; + } + } + else + { + NdefMap->Felica.Rd_NoBytesToCopy = (uint8_t)(NdefMap->Felica.TrxLen - (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)); + ExtrBytesToCpy = TRUE; + } + if ( ExtrBytesToCpy == TRUE ) + { + /*Copy the read data from trx buffer to apdu of size apdu*/ + (void)memcpy( (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (&(NdefMap->SendRecvBuf[13])), + NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + + /*copy bytesToCopy to internal buffer*/ + (void)memcpy( NdefMap->Felica.Rd_BytesToCopyBuff, + (&(NdefMap->SendRecvBuf[13+(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)])), + NdefMap->Felica.Rd_NoBytesToCopy); + + NdefMap->Felica.IntermediateCpyFlag = TRUE; + NdefMap->ApduBuffIndex += (uint16_t)NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex; + } + else + { + /*Copy data from the internal buffer to user buffer*/ + (void)memcpy( (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (&(NdefMap->SendRecvBuf[13])), + NdefMap->Felica.Rd_NoBytesToCopy); + + NdefMap->ApduBuffIndex += NdefMap->Felica.Rd_NoBytesToCopy; + ResetFlag = TRUE; + + } + if ( DataLen <= (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) ) + { + NdefMap->Felica.EofCardReachedFlag =FELICA_RD_WR_EOF_CARD_REACHED; + } + else + { + ; + } + } + else if ((NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) == NdefMap->Felica.TrxLen ) + { + /*Copy exactly remained last bytes to user buffer and increment the index*/ + /*13 : 1+12 : 1st byte entire pkt length + 12 bytes to skip manuf details*/ + (void)memcpy( (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (&(NdefMap->SendRecvBuf[13])), + (NdefMap->Felica.TrxLen )); + + NdefMap->ApduBuffIndex += NdefMap->Felica.TrxLen; + } + else + { + if ((NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) > NdefMap->Felica.TrxLen ) + { + /*Copy the data to apdu buffer and increment the index */ + (void)memcpy( (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (&(NdefMap->SendRecvBuf[PH_NFCFRI_NDEFMAP_FELI_RESP_HEADER_LEN])), + NdefMap->Felica.TrxLen); + + NdefMap->ApduBuffIndex += (uint16_t)NdefMap->Felica.TrxLen; + } + } + } + } + if ( ResetFlag == TRUE ) + { + /* reset the internal buffer variables*/ + NdefMap->Felica.Rd_NoBytesToCopy =0; + NdefMap->Felica.IntermediateCpyLen =0; + NdefMap->Felica.IntermediateCpyFlag =FALSE; + } + return; +} + + +/*! + * \brief Used in Read Opearation.After a successful read operation, + Checks the relavent buffer sizes and set the status.Following function is used + when we read the Nmaxb blocks. Retained for future purpose. + */ + +static NFCSTATUS phFriNfc_Felica_HChkApduBuff_Size( phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint8_t ResetFlag = FALSE; + uint32_t Nbc = 0; + uint32_t DataLen = 0; + + Nbc = phFriNfc_Felica_HGetMaximumBlksToRead(NdefMap,PH_NFCFRI_NDEFMAP_FELI_NBC); + + /* set status to Success : User Buffer is full and Curblk < nmaxb*/ + if ( (( NdefMap->ApduBufferSize-NdefMap->ApduBuffIndex )== 0) && + (NdefMap->Felica.CurBlockNo < Nbc )) + { + status = PHNFCSTVAL(CID_NFC_NONE, + NFCSTATUS_SUCCESS); + /*Reset the index, internal buffer counters back to zero*/ + *NdefMap->NumOfBytesRead = NdefMap->ApduBuffIndex; + NdefMap->ApduBuffIndex = 0; + + }/*if( (NdefMap->ApduBufferSize-NdefMap->ApduBuffIndex )== 0 && NdefMap->Felica.CurBlockNo < NdefMap->FelicaAttrInfo.Nmaxb )*/ + else + { + if (( ( NdefMap->ApduBufferSize-NdefMap->ApduBuffIndex )== 0) && + (NdefMap->Felica.CurBlockNo == Nbc )) + { + status = PHNFCSTVAL(CID_NFC_NONE, + NFCSTATUS_SUCCESS); + + ResetFlag = ((NdefMap->Felica.Rd_NoBytesToCopy > 0 )? + FALSE: + TRUE); + if( ResetFlag== FALSE) + { + *NdefMap->NumOfBytesRead = NdefMap->ApduBuffIndex; + /*Reset the index, internal buffer counters back to zero*/ + NdefMap->ApduBuffIndex = 0; + } + }/*if ((NdefMap->ApduBufferSize-NdefMap->ApduBuffIndex )== 0 && NdefMap->Felica.CurBlockNo == NdefMap->FelicaAttrInfo.Nmaxb )*/ + else + { + /* reached reading all the blks available in the card: set EOF flag*/ + if ( NdefMap->ApduBuffIndex == (Nbc*16)) + { + status = PHNFCSTVAL(CID_NFC_NONE, + NFCSTATUS_SUCCESS); + ResetFlag = TRUE; + } + else + { + if ((NdefMap->ApduBufferSize-NdefMap->ApduBuffIndex )> 0 ) + { + if ( NdefMap->Felica.CurBlockNo == Nbc ) + { + /* bytes pending in internal buffer , No Space in User Buffer*/ + if ( NdefMap->Felica.Rd_NoBytesToCopy > 0) + { + if ( NdefMap->Felica.EofCardReachedFlag == TRUE ) + { + status = PHNFCSTVAL(CID_NFC_NONE, + NFCSTATUS_SUCCESS); + *NdefMap->NumOfBytesRead = NdefMap->ApduBuffIndex; + NdefMap->ApduBuffIndex=0; + } + else + { + phFriNfc_Felica_HAfterRead_CopyDataToBuff(NdefMap); + if( NdefMap->Felica.Rd_NoBytesToCopy > 0 ) + { + status = PHNFCSTVAL(CID_NFC_NONE, + NFCSTATUS_SUCCESS); + *NdefMap->NumOfBytesRead = NdefMap->ApduBuffIndex; + NdefMap->ApduBuffIndex=0; + } + else + { + /* EOF Card Reached set the internal EOF Flag*/ + status = PHNFCSTVAL(CID_NFC_NONE, + NFCSTATUS_SUCCESS); + + ResetFlag = TRUE; + } + } + } + /* All bytes from internal buffer are copied and set eof flag*/ + else + { + status = PHNFCSTVAL(CID_NFC_NONE, + NFCSTATUS_SUCCESS); + ResetFlag = TRUE; + } + } + else + { + /* This flag is set to ensure that, need of Read Opearation + we completed coying the data from internal buffer to external buffer + left some more bytes,in User bufer so initiate the read operation */ + NdefMap->Felica.IntermediateRdFlag = TRUE; + } + } + else + { + status = PHNFCSTVAL(CID_NFC_NONE, + NFCSTATUS_SUCCESS); + } + } + } + if ( ResetFlag == TRUE) + { + PH_NFCFRI_NDEFMAP_FELI_CAL_LEN_BYTES(NdefMap->FelicaAttrInfo.LenBytes[0], + NdefMap->FelicaAttrInfo.LenBytes[1], + NdefMap->FelicaAttrInfo.LenBytes[2], + DataLen); + if (NdefMap->ApduBuffIndex > DataLen) + { + *NdefMap->NumOfBytesRead = DataLen; + } + else + { + *NdefMap->NumOfBytesRead = NdefMap->ApduBuffIndex; + } + /*Reset the index, internal buffer counters back to zero*/ + NdefMap->ApduBuffIndex = 0; + NdefMap->Felica.Rd_NoBytesToCopy=0; + NdefMap->Felica.EofCardReachedFlag=FELICA_RD_WR_EOF_CARD_REACHED; + + } + + } + return( status); +} + +/*! + * \brief Used in Read Opearation.Sets the transceive Command for read. + */ +static NFCSTATUS phFriNfc_Felica_HSetTransceiveForRead(phFriNfc_NdefMap_t *NdefMap,uint16_t TrxLen,uint8_t Offset) +{ + NFCSTATUS TrxStatus = NFCSTATUS_PENDING; + uint16_t BufIndex=0,i=0; + + /* set the felica cmd */ +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.FelCmd = (phNfc_eFelicaCmdList_t)phHal_eFelica_Raw; +#else + NdefMap->Cmd.FelCmd = phHal_eFelicaCmdListFelicaCmd; +#endif /* #ifdef PH_HAL4_ENABLE */ + + /*Change the state to Read */ + NdefMap->State = PH_NFCFRI_NDEFMAP_FELI_STATE_RD_BLOCK; + + /* set the complition routines for the mifare operations */ + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_Felica_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + /*set the additional informations for the data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + + /* pkt len : updated at the end*/ + NdefMap->SendRecvBuf[BufIndex] = 0x00; + BufIndex ++; + + NdefMap->SendRecvBuf[BufIndex] = 0x06; + BufIndex++; + + /* IDm - Manufacturer Id : 8bytes*/ +#ifdef PH_HAL4_ENABLE + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + (void * )(&(NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.IDm)), + 8); +#else + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + (void * )(&(NdefMap->psRemoteDevInfo->RemoteDevInfo.CardInfo212_424.Startup212_424.NFCID2t)), + 8); +#endif /* #ifdef PH_HAL4_ENABLE */ + + BufIndex+=8; + + /*Number of Services (n=1 ==> 0x80)*/ + NdefMap->SendRecvBuf[BufIndex] = 0x01; + BufIndex++; + + /*Service Code List*/ + NdefMap->SendRecvBuf[BufIndex] = 0x0B; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; + BufIndex++; + + /*Number of Blocks to read*/ + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)(TrxLen/16); + BufIndex++; + /* Set the Blk numbers as per the offset set by the user : Block List*/ + if ( Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN ) + { + for ( i=0;i<(TrxLen/16);i++) + { + /*1st Service Code list : byte 1*/ + NdefMap->SendRecvBuf[BufIndex] = 0x80; + BufIndex++; + + /* No. Of Blocks*/ + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)(i + 1); + BufIndex++; + } + } + else + { + for ( i= 1;i<=(TrxLen/16);i++) + { + /*1st Service Code list : byte 1*/ + NdefMap->SendRecvBuf[BufIndex] = 0x80; + BufIndex++; + + /* No. Of Blocks*/ + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)(NdefMap->Felica.CurBlockNo + i); + BufIndex++; + } + } + + /* len of entire pkt*/ + NdefMap->SendRecvBuf[PH_NFCFRI_NDEFMAP_FELI_PKT_LEN_INDEX] = (uint8_t) BufIndex; + + /* Set the Pkt Len*/ + NdefMap->SendLength = BufIndex; + + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + + TrxStatus = phFriNfc_OvrHal_Transceive(NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + return (TrxStatus); +} + +/*! + * \brief Initiates Writing of NDEF information to the Remote Device. + * + * The function initiates the writing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action + * has been triggered. + */ + +NFCSTATUS phFriNfc_Felica_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + + NdefMap->ApduBufferSize = *PacketDataLength; + /*Store the packet data buffer*/ + NdefMap->ApduBuffer = PacketData; + + /* To Update the Acutal written bytes to context*/ + NdefMap->WrNdefPacketLength = PacketDataLength; + *NdefMap->WrNdefPacketLength = 0; + + + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + NdefMap->Felica.Offset = Offset; + + NdefMap->Felica.OpFlag = PH_FRINFC_NDEFMAP_FELI_WR_ATTR_RD_OP; + status = phFriNfc_Felica_HRdAttrInfo(NdefMap); + /* handle the error in Transc function*/ + if ( (status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_CHK_NDEF,status); + } + return (status); +} + +/*! + * \brief Initiates Writing of Empty NDEF information to the Remote Device. + * + * The function initiates the writing empty of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action + * has been triggered. + */ + +NFCSTATUS phFriNfc_Felica_EraseNdef( phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + static uint32_t PktDtLength =0; + + if ( NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INVALID ) + { + /* Card is in invalid state, cannot have any read/write + operations*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_FORMAT); + } + else if ( NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_ONLY ) + { + /*Can't write to the card :No Grants */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_WRITE_FAILED); + /* set the no. bytes written is zero*/ + NdefMap->WrNdefPacketLength = &PktDtLength; + *NdefMap->WrNdefPacketLength = 0; + } + else + { + + /* set the Operation*/ + NdefMap->Felica.OpFlag = PH_FRINFC_NDEFMAP_FELI_WR_EMPTY_MSG_OP; + + status = phFriNfc_Felica_HRdAttrInfo(NdefMap); + } + return (status); +} + + +/*! + * \brief Used in Write Opearation. + * check the value set for the Write Flag, in first write operation(begin), sets the + * WR flag in attribute blck. + * After a successful write operation, This function sets the WR flag off and updates + * the LEN bytes in attribute Block. + */ + +static NFCSTATUS phFriNfc_Felica_HUpdateAttrBlkForWrOp(phFriNfc_NdefMap_t *NdefMap,uint8_t isStarted) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + uint16_t ChkSum=0,index=0; + uint8_t BufIndex=0, ErrFlag = FALSE; + uint32_t TotNoWrittenBytes=0; + + /* Write Operation : Begin/End Check*/ + + NdefMap->State = + (( isStarted == FELICA_WRITE_STARTED )? + PH_NFCFRI_NDEFMAP_FELI_STATE_ATTR_BLK_WR_BEGIN: + PH_NFCFRI_NDEFMAP_FELI_STATE_ATTR_BLK_WR_END); + + if( ( NdefMap->State == PH_NFCFRI_NDEFMAP_FELI_STATE_ATTR_BLK_WR_BEGIN)|| + ( NdefMap->State == PH_NFCFRI_NDEFMAP_FELI_STATE_ATTR_BLK_WR_END) ) + { + + /* Set the Felica Cmd*/ +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.FelCmd = (phNfc_eFelicaCmdList_t)phHal_eFelica_Raw; +#else + NdefMap->Cmd.FelCmd = phHal_eFelicaCmdListFelicaCmd; +#endif /* #ifdef PH_HAL4_ENABLE */ + + /* 1st byte represents the length of the cmd packet*/ + NdefMap->SendRecvBuf[BufIndex] = 0x00; + BufIndex++; + + /* Write/Update command code*/ + NdefMap->SendRecvBuf[BufIndex] = 0x08; + BufIndex++; + + /* IDm - Manufacturer Id : 8bytes*/ +#ifdef PH_HAL4_ENABLE + (void)memcpy( (&(NdefMap->SendRecvBuf[BufIndex])), + (void*)(&(NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.IDm)), + 8); +#else + (void)memcpy( (&(NdefMap->SendRecvBuf[BufIndex])), + (void*)(&(NdefMap->psRemoteDevInfo->RemoteDevInfo.CardInfo212_424.Startup212_424.NFCID2t)), + 8); +#endif /* #ifdef PH_HAL4_ENABLE */ + + BufIndex+=8; + + NdefMap->SendRecvBuf[BufIndex] = 0x01; /* Number of Services (n=1 ==> 0x80)*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x09; /* Service Code List*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /* Service Code List*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x01; /* Number of Blocks to Write*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x80; /* 1st Block Element : byte 1*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /* 1st Block Element : byte 2, block 1*/ + BufIndex++; + + /* Fill Attribute Blk Information*/ + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.Version; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.Nbr; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.Nbw; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)((NdefMap->FelicaAttrInfo.Nmaxb) >> 8); + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)((NdefMap->FelicaAttrInfo.Nmaxb) & (0x00ff)); + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /*RFU*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /*RFU*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /*RFU*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /*RFU*/ + BufIndex++; + + if (isStarted == FELICA_WRITE_STARTED ) + { + NdefMap->SendRecvBuf[BufIndex] = 0x0F; /* Write Flag Made On*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.RdWrFlag; /* Read write flag*/ + BufIndex++; + + /* Len Bytes*/ + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.LenBytes[0]; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.LenBytes[1]; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.LenBytes[2]; + BufIndex++; + } + else + { + /* Case: Previous Write Operation failed and integration context continues with write + operation with offset set to Current. In this case, if we find Internal Bytes remained in the + felica context is true(>0) and current block number is Zero. Then we shouldn't allow the module + to write the data to card, as this is a invalid case*/ + if ( (NdefMap->Felica.Wr_BytesRemained > 0) && (NdefMap->Felica.CurBlockNo == 0)) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + ErrFlag = TRUE; + } + else + { + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /* Write Flag Made Off*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.RdWrFlag; /* Read write flag*/ + BufIndex++; + + if ( NdefMap->Felica.Wr_BytesRemained > 0 ) + { + TotNoWrittenBytes = ( (NdefMap->Felica.CurBlockNo *16)- (16 - (NdefMap->Felica.Wr_BytesRemained))); + } + else + { + TotNoWrittenBytes = ( NdefMap->Felica.CurBlockNo *16); + + } + + /* Update Len Bytes*/ + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)(( TotNoWrittenBytes & 0x00ff0000) >> 16); + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)((TotNoWrittenBytes & 0x0000ff00) >> 8); + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)(TotNoWrittenBytes & 0x000000ff); + BufIndex++; + } + } + + if ( ErrFlag != TRUE ) + { + /* check sum update*/ + for ( index = 16 ; index < 30 ; index ++) + { + ChkSum += NdefMap->SendRecvBuf[index]; + } + + /* fill check sum in command pkt*/ + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)(ChkSum >> 8); + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = (uint8_t )(ChkSum & 0x00ff); + BufIndex++; + + /* update length of the cmd pkt*/ + NdefMap->SendRecvBuf[PH_NFCFRI_NDEFMAP_FELI_PKT_LEN_INDEX] = BufIndex; + + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + + /* Update the Send Len*/ + NdefMap->SendLength = BufIndex; + + /*set the completion routines for the desfire card operations*/ + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_NdefMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + /*set the additional informations for the data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + + /*Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + } + } + else + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + + } + return (status); +} + +static NFCSTATUS phFriNfc_Felica_HWrEmptyMsg(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + uint16_t ChkSum=0,index=0; + uint8_t BufIndex=0; + + /* Write Operation : To Erase the present NDEF Data*/ + + NdefMap->State = PH_NFCFRI_NDEFMAP_FELI_STATE_WR_EMPTY_MSG; + + /* Set the Felica Cmd*/ +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.FelCmd = (phNfc_eFelicaCmdList_t)phHal_eFelica_Raw; +#else + NdefMap->Cmd.FelCmd = phHal_eFelicaCmdListFelicaCmd; +#endif /* #ifdef PH_HAL4_ENABLE */ + + /* 1st byte represents the length of the cmd packet*/ + NdefMap->SendRecvBuf[BufIndex] = 0x00; + BufIndex++; + + /* Write/Update command code*/ + NdefMap->SendRecvBuf[BufIndex] = 0x08; + BufIndex++; + + /* IDm - Manufacturer Id : 8bytes*/ +#ifdef PH_HAL4_ENABLE + (void)memcpy( (&(NdefMap->SendRecvBuf[BufIndex])), + (void*)(&(NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.IDm)), + 8); +#else + (void)memcpy( (&(NdefMap->SendRecvBuf[BufIndex])), + (void*)(&(NdefMap->psRemoteDevInfo->RemoteDevInfo.CardInfo212_424.Startup212_424.NFCID2t)), + 8); +#endif /* #ifdef PH_HAL4_ENABLE */ + + + BufIndex+=8; + + NdefMap->SendRecvBuf[BufIndex] = 0x01; /* Number of Services (n=1 ==> 0x80)*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x09; /* Service Code List*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /* Service Code List*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x01; /* Number of Blocks to Write*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x80; /* 1st Block Element : byte 1*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /* 1st Block Element : byte 2, block 1*/ + BufIndex++; + + /* Fill Attribute Blk Information*/ + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.Version; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.Nbr; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.Nbw; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)((NdefMap->FelicaAttrInfo.Nmaxb) >> 8); + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)((NdefMap->FelicaAttrInfo.Nmaxb) & (0x00ff)); + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /*RFU*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /*RFU*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /*RFU*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /*RFU*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.WriteFlag; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.RdWrFlag; /* Read write flag*/ + BufIndex++; + + /* Len Bytes are set to 0 : Empty Msg*/ + NdefMap->SendRecvBuf[BufIndex] = 0x00; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; + BufIndex++; + + /* check sum update*/ + for ( index = 16 ; index < 30 ; index ++) + { + ChkSum += NdefMap->SendRecvBuf[index]; + } + + /* fill check sum in command pkt*/ + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)(ChkSum >> 8); + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = (uint8_t )(ChkSum & 0x00ff); + BufIndex++; + + /* update length of the cmd pkt*/ + NdefMap->SendRecvBuf[PH_NFCFRI_NDEFMAP_FELI_PKT_LEN_INDEX] = BufIndex; + + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + + /* Update the Send Len*/ + NdefMap->SendLength = BufIndex; + + /*set the completion routines for the desfire card operations*/ + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_NdefMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + /*set the additional informations for the data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + + /*Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + + return (status); +} + + + + +/*! + * \brief Used in Write Opearation. + * This Function is called after a successful validation and storing of attribution block + * content in to context. + * If the write operation is initiated with begin,function initiates the write operation with + * RdWr flag. + * If the Offset is set to Current, Checks for the EOF card reached status and writes data to + * The Card + */ + +static NFCSTATUS phFriNfc_Felica_HChkAttrBlkForWrOp(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint32_t DataLen=0; + + /*check RW Flag Access Rights*/ + /* set to read only cannot write*/ + if ( NdefMap->FelicaAttrInfo.RdWrFlag == 0x00) + + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + } + else + { + if ( ( NdefMap->Felica.Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || + ( ( NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE) && + (NdefMap->Felica.Offset != PH_FRINFC_NDEFMAP_SEEK_BEGIN ) )) + { + /* check allready written number of bytes and apdu buffer size*/ + if (NdefMap->ApduBufferSize > (uint32_t)(NdefMap->FelicaAttrInfo.Nmaxb *16)) + { + NdefMap->Felica.EofCardReachedFlag = FELICA_EOF_REACHED_WR_WITH_BEGIN_OFFSET; + } + else + { + NdefMap->Felica.EofCardReachedFlag = FALSE; + } + + + /* reset the internal variables initiate toupdate the attribute blk*/ + NdefMap->Felica.Wr_BytesRemained = 0; + NdefMap->Felica.CurBlockNo = 0; + NdefMap->Felica.NoBlocksWritten = 0; + phFriNfc_Felica_HInitInternalBuf(NdefMap->Felica.Wr_RemainedBytesBuff); + status= phFriNfc_Felica_HUpdateAttrBlkForWrOp(NdefMap,FELICA_WRITE_STARTED); + + } + else + { + if (NdefMap->Felica.Offset == PH_FRINFC_NDEFMAP_SEEK_CUR ) + { + /* Calculate the Allready Written No. Of Blocks*/ + PH_NFCFRI_NDEFMAP_FELI_CAL_LEN_BYTES(NdefMap->FelicaAttrInfo.LenBytes[0], + NdefMap->FelicaAttrInfo.LenBytes[1], + NdefMap->FelicaAttrInfo.LenBytes[2], + DataLen); + + if (( NdefMap->ApduBufferSize + (DataLen )) > + (uint32_t)( NdefMap->FelicaAttrInfo.Nmaxb *16)) + { + if(( DataLen ) == (uint32_t)(NdefMap->FelicaAttrInfo.Nmaxb *16) ) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + + NdefMap->Felica.EofCardReachedFlag =FELICA_EOF_REACHED_WR_WITH_CURR_OFFSET; + NdefMap->ApduBuffIndex =0; + NdefMap->Felica.NoBlocksWritten = 0; + status= phFriNfc_Felica_HUpdateAttrBlkForWrOp(NdefMap,FELICA_WRITE_STARTED); + } + } + else + { + NdefMap->ApduBuffIndex =0; + NdefMap->Felica.NoBlocksWritten = 0; + status= phFriNfc_Felica_HUpdateAttrBlkForWrOp(NdefMap,FELICA_WRITE_STARTED); + } + }/*if (NdefMap->Felica.Offset == PH_FRINFC_NDEFMAP_SEEK_CUR )*/ + } + } + return (status); +} + +/*! + * \brief Used in Read Opearation. + * This Function is called after a successful validation and storing of attribution block + * content in to context. + * While Offset is set to Current, Checks for the EOF card reached status and reads data from + * The Card + */ + +static NFCSTATUS phFriNfc_Felica_HChkAttrBlkForRdOp(phFriNfc_NdefMap_t *NdefMap, + uint32_t NdefLen) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + /*check WR Flag Access Rights*/ + /* set to still writing data state only cannot Read*/ + if ( NdefMap->FelicaAttrInfo.WriteFlag == 0x0F ) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_READ_FAILED); + /* As we are not able to continue with reading data + bytes read set to zero*/ + *NdefMap->NumOfBytesRead = 0; + } + else + { + status = phFriNfc_MapTool_SetCardState( NdefMap,NdefLen); + if ( status == NFCSTATUS_SUCCESS) + { + /* Read data From the card*/ + status = phFriNfc_Felica_HReadData(NdefMap,NdefMap->Felica.Offset); + } + } + + return (status); +} + +/*! + * \brief Used in Write Opearation. + * This function writes the data in terms of blocks. + * Each write operation supports,minimum Nbw blocks of bytes. + * Also checks for the EOF,>=NBW,ApduBufferSize - NdefMap->ApduBuffIndex) > 0 ) + { + /* Prepare the write cmd pkt for felica*/ + /* 1st byte represents the length of the cmd packet*/ + NdefMap->SendRecvBuf[BufIndex] = 0x00; + BufIndex++; + + /* Write/Update command code*/ + NdefMap->SendRecvBuf[BufIndex] = 0x08; + BufIndex++; + + /* IDm - Manufacturer Id : 8bytes*/ +#ifdef PH_HAL4_ENABLE + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + (&(NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.IDm)), + 8); +#else + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + (&(NdefMap->psRemoteDevInfo->RemoteDevInfo.CardInfo212_424.Startup212_424.NFCID2t)), + 8); +#endif /* #ifdef PH_HAL4_ENABLE */ + + BufIndex+=8; + + NdefMap->SendRecvBuf[BufIndex] = 0x01; /* Number of Services (n=1 ==> 0x80)*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x09; /* Service Code List*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /* Service Code List*/ + BufIndex++; + + if ( NdefMap->Felica.EofCardReachedFlag == FELICA_EOF_REACHED_WR_WITH_BEGIN_OFFSET) + { + /* check for the eof card reached flag.Need to write only mamximum bytes(memory)to card. + Used when, offset set to begin case*/ + BytesRemainedInCard= ( (NdefMap->FelicaAttrInfo.Nmaxb*16) - (NdefMap->Felica.CurBlockNo * 16)); + } + else + { + /* Offset : Cuurent*/ + if ( NdefMap->Felica.EofCardReachedFlag == FELICA_EOF_REACHED_WR_WITH_CURR_OFFSET ) + { + /* caculate previously written Ndef blks*/ + (void)phFriNfc_Felica_HGetMaximumBlksToRead(NdefMap,PH_NFCFRI_NDEFMAP_FELI_NBC); + + if ( NdefMap->Felica.Wr_BytesRemained ) + { + TotNoWrittenBytes = ( (NdefMap->Felica.CurBlockNo *16)- (16 - (NdefMap->Felica.Wr_BytesRemained))); + } + else + { + TotNoWrittenBytes = ( NdefMap->Felica.CurBlockNo *16); + } + /* Determine exactly, how many bytes we can write*/ + BytesRemainedInCard = (NdefMap->FelicaAttrInfo.Nmaxb*16 - (TotNoWrittenBytes)); + } + + } + /* Write Data Pending in the Internal Buffer*/ + if(NdefMap->Felica.Wr_BytesRemained > 0) + { + /* update the number of blocks to write with the block list elements*/ + /* Total Number of blocks to write*/ + NdefMap->SendRecvBuf[BufIndex] = 0; + BufIndex++; + + /* Update this Total no. Bloks later*/ + NoOfBlks = BufIndex; + + /* As we are writing atleast one block*/ + TotNoBlks = 1; + + /* check do we have some extra bytes to write? in User Buffer*/ + if ( NdefMap->ApduBufferSize >(uint32_t) (16 - NdefMap->Felica.Wr_BytesRemained)) + { + /* Have we reached EOF?*/ + if ( NdefMap->Felica.EofCardReachedFlag ) + { + BytesRemained = BytesRemainedInCard; + } + else + { + /* This value tells how many extra bytes we can write other than internal buffer bytes*/ + BytesRemained = (uint8_t)NdefMap->ApduBufferSize - (16 - NdefMap->Felica.Wr_BytesRemained); + } + + if ( BytesRemained ) + { + /* Not reached EOF*/ + if (!NdefMap->Felica.EofCardReachedFlag) + { + /* Calculate How many blks we need to write*/ + BlkNo =((uint8_t)( BytesRemained )/16); + + /* check blocks to write exceeds nbw*/ + if ( BlkNo >= NdefMap->FelicaAttrInfo.Nbw ) + { + BlkNo = NdefMap->FelicaAttrInfo.Nbw; + /* No. Blks to write are more than Nbw*/ + NbwCheck = 1; + } + else + { + if ((( BytesRemained %16) == 0)&& (BlkNo == 0 )) + { + BlkNo=1; + } + } + /* check do we need pad bytes?*/ + if( (!NbwCheck && (uint8_t)( BytesRemained)%16) != 0) + { + BlkNo++; + PadBytes = (BlkNo * 16) - (uint8_t)( BytesRemained); + NdefMap->Felica.PadByteFlag = TRUE; + NdefMap->Felica.NoBlocksWritten = BlkNo; + TotNoBlks += BlkNo; + + } + else + { + if ( NbwCheck ) + { + /* as we have to write only 8 blocks and already we have pad bytes so we have + to strat from previous block*/ + TotNoBlks += BlkNo - 1; + NdefMap->Felica.NoBlocksWritten = TotNoBlks-1; + } + else + { + if ( !(BytesRemained - (16 -NdefMap->Felica.Wr_BytesRemained)== 0 )) + { + TotNoBlks += BlkNo; + } + else + { + + } + if ( NdefMap->Felica.PadByteFlag ) + { + NdefMap->Felica.NoBlocksWritten = TotNoBlks-1; + + } + } + } + } + else + { + /* we have reached the eof card & hv bytes to write*/ + BlkNo =(uint8_t)(( BytesRemained - ((16 -NdefMap->Felica.Wr_BytesRemained)) )/16); + + /* check are we exceeding the NBW limit, while a write?*/ + if ( BlkNo >= NdefMap->FelicaAttrInfo.Nbw ) + { + BlkNo = NdefMap->FelicaAttrInfo.Nbw; + + /* No. Blks to write are more than Nbw*/ + NbwCheck = 1; + + } + else + { + if ((( BytesRemained %16) == 0)&& (BlkNo == 0 )) + { + BlkNo=1; + } + } + + /*check Total how many blocks to write*/ + if(((!NbwCheck) &&( BytesRemained- (16 - NdefMap->Felica.Wr_BytesRemained))%16) != 0) + { + BlkNo++; + PadBytes = (BlkNo * 16) - (uint8_t)( BytesRemained); + NdefMap->Felica.PadByteFlag = TRUE; + NdefMap->Felica.NoBlocksWritten = BlkNo; + TotNoBlks += BlkNo; + + } + else + { + if ( NbwCheck ) + { + /* as we have to write only 8 blocks and already we have pad bytes so we have + to strat from previous last block*/ + TotNoBlks += BlkNo - 1; + NdefMap->Felica.NoBlocksWritten = TotNoBlks-1; + } + else + { + /* we need to write only one block ( bytesremanind + internal buffer size = 16)*/ + if ( !(BytesRemained - (16 -NdefMap->Felica.Wr_BytesRemained)== 0 )) + { + TotNoBlks += BlkNo; + } + else + { + ;/* we are not incrementing the Total no. of blocks to write*/ + } + + if ( NdefMap->Felica.PadByteFlag ) + { + NdefMap->Felica.NoBlocksWritten = TotNoBlks -1; + + } + } + } + } + }/*if ( BytesRemained )*/ + else + { + ; /*Nothing to process here*/ + } + }/*if ( NdefMap->ApduBufferSize >(uint32_t) (16 - NdefMap->Felica.Wr_BytesRemained))*/ + else + { + /* No new blks to write*/ + NdefMap->Felica.NoBlocksWritten = 0; + } + /* Prepare the Blk List for Write Operation*/ + /* Block List for NBw : 1st byte : two byte len list: 2nd byte is the block number*/ + for ( i=0; i< TotNoBlks; i++) + { + NdefMap->SendRecvBuf[BufIndex] = 0x80; + BufIndex++; + /* remember the previous Blk no and continue from there*/ + if ( NdefMap->Felica.PadByteFlag == TRUE ) + { + NdefMap->SendRecvBuf[BufIndex] = NdefMap->Felica.CurBlockNo + i; + BufIndex++; + } + else + { + CurBlk = NdefMap->Felica.CurBlockNo +1; + NdefMap->SendRecvBuf[BufIndex] = CurBlk + i; + BufIndex++; + } + } + /* Copy relevant data to Transc buffer*/ + if((NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >= (uint32_t)(16 - NdefMap->Felica.Wr_BytesRemained)) + { + + /*Copy the Remained bytes from the internal buffer to trxbuffer */ + (void)memcpy( (&(NdefMap->SendRecvBuf[BufIndex])), + NdefMap->Felica.Wr_RemainedBytesBuff, + NdefMap->Felica.Wr_BytesRemained); + + /*Increment the buff index*/ + BufIndex += NdefMap->Felica.Wr_BytesRemained; + + + /*append copy 16-bytesToPad to trxBuffer*/ + (void)memcpy( (&(NdefMap->SendRecvBuf[BufIndex])), + (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (16 - NdefMap->Felica.Wr_BytesRemained)); + + /* Update Number Of Bytes Writtened*/ + NdefMap->NumOfBytesWritten = 16 - NdefMap->Felica.Wr_BytesRemained; + + /* increment the index*/ + BufIndex += 16 - NdefMap->Felica.Wr_BytesRemained; + + if ( BytesRemained ) + { + if (!NdefMap->Felica.EofCardReachedFlag) + { + /* check nbw limit*/ + if ( NbwCheck != 1 ) + { + /* Copy Extra Bytes other than the internal buffer bytes*/ + (void)memcpy( (&(NdefMap->SendRecvBuf[BufIndex])), + (&(NdefMap->ApduBuffer[(16 - NdefMap->Felica.Wr_BytesRemained)])), + (NdefMap->ApduBufferSize - (16 - NdefMap->Felica.Wr_BytesRemained))); + + + /* Update Number Of Bytes Writtened*/ + NdefMap->NumOfBytesWritten += (uint16_t)(NdefMap->ApduBufferSize - (16 - NdefMap->Felica.Wr_BytesRemained)); + + BufIndex += (uint8_t)(NdefMap->ApduBufferSize - (16 - NdefMap->Felica.Wr_BytesRemained)); + + if ( PadBytes ) + { + for(i= 0; i< PadBytes; i++) + { + NdefMap->SendRecvBuf[BufIndex] =0x00; + BufIndex++; + } + /* no of bytes remained copy*/ + NdefMap->Felica.Wr_BytesRemained = (uint8_t)(16 - PadBytes); + + /*copy the data to internal buffer : Bytes remained*/ + (void)memcpy( NdefMap->Felica.Wr_RemainedBytesBuff, + (&( NdefMap->ApduBuffer[(NdefMap->ApduBufferSize - NdefMap->Felica.Wr_BytesRemained)])), + ( NdefMap->Felica.Wr_BytesRemained)); + } + else + { + /* No Bytes in Internal buffer*/ + NdefMap->Felica.Wr_BytesRemained = 0; + } + + } + else + { + + /*Copy Nbw*16 bytes of data to the trx buffer*/ + (void)memcpy( (&(NdefMap->SendRecvBuf[BufIndex])), + (&(NdefMap->ApduBuffer[(16 - NdefMap->Felica.Wr_BytesRemained)])), + (NdefMap->FelicaAttrInfo.Nbw - 1) * 16); + + /* increment the Buffindex*/ + BufIndex += ((NdefMap->FelicaAttrInfo.Nbw - 1 )*16); + + NdefMap->Felica.Wr_BytesRemained = 0; + NdefMap->NumOfBytesWritten+= ((NdefMap->FelicaAttrInfo.Nbw -1)*16); + NdefMap->Felica.PadByteFlag =FALSE; + } + }/*if (!NdefMap->Felica.EofCardReachedFlag)*/ + else + { + /* check nbw limit*/ + if ( NbwCheck != 1 ) + { + /* handle EOF card reached case*/ + (void)memcpy( (&(NdefMap->SendRecvBuf[BufIndex])), + (&(NdefMap->ApduBuffer[(16 - NdefMap->Felica.Wr_BytesRemained)])), + ( BytesRemained - ((16 -NdefMap->Felica.Wr_BytesRemained) ))); + + /* Update Number Of Bytes Writtened*/ + NdefMap->NumOfBytesWritten += (uint16_t)( BytesRemained - (16 -NdefMap->Felica.Wr_BytesRemained)); + + BufIndex += (uint8_t)( BytesRemained - (16 -NdefMap->Felica.Wr_BytesRemained)); + + if ( PadBytes ) + { + for(i= 0; i< PadBytes; i++) + { + NdefMap->SendRecvBuf[BufIndex] =0x00; + BufIndex++; + } + + /*no of bytes remained copy*/ + NdefMap->Felica.Wr_BytesRemained = (uint8_t)(16 - PadBytes); + + /*copy the data to internal buffer : Bytes remained*/ + (void)memcpy(NdefMap->Felica.Wr_RemainedBytesBuff, + (&(NdefMap->ApduBuffer[(NdefMap->ApduBufferSize - NdefMap->Felica.Wr_BytesRemained)])), + (NdefMap->Felica.Wr_BytesRemained)); + + } + else + { + NdefMap->Felica.Wr_BytesRemained = 0; + } + } + else + { + + /*Copy Nbw*16 bytes of data to the trx buffer*/ + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + (&(NdefMap->ApduBuffer[(16 - NdefMap->Felica.Wr_BytesRemained)])), + (NdefMap->FelicaAttrInfo.Nbw - 1) * 16); + + /* increment the Buffindex*/ + BufIndex += ((NdefMap->FelicaAttrInfo.Nbw - 1 )*16); + + NdefMap->Felica.Wr_BytesRemained = 0; + NdefMap->NumOfBytesWritten+= ((NdefMap->FelicaAttrInfo.Nbw -1)*16); + + NdefMap->Felica.PadByteFlag =FALSE; + } + } + }/*if ( BytesRemained )*/ + else + { + NdefMap->Felica.Wr_BytesRemained = 0; + } + /* Update Total No. of blocks writtened*/ + NdefMap->SendRecvBuf[NoOfBlks -1 ]=TotNoBlks; + }/*if((NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >= (uint32_t)(16 - NdefMap->Felica.Wr_BytesRemained))*/ + else + { + /*copy the internal buffer data to trx buffer*/ + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + NdefMap->Felica.Wr_RemainedBytesBuff, + (NdefMap->Felica.Wr_BytesRemained)); + + /* increment the index*/ + BufIndex+=NdefMap->Felica.Wr_BytesRemained; + + /*append the apdusize data to the trx buffer*/ + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + NdefMap->ApduBufferSize); + + /* Index increment*/ + BufIndex+= (uint8_t)NdefMap->ApduBufferSize; + + /* Tells how many bytes present in the internal buffer*/ + BytesRemained = NdefMap->Felica.Wr_BytesRemained + NdefMap->ApduBufferSize; + + PadBytes = (uint8_t)(16-BytesRemained); + + /* Pad empty bytes with Zeroes to complete 16 bytes*/ + for(i= 0; i< PadBytes; i++) + { + NdefMap->SendRecvBuf[BufIndex] =0x00; + BufIndex++; + } + + /* Update Number Of Bytes Writtened*/ + NdefMap->NumOfBytesWritten = (uint16_t)NdefMap->ApduBufferSize; + + /* Flag set to understand that , we have received less no. of bytes than + present in the internal buffer*/ + NdefMap->Felica.IntermediateWrFlag = TRUE; + + if ( NdefMap->Felica.PadByteFlag ) + { + NdefMap->Felica.NoBlocksWritten = 0; + } + } + + NdefMap->SendRecvBuf[PH_NFCFRI_NDEFMAP_FELI_PKT_LEN_INDEX] = BufIndex; + NdefMap->SendLength = BufIndex; + /* Update Total No. of blocks writtened*/ + NdefMap->SendRecvBuf[NoOfBlks -1 ]=TotNoBlks; + } + else + { + /*Fresh write, starting from a new block*/ + if ( (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >= (uint32_t)(16* NdefMap->FelicaAttrInfo.Nbw )) + { + /* check for the card size and write Nbw Blks*/ + if ( NdefMap->FelicaAttrInfo.Nmaxb - NdefMap->Felica.CurBlockNo >= NdefMap->FelicaAttrInfo.Nbw) + { + /* update the number of blocks to write with the block list elements*/ + /* Total Number of blocks to write*/ + NdefMap->SendRecvBuf[BufIndex] = NdefMap->FelicaAttrInfo.Nbw; + BufIndex++; + + /* Block List for NBw : 1st byte : two byte len list: 2nd byte is the block number*/ + for ( i=1; i<= NdefMap->FelicaAttrInfo.Nbw; i++) + { + NdefMap->SendRecvBuf[BufIndex] = 0x80; + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = NdefMap->Felica.CurBlockNo + i; + BufIndex++; + } + /*Copy Nbw*16 bytes of data to the trx buffer*/ + + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + NdefMap->FelicaAttrInfo.Nbw * 16); + + /* increment the Buffindex*/ + BufIndex += (NdefMap->FelicaAttrInfo.Nbw*16); + + /* update the length*/ + NdefMap->SendRecvBuf[PH_NFCFRI_NDEFMAP_FELI_PKT_LEN_INDEX] = BufIndex; + + NdefMap->Felica.Wr_BytesRemained = 0; + NdefMap->NumOfBytesWritten = (NdefMap->FelicaAttrInfo.Nbw*16); + NdefMap->Felica.NoBlocksWritten = NdefMap->FelicaAttrInfo.Nbw; + + /* update the Send length*/ + NdefMap->SendLength = BufIndex; + + NdefMap->Felica.PadByteFlag = FALSE; + }/*if ( NdefMap->FelicaAttrInfo.Nmaxb - NdefMap->Felica.CurBlockNo >= NdefMap->FelicaAttrInfo.Nbw)*/ + else + { + /* we need to write less than nbw blks*/ + /* update the number of blocks to write with the block list elements*/ + /* Total Number of blocks to write*/ + NdefMap->SendRecvBuf[BufIndex] = (uint8_t)( NdefMap->FelicaAttrInfo.Nmaxb - NdefMap->Felica.CurBlockNo); + BufIndex++; + + /* Block List for NBw : 1st byte : two byte len list: 2nd byte is the block number*/ + for ( i=1; i<= (NdefMap->FelicaAttrInfo.Nmaxb - NdefMap->Felica.CurBlockNo); i++) + { + NdefMap->SendRecvBuf[BufIndex] = 0x80; + BufIndex++; + NdefMap->SendRecvBuf[BufIndex] = NdefMap->Felica.CurBlockNo + i; + BufIndex++; + } + + /*Copy Nbw*16 bytes of data to the trx buffer*/ + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (NdefMap->FelicaAttrInfo.Nmaxb - NdefMap->Felica.CurBlockNo)*16); + + /* increment the Buffindex*/ + BufIndex += (uint8_t)((NdefMap->FelicaAttrInfo.Nmaxb - NdefMap->Felica.CurBlockNo )*16); + + /* update the length*/ + NdefMap->SendRecvBuf[PH_NFCFRI_NDEFMAP_FELI_PKT_LEN_INDEX] = BufIndex; + + NdefMap->NumOfBytesWritten = ((NdefMap->FelicaAttrInfo.Nmaxb - NdefMap->Felica.CurBlockNo)*16); + NdefMap->Felica.NoBlocksWritten = (uint8_t)(NdefMap->FelicaAttrInfo.Nmaxb - NdefMap->Felica.CurBlockNo); + + /* update the Send length*/ + NdefMap->SendLength = BufIndex; + + NdefMap->Felica.PadByteFlag =FALSE; + NdefMap->Felica.Wr_BytesRemained = 0; + } + }/* if ( (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >= (uint32_t)(16* NdefMap->FelicaAttrInfo.Nbw )) */ + else + { + /*chk eof reached*/ + if ( NdefMap->Felica.EofCardReachedFlag) + { + BlkNo =((uint8_t)(BytesRemainedInCard )/16); + if(((uint8_t)( BytesRemainedInCard )%16) != 0) + { + BlkNo++; + PadBytes = ((BlkNo * 16) - (uint8_t)(BytesRemainedInCard )); + NdefMap->Felica.PadByteFlag = TRUE; + } + } + else + { + + BlkNo =((uint8_t)( NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)/16); + if(((uint8_t)( NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)%16) != 0) + { + BlkNo++; + PadBytes = (BlkNo * 16) - (uint8_t)( NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + NdefMap->Felica.PadByteFlag = TRUE; + + } + + + } + + /* update the number of blocks to write with the block list elements*/ + /* Total Number of blocks to write*/ + NdefMap->SendRecvBuf[BufIndex] = BlkNo; + BufIndex++; + + NdefMap->Felica.NoBlocksWritten = BlkNo; + + /* Block List for NBw : 1st byte : two byte len list: 2nd byte is the block number*/ + for ( i=0; i< BlkNo; i++) + { + NdefMap->SendRecvBuf[BufIndex] = 0x80; + BufIndex++; + { + CurBlk = NdefMap->Felica.CurBlockNo +1; + NdefMap->SendRecvBuf[BufIndex] = CurBlk + i; + BufIndex++; + } + } + if ( NdefMap->Felica.EofCardReachedFlag ) + { + /*Copy last data to the trx buffer*/ + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + BytesRemainedInCard ); + + /* increment the bufindex and bytes written*/ + BufIndex += (uint8_t )BytesRemainedInCard ; + NdefMap->NumOfBytesWritten = (uint16_t)BytesRemainedInCard ; + } + else + { + /*Copy data to the trx buffer*/ + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + (&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex])), + (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex)); + + /* increment the bufindex and bytes written*/ + BufIndex += (uint8_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + NdefMap->NumOfBytesWritten = (uint8_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + } + if ( PadBytes ) + { + for(i= 0; i< PadBytes; i++) + { + NdefMap->SendRecvBuf[BufIndex] =0x00; + BufIndex++; + } + /*no of bytes remained copy*/ + NdefMap->Felica.Wr_BytesRemained = (uint8_t)(16 - PadBytes); + + if ( NdefMap->Felica.EofCardReachedFlag ) + { + /*copy the data to internal buffer : Bytes remained*/ + (void)memcpy(NdefMap->Felica.Wr_RemainedBytesBuff, + (&(NdefMap->ApduBuffer[((BytesRemainedInCard - (BytesRemainedInCard % 16)))])), + ( NdefMap->Felica.Wr_BytesRemained)); + + } + else + { + /*copy the data to internal buffer : Bytes remained*/ + (void)memcpy( NdefMap->Felica.Wr_RemainedBytesBuff, + (&(NdefMap->ApduBuffer[((NdefMap->ApduBufferSize - NdefMap->Felica.Wr_BytesRemained))])), + ( NdefMap->Felica.Wr_BytesRemained)); + + } + }/*if ( PadBytes )*/ + else + { + NdefMap->Felica.Wr_BytesRemained = 0; + NdefMap->Felica.PadByteFlag = FALSE; + } + /* update the pkt len*/ + NdefMap->SendRecvBuf[PH_NFCFRI_NDEFMAP_FELI_PKT_LEN_INDEX] = BufIndex; + NdefMap->SendLength = BufIndex; + } + }/* else of if ( (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) >= (uint32_t)(16* NdefMap->FelicaAttrInfo.Nbw )) */ + status = phFriNfc_Felica_HWriteDataBlk(NdefMap); + } + else + { + /*0 represents the write operation ended*/ + status = phFriNfc_Felica_HUpdateAttrBlkForWrOp(NdefMap,FELICA_WRITE_ENDED); + } + return (status); +} + + +/*! + * \brief Used in Write Opearation. + * This function prepares and sends transcc Cmd Pkt. + */ + +static NFCSTATUS phFriNfc_Felica_HWriteDataBlk(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + /*set the additional informations for the data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + + /*Set the ISO14434 command*/ +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.FelCmd = (phNfc_eFelicaCmdList_t)phHal_eFelica_Raw; +#else + NdefMap->Cmd.FelCmd = phHal_eFelicaCmdListFelicaCmd; +#endif /* #ifdef PH_HAL4_ENABLE */ + + /* set the state*/ + NdefMap->State = PH_NFCFRI_NDEFMAP_FELI_STATE_WR_BLOCK; + + /* set send receive length*/ + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + + /*Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + return (status); +} + +/*! + * \brief Check whether a particular Remote Device is NDEF compliant. + * The function checks whether the peer device is NDEF compliant. + */ + +NFCSTATUS phFriNfc_Felica_ChkNdef( phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint8_t sysCode[2]; + + /* set the system code for selecting the wild card*/ + sysCode[0] = 0x12; + sysCode[1] = 0xFC; + + status = phFriNfc_Felica_HPollCard( NdefMap,sysCode,PH_NFCFRI_NDEFMAP_FELI_STATE_SELECT_NDEF_APP); + + return (status); + +} +/*! + * \brief Check whether a particular Remote Device is NDEF compliant. + * selects the sysCode and then NFC Forum Reference Applications + */ +#ifdef PH_HAL4_ENABLE +static NFCSTATUS phFriNfc_Felica_HPollCard( phFriNfc_NdefMap_t *NdefMap, + const uint8_t sysCode[], + uint8_t state) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + /*Format the Poll Packet for selecting the system code passed as parameter */ + NdefMap->SendRecvBuf[0] = 0x06; + NdefMap->SendRecvBuf[1] = 0x00; + NdefMap->SendRecvBuf[2] = sysCode[0]; + NdefMap->SendRecvBuf[3] = sysCode[1]; + NdefMap->SendRecvBuf[4] = 0x01; + NdefMap->SendRecvBuf[5] = 0x03; + + NdefMap->SendLength = 6; + + /*set the completion routines for the felica card operations*/ + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_Felica_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + /*Set Ndef State*/ + NdefMap->State = state; + + /* set the felica cmd */ + NdefMap->Cmd.FelCmd = (phNfc_eFelicaCmdList_t)phHal_eFelica_Raw; + + /*set the additional informations for the data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + + status = phFriNfc_OvrHal_Transceive(NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + return (status); +} +#endif + + +#ifndef PH_HAL4_ENABLE +static NFCSTATUS phFriNfc_Felica_HPollCard( phFriNfc_NdefMap_t *NdefMap, + const uint8_t sysCode[], + uint8_t state) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + /*Format the Poll Packet for selecting the wild card "0xff 0xff as system code*/ + NdefMap->FelicaPollDetails.DevInputParam->FelicaPollPayload[0] = 0x00; + NdefMap->FelicaPollDetails.DevInputParam->FelicaPollPayload[1] = sysCode[0]; + NdefMap->FelicaPollDetails.DevInputParam->FelicaPollPayload[2] = sysCode[1]; + NdefMap->FelicaPollDetails.DevInputParam->FelicaPollPayload[3] = 0x01; + NdefMap->FelicaPollDetails.DevInputParam->FelicaPollPayload[4] = 0x03; + + /* set the length to zero*/ + NdefMap->FelicaPollDetails.DevInputParam->GeneralByteLength =0x00; + + NdefMap->NoOfDevices = PH_FRINFC_NDEFMAP_FELI_NUM_DEVICE_TO_DETECT; + + /*set the completion routines for the felica card operations*/ + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_Felica_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + /*Set Ndef State*/ + NdefMap->State = state; + + /* Harsha: This is a special case for felica. + Make a copy of the remote device information and send it for + polling. Return the original remote device information to the + caller. The user does not need the updated results of the poll + that we are going to call now. This is only used for checking + whether the felica card is NDEF compliant or not. */ + (void) memcpy( &NdefMap->FelicaPollDetails.psTempRemoteDevInfo, + NdefMap->psRemoteDevInfo, + sizeof(phHal_sRemoteDevInformation_t)); + + /* Reset the session opened flag */ + NdefMap->FelicaPollDetails.psTempRemoteDevInfo.SessionOpened = 0x00; + + /*Call the Overlapped HAL POLL function */ + status = phFriNfc_OvrHal_Poll( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->OpModeType, + &NdefMap->FelicaPollDetails.psTempRemoteDevInfo, + &NdefMap->NoOfDevices, + NdefMap->FelicaPollDetails.DevInputParam); + + return (status); +} +#endif /* #ifndef PH_HAL4_ENABLE */ +/*! + * \brief Checks validity of system code sent from the lower device, during poll operation. + */ + +static NFCSTATUS phFriNfc_Felica_HUpdateManufIdDetails(const phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + /* Get the details from Poll Response packet */ + if (NdefMap->SendRecvLength >= (uint16_t*)20) + { + (void)memcpy( (uint8_t *)NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.IDm, + (uint8_t *)&NdefMap->SendRecvBuf[2], 8); + (void)memcpy( (uint8_t *)NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm, + (uint8_t *)&NdefMap->SendRecvBuf[10], 8); + NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode[1] = NdefMap->SendRecvBuf[18]; + NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode[0] = NdefMap->SendRecvBuf[19]; + NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.IDmLength = 8; + + /* copy the IDm and PMm in Manufacture Details Structure*/ + (void)memcpy( (uint8_t *)(NdefMap->FelicaManufDetails.ManufID), + (uint8_t *)NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.IDm, + 8); + (void)memcpy( (uint8_t *)(NdefMap->FelicaManufDetails.ManufParameter), + (uint8_t *)NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm, + 8); + if((NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode[1] == 0x12) + && (NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode[0] == 0xFC)) + { + status = PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS); + } + else + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + } + else + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + + return (status); +} + + +/*! + * \brief Completion Routine, Processing function, needed to avoid long blocking. + * \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion + * Routine in order to be able to notify the component that an I/O has finished and data are + * ready to be processed. + */ + +void phFriNfc_Felica_Process(void *Context, + NFCSTATUS Status) +{ + uint8_t CRFlag = FALSE; + uint16_t RecvTxLen = 0, + BytesToRecv = 0, + Nbc = 0; + uint32_t TotNoWrittenBytes = 0, + NDEFLen=0; + + /*Set the context to Map Module*/ + phFriNfc_NdefMap_t *NdefMap = (phFriNfc_NdefMap_t *)Context; + + if ( Status == NFCSTATUS_SUCCESS ) + { + switch (NdefMap->State) + { + case PH_NFCFRI_NDEFMAP_FELI_STATE_SELECT_NDEF_APP: + + /* check the ndef compliency with the system code reecived in the RemoteDevInfo*/ + Status = phFriNfc_Felica_HUpdateManufIdDetails(NdefMap); + + if (Status == NFCSTATUS_SUCCESS) + { + /* Mantis ID : 645*/ + /* set the operation type to Check ndef type*/ + NdefMap->Felica.OpFlag = PH_FRINFC_NDEFMAP_FELI_CHK_NDEF_OP; + Status = phFriNfc_Felica_HRdAttrInfo(NdefMap); + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + CRFlag = TRUE; + } + } + else + { + CRFlag = TRUE; + } + if ( CRFlag == TRUE ) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_CHK_NDEF,Status); + + } + break; + + case PH_NFCFRI_NDEFMAP_FELI_STATE_RD_ATTR: + /* check for the status flag1 and status flag2for the successful read operation*/ + if ( NdefMap->SendRecvBuf[10] == 0x00) + { + /* check the Manuf Id in the receive buffer*/ + Status = phFriNfc_Felica_HCheckManufId(NdefMap); + if ( Status == NFCSTATUS_SUCCESS) + { + /* Update the Attribute Information in to the context structure*/ + Status = phFriNfc_Felica_HUpdateAttrInfo(NdefMap); + if ( Status == NFCSTATUS_SUCCESS ) + { + PH_NFCFRI_NDEFMAP_FELI_CAL_LEN_BYTES(NdefMap->FelicaAttrInfo.LenBytes[0], + NdefMap->FelicaAttrInfo.LenBytes[1], + NdefMap->FelicaAttrInfo.LenBytes[2], + NDEFLen); + + if ( NdefMap->Felica.OpFlag == PH_FRINFC_NDEFMAP_FELI_WR_ATTR_RD_OP ) + { + /* Proceed With Write Functinality*/ + Status = phFriNfc_Felica_HChkAttrBlkForWrOp(NdefMap); + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_WR_NDEF,Status); + } + } + else if( NdefMap->Felica.OpFlag == PH_FRINFC_NDEFMAP_FELI_RD_ATTR_RD_OP ) + { + /* Proceed With Read Functinality*/ + Status = phFriNfc_Felica_HChkAttrBlkForRdOp(NdefMap,NDEFLen); + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_RD_NDEF,Status); + } + } + else if( NdefMap->Felica.OpFlag == PH_FRINFC_NDEFMAP_FELI_CHK_NDEF_OP ) + { + + Status = phFriNfc_MapTool_SetCardState( NdefMap, + NDEFLen); + /* check status value*/ + NdefMap->CardType = PH_FRINFC_NDEFMAP_FELICA_SMART_CARD; + /*reset the buffer index*/ + NdefMap->ApduBuffIndex = 0; + /* set the Next operation Flag to indicate need of reading attribute information*/ + NdefMap->Felica.OpFlag = PH_FRINFC_NDEFMAP_FELI_OP_NONE; + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_CHK_NDEF,Status); + } + else if ( NdefMap->Felica.OpFlag == PH_FRINFC_NDEFMAP_FELI_WR_EMPTY_MSG_OP ) + { + /* Proceed With Write Functinality*/ + Status = phFriNfc_Felica_HWrEmptyMsg(NdefMap); + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_ERASE_NDEF,Status); + } + } + else + { + + /* invalid operation occured*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_DEVICE_REQUEST); + CRFlag =TRUE ; + } + } + else + { + CRFlag =TRUE ; + } + } + else + { + CRFlag =TRUE ; + } + } + else + { + CRFlag =TRUE; + /*handle the Error case*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_READ_FAILED); + } + if ( CRFlag == TRUE ) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_RD_NDEF,Status); + } + break; + + case PH_NFCFRI_NDEFMAP_FELI_STATE_ATTR_BLK_WR_BEGIN: + /* chk the status flags 1 and 2*/ + if ( NdefMap->SendRecvBuf[10] == 0x00 ) + { + /* Update Data Call*/ + Status =phFriNfc_Felica_HUpdateData(NdefMap); + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_WR_NDEF,Status); + } + } + else + { + /*handle the Error case*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_WRITE_FAILED); + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_WR_NDEF,Status); + + } + break; + case PH_NFCFRI_NDEFMAP_FELI_STATE_ATTR_BLK_WR_END: + + /* chk the status flags 1 and 2*/ + if ( NdefMap->SendRecvBuf[10] == 0x00) + { + /* Entire Write Operation is complete*/ + Status = PHNFCSTVAL(CID_NFC_NONE,\ + NFCSTATUS_SUCCESS); + } + else + { + /*handle the Error case*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_WRITE_FAILED); + } + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_WR_NDEF,Status); + break; + + case PH_NFCFRI_NDEFMAP_FELI_STATE_WR_EMPTY_MSG : + + /* chk the status flags 1 and 2*/ + if ( NdefMap->SendRecvBuf[10] == 0x00) + { + /* Entire Write Operation is complete*/ + Status = PHNFCSTVAL(CID_NFC_NONE,\ + NFCSTATUS_SUCCESS); + } + else + { + /*handle the Error case*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_WRITE_FAILED); + } + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_WR_NDEF,Status); + break; + + case PH_NFCFRI_NDEFMAP_FELI_STATE_WR_BLOCK : + if(NdefMap->SendRecvBuf[1] == PH_NFCFRI_NDEFMAP_FELI_WR_RESP_BYTE ) + { + /* chk the status flags 1 and 2*/ + if ( NdefMap->SendRecvBuf[10] == 0x00 ) + { + /* This is used when we have bytes less than 16 bytes*/ + if ( NdefMap->Felica.IntermediateWrFlag == TRUE ) + { + /* after Successful write copy the last writtened bytes back to the + internal buffer*/ + (void)memcpy( (&(NdefMap->Felica.Wr_RemainedBytesBuff[NdefMap->Felica.Wr_BytesRemained])), + NdefMap->ApduBuffer, + NdefMap->NumOfBytesWritten); + + NdefMap->Felica.Wr_BytesRemained += + (uint8_t)( NdefMap->NumOfBytesWritten); + + /* Increment the Send Buffer index */ + NdefMap->ApduBuffIndex += + NdefMap->NumOfBytesWritten; + + *NdefMap->WrNdefPacketLength = NdefMap->ApduBuffIndex; + NdefMap->Felica.IntermediateWrFlag = FALSE; + /* Call Update Data()*/ + Status = phFriNfc_Felica_HUpdateData(NdefMap); + } + else + { + /* update the index and bytes writtened*/ + NdefMap->ApduBuffIndex += NdefMap->NumOfBytesWritten; + *NdefMap->WrNdefPacketLength = NdefMap->ApduBuffIndex; + if ( NdefMap->Felica.EofCardReachedFlag ) + { + if ( NdefMap->Felica.CurBlockNo < NdefMap->FelicaAttrInfo.Nmaxb) + { + NdefMap->Felica.CurBlockNo += NdefMap->Felica.NoBlocksWritten; + } + if (( NdefMap->Felica.CurBlockNo == NdefMap->FelicaAttrInfo.Nmaxb) && + ( NdefMap->ApduBuffIndex == (NdefMap->FelicaAttrInfo.Nmaxb*16))) + { + NdefMap->Felica.EofCardReachedFlag = FELICA_RD_WR_EOF_CARD_REACHED ; + /*0 represents the write ended*/ + Status = phFriNfc_Felica_HUpdateAttrBlkForWrOp(NdefMap,FELICA_WRITE_ENDED); + if( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_WR_NDEF,Status); + } + } + else + { + PH_NFCFRI_NDEFMAP_FELI_CAL_LEN_BYTES(NdefMap->FelicaAttrInfo.LenBytes[0], + NdefMap->FelicaAttrInfo.LenBytes[1], + NdefMap->FelicaAttrInfo.LenBytes[2], + TotNoWrittenBytes); + if ( ( NdefMap->Felica.CurBlockNo == NdefMap->FelicaAttrInfo.Nmaxb) && + ((TotNoWrittenBytes + NdefMap->ApduBuffIndex) == (uint32_t)(NdefMap->FelicaAttrInfo.Nmaxb*16))) + { + NdefMap->Felica.EofCardReachedFlag =FELICA_RD_WR_EOF_CARD_REACHED; + /*0 represents the write ended*/ + Status = phFriNfc_Felica_HUpdateAttrBlkForWrOp(NdefMap,FELICA_WRITE_ENDED); + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_WR_NDEF,Status); + } + } + else + { + /* Call Update Data()*/ + Status = phFriNfc_Felica_HUpdateData(NdefMap); + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_WR_NDEF,Status); + } + } + } + }/*if ( NdefMap->Felica.EofCardReachedFlag )*/ + else + { + NdefMap->Felica.CurBlockNo += NdefMap->Felica.NoBlocksWritten; + /* Call Update Data()*/ + Status = phFriNfc_Felica_HUpdateData(NdefMap); + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_WR_NDEF,Status); + } + } + } + }/*if ( NdefMap->SendRecvBuf[10] == 0x00 )*/ + else + { + /*handle the Error case*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_WRITE_FAILED); + CRFlag = TRUE; + + } + }/*if(NdefMap->SendRecvBuf[1] == PH_NFCFRI_NDEFMAP_FELI_WR_RESP_BYTE )*/ + else + { + /*return Error "Invalid Write Response Code"*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_WRITE_FAILED); + CRFlag = TRUE; + + } + if ( CRFlag == TRUE ) + { + /* Reset following parameters*/ + NdefMap->ApduBuffIndex=0; + NdefMap->Felica.Wr_BytesRemained = 0; + NdefMap->ApduBufferSize = 0; + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_WR_NDEF,Status); + } + + break; + + case PH_NFCFRI_NDEFMAP_FELI_STATE_RD_BLOCK : + + /* check the Manuf Id in the receive buffer*/ + Status = phFriNfc_Felica_HCheckManufId(NdefMap); + if ( Status == NFCSTATUS_SUCCESS ) + { + if(NdefMap->SendRecvBuf[1] == PH_NFCFRI_NDEFMAP_FELI_RD_RESP_BYTE ) + { + /* calculate the Nmaxb*/ + Nbc = phFriNfc_Felica_HGetMaximumBlksToRead(NdefMap,PH_NFCFRI_NDEFMAP_FELI_NBC); + /*get Receive length from the card for corss verifications*/ + RecvTxLen= phFriNfc_Felica_HSetTrxLen(NdefMap,Nbc); + BytesToRecv = NdefMap->SendRecvBuf[12]*16; + + /* chk the status flags 1 */ + if ( NdefMap->SendRecvBuf[10] == 0x00) + { + if ( RecvTxLen == BytesToRecv) + { + NdefMap->Felica.CurBlockNo += (uint8_t)(RecvTxLen/16); + phFriNfc_Felica_HAfterRead_CopyDataToBuff(NdefMap); + Status = phFriNfc_Felica_HReadData(NdefMap,PH_FRINFC_NDEFMAP_SEEK_CUR); + /* handle the error in Transc function*/ + if ( (Status & PHNFCSTBLOWER) != (NFCSTATUS_PENDING & PHNFCSTBLOWER)) + { + CRFlag =TRUE; + } + } + else + { + CRFlag =TRUE; + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + /*set the buffer index back to zero*/ + NdefMap->ApduBuffIndex = 0; + NdefMap->Felica.Rd_NoBytesToCopy = 0; + } + } + else + { + NdefMap->ApduBuffIndex=0; + /*handle the Error case*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_READ_FAILED); + CRFlag =TRUE; + } + } + else + { + CRFlag =TRUE; + NdefMap->ApduBuffIndex=0; + /*return Error "Invalid Read Response Code"*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_READ_FAILED); + } + } + else + { + CRFlag =TRUE; + } + if ( CRFlag ==TRUE ) + { + /* call respective CR */ + phFriNfc_Felica_HCrHandler(NdefMap,PH_FRINFC_NDEFMAP_CR_RD_NDEF,Status); + } + break; + + default: + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + phFriNfc_Felica_HCrHandler(NdefMap, PH_FRINFC_NDEFMAP_CR_INVALID_OPE, Status); + break; + + + } + } + else + { + /* Call CR for unknown Error's*/ + switch ( NdefMap->State) + { + case PH_FRINFC_NDEFMAP_FELI_STATE_CHK_NDEF : + case PH_NFCFRI_NDEFMAP_FELI_STATE_SELECT_WILD_CARD : + case PH_NFCFRI_NDEFMAP_FELI_STATE_SELECT_NDEF_APP : + case PH_NFCFRI_NDEFMAP_FELI_STATE_RD_ATTR : + phFriNfc_Felica_HCrHandler(NdefMap, PH_FRINFC_NDEFMAP_CR_CHK_NDEF, + Status); + break; + case PH_NFCFRI_NDEFMAP_FELI_STATE_WR_BLOCK : + case PH_NFCFRI_NDEFMAP_FELI_STATE_ATTR_BLK_WR_BEGIN : + case PH_NFCFRI_NDEFMAP_FELI_STATE_ATTR_BLK_WR_END : + phFriNfc_Felica_HCrHandler(NdefMap, PH_FRINFC_NDEFMAP_CR_WR_NDEF, + Status); + break; + case PH_NFCFRI_NDEFMAP_FELI_STATE_RD_BLOCK : + phFriNfc_Felica_HCrHandler(NdefMap, PH_FRINFC_NDEFMAP_CR_RD_NDEF, + Status); + break; + default : + /*set the invalid state*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_DEVICE_REQUEST); + phFriNfc_Felica_HCrHandler(NdefMap, PH_FRINFC_NDEFMAP_CR_INVALID_OPE, Status); + break; + } + } + +} + +/*! + * \brief Prepares Cmd Pkt for reading attribute Blk information. + */ +static NFCSTATUS phFriNfc_Felica_HRdAttrInfo(phFriNfc_NdefMap_t *NdefMap) +{ + + NFCSTATUS status = NFCSTATUS_PENDING; + uint8_t BufIndex = 0; + + /* Set the Felica Cmd*/ +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.FelCmd = (phNfc_eFelicaCmdList_t)phHal_eFelica_Raw; +#else + NdefMap->Cmd.FelCmd = phHal_eFelicaCmdListFelicaCmd; +#endif /* #ifdef PH_HAL4_ENABLE */ + + /*set the additional informations for the data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + + /* 1st byte represents the length of the cmd packet*/ + NdefMap->SendRecvBuf[BufIndex] = 0x00; + BufIndex++; + + /* Read/check command code*/ + NdefMap->SendRecvBuf[BufIndex] = 0x06; + BufIndex++; + + /* IDm - Manufacturer Id : 8bytes*/ +#ifdef PH_HAL4_ENABLE + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + (void * )&NdefMap->psRemoteDevInfo->RemoteDevInfo.Felica_Info.IDm, + 8); +#else + (void)memcpy((&(NdefMap->SendRecvBuf[BufIndex])), + (void * )&NdefMap->psRemoteDevInfo->RemoteDevInfo.CardInfo212_424.Startup212_424.NFCID2t, + 8); + +#endif /* #ifdef PH_HAL4_ENABLE */ + + BufIndex+=8; + + NdefMap->SendRecvBuf[BufIndex] = 0x01; /* Number of Services (n=1 ==> 0x80)*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x0B; /* Service Code List*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /* Service Code List*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x01; /* Number of Blocks to read)*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x80; /* 1st Block Element : byte 1*/ + BufIndex++; + + NdefMap->SendRecvBuf[BufIndex] = 0x00; /* 1st Block Element : byte 2, block 1*/ + BufIndex++; + + NdefMap->SendRecvBuf[PH_NFCFRI_NDEFMAP_FELI_PKT_LEN_INDEX] = BufIndex; + + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + + /* Update the Send Len*/ + NdefMap->SendLength = BufIndex; + + /* Change the state to PH_NFCFRI_NDEFMAP_FELI_STATE_RD_ATTR */ + NdefMap->State = PH_NFCFRI_NDEFMAP_FELI_STATE_RD_ATTR; + + /*set the completion routines for the desfire card operations*/ + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_NdefMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + /*Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + return (status); + +} + +/*! + * \brief Validated manufacturer Details, during the read/write operations. + */ + +static NFCSTATUS phFriNfc_Felica_HCheckManufId(const phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + uint8_t result = 0; + + /* check the stored manufacture id with the received manufacture id*/ + result = (uint8_t)(phFriNfc_Felica_MemCompare( (void *)(&(NdefMap->SendRecvBuf[2])), + (void *)NdefMap->FelicaManufDetails.ManufID, + 8)); + + if ( result != 0) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_REMOTE_DEVICE); + + } + else + { + status = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS); + + } + return (status); +} + +static NFCSTATUS phFriNfc_Felica_HCalCheckSum(const uint8_t *TempBuffer, + uint8_t StartIndex, + uint8_t EndIndex, + uint16_t RecvChkSum) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint16_t CheckSum=0, + BufIndex=0; + + for(BufIndex = StartIndex;BufIndex <=EndIndex;BufIndex++) + { + CheckSum += TempBuffer[BufIndex]; + } + if( RecvChkSum != CheckSum ) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT); + } + return (Result); +} + + + + + + + + + + + +/*! + * \brief On successful read attribute blk information, this function validates and stores the + * Attribute informations in to the context. + */ +static NFCSTATUS phFriNfc_Felica_HUpdateAttrInfo(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint8_t CRFlag = FALSE, + Nmaxb1, Nmaxb2 = 0, + ChkSum1 = 0, ChkSum2=0; + + uint16_t Nmaxblk = 0, + RecvChkSum=0, + NdefBlk = 0; + uint32_t DataLen =0; + + + /* Validate T3VNo and NFCDevVNo */ + status = phFriNfc_MapTool_ChkSpcVer(NdefMap, + PH_NFCFRI_NDEFMAP_FELI_VERSION_INDEX); + if ( status != NFCSTATUS_SUCCESS ) + { + CRFlag = TRUE; + } + else + { + /* get the Nmaxb from the receive buffer*/ + Nmaxb1 = NdefMap->SendRecvBuf[16]; + Nmaxb2 = NdefMap->SendRecvBuf[17]; + + Nmaxblk = (((uint16_t)Nmaxb1 << 8) | (Nmaxb2 & 0x00ff)); + + if ( Nmaxblk != 0 ) + { + /* check the Nbr against the Nmaxb*/ + if ( NdefMap->SendRecvBuf[14] > Nmaxblk ) + { + CRFlag = TRUE; + } + else + { + /*check Nbw > Nmaxb*/ + /*check the write flag validity*/ + /*check for the RFU bytes validity*/ + if ( (NdefMap->SendRecvBuf[15] > Nmaxblk) || + ((NdefMap->SendRecvBuf[22] != 0x00) && (NdefMap->SendRecvBuf[22] !=0x0f ))|| + ( (NdefMap->SendRecvBuf[23] != 0x00) && (NdefMap->SendRecvBuf[23] !=0x01 ))|| + ( NdefMap->SendRecvBuf[18] != 0x00) || + ( NdefMap->SendRecvBuf[19] != 0x00) || + ( NdefMap->SendRecvBuf[20] != 0x00) || + ( NdefMap->SendRecvBuf[21] != 0x00)) + + { + CRFlag = TRUE; + } + else + { + /* check the validity of the actual ndef data len*/ + PH_NFCFRI_NDEFMAP_FELI_CAL_LEN_BYTES( NdefMap->SendRecvBuf[24], + NdefMap->SendRecvBuf[25], + NdefMap->SendRecvBuf[26], + DataLen); + + + /* Calculate Nbc*/ + NdefBlk = (uint16_t )((( DataLen % 16) == 0 ) ? (DataLen >> 4) : ((DataLen >> 4) +1)); + + /* check Nbc against Nmaxb*/ + if ((NdefBlk > Nmaxblk)) + { + CRFlag = TRUE; + } + else + { + /*Store the attribute information in phFriNfc_Felica_AttrInfo*/ + NdefMap->FelicaAttrInfo.Version = NdefMap->SendRecvBuf[PH_NFCFRI_NDEFMAP_FELI_VERSION_INDEX]; + NdefMap->FelicaAttrInfo.Nbr = NdefMap->SendRecvBuf[14]; + NdefMap->FelicaAttrInfo.Nbw = NdefMap->SendRecvBuf[15]; + + NdefMap->FelicaAttrInfo.Nmaxb = Nmaxblk; + + NdefMap->FelicaAttrInfo.WriteFlag = NdefMap->SendRecvBuf[22]; + NdefMap->FelicaAttrInfo.RdWrFlag = NdefMap->SendRecvBuf[23]; + + /* Get CheckSum*/ + ChkSum1 = NdefMap->SendRecvBuf[27]; + ChkSum2 = NdefMap->SendRecvBuf[28]; + + RecvChkSum = (((uint16_t)ChkSum1 << 8) | (ChkSum2 & 0x00ff)); + + /* Check the check sum validity?*/ + status = phFriNfc_Felica_HCalCheckSum(NdefMap->SendRecvBuf, + PH_NFCFRI_NDEFMAP_FELI_VERSION_INDEX, + 26, + RecvChkSum); + if ( status != NFCSTATUS_SUCCESS ) + { + CRFlag = TRUE; + } + else + { + /*check RW Flag Access Rights*/ + /* set to read only cannot write*/ + if ( NdefMap->FelicaAttrInfo.RdWrFlag == 0x00 ) + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY; + } + else if ( NdefMap->FelicaAttrInfo.RdWrFlag == 0x01 ) // additional check for R/W access + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE; + } + else // otherwise invalid + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } + + NdefMap->FelicaAttrInfo.LenBytes[0] = NdefMap->SendRecvBuf[24]; + NdefMap->FelicaAttrInfo.LenBytes[1] = NdefMap->SendRecvBuf[25]; + NdefMap->FelicaAttrInfo.LenBytes[2] = NdefMap->SendRecvBuf[26]; + status = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS); + } + } + } + } + } + else + { + CRFlag = TRUE; + } + } + if ( (status == NFCSTATUS_INVALID_FORMAT ) && (CRFlag == TRUE )) + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } + if ( CRFlag == TRUE ) + { + /*Return Status Error “ Invalid Format”*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT); + } + + return (status); +} + +/*! + * \brief this shall notify the integration software with respective + * success/error status along with the completion routines. + */ +static void phFriNfc_Felica_HCrHandler(phFriNfc_NdefMap_t *NdefMap, + uint8_t CrIndex, + NFCSTATUS Status) +{ + /* set the state back to the Reset_Init state*/ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; + + /* set the completion routine*/ + NdefMap->CompletionRoutine[CrIndex]. + CompletionRoutine(NdefMap->CompletionRoutine->Context, Status); +} + +/*! + * \brief this shall initialise the internal buffer data to zero. + */ +static void phFriNfc_Felica_HInitInternalBuf(uint8_t *Buffer) +{ + uint8_t index=0; + + for( index = 0; index< 16 ; index++) + { + Buffer[index] = 0; + } +} + +static int phFriNfc_Felica_MemCompare ( void *s1, void *s2, unsigned int n ) +{ + int8_t diff = 0; + int8_t *char_1 =(int8_t *)s1; + int8_t *char_2 =(int8_t *)s2; + if(NULL == s1 || NULL == s2) + { + PHDBG_CRITICAL_ERROR("NULL pointer passed to memcompare"); + } + else + { + for(;((n>0)&&(diff==0));n--,char_1++,char_2++) + { + diff = *char_1 - *char_2; + } + } + return (int)diff; +} + + +#ifdef UNIT_TEST +#include +#endif + +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ diff --git a/libnfc-nxp/phFriNfc_FelicaMap.h b/libnfc-nxp/phFriNfc_FelicaMap.h new file mode 100644 index 0000000..298ffff --- /dev/null +++ b/libnfc-nxp/phFriNfc_FelicaMap.h @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc_FelicaMap.h + * \brief NFC Ndef Mapping For Felica Smart Card. + * + * Project: NFC-FRI + * + * $Date: Wed Apr 8 14:37:05 2009 $ + * $Author: ing02260 $ + * $Revision: 1.4 $ + * $Aliases: NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PHFRINFC_FELICAMAP_H +#define PHFRINFC_FELICAMAP_H + +#include +#if !defined PH_HAL4_ENABLE +#include +#endif +#include +#include +#include + + +#ifndef PH_FRINFC_EXCLUDE_FROM_TESTFW /* */ + +#define PH_FRINFC_NDEFMAP_FELICAMAP_FILEREVISION "$Revision: 1.4 $" +#define PH_FRINFC_NDEFMAP_FELLICAMAP_FILEALIASES "$Aliases: NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" + +/* NDEF Mapping - states of the Finite State machine */ +#define PH_NFCFRI_NDEFMAP_FELI_STATE_SELECT_WILD_CARD 1 /* Select Wild Card State*/ +#define PH_NFCFRI_NDEFMAP_FELI_STATE_SELECT_NDEF_APP 2 /* Select NFC Forum Application State*/ +#define PH_FRINFC_NDEFMAP_FELI_STATE_CHK_NDEF 3 /* Ndef Complient State*/ +#define PH_NFCFRI_NDEFMAP_FELI_STATE_RD_ATTR 4 /* Read Attribute Information State*/ +#define PH_NFCFRI_NDEFMAP_FELI_STATE_RD_BLOCK 5 /* Read Data state*/ +#define PH_NFCFRI_NDEFMAP_FELI_STATE_WR_BLOCK 6 /* Write Data State*/ +#define PH_NFCFRI_NDEFMAP_FELI_STATE_ATTR_BLK_WR_BEGIN 7 /* Write Attrib Blk for write Begin*/ +#define PH_NFCFRI_NDEFMAP_FELI_STATE_ATTR_BLK_WR_END 8 /* Write Attrib Blk for write End*/ +#define PH_NFCFRI_NDEFMAP_FELI_STATE_WR_EMPTY_MSG 9 /* write Empty Ndef Msg*/ + + +#define PH_NFCFRI_NDEFMAP_FELI_WR_RESP_BYTE 0x09 /* Write Cmd Response Byte*/ +#define PH_NFCFRI_NDEFMAP_FELI_RD_RESP_BYTE 0x07 /* Read Cmd Response Byte*/ + +#define PH_NFCFRI_NDEFMAP_FELI_NMAXB 13 /* Nmaxb Identifier*/ +#define PH_NFCFRI_NDEFMAP_FELI_NBC 14 /* Nbc Identifier*/ + +#define PH_FRINFC_NDEFMAP_FELI_OP_NONE 15 /* To Read the attribute information*/ +#define PH_FRINFC_NDEFMAP_FELI_WR_ATTR_RD_OP 16 /* To Read the attribute info. while a WR Operationg*/ +#define PH_FRINFC_NDEFMAP_FELI_RD_ATTR_RD_OP 17 /* To Read the attribute info. while a RD Operationg*/ +#define PH_FRINFC_NDEFMAP_FELI_CHK_NDEF_OP 18 /* To Process the read attribute info. while a ChkNdef Operation*/ +#define PH_FRINFC_NDEFMAP_FELI_WR_EMPTY_MSG_OP 19 /* To Process the Empty NDEF Msg while erasing the NDEF data*/ + +#define PH_FRINFC_NDEFMAP_FELI_NUM_DEVICE_TO_DETECT 1 + +#define PH_NFCFRI_NDEFMAP_FELI_RESP_HEADER_LEN 13 /* To skip response code, IDm, status flgas and Nb*/ +#define PH_NFCFRI_NDEFMAP_FELI_VERSION_INDEX 13 /* Specifies Index of the version in Attribute Resp Buffer*/ +#define PH_NFCFRI_NDEFMAP_FELI_PKT_LEN_INDEX 0 /* Specifies Index of the Packet Length*/ + + +/* To Handle the EOF staus*/ +#ifndef TRUE +#define TRUE 1 +#endif /* #ifndef TRUE */ + +#ifndef FALSE +#define FALSE 0 +#endif /* #ifndef FALSE */ + + +/* NFC Device Major and Minor Version numbers*/ +/* !!CAUTION!! these needs to be updated periodically.Major and Minor version numbers + should be compatible to the version number of currently implemented mapping document. + Example : NFC Device version Number : 1.0 , specifies + Major VNo is 1, + Minor VNo is 0 */ +#define PH_NFCFRI_NDEFMAP_FELI_NFCDEV_MAJOR_VER_NUM 0x01 +#define PH_NFCFRI_NDEFMAP_FELI_NFCDEV_MINOR_VER_NUM 0x00 + +/* Macros to find major and minor T3T version numbers*/ +#define PH_NFCFRI_NDEFMAP_FELI_GET_MAJOR_T3T_VERNO(a)\ +do\ +{\ + (((a) & (0xf0))>>(4))\ +}while (0) + +#define PH_NFCFRI_NDEFMAP_FELI_GET_MINOR_T3T_VERNO(a)\ +do\ +{\ + ((a) & (0x0f))\ +}while (0) + + +/* Macro for LEN Byte Calculation*/ +#define PH_NFCFRI_NDEFMAP_FELI_CAL_LEN_BYTES(Byte1,Byte2,Byte3,DataLen)\ +do\ +{ \ + (DataLen) = (Byte1); \ + (DataLen) = (DataLen) << (16);\ + (DataLen) += (Byte2);\ + (DataLen) = (DataLen) << (8);\ + (DataLen) += (Byte3);\ +}while(0) + + + + +/* Enum for the data write operations*/ +typedef enum +{ + FELICA_WRITE_STARTED, + FELICA_WRITE_ENDED, + FELICA_EOF_REACHED_WR_WITH_BEGIN_OFFSET, + FELICA_EOF_REACHED_WR_WITH_CURR_OFFSET, + FELICA_RD_WR_EOF_CARD_REACHED, + FELICA_WRITE_EMPTY_MSG + +}phFriNfc_FelicaError_t; + + + +/*! + * \brief \copydoc page_ovr Initiates Reading of NDEF information from the Remote Device. + * + * The function initiates the reading of NDEF information from a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that receives the NDEF Packet. + * + * \param[in,out] PacketDataLength Pointer to a variable receiving the length of the NDEF packet. + * + * \param[in] Offset Indicates whether the read operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start reading from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start reading + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED No Space in the File to read. + * \retval NFCSTATUS_SUCCESS Last Byte of the card read. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_Felica_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + +/*! + * \brief \copydoc page_ovr Initiates Writing of NDEF information to the Remote Device. + * + * The function initiates the writing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that holds the prepared NDEF Packet. + * + * \param[in,out] PacketDataLength Variable specifying the length of the prepared NDEF packet. + * + * \param[in] Offset Indicates whether the write operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start writing from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start writing + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED Last byte is written to the card after this + * no further writing is possible. + * \retval NFCSTATUS_SUCCESS Buffer provided by the user is completely written + * into the card. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_Felica_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + +/*! + * \brief \copydoc page_ovr Initiates Writing of Empty NDEF information to the Remote Device. + * + * The function initiates the erasing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_SUCCESS Empty msessage is completely written + * into the card. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_Felica_EraseNdef( phFriNfc_NdefMap_t *NdefMap); + + +/*! + * \brief \copydoc page_ovr Check whether a particulat Remote Device is NDEF compliant. + * + * The function checks whether the peer device is NDEF compliant. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_Felica_ChkNdef( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_cb Completion Routine, Processing function, needed to avoid long blocking. + * + * The function call scheme is according to \ref grp_interact. No State reset is performed during operation. + * + * \copydoc pphFriNfc_Cr_t + * + * \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion + * Routine in order to be able to notify the component that an I/O has finished and data are + * ready to be processed. + * + */ + +void phFriNfc_Felica_Process(void *Context, + NFCSTATUS Status); + + +#endif /* PH_FRINFC_EXCLUDE_FROM_TESTFW */ + + +#endif /* PHFRINFC_FELICAMAP_H */ + + diff --git a/libnfc-nxp/phFriNfc_ISO15693Format.c b/libnfc-nxp/phFriNfc_ISO15693Format.c new file mode 100644 index 0000000..a477f2a --- /dev/null +++ b/libnfc-nxp/phFriNfc_ISO15693Format.c @@ -0,0 +1,578 @@ +/* + * + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phFriNfc_ISO15693Format.c +* \brief This component encapsulates different format functinalities , +* for the ISO-15693 card. +* +* Project: NFC-FRI +* +* $Date: $ +* $Author: ing02260 $ +* $Revision: 1.0 $ +* $Aliases: $ +* +*/ + +#ifndef PH_FRINFC_FMT_ISO15693_DISABLED + +#include +#include +#include +#include + + +/****************************** Macro definitions start ********************************/ +/* State for the format */ +#define ISO15693_FORMAT 0x01U + +/* Bytes per block in the ISO-15693 */ +#define ISO15693_BYTES_PER_BLOCK 0x04U + +/* ISO-15693 Commands +GET SYSTEM INFORMATION COMMAND +*/ +#define ISO15693_GET_SYSTEM_INFO_CMD 0x2BU +/* READ SINGLE BLOCK COMMAND */ +#define ISO15693_RD_SINGLE_BLK_CMD 0x20U +/* WRITE SINGLE BLOCK COMMAND */ +#define ISO15693_WR_SINGLE_BLK_CMD 0x21U +/* READ MULTIPLE BLOCK COMMAND */ +#define ISO15693_RD_MULTIPLE_BLKS_CMD 0x23U + +/* CC bytes +CC BYTE 0 - Magic Number - 0xE1 +*/ +#define ISO15693_CC_MAGIC_NUM 0xE1U +/* CC BYTE 1 - Mapping version and READ WRITE settings 0x40 +*/ +#define ISO15693_CC_VER_RW 0x40U +/* CC BYTE 2 - max size is calaculated using the byte 3 multiplied by 8 */ +#define ISO15693_CC_MULTIPLE_FACTOR 0x08U + +/* Inventory command support mask for the CC byte 4 */ +#define ISO15693_INVENTORY_CMD_MASK 0x02U +/* Read MULTIPLE blocks support mask for CC byte 4 */ +#define ISO15693_RDMULBLKS_CMD_MASK 0x01U +/* Flags for the command */ +#define ISO15693_FMT_FLAGS 0x20U + +/* Read two blocks */ +#define ISO15693_RD_2_BLOCKS 0x02U + +/* TYPE identifier of the NDEF TLV */ +#define ISO15693_NDEF_TLV_TYPE_ID 0x03U +/* Terminator TLV identifier */ +#define ISO15693_TERMINATOR_TLV_ID 0xFEU + +/* UID 7th byte value shall be 0xE0 */ +#define ISO15693_7TH_BYTE_UID_VALUE 0xE0U +#define ISO15693_BYTE_7_INDEX 0x07U + +/* UID 6th byte value shall be 0x04 - NXP manufacturer */ +#define ISO15693_6TH_BYTE_UID_VALUE 0x04U +#define ISO15693_BYTE_6_INDEX 0x06U + +#define ISO15693_EXTRA_RESPONSE_FLAG 0x01U + +#define ISO15693_GET_SYS_INFO_RESP_LEN 0x0EU +#define ISO15693_DSFID_MASK 0x01U +#define ISO15693_AFI_MASK 0x02U +#define ISO15693_MAX_SIZE_MASK 0x04U +#define ISO15693_ICREF_MASK 0x08U +#define ISO15693_SKIP_DFSID 0x01U +#define ISO15693_SKIP_AFI 0x01U +#define ISO15693_BLOCK_SIZE_IN_BYTES_MASK 0x1FU + + +/* MAXimum size of ICODE SLI/X */ +#define ISO15693_SLI_X_MAX_SIZE 112U +/* MAXimum size of ICODE SLI/X - S */ +#define ISO15693_SLI_X_S_MAX_SIZE 160U +/* MAXimum size of ICODE SLI/X - L */ +#define ISO15693_SLI_X_L_MAX_SIZE 32U +/****************************** Macro definitions end ********************************/ + +/****************************** Data structures start ********************************/ +typedef enum phFriNfc_ISO15693_FormatSeq +{ + ISO15693_GET_SYS_INFO, + ISO15693_RD_SINGLE_BLK_CHECK, + ISO15693_WRITE_CC_FMT, + ISO15693_WRITE_NDEF_TLV +}phFriNfc_ISO15693_FormatSeq_t; +/****************************** Data structures end ********************************/ + +/*********************** Static function declarations start ***********************/ +static +NFCSTATUS +phFriNfc_ISO15693_H_ProFormat ( + phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt); + +static +NFCSTATUS +phFriNfc_ISO15693_H_GetMaxDataSize ( + phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt, + uint8_t *p_recv_buf, + uint8_t recv_length); + +static +NFCSTATUS +phFriNfc_ISO15693_H_FmtReadWrite ( + phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt, + uint8_t command, + uint8_t *p_data, + uint8_t data_length); +/*********************** Static function declarations end ***********************/ + +/*********************** Static function definitions start ***********************/ + +static +NFCSTATUS +phFriNfc_ISO15693_H_FmtReadWrite ( + phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt, + uint8_t command, + uint8_t *p_data, + uint8_t data_length) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t send_index = 0; + + /* set the data for additional data exchange*/ + psNdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + psNdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.NADPresent = 0; + psNdefSmtCrdFmt->psDepAdditionalInfo.NAD = 0; + + psNdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = + phFriNfc_ISO15693_FmtProcess; + psNdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = psNdefSmtCrdFmt; + + *psNdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE; + + psNdefSmtCrdFmt->Cmd.Iso15693Cmd = phHal_eIso15693_Cmd; + + *(psNdefSmtCrdFmt->SendRecvBuf + send_index) = (uint8_t)ISO15693_FMT_FLAGS; + send_index = (uint8_t)(send_index + 1); + + *(psNdefSmtCrdFmt->SendRecvBuf + send_index) = (uint8_t)command; + send_index = (uint8_t)(send_index + 1); + + (void)memcpy ((void *)(psNdefSmtCrdFmt->SendRecvBuf + send_index), + (void *)psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Uid, + psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength); + send_index = (uint8_t)(send_index + + psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength); + + switch (command) + { + case ISO15693_WR_SINGLE_BLK_CMD: + case ISO15693_RD_MULTIPLE_BLKS_CMD: + { + *(psNdefSmtCrdFmt->SendRecvBuf + send_index) = (uint8_t) + psNdefSmtCrdFmt->AddInfo.s_iso15693_info.current_block; + send_index = (uint8_t)(send_index + 1); + + if (data_length) + { + (void)memcpy ((void *)(psNdefSmtCrdFmt->SendRecvBuf + send_index), + (void *)p_data, data_length); + send_index = (uint8_t)(send_index + data_length); + } + else + { + result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + } + break; + } + + case ISO15693_RD_SINGLE_BLK_CMD: + { + *(psNdefSmtCrdFmt->SendRecvBuf + send_index) = (uint8_t) + psNdefSmtCrdFmt->AddInfo.s_iso15693_info.current_block; + send_index = (uint8_t)(send_index + 1); + break; + } + + case ISO15693_GET_SYSTEM_INFO_CMD: + { + /* Dont do anything */ + break; + } + + default: + { + result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + + psNdefSmtCrdFmt->SendLength = send_index; + + if (!result) + { + result = phFriNfc_OvrHal_Transceive(psNdefSmtCrdFmt->LowerDevice, + &psNdefSmtCrdFmt->SmtCrdFmtCompletionInfo, + psNdefSmtCrdFmt->psRemoteDevInfo, + psNdefSmtCrdFmt->Cmd, + &psNdefSmtCrdFmt->psDepAdditionalInfo, + psNdefSmtCrdFmt->SendRecvBuf, + psNdefSmtCrdFmt->SendLength, + psNdefSmtCrdFmt->SendRecvBuf, + psNdefSmtCrdFmt->SendRecvLength); + } + + return result; +} + +static +NFCSTATUS +phFriNfc_ISO15693_H_GetMaxDataSize ( + phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt, + uint8_t *p_recv_buf, + uint8_t recv_length) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693_AddInfo_t *ps_iso15693_info = + &(psNdefSmtCrdFmt->AddInfo.s_iso15693_info); + phHal_sIso15693Info_t *ps_rem_iso_15693_info = + &(psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info); + uint8_t recv_index = 0; + + if ((ISO15693_GET_SYS_INFO_RESP_LEN == recv_length) + && (ISO15693_MAX_SIZE_MASK == (*p_recv_buf & ISO15693_MAX_SIZE_MASK))) + { + uint8_t information_flag = *p_recv_buf; + /* MAX size is present in the system information and + also response length is correct */ + recv_index = (uint8_t)(recv_index + 1); + + if (!phOsalNfc_MemCompare ((void *)ps_rem_iso_15693_info->Uid, + (void *)(p_recv_buf + recv_index), + ps_rem_iso_15693_info->UidLength)) + { + /* UID comaparision successful */ + uint8_t no_of_blocks = 0; + uint8_t blk_size_in_bytes = 0; + uint8_t ic_reference = 0; + + /* So skip the UID size compared in the received buffer */ + recv_index = (uint8_t)(recv_index + + ps_rem_iso_15693_info->UidLength); + + if (information_flag & ISO15693_DSFID_MASK) { + /* Skip DFSID */ + recv_index = (uint8_t)(recv_index + ISO15693_SKIP_DFSID); + } + if (information_flag & ISO15693_AFI_MASK) { + /* Skip AFI */ + recv_index = (uint8_t)(recv_index + ISO15693_SKIP_AFI); + } + + /* To get the number of blocks in the card */ + no_of_blocks = (uint8_t)(*(p_recv_buf + recv_index) + 1); + recv_index = (uint8_t)(recv_index + 1); + + /* To get the each block size in bytes */ + blk_size_in_bytes = (uint8_t)((*(p_recv_buf + recv_index) + & ISO15693_BLOCK_SIZE_IN_BYTES_MASK) + 1); + recv_index = (uint8_t)(recv_index + 1); + + if (information_flag & ISO15693_ICREF_MASK) { + /* Get the IC reference */ + ic_reference = (uint8_t)(*(p_recv_buf + recv_index)); + if (ic_reference == 0x03) { + no_of_blocks = 8; + } + } + + /* calculate maximum data size in the card */ + ps_iso15693_info->max_data_size = (uint16_t) + (no_of_blocks * blk_size_in_bytes); + + } + else + { + result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + } + } + else + { + result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + } + + + return result; +} + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProFormat ( + phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693_AddInfo_t *ps_iso15693_info = + &(psNdefSmtCrdFmt->AddInfo.s_iso15693_info); + phFriNfc_ISO15693_FormatSeq_t e_format_seq = + (phFriNfc_ISO15693_FormatSeq_t) + ps_iso15693_info->format_seq; + uint8_t command_type = 0; + uint8_t a_send_byte[ISO15693_BYTES_PER_BLOCK] = {0}; + uint8_t send_length = 0; + uint8_t send_index = 0; + uint8_t format_complete = FALSE; + + switch (e_format_seq) + { + case ISO15693_GET_SYS_INFO: + { + /* RESPONSE received for GET SYSTEM INFO */ + + if (!phFriNfc_ISO15693_H_GetMaxDataSize (psNdefSmtCrdFmt, + (psNdefSmtCrdFmt->SendRecvBuf + ISO15693_EXTRA_RESPONSE_FLAG), + (uint8_t)(*psNdefSmtCrdFmt->SendRecvLength - + ISO15693_EXTRA_RESPONSE_FLAG))) + { + /* Send the READ SINGLE BLOCK COMMAND */ + command_type = ISO15693_RD_SINGLE_BLK_CMD; + e_format_seq = ISO15693_RD_SINGLE_BLK_CHECK; + + /* Block number 0 to read */ + psNdefSmtCrdFmt->AddInfo.s_iso15693_info.current_block = 0x00; + } + else + { + result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case ISO15693_RD_SINGLE_BLK_CHECK: + { + /* RESPONSE received for READ SINGLE BLOCK + received*/ + + /* Check if Card is really fresh + First 4 bytes must be 0 for fresh card */ + + if ((psNdefSmtCrdFmt->AddInfo.s_iso15693_info.current_block == 0x00) && + (psNdefSmtCrdFmt->SendRecvBuf[1] != 0x00 || + psNdefSmtCrdFmt->SendRecvBuf[2] != 0x00 || + psNdefSmtCrdFmt->SendRecvBuf[3] != 0x00 || + psNdefSmtCrdFmt->SendRecvBuf[4] != 0x00)) + { + result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_FORMAT); + } + else + { + /* prepare data for writing CC bytes */ + + command_type = ISO15693_WR_SINGLE_BLK_CMD; + e_format_seq = ISO15693_WRITE_CC_FMT; + + /* CC magic number */ + *a_send_byte = (uint8_t)ISO15693_CC_MAGIC_NUM; + send_index = (uint8_t)(send_index + 1); + + /* CC Version and read/write access */ + *(a_send_byte + send_index) = (uint8_t) ISO15693_CC_VER_RW; + send_index = (uint8_t)(send_index + 1); + + /* CC MAX data size, calculated during GET system information */ + *(a_send_byte + send_index) = (uint8_t) (ps_iso15693_info->max_data_size / ISO15693_CC_MULTIPLE_FACTOR); + send_index = (uint8_t)(send_index + 1); + + switch (ps_iso15693_info->max_data_size) + { + case ISO15693_SLI_X_MAX_SIZE: + { + /* For SLI tags : Inventory Page read not supported */ + *(a_send_byte + send_index) = (uint8_t) ISO15693_RDMULBLKS_CMD_MASK; + break; + } + + case ISO15693_SLI_X_S_MAX_SIZE: + { + /* For SLI - S tags : Read multiple blocks not supported */ + *(a_send_byte + send_index) = (uint8_t) ISO15693_INVENTORY_CMD_MASK; + break; + } + + case ISO15693_SLI_X_L_MAX_SIZE: + { + /* For SLI - L tags : Read multiple blocks not supported */ + *(a_send_byte + send_index) = (uint8_t) ISO15693_INVENTORY_CMD_MASK; + break; + } + + default: + { + result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + + send_index = (uint8_t)(send_index + 1); + + send_length = sizeof (a_send_byte); + } + + break; + } + + case ISO15693_WRITE_CC_FMT: + { + /* CC byte write succcessful. + Prepare data for NDEF TLV writing */ + command_type = ISO15693_WR_SINGLE_BLK_CMD; + e_format_seq = ISO15693_WRITE_NDEF_TLV; + + ps_iso15693_info->current_block = (uint16_t) + (ps_iso15693_info->current_block + 1); + + /* NDEF TLV - Type byte updated to 0x03 */ + *a_send_byte = (uint8_t)ISO15693_NDEF_TLV_TYPE_ID; + send_index = (uint8_t)(send_index + 1); + + /* NDEF TLV - Length byte updated to 0 */ + *(a_send_byte + send_index) = 0; + send_index = (uint8_t)(send_index + 1); + + /* Terminator TLV - value updated to 0xFEU */ + *(a_send_byte + send_index) = (uint8_t) + ISO15693_TERMINATOR_TLV_ID; + send_index = (uint8_t)(send_index + 1); + + send_length = sizeof (a_send_byte); + break; + } + + case ISO15693_WRITE_NDEF_TLV: + { + /* SUCCESSFUL formatting complete */ + format_complete = TRUE; + break; + } + + default: + { + result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + + if ((!format_complete) && (!result)) + { + result = phFriNfc_ISO15693_H_FmtReadWrite (psNdefSmtCrdFmt, + command_type, a_send_byte, send_length); + } + + ps_iso15693_info->format_seq = (uint8_t)e_format_seq; + return result; +} + +/*********************** Static function definitions end ***********************/ + +/*********************** External function definitions start ***********************/ +void +phFriNfc_ISO15693_FmtReset ( + phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt) +{ + /* reset to ISO15693 data structure */ + (void)memset((void *)&(psNdefSmtCrdFmt->AddInfo.s_iso15693_info), + 0x00, sizeof (phFriNfc_ISO15693_AddInfo_t)); + psNdefSmtCrdFmt->FmtProcStatus = 0; +} + +NFCSTATUS +phFriNfc_ISO15693_Format ( + phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phHal_sIso15693Info_t *ps_rem_iso_15693_info = + &(psNdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info); + + + if ((ISO15693_7TH_BYTE_UID_VALUE == + ps_rem_iso_15693_info->Uid[ISO15693_BYTE_7_INDEX]) + && (ISO15693_6TH_BYTE_UID_VALUE == + ps_rem_iso_15693_info->Uid[ISO15693_BYTE_6_INDEX])) + { + /* Check if the card is manufactured by NXP (6th byte + index of UID value = 0x04 and the + last byte of UID is 0xE0, only then the card detected + is NDEF compliant */ + psNdefSmtCrdFmt->State = ISO15693_FORMAT; + + /* GET system information command to get the card size */ + result = phFriNfc_ISO15693_H_FmtReadWrite (psNdefSmtCrdFmt, + ISO15693_GET_SYSTEM_INFO_CMD, NULL, 0); + } + else + { + result = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + } + + return result; +} + +void +phFriNfc_ISO15693_FmtProcess ( + void *pContext, + NFCSTATUS Status) +{ + phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt = + (phFriNfc_sNdefSmtCrdFmt_t *)pContext; + + if((NFCSTATUS_SUCCESS & PHNFCSTBLOWER) == (Status & PHNFCSTBLOWER)) + { + if (ISO15693_FORMAT == psNdefSmtCrdFmt->State) + { + /* Check for further formatting */ + Status = phFriNfc_ISO15693_H_ProFormat (psNdefSmtCrdFmt); + } + else + { + Status = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + } + } + else + { + Status = PHNFCSTVAL (CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_FORMAT_ERROR); + } + + /* Handle the all the error cases */ + if ((NFCSTATUS_PENDING & PHNFCSTBLOWER) != (Status & PHNFCSTBLOWER)) + { + /* call respective CR */ + phFriNfc_SmtCrdFmt_HCrHandler (psNdefSmtCrdFmt, Status); + } +} +/*********************** External function definitions end ***********************/ + + +#endif /* #ifndef PH_FRINFC_FMT_ISO15693_DISABLED */ + diff --git a/libnfc-nxp/phFriNfc_ISO15693Format.h b/libnfc-nxp/phFriNfc_ISO15693Format.h new file mode 100644 index 0000000..9dab3c1 --- /dev/null +++ b/libnfc-nxp/phFriNfc_ISO15693Format.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phFriNfc_ISO15693Format.h +* \brief ISO-15693 Smart card formatting. +* +* Project: NFC-FRI +* +* $Date: $ +* $Author: ing02260 $ +* $Revision: 1.0 $ +* $Aliases: $ +* +*/ + +#ifndef PHFRINFC_ISO15693FORMAT_H +#define PHFRINFC_ISO15693FORMAT_H + +/****************************** Macro definitions start ********************************/ + +/****************************** Macro definitions end ********************************/ + +/****************************** Data structures start ********************************/ + +/****************************** Data structures end ********************************/ + +/*********************** External function declarations start ***********************/ +/*! +* \brief \copydoc page_reg Resets the component instance to the initial state and lets the component forget about +* the list of registered items. Moreover, the lower device is set. +* +* \param[in] NdefSmtCrdFmt Pointer to a valid or uninitialized instance of \ref phFriNfc_sNdefSmtCrdFmt_t. +* +* \note This function has to be called at the beginning, after creating an instance of +* \ref phFriNfc_sNdefSmtCrdFmt_t. Use this function to reset the instance of smart card +formatting context variables. +*/ +void +phFriNfc_ISO15693_FmtReset ( + phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt); + +/*! +* \ingroup grp_fri_smart_card_formatting +* +* \brief Initiates the card formatting procedure for Remote Smart Card Type. +* +* \copydoc page_ovr The function initiates and formats the ISO-15693 Card.After this +* operation,remote card would be properly initialized and +* Ndef Compliant.Depending upon the different card type, this +* function handles formatting procedure.This function also handles +* the different recovery procedures for different types of the cards. +* For both Format and Recovery Management same API is used. +* +* \param[in] phFriNfc_sNdefSmartCardFmt_t Pointer to a valid instance of the \ref phFriNfc_sNdefSmartCardFmt_t +* structure describing the component context. +* +* \retval NFCSTATUS_SUCCESS Card formatting has been successfully completed. +* \retval NFCSTATUS_PENDING The action has been successfully triggered. +* \retval NFCSTATUS_FORMAT_ERROR Error occured during the formatting procedure. +* \retval NFCSTATUS_INVALID_REMOTE_DEVICE Card Type is unsupported. +* \retval NFCSTATUS_INVALID_DEVICE_REQUEST Command or Operation types are mismatching. +* +*/ +NFCSTATUS +phFriNfc_ISO15693_Format ( + phFriNfc_sNdefSmtCrdFmt_t *psNdefSmtCrdFmt); + +/** +*\ingroup grp_fri_smart_card_formatting +* +* \brief Smart card Formatting \b Completion \b Routine or \b Process function +* +* \copydoc page_ovr Completion Routine: This function is called by the lower layer (OVR HAL) +* when an I/O operation has finished. The internal state machine decides +* whether to call into the lower device again or to complete the process +* by calling into the upper layer's completion routine, stored within this +* component's context (\ref phFriNfc_sNdefSmtCrdFmt_t). +* +* The function call scheme is according to \ref grp_interact. No State reset is performed during +* operation. +* +* \param[in] Context The context of the current (not the lower/upper) instance, as set by the lower, +* calling layer, upon its completion. +* \param[in] Status The completion status of the lower layer (to be handled by the implementation of +* the state machine of this function like a regular return value of an internally +* called function). +* +* \note For general information about the completion routine interface please see \ref pphFriNfc_Cr_t . +* The Different Status Values are as follows +* +*/ +void +phFriNfc_ISO15693_FmtProcess ( + void *pContext, + NFCSTATUS Status); + +/*********************** External function declarations end ***********************/ + +#endif /* #define PHFRINFC_ISO15693FORMAT_H */ + + + diff --git a/libnfc-nxp/phFriNfc_ISO15693Map.c b/libnfc-nxp/phFriNfc_ISO15693Map.c new file mode 100644 index 0000000..a21d9c8 --- /dev/null +++ b/libnfc-nxp/phFriNfc_ISO15693Map.c @@ -0,0 +1,1819 @@ +/* + * + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phFriNfc_ISO15693Map.c +* \brief This component encapsulates read/write/check ndef/process functionalities, +* for the ISO-15693 Card. +* +* Project: NFC-FRI +* +* $Date: $ +* $Author: ing02260 $ +* $Revision: $ +* $Aliases: $ +* +*/ + +#ifndef PH_FRINFC_MAP_ISO15693_DISABLED + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/************************** START DATA STRUCTURE *********************/ + +typedef enum phFriNfc_eChkNdefSeq +{ + ISO15693_NDEF_TLV_T, + ISO15693_NDEF_TLV_L, + ISO15693_NDEF_TLV_V, + ISO15693_PROP_TLV_L, + ISO15693_PROP_TLV_V + +}phFriNfc_eChkNdefSeq_t; + +typedef enum phFriNfc_eWrNdefSeq +{ + ISO15693_RD_BEFORE_WR_NDEF_L_0, + ISO15693_WRITE_DATA, + ISO15693_RD_BEFORE_WR_NDEF_L, + ISO15693_WRITE_NDEF_TLV_L + +}phFriNfc_eWrNdefSeq_t; + +#ifdef FRINFC_READONLY_NDEF + +typedef enum phFriNfc_eRONdefSeq +{ + ISO15693_RD_BEFORE_WR_CC, + ISO15693_WRITE_CC, + ISO15693_LOCK_BLOCK + +}phFriNfc_eRONdefSeq_t; + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/************************** END DATA STRUCTURE *********************/ + +/************************** START MACROS definition *********************/ + + + + +/* UID bytes to differentiate ICODE cards */ +#define ISO15693_UID_BYTE_4 0x04U +#define ISO15693_UID_BYTE_5 0x05U +#define ISO15693_UID_BYTE_6 0x06U +#define ISO15693_UID_BYTE_7 0x07U + +/* UID 7th byte value shall be 0xE0 */ +#define ISO15693_UIDBYTE_7_VALUE 0xE0U +/* UID 6th byte value shall be 0x04 - NXP manufacturer */ +#define ISO15693_UIDBYTE_6_VALUE 0x04U + + +/* UID value for + SL2 ICS20 + SL2S2002 + */ +#define ISO15693_UIDBYTE_5_VALUE_SLI_X 0x01U +/* Card size SL2 ICS20 / SL2S2002 */ +#define ISO15693_SL2_S2002_ICS20 112U + +/* UID value for + SL2 ICS53, + SL2 ICS54 + SL2S5302 +*/ +#define ISO15693_UIDBYTE_5_VALUE_SLI_X_S 0x02U +#define ISO15693_UIDBYTE_4_VALUE_SLI_X_S 0x00U +#define ISO15693_UIDBYTE_4_VALUE_SLI_X_SHC 0x80U +#define ISO15693_UIDBYTE_4_VALUE_SLI_X_SY 0x40U +/* SL2 ICS53, SL2 ICS54 and SL2S5302 */ +#define ISO15693_SL2_S5302_ICS53_ICS54 160U + +/* UID value for + SL2 ICS50 + SL2 ICS51 + SL2S5002 +*/ +#define ISO15693_UIDBYTE_5_VALUE_SLI_X_L 0x03U +#define ISO15693_UIDBYTE_4_VALUE_SLI_X_L 0x00U +#define ISO15693_UIDBYTE_4_VALUE_SLI_X_LHC 0x80U +/* SL2 ICS50, SL2 ICS51 and SL2S5002 */ +#define ISO15693_SL2_S5002_ICS50_ICS51 32U + + +/* State Machine declaration +CHECK NDEF state */ +#define ISO15693_CHECK_NDEF 0x01U +/* READ NDEF state */ +#define ISO15693_READ_NDEF 0x02U +/* WRITE NDEF state */ +#define ISO15693_WRITE_NDEF 0x03U +#ifdef FRINFC_READONLY_NDEF + + /* READ ONLY NDEF state */ + #define ISO15693_READ_ONLY_NDEF 0x04U + + /* READ ONLY MASK byte for CC */ + #define ISO15693_CC_READ_ONLY_MASK 0x03U + + /* CC READ WRITE index */ + #define ISO15693_RW_BTYE_INDEX 0x01U + + /* LOCK BLOCK command */ + #define ISO15693_LOCK_BLOCK_CMD 0x22U + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/* CC Bytes +Magic number */ +#define ISO15693_CC_MAGIC_BYTE 0xE1U +/* Expected mapping version */ +#define ISO15693_MAPPING_VERSION 0x01U +/* Major version is in upper 2 bits */ +#define ISO15693_MAJOR_VERSION_MASK 0xC0U + +/* CC indicating tag is capable of multi-block read */ +#define ISO15693_CC_USE_MBR 0x01U +/* CC indicating tag is capable of inventory page read */ +#define ISO15693_CC_USE_IPR 0x02U +/* EXTRA byte in the response */ +#define ISO15693_EXTRA_RESP_BYTE 0x01U + +/* Maximum card size multiplication factor */ +#define ISO15693_MULT_FACTOR 0x08U +/* NIBBLE mask for READ WRITE access */ +#define ISO15693_LSB_NIBBLE_MASK 0x0FU +#define ISO15693_RD_WR_PERMISSION 0x00U +#define ISO15693_RD_ONLY_PERMISSION 0x03U + +/* READ command identifier */ +#define ISO15693_READ_COMMAND 0x20U + +/* READ multiple command identifier */ +#define ISO15693_READ_MULTIPLE_COMMAND 0x23U + +/* INVENTORY pageread command identifier */ +#define ICODE_INVENTORY_PAGEREAD_COMMAND 0xB0U +#define INVENTORY_PAGEREAD_FLAGS 0x24U +#define NXP_MANUFACTURING_CODE 0x04U + +/* WRITE command identifier */ +#define ISO15693_WRITE_COMMAND 0x21U +/* FLAG option */ +#define ISO15693_FLAGS 0x20U + +/* RESPONSE length expected for single block READ */ +#define ISO15693_SINGLE_BLK_RD_RESP_LEN 0x04U +/* NULL TLV identifier */ +#define ISO15693_NULL_TLV_ID 0x00U +/* NDEF TLV, TYPE identifier */ +#define ISO15693_NDEF_TLV_TYPE_ID 0x03U + +/* 8 BIT shift */ +#define ISO15693_BTYE_SHIFT 0x08U + +/* Proprietary TLV TYPE identifier */ +#define ISO15693_PROP_TLV_ID 0xFDU + +/* CC SIZE in BYTES */ +#define ISO15693_CC_SIZE 0x04U + +/* To get the remaining size in the card. +Inputs are +1. maximum data size +2. block number +3. index of the block number */ +#define ISO15693_GET_REMAINING_SIZE(max_data_size, blk, index) \ + (max_data_size - ((blk * ISO15693_BYTES_PER_BLOCK) + index)) + +#define ISO15693_GET_LEN_FIELD_BLOCK_NO(blk, byte_addr, ndef_size) \ + (((byte_addr + ((ndef_size >= ISO15693_THREE_BYTE_LENGTH_ID) ? 3 : 1)) > \ + (ISO15693_BYTES_PER_BLOCK - 1)) ? (blk + 1) : blk) + +#define ISO15693_GET_LEN_FIELD_BYTE_NO(blk, byte_addr, ndef_size) \ + (((byte_addr + ((ndef_size >= ISO15693_THREE_BYTE_LENGTH_ID) ? 3 : 1)) % \ + ISO15693_BYTES_PER_BLOCK)) + + + +/************************** END MACROS definition *********************/ + +/************************** START static functions declaration *********************/ +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessReadOnly ( + phFriNfc_NdefMap_t *psNdefMap); + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessWriteNdef ( + phFriNfc_NdefMap_t *psNdefMap); + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessReadNdef ( + phFriNfc_NdefMap_t *psNdefMap); + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessCheckNdef ( + phFriNfc_NdefMap_t *psNdefMap); + +static +void +phFriNfc_ISO15693_H_Complete ( + phFriNfc_NdefMap_t *psNdefMap, + NFCSTATUS Status); + +static +NFCSTATUS +phFriNfc_ISO15693_H_ReadWrite ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t command, + uint8_t *p_data, + uint8_t data_length); + +static +NFCSTATUS +phFriNfc_ReadRemainingInMultiple ( + phFriNfc_NdefMap_t *psNdefMap, + uint32_t startBlock); + +/************************** END static functions declaration *********************/ + +/************************** START static functions definition *********************/ + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessWriteNdef ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + phFriNfc_eWrNdefSeq_t e_wr_ndef_seq = (phFriNfc_eWrNdefSeq_t) + psNdefMap->ISO15693Container.ndef_seq; + uint8_t *p_recv_buf = NULL; + uint8_t recv_length = 0; + uint8_t write_flag = FALSE; + uint8_t a_write_buf[ISO15693_BYTES_PER_BLOCK] = {0}; + uint8_t remaining_size = 0; + + switch (e_wr_ndef_seq) + { + case ISO15693_RD_BEFORE_WR_NDEF_L_0: + { + /* L byte is read */ + p_recv_buf = (psNdefMap->SendRecvBuf + ISO15693_EXTRA_RESP_BYTE); + recv_length = (uint8_t) + (*psNdefMap->SendRecvLength - ISO15693_EXTRA_RESP_BYTE); + + if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length) + { + /* Response length is correct */ + uint8_t byte_index = 0; + + /* Copy the recevied buffer */ + (void)memcpy ((void *)a_write_buf, (void *)p_recv_buf, + recv_length); + + byte_index = ISO15693_GET_LEN_FIELD_BYTE_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + psNdefMap->ApduBufferSize); + + /* Writing length field to 0, Update length field to 0 */ + *(a_write_buf + byte_index) = 0x00; + + if ((ISO15693_BYTES_PER_BLOCK - 1) != byte_index) + { + /* User data is updated in the buffer */ + byte_index = (uint8_t)(byte_index + 1); + /* Block number shall be udate */ + remaining_size = (ISO15693_BYTES_PER_BLOCK - byte_index); + + if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex) + < remaining_size) + { + remaining_size = (uint8_t)(psNdefMap->ApduBufferSize - + psNdefMap->ApduBuffIndex); + } + + /* Go to next byte to fill the write buffer */ + (void)memcpy ((void *)(a_write_buf + byte_index), + (void *)(psNdefMap->ApduBuffer + + psNdefMap->ApduBuffIndex), remaining_size); + + /* Write index updated */ + psNdefMap->ApduBuffIndex = (uint8_t)(psNdefMap->ApduBuffIndex + + remaining_size); + } + + /* After this write, user data can be written. + Update the sequence accordingly */ + e_wr_ndef_seq = ISO15693_WRITE_DATA; + write_flag = TRUE; + } /* if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length) */ + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } /* case ISO15693_RD_BEFORE_WR_NDEF_L_0: */ + + case ISO15693_RD_BEFORE_WR_NDEF_L: + { + p_recv_buf = (psNdefMap->SendRecvBuf + ISO15693_EXTRA_RESP_BYTE); + recv_length = (uint8_t)(*psNdefMap->SendRecvLength - + ISO15693_EXTRA_RESP_BYTE); + + if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length) + { + uint8_t byte_index = 0; + + (void)memcpy ((void *)a_write_buf, (void *)p_recv_buf, + recv_length); + + byte_index = ISO15693_GET_LEN_FIELD_BYTE_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + psNdefMap->ApduBuffIndex); + + *(a_write_buf + byte_index) = (uint8_t)psNdefMap->ApduBuffIndex; + e_wr_ndef_seq = ISO15693_WRITE_NDEF_TLV_L; + write_flag = TRUE; + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case ISO15693_WRITE_DATA: + { + if ((psNdefMap->ApduBufferSize == psNdefMap->ApduBuffIndex) + || (ps_iso_15693_con->current_block == + (ps_iso_15693_con->max_data_size / ISO15693_BYTES_PER_BLOCK))) + { + ps_iso_15693_con->current_block = + ISO15693_GET_LEN_FIELD_BLOCK_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + psNdefMap->ApduBuffIndex); + e_wr_ndef_seq = ISO15693_RD_BEFORE_WR_NDEF_L; + } + else + { + remaining_size = ISO15693_BYTES_PER_BLOCK; + + ps_iso_15693_con->current_block = (uint16_t) + (ps_iso_15693_con->current_block + 1); + + if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex) + < remaining_size) + { + remaining_size = (uint8_t)(psNdefMap->ApduBufferSize - + psNdefMap->ApduBuffIndex); + } + + (void)memcpy ((void *)a_write_buf, (void *) + (psNdefMap->ApduBuffer + + psNdefMap->ApduBuffIndex), remaining_size); + + psNdefMap->ApduBuffIndex = (uint8_t)(psNdefMap->ApduBuffIndex + + remaining_size); + write_flag = TRUE; + } + break; + } /* case ISO15693_WRITE_DATA: */ + + case ISO15693_WRITE_NDEF_TLV_L: + { + *psNdefMap->WrNdefPacketLength = psNdefMap->ApduBuffIndex; + ps_iso_15693_con->actual_ndef_size = psNdefMap->ApduBuffIndex; + break; + } + + default: + { + break; + } + } /* switch (e_wr_ndef_seq) */ + + if (((0 == psNdefMap->ApduBuffIndex) + || (*psNdefMap->WrNdefPacketLength != psNdefMap->ApduBuffIndex)) + && (!result)) + { + if (FALSE == write_flag) + { + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_READ_COMMAND, NULL, 0); + } + else + { + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_WRITE_COMMAND, + a_write_buf, sizeof (a_write_buf)); + } + } + + psNdefMap->ISO15693Container.ndef_seq = (uint8_t)e_wr_ndef_seq; + return result; +} + +static +NFCSTATUS +phFriNfc_ISO15693_H_ReadWrite ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t command, + uint8_t *p_data, + uint8_t data_length) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t send_index = 0; + + /* set the data for additional data exchange*/ + psNdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + psNdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + psNdefMap->psDepAdditionalInfo.NAD = 0; + + psNdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_ISO15693_Process; + psNdefMap->MapCompletionInfo.Context = psNdefMap; + + *psNdefMap->SendRecvLength = psNdefMap->TempReceiveLength; + + psNdefMap->Cmd.Iso15693Cmd = phHal_eIso15693_Cmd; + + *(psNdefMap->SendRecvBuf + send_index) = (uint8_t)ISO15693_FLAGS; + send_index = (uint8_t)(send_index + 1); + + *(psNdefMap->SendRecvBuf + send_index) = (uint8_t)command; + send_index = (uint8_t)(send_index + 1); + + (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), + (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Uid, + psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength); + send_index = (uint8_t)(send_index + + psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength); + + *(psNdefMap->SendRecvBuf + send_index) = (uint8_t) + psNdefMap->ISO15693Container.current_block; + send_index = (uint8_t)(send_index + 1); + + if ((ISO15693_WRITE_COMMAND == command) || + (ISO15693_READ_MULTIPLE_COMMAND == command)) + { + (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), + (void *)p_data, data_length); + send_index = (uint8_t)(send_index + data_length); + } + + psNdefMap->SendLength = send_index; + result = phFriNfc_OvrHal_Transceive(psNdefMap->LowerDevice, + &psNdefMap->MapCompletionInfo, + psNdefMap->psRemoteDevInfo, + psNdefMap->Cmd, + &psNdefMap->psDepAdditionalInfo, + psNdefMap->SendRecvBuf, + psNdefMap->SendLength, + psNdefMap->SendRecvBuf, + psNdefMap->SendRecvLength); + + return result; +} + +static +NFCSTATUS +phFriNfc_ISO15693_H_Inventory_Page_Read ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t command, + uint8_t page, + uint8_t numPages) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t send_index = 0; + + /* set the data for additional data exchange*/ + psNdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + psNdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + psNdefMap->psDepAdditionalInfo.NAD = 0; + + psNdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_ISO15693_Process; + psNdefMap->MapCompletionInfo.Context = psNdefMap; + + *psNdefMap->SendRecvLength = psNdefMap->TempReceiveLength; + + psNdefMap->Cmd.Iso15693Cmd = phHal_eIso15693_Cmd; + + *(psNdefMap->SendRecvBuf + send_index) = INVENTORY_PAGEREAD_FLAGS; + send_index = (uint8_t)(send_index + 1); + + *(psNdefMap->SendRecvBuf + send_index) = (uint8_t)command; + send_index = (uint8_t)(send_index + 1); + + *(psNdefMap->SendRecvBuf + send_index) = NXP_MANUFACTURING_CODE; + send_index = (uint8_t)(send_index + 1); + + *(psNdefMap->SendRecvBuf + send_index) = 0x40; + send_index = (uint8_t)(send_index + 1); + + (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), + (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Uid, + psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength); + send_index = (uint8_t)(send_index + + psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength); + + *(psNdefMap->SendRecvBuf + send_index) = (uint8_t) + page; + send_index = (uint8_t)(send_index + 1); + + *(psNdefMap->SendRecvBuf + send_index) = (uint8_t) + numPages; + send_index = (uint8_t)(send_index + 1); + + psNdefMap->SendLength = send_index; + + result = phFriNfc_OvrHal_Transceive(psNdefMap->LowerDevice, + &psNdefMap->MapCompletionInfo, + psNdefMap->psRemoteDevInfo, + psNdefMap->Cmd, + &psNdefMap->psDepAdditionalInfo, + psNdefMap->SendRecvBuf, + psNdefMap->SendLength, + psNdefMap->SendRecvBuf, + psNdefMap->SendRecvLength); + + return result; +} + +static +NFCSTATUS +phFriNfc_ISO15693_Reformat_Pageread_Buffer ( + uint8_t *p_recv_buf, + uint8_t recv_length, + uint8_t *p_dst_buf, + uint8_t dst_length) +{ + // Inventory page reads return an extra security byte per page + // So we need to reformat the returned buffer in memory + uint32_t i = 0; + uint32_t reformatted_index = 0; + while (i < recv_length) { + // Going for another page of 16 bytes, check for space in dst buffer + if (reformatted_index + 16 > dst_length) { + break; + } + if (p_recv_buf[i] == 0x0F) { + // Security, insert 16 0 bytes + memset(&(p_dst_buf[reformatted_index]), 0, 16); + reformatted_index += 16; + i++; + } else { + // Skip security byte + i++; + if (i + 16 <= recv_length) { + memcpy(&(p_dst_buf[reformatted_index]), &(p_recv_buf[i]), 16); + reformatted_index += 16; + } else { + break; + } + i+=16; + } + } + return reformatted_index; +} + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessReadNdef ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + uint16_t remaining_data_size = 0; + uint8_t *p_recv_buf = + (psNdefMap->SendRecvBuf + ISO15693_EXTRA_RESP_BYTE); + uint8_t recv_length = (uint8_t) + (*psNdefMap->SendRecvLength - ISO15693_EXTRA_RESP_BYTE); + + uint8_t *reformatted_buf = (uint8_t*) phOsalNfc_GetMemory(ps_iso_15693_con->max_data_size); + + if (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR) + { + uint8_t reformatted_size = phFriNfc_ISO15693_Reformat_Pageread_Buffer(p_recv_buf, recv_length, + reformatted_buf, ps_iso_15693_con->max_data_size); + p_recv_buf = reformatted_buf + (ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK); + recv_length = reformatted_size - (ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK); + } + if (ps_iso_15693_con->store_length) + { + /* Continue Offset option selected + So stored data already existing, + copy the information to the user buffer + */ + if (ps_iso_15693_con->store_length + <= (psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex)) + { + /* Stored data length is less than or equal + to the user expected size */ + (void)memcpy ((void *)(psNdefMap->ApduBuffer + + psNdefMap->ApduBuffIndex), + (void *)ps_iso_15693_con->store_read_data, + ps_iso_15693_con->store_length); + + psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + + ps_iso_15693_con->store_length); + + remaining_data_size = ps_iso_15693_con->store_length; + + ps_iso_15693_con->store_length = 0; + } + else + { + /* stored length is more than the user expected size */ + remaining_data_size = (uint16_t)(ps_iso_15693_con->store_length - + (psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex)); + + (void)memcpy ((void *)(psNdefMap->ApduBuffer + + psNdefMap->ApduBuffIndex), + (void *)ps_iso_15693_con->store_read_data, + remaining_data_size); + + /* As stored data is more than the user expected data. So store + the remaining bytes again into the data structure */ + (void)memcpy ((void *)ps_iso_15693_con->store_read_data, + (void *)(ps_iso_15693_con->store_read_data + + remaining_data_size), + (ps_iso_15693_con->store_length - remaining_data_size)); + + psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + + remaining_data_size); + + ps_iso_15693_con->store_length = (uint8_t) + (ps_iso_15693_con->store_length - remaining_data_size); + } + } /* if (ps_iso_15693_con->store_length) */ + else + { + /* Data is read from the card. */ + uint8_t byte_index = 0; + + remaining_data_size = ps_iso_15693_con->remaining_size_to_read; + + /* Check if the block number is to read the first VALUE field */ + if (ISO15693_GET_VALUE_FIELD_BLOCK_NO(ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + ps_iso_15693_con->actual_ndef_size) + == ps_iso_15693_con->current_block) + { + /* Read from the beginning option selected, + BYTE number may start from the middle */ + byte_index = (uint8_t)ISO15693_GET_VALUE_FIELD_BYTE_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + ps_iso_15693_con->actual_ndef_size); + } + + if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex) + < remaining_data_size) + { + remaining_data_size = (uint8_t) + (recv_length - byte_index); + /* user input is less than the remaining card size */ + if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex) + < (uint16_t)remaining_data_size) + { + /* user data required is less than the data read */ + remaining_data_size = (uint8_t)(psNdefMap->ApduBufferSize - + psNdefMap->ApduBuffIndex); + + if (0 != (recv_length - (byte_index + + remaining_data_size))) + { + /* Store the data for the continue read option */ + (void)memcpy ((void *)ps_iso_15693_con->store_read_data, + (void *)(p_recv_buf + (byte_index + + remaining_data_size)), + (recv_length - (byte_index + + remaining_data_size))); + + ps_iso_15693_con->store_length = (uint8_t) + (recv_length - (byte_index + + remaining_data_size)); + } + } + } + else + { + /* user data required is equal or greater than the data read */ + if (remaining_data_size > (recv_length - byte_index)) + { + remaining_data_size = (uint8_t) + (recv_length - byte_index); + } + } + + /* Copy data in the user buffer */ + (void)memcpy ((void *)(psNdefMap->ApduBuffer + + psNdefMap->ApduBuffIndex), + (void *)(p_recv_buf + byte_index), + remaining_data_size); + + /* Update the read index */ + psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + + remaining_data_size); + + } /* else part of if (ps_iso_15693_con->store_length) */ + + /* Remaining size is decremented */ + ps_iso_15693_con->remaining_size_to_read = (uint8_t) + (ps_iso_15693_con->remaining_size_to_read - + remaining_data_size); + + if ((psNdefMap->ApduBuffIndex != psNdefMap->ApduBufferSize) + && (0 != ps_iso_15693_con->remaining_size_to_read)) + { + ps_iso_15693_con->current_block = (uint16_t) + (ps_iso_15693_con->current_block + 1); + /* READ again */ + if ((ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_MBR) || + (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR)) { + result = phFriNfc_ReadRemainingInMultiple(psNdefMap, ps_iso_15693_con->current_block); + } + else { + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND, + NULL, 0); + } + } + else + { + /* Read completed, EITHER index has reached to the user size + OR end of the card is reached + update the user data structure with read data size */ + *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex; + } + if (reformatted_buf != NULL) { + phOsalNfc_FreeMemory(reformatted_buf); + } + return result; +} + +static +NFCSTATUS +phFriNfc_ISO15693_H_CheckCCBytes ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + uint8_t recv_index = 0; + uint8_t *p_recv_buf = (psNdefMap->SendRecvBuf + 1); + + /* expected CC byte : E1 40 "MAX SIZE depends on tag" */ + if (ISO15693_CC_MAGIC_BYTE == *p_recv_buf) + { + /* 0xE1 magic byte found*/ + recv_index = (uint8_t)(recv_index + 1); + uint8_t tag_major_version = (*(p_recv_buf + recv_index) & ISO15693_MAJOR_VERSION_MASK) >> 6; + if (ISO15693_MAPPING_VERSION >= tag_major_version) + { + /* Correct mapping version found */ + switch (*(p_recv_buf + recv_index) & ISO15693_LSB_NIBBLE_MASK) + { + case ISO15693_RD_WR_PERMISSION: + { + /* READ/WRITE possible */ + psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE; + break; + } + + case ISO15693_RD_ONLY_PERMISSION: + { + /* ONLY READ possible, WRITE NOT possible */ + psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY; + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + recv_index = (uint8_t)(recv_index + 1); + + if (!result) + { + /* Update MAX SIZE */ + ps_iso_15693_con->max_data_size = (uint16_t) + (*(p_recv_buf + recv_index) * + ISO15693_MULT_FACTOR); + recv_index = (uint8_t)(recv_index + 1); + ps_iso_15693_con->read_capabilities = (*(p_recv_buf + recv_index)); + + + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + return result; +} + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessCheckNdef ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + phFriNfc_eChkNdefSeq_t e_chk_ndef_seq = (phFriNfc_eChkNdefSeq_t) + psNdefMap->ISO15693Container.ndef_seq; + + uint8_t *p_recv_buf = + (psNdefMap->SendRecvBuf + ISO15693_EXTRA_RESP_BYTE); + uint8_t recv_length = (uint8_t) + (*psNdefMap->SendRecvLength - ISO15693_EXTRA_RESP_BYTE); + uint8_t parse_index = 0; + static uint16_t prop_ndef_index = 0; + uint8_t *reformatted_buf = (uint8_t*) phOsalNfc_GetMemory(ps_iso_15693_con->max_data_size); + + if (0 == ps_iso_15693_con->current_block) + { + /* Check CC byte */ + result = phFriNfc_ISO15693_H_CheckCCBytes (psNdefMap); + parse_index = (uint8_t)(parse_index + recv_length); + } + else if (1 == ps_iso_15693_con->current_block && + (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR)) + { + + uint8_t reformatted_size = phFriNfc_ISO15693_Reformat_Pageread_Buffer(p_recv_buf, recv_length, + reformatted_buf, ps_iso_15693_con->max_data_size); + // Skip initial CC bytes + p_recv_buf = reformatted_buf + (ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK); + recv_length = reformatted_size - (ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK); + } + else + { + /* Propreitary TLVs VALUE can end in between a block, + so when that block is read, update the parse_index + with byte address value */ + if (ISO15693_PROP_TLV_V == e_chk_ndef_seq) + { + parse_index = ps_iso_15693_con->ndef_tlv_type_byte; + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + } + } + + while ((parse_index < recv_length) + && (NFCSTATUS_SUCCESS == result) + && (ISO15693_NDEF_TLV_V != e_chk_ndef_seq)) + { + /* Parse + 1. till the received length of the block + 2. till there is no error during parse + 3. till LENGTH field of NDEF TLV is found + */ + switch (e_chk_ndef_seq) + { + case ISO15693_NDEF_TLV_T: + { + /* Expected value is 0x03 TYPE identifier + of the NDEF TLV */ + prop_ndef_index = 0; + switch (*(p_recv_buf + parse_index)) + { + case ISO15693_NDEF_TLV_TYPE_ID: + { + /* Update the data structure with the byte address and + the block number */ + ps_iso_15693_con->ndef_tlv_type_byte = parse_index; + ps_iso_15693_con->ndef_tlv_type_blk = + ps_iso_15693_con->current_block; + e_chk_ndef_seq = ISO15693_NDEF_TLV_L; + + break; + } + + case ISO15693_NULL_TLV_ID: + { + /* Dont do any thing, go to next byte */ + break; + } + + case ISO15693_PROP_TLV_ID: + { + /* Move the sequence to find the length + of the proprietary TLV */ + e_chk_ndef_seq = ISO15693_PROP_TLV_L; + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } /* switch (*(p_recv_buf + parse_index)) */ + break; + } + + case ISO15693_PROP_TLV_L: + { + /* Length field of the proprietary TLV */ + switch (prop_ndef_index) + { + /* Length field can have 1 or 3 bytes depending + on the data size, so check for each index byte */ + case 0: + { + /* 1st index of the length field of the TLV */ + if (0 == *(p_recv_buf + parse_index)) + { + /* LENGTH is 0, not possible, so error */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + } + else + { + if (ISO15693_THREE_BYTE_LENGTH_ID == + *(p_recv_buf + parse_index)) + { + /* 3 byte LENGTH field identified, so increment the + index, so next time 2nd byte is parsed */ + prop_ndef_index = (uint8_t)(prop_ndef_index + 1); + } + else + { + /* 1 byte LENGTH field identified, so "static" + index is set to 0 and actual ndef size is + copied to the data structure + */ + ps_iso_15693_con->actual_ndef_size = + *(p_recv_buf + parse_index); + e_chk_ndef_seq = ISO15693_PROP_TLV_V; + prop_ndef_index = 0; + } + } + break; + } + + case 1: + { + /* 2nd index of the LENGTH field that is MSB of the length, + so the length is left shifted by 8 */ + ps_iso_15693_con->actual_ndef_size = (uint16_t) + (*(p_recv_buf + parse_index) << + ISO15693_BTYE_SHIFT); + prop_ndef_index = (uint8_t)(prop_ndef_index + 1); + break; + } + + case 2: + { + /* 3rd index of the LENGTH field that is LSB of the length, + so the length ORed with the previously stored size */ + ps_iso_15693_con->actual_ndef_size = (uint16_t) + (ps_iso_15693_con->actual_ndef_size | + *(p_recv_buf + parse_index)); + + e_chk_ndef_seq = ISO15693_PROP_TLV_V; + prop_ndef_index = 0; + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } /* switch (prop_ndef_index) */ + + if ((ISO15693_PROP_TLV_V == e_chk_ndef_seq) + && (ISO15693_GET_REMAINING_SIZE(ps_iso_15693_con->max_data_size, + ps_iso_15693_con->current_block, parse_index) + <= ps_iso_15693_con->actual_ndef_size)) + { + /* Check for the length field value has not exceeded the card size, + if size is exceeded or then return error */ + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + uint16_t prop_byte_addr = 0; + + /* skip the proprietary TLVs value field */ + prop_byte_addr = (uint16_t) + ((ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK) + + parse_index + ps_iso_15693_con->actual_ndef_size); + + ps_iso_15693_con->ndef_tlv_type_byte = (uint8_t)(prop_byte_addr % + ISO15693_BYTES_PER_BLOCK); + ps_iso_15693_con->ndef_tlv_type_blk = (uint16_t)(prop_byte_addr / + ISO15693_BYTES_PER_BLOCK); + if (parse_index + ps_iso_15693_con->actual_ndef_size >= + recv_length) + { + parse_index = (uint8_t)recv_length; + } + else + { + parse_index = (uint8_t)(parse_index + + ps_iso_15693_con->actual_ndef_size); + } + + } + break; + } /* case ISO15693_PROP_TLV_L: */ + + case ISO15693_PROP_TLV_V: + { + uint8_t remaining_length = (uint8_t)(recv_length - + parse_index); + + if ((ps_iso_15693_con->actual_ndef_size - prop_ndef_index) + > remaining_length) + { + parse_index = (uint8_t)(parse_index + remaining_length); + prop_ndef_index = (uint8_t)(prop_ndef_index + remaining_length); + } + else if ((ps_iso_15693_con->actual_ndef_size - prop_ndef_index) + == remaining_length) + { + parse_index = (uint8_t)(parse_index + remaining_length); + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + prop_ndef_index = 0; + } + else + { + parse_index = (uint8_t)(parse_index + + (ps_iso_15693_con->actual_ndef_size - + prop_ndef_index)); + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + prop_ndef_index = 0; + } + break; + } /* case ISO15693_PROP_TLV_V: */ + + case ISO15693_NDEF_TLV_L: + { + /* Length field of the NDEF TLV */ + switch (prop_ndef_index) + { + /* Length field can have 1 or 3 bytes depending + on the data size, so check for each index byte */ + case 0: + { + /* 1st index of the length field of the TLV */ + if (0 == *(p_recv_buf + parse_index)) + { + /* LENGTH is 0, card is in INITILIASED STATE */ + e_chk_ndef_seq = ISO15693_NDEF_TLV_V; + ps_iso_15693_con->actual_ndef_size = 0; + } + else + { + prop_ndef_index = (uint8_t)(prop_ndef_index + 1); + + if (ISO15693_THREE_BYTE_LENGTH_ID == + *(p_recv_buf + parse_index)) + { + /* At present no CARD supports more than 255 bytes, + so error is returned */ + prop_ndef_index = (uint8_t)(prop_ndef_index + 1); + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + prop_ndef_index = 0; + } + else + { + /* 1 byte LENGTH field identified, so "static" + index is set to 0 and actual ndef size is + copied to the data structure + */ + ps_iso_15693_con->actual_ndef_size = + *(p_recv_buf + parse_index); + /* next values are the DATA field of the NDEF TLV */ + e_chk_ndef_seq = ISO15693_NDEF_TLV_V; + prop_ndef_index = 0; + } + } + break; + } + + case 1: + { + /* 2nd index of the LENGTH field that is MSB of the length, + so the length is left shifted by 8 */ + ps_iso_15693_con->actual_ndef_size = (uint16_t) + (*(p_recv_buf + parse_index) << + ISO15693_BTYE_SHIFT); + prop_ndef_index = (uint8_t)(prop_ndef_index + 1); + break; + } + + case 2: + { + /* 3rd index of the LENGTH field that is LSB of the length, + so the length ORed with the previously stored size */ + ps_iso_15693_con->actual_ndef_size = (uint16_t) + (ps_iso_15693_con->actual_ndef_size | + *(p_recv_buf + parse_index)); + + e_chk_ndef_seq = ISO15693_NDEF_TLV_V; + prop_ndef_index = 0; + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } /* switch (prop_ndef_index) */ + + if ((ISO15693_NDEF_TLV_V == e_chk_ndef_seq) + && (ISO15693_GET_REMAINING_SIZE(ps_iso_15693_con->max_data_size, + /* parse_index + 1 is done because the data starts from the next index. + "MOD" operation is used to know that parse_index > + ISO15693_BYTES_PER_BLOCK, then block shall be incremented + */ + (((parse_index + 1) % ISO15693_BYTES_PER_BLOCK) ? + ps_iso_15693_con->current_block : + ps_iso_15693_con->current_block + 1), ((parse_index + 1) % + ISO15693_BYTES_PER_BLOCK)) + < ps_iso_15693_con->actual_ndef_size)) + { + /* Check for the length field value has not exceeded the card size */ + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + psNdefMap->CardState = (uint8_t) + ((PH_NDEFMAP_CARD_STATE_READ_ONLY + == psNdefMap->CardState) ? + PH_NDEFMAP_CARD_STATE_READ_ONLY : + ((ps_iso_15693_con->actual_ndef_size) ? + PH_NDEFMAP_CARD_STATE_READ_WRITE : + PH_NDEFMAP_CARD_STATE_INITIALIZED)); + } + break; + } /* case ISO15693_NDEF_TLV_L: */ + + case ISO15693_NDEF_TLV_V: + { + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } /* switch (e_chk_ndef_seq) */ + parse_index = (uint8_t)(parse_index + 1); + } /* while ((parse_index < recv_length) + && (NFCSTATUS_SUCCESS == result) + && (ISO15693_NDEF_TLV_V != e_chk_ndef_seq)) */ + + if (result) + { + /* Error returned while parsing, so STOP read */ + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + prop_ndef_index = 0; + } + else if (ISO15693_NDEF_TLV_V != e_chk_ndef_seq) + { + /* READ again */ + if (ISO15693_PROP_TLV_V != e_chk_ndef_seq) + { + ps_iso_15693_con->current_block = (uint16_t) + (ps_iso_15693_con->current_block + 1); + } + else + { + /* Proprietary TLV detected, so skip the proprietary blocks */ + ps_iso_15693_con->current_block = ps_iso_15693_con->ndef_tlv_type_blk; + } + + uint32_t remaining_size = ISO15693_GET_REMAINING_SIZE(ps_iso_15693_con->max_data_size, + ps_iso_15693_con->current_block, 0); + if (remaining_size > 0) + { + if ((ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_MBR) || + (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR)) { + result = phFriNfc_ReadRemainingInMultiple(psNdefMap, ps_iso_15693_con->current_block); + } else { + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND, + NULL, 0); + } + } + else + { + /* End of card reached, error no NDEF information found */ + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + prop_ndef_index = 0; + /* Error, no size to parse */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + + } + else + { + /* Successful read with proper NDEF information updated */ + prop_ndef_index = 0; + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + psNdefMap->CardType = (uint8_t)PH_FRINFC_NDEFMAP_ISO15693_CARD; + } + + psNdefMap->ISO15693Container.ndef_seq = (uint8_t)e_chk_ndef_seq; + + if (reformatted_buf != NULL) { + phOsalNfc_FreeMemory(reformatted_buf); + } + return result; +} + +static +void +phFriNfc_ISO15693_H_Complete ( + phFriNfc_NdefMap_t *psNdefMap, + NFCSTATUS Status) +{ + /* set the state back to the RESET_INIT state*/ + psNdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; + + /* set the completion routine*/ + psNdefMap->CompletionRoutine[psNdefMap->ISO15693Container.cr_index]. + CompletionRoutine (psNdefMap->CompletionRoutine->Context, Status); +} + +#ifdef FRINFC_READONLY_NDEF + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessReadOnly ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + phFriNfc_eRONdefSeq_t e_ro_ndef_seq = (phFriNfc_eRONdefSeq_t) + ps_iso_15693_con->ndef_seq; + uint8_t *p_recv_buf = (psNdefMap->SendRecvBuf + + ISO15693_EXTRA_RESP_BYTE); + uint8_t recv_length = (uint8_t)(*psNdefMap->SendRecvLength - + ISO15693_EXTRA_RESP_BYTE); + uint8_t a_write_buf[ISO15693_BYTES_PER_BLOCK] = {0}; + + switch (e_ro_ndef_seq) + { + case ISO15693_RD_BEFORE_WR_CC: + { + if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length) + { + result = phFriNfc_ISO15693_H_CheckCCBytes (psNdefMap); + /* Check CC bytes and also the card state for READ ONLY, + if the card is already read only, then dont continue with + next operation */ + if ((PH_NDEFMAP_CARD_STATE_READ_ONLY != psNdefMap->CardState) + && (!result)) + { + /* CC byte read successful */ + (void)memcpy ((void *)a_write_buf, (void *)p_recv_buf, + sizeof (a_write_buf)); + + /* Change the read write access to read only */ + *(a_write_buf + ISO15693_RW_BTYE_INDEX) = (uint8_t) + (*(a_write_buf + ISO15693_RW_BTYE_INDEX) | + ISO15693_CC_READ_ONLY_MASK); + + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_WRITE_COMMAND, a_write_buf, + sizeof (a_write_buf)); + + e_ro_ndef_seq = ISO15693_WRITE_CC; + } + } + break; + } + + case ISO15693_WRITE_CC: + { + /* Write to CC is successful. */ + e_ro_ndef_seq = ISO15693_LOCK_BLOCK; + /* Start the lock block command to lock the blocks */ + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_LOCK_BLOCK_CMD, NULL, 0); + break; + } + + case ISO15693_LOCK_BLOCK: + { + if (ps_iso_15693_con->current_block == + ((ps_iso_15693_con->max_data_size / ISO15693_BYTES_PER_BLOCK) - + 1)) + { + /* End of card reached, READ ONLY successful */ + } + else + { + /* current block is incremented */ + ps_iso_15693_con->current_block = (uint16_t) + (ps_iso_15693_con->current_block + 1); + /* Lock the current block */ + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_LOCK_BLOCK_CMD, NULL, 0); + } + break; + } + + default: + { + break; + } + } + + ps_iso_15693_con->ndef_seq = (uint8_t)e_ro_ndef_seq; + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ +/************************** END static functions definition *********************/ + +/************************** START external functions *********************/ + +NFCSTATUS +phFriNfc_ISO15693_ChkNdef ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phHal_sIso15693Info_t *ps_iso_15693_info = + &(psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info); + + /* Update the previous operation with current operation. + This becomes the previous operation after this execution */ + psNdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE; + /* Update the CR index to know from which operation completion + routine has to be called */ + psNdefMap->ISO15693Container.cr_index = PH_FRINFC_NDEFMAP_CR_CHK_NDEF; + /* State update */ + psNdefMap->State = ISO15693_CHECK_NDEF; + /* Reset the NDEF sequence */ + psNdefMap->ISO15693Container.ndef_seq = 0; + psNdefMap->ISO15693Container.current_block = 0; + psNdefMap->ISO15693Container.actual_ndef_size = 0; + psNdefMap->ISO15693Container.ndef_tlv_type_blk = 0; + psNdefMap->ISO15693Container.ndef_tlv_type_byte = 0; + psNdefMap->ISO15693Container.store_length = 0; + psNdefMap->ISO15693Container.remaining_size_to_read = 0; + psNdefMap->ISO15693Container.read_capabilities = 0; + + if ((ISO15693_UIDBYTE_6_VALUE == + ps_iso_15693_info->Uid[ISO15693_UID_BYTE_6]) + && (ISO15693_UIDBYTE_7_VALUE == + ps_iso_15693_info->Uid[ISO15693_UID_BYTE_7])) + { + /* Check if the card is manufactured by NXP (6th byte + index of UID value = 0x04 and the + last byte i.e., 7th byte of UID is 0xE0, only then the card detected + is NDEF compliant */ + switch (ps_iso_15693_info->Uid[ISO15693_UID_BYTE_5]) + { + /* Check for supported tags, by checking the 5th byte index of UID */ + case ISO15693_UIDBYTE_5_VALUE_SLI_X: + { + /* ISO 15693 card type is ICODE SLI + so maximum size is 112 */ + psNdefMap->ISO15693Container.max_data_size = + ISO15693_SL2_S2002_ICS20; + break; + } + + case ISO15693_UIDBYTE_5_VALUE_SLI_X_S: + { + /* ISO 15693 card type is ICODE SLI/X S + so maximum size depends on the 4th UID byte index */ + switch (ps_iso_15693_info->Uid[ISO15693_UID_BYTE_4]) + { + case ISO15693_UIDBYTE_4_VALUE_SLI_X_S: + case ISO15693_UIDBYTE_4_VALUE_SLI_X_SHC: + case ISO15693_UIDBYTE_4_VALUE_SLI_X_SY: + { + /* Supported tags are with value (4th byte UID index) + of 0x00, 0x80 and 0x40 + For these cards max size is 160 bytes */ + psNdefMap->ISO15693Container.max_data_size = + ISO15693_SL2_S5302_ICS53_ICS54; + break; + } + + default: + { + /* Tag not supported */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + break; + } + + case ISO15693_UIDBYTE_5_VALUE_SLI_X_L: + { + /* ISO 15693 card type is ICODE SLI/X L + so maximum size depends on the 4th UID byte index */ + switch (ps_iso_15693_info->Uid[ISO15693_UID_BYTE_4]) + { + case ISO15693_UIDBYTE_4_VALUE_SLI_X_L: + case ISO15693_UIDBYTE_4_VALUE_SLI_X_LHC: + { + /* Supported tags are with value (4th byte UID index) + of 0x00 and 0x80 + For these cards max size is 32 bytes */ + psNdefMap->ISO15693Container.max_data_size = + ISO15693_SL2_S5002_ICS50_ICS51; + break; + } + + default: + { + /* Tag not supported */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + break; + } + + default: + { + /* Tag not supported */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + } + else + { + /* Tag not supported */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + } + + if (!result) + { + /* Start reading the data */ + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND, + NULL, 0); + } + + + return result; +} + +NFCSTATUS +phFriNfc_ISO15693_RdNdef ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *pPacketData, + uint32_t *pPacketDataLength, + uint8_t Offset) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + + /* Update the previous operation with current operation. + This becomes the previous operation after this execution */ + psNdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + /* Update the CR index to know from which operation completion + routine has to be called */ + psNdefMap->ISO15693Container.cr_index = PH_FRINFC_NDEFMAP_CR_RD_NDEF; + /* State update */ + psNdefMap->State = ISO15693_READ_NDEF; + /* Copy user buffer to the context */ + psNdefMap->ApduBuffer = pPacketData; + /* Copy user length to the context */ + psNdefMap->ApduBufferSize = *pPacketDataLength; + /* Update the user memory size to a context variable */ + psNdefMap->NumOfBytesRead = pPacketDataLength; + /* Number of bytes read from the card is zero. + This variable returns the number of bytes read + from the card. */ + *psNdefMap->NumOfBytesRead = 0; + /* Index to know the length read */ + psNdefMap->ApduBuffIndex = 0; + /* Store the offset in the context */ + psNdefMap->Offset = Offset; + + if ((!ps_iso_15693_con->remaining_size_to_read) + && (!psNdefMap->Offset)) + { + /* Entire data is already read from the card. + There is no data to give */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else if (0 == ps_iso_15693_con->actual_ndef_size) + { + /* Card is NDEF, but no data in the card. */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_READ_FAILED); + } + else if (PH_NDEFMAP_CARD_STATE_INITIALIZED == psNdefMap->CardState) + { + /* Card is NDEF, but no data in the card. */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_READ_FAILED); + } + else if (psNdefMap->Offset) + { + /* BEGIN offset, so reset the remaining read size and + also the curretn block */ + ps_iso_15693_con->remaining_size_to_read = + ps_iso_15693_con->actual_ndef_size; + ps_iso_15693_con->current_block = + ISO15693_GET_VALUE_FIELD_BLOCK_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + ps_iso_15693_con->actual_ndef_size); + + // Check capabilities + if ((ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_MBR) || + (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR)) { + result = phFriNfc_ReadRemainingInMultiple(psNdefMap, ps_iso_15693_con->current_block); + } else { + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND, + NULL, 0); + } + } + else + { + /* CONTINUE offset */ + if (ps_iso_15693_con->store_length > 0) + { + /* Previous read had extra bytes, so data is stored, so give that take + that data from store. If more data is required, then read remaining bytes */ + result = phFriNfc_ISO15693_H_ProcessReadNdef (psNdefMap); + } + else + { + ps_iso_15693_con->current_block = (uint16_t) + (ps_iso_15693_con->current_block + 1); + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_READ_COMMAND, NULL, 0); + } + } + + return result; +} + +static +NFCSTATUS +phFriNfc_ReadRemainingInMultiple ( + phFriNfc_NdefMap_t *psNdefMap, + uint32_t startBlock) +{ + NFCSTATUS result = NFCSTATUS_FAILED; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = &(psNdefMap->ISO15693Container); + + uint32_t remaining_size = ISO15693_GET_REMAINING_SIZE(ps_iso_15693_con->max_data_size, + startBlock, 0); + // Check capabilities + if (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_MBR) { + // Multi-page read command + uint8_t mbread[1]; + mbread[0] = (remaining_size / ISO15693_BYTES_PER_BLOCK) - 1; + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_MULTIPLE_COMMAND, + mbread, 1); + } else if (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR) { + uint32_t page = 0; + uint32_t pagesToRead = (remaining_size / ISO15693_BYTES_PER_BLOCK / 4) - 1; + if ((remaining_size % (ISO15693_BYTES_PER_BLOCK * ISO15693_BLOCKS_PER_PAGE)) != 0) { + pagesToRead++; + } + result = phFriNfc_ISO15693_H_Inventory_Page_Read (psNdefMap, ICODE_INVENTORY_PAGEREAD_COMMAND, + page, pagesToRead); + // Inventory + } else { + result = NFCSTATUS_FAILED; + } + return result; +} + +NFCSTATUS +phFriNfc_ISO15693_WrNdef ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *pPacketData, + uint32_t *pPacketDataLength, + uint8_t Offset) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + uint8_t a_write_buf[ISO15693_BYTES_PER_BLOCK] = {0}; + + /* Update the previous operation with current operation. + This becomes the previous operation after this execution */ + psNdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + /* Update the CR index to know from which operation completion + routine has to be called */ + psNdefMap->ISO15693Container.cr_index = PH_FRINFC_NDEFMAP_CR_WR_NDEF; + /* State update */ + psNdefMap->State = ISO15693_WRITE_NDEF; + /* Copy user buffer to the context */ + psNdefMap->ApduBuffer = pPacketData; + /* Copy user length to the context */ + psNdefMap->ApduBufferSize = *pPacketDataLength; + /* Update the user memory size to a context variable */ + psNdefMap->NumOfBytesRead = pPacketDataLength; + /* Number of bytes written to the card is zero. + This variable returns the number of bytes written + to the card. */ + *psNdefMap->WrNdefPacketLength = 0; + /* Index to know the length read */ + psNdefMap->ApduBuffIndex = 0; + /* Store the offset in the context */ + psNdefMap->Offset = Offset; + + /* Set the current block correctly to write the length field to 0 */ + ps_iso_15693_con->current_block = + ISO15693_GET_LEN_FIELD_BLOCK_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + *pPacketDataLength); + + if (ISO15693_GET_LEN_FIELD_BYTE_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + *pPacketDataLength)) + { + /* Check the byte address to write. If length byte address is in between or + is the last byte of the block, then READ before write + reason, write should not corrupt other data + */ + ps_iso_15693_con->ndef_seq = (uint8_t)ISO15693_RD_BEFORE_WR_NDEF_L_0; + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_READ_COMMAND, NULL, 0); + } + else + { + /* If length byte address is at the beginning of the block then WRITE + length field to 0 and as also write user DATA */ + ps_iso_15693_con->ndef_seq = (uint8_t)ISO15693_WRITE_DATA; + + /* Length is made 0x00 */ + *a_write_buf = 0x00; + + /* Write remaining data */ + (void)memcpy ((void *)(a_write_buf + 1), + (void *)psNdefMap->ApduBuffer, + (ISO15693_BYTES_PER_BLOCK - 1)); + + /* Write data */ + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_WRITE_COMMAND, + a_write_buf, ISO15693_BYTES_PER_BLOCK); + + /* Increment the index to keep track of bytes sent for write */ + psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + + (ISO15693_BYTES_PER_BLOCK - 1)); + } + + return result; +} + +#ifdef FRINFC_READONLY_NDEF + +NFCSTATUS +phFriNfc_ISO15693_ConvertToReadOnly ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + + psNdefMap->State = ISO15693_READ_ONLY_NDEF; + /* READ CC bytes */ + ps_iso_15693_con->ndef_seq = (uint8_t)ISO15693_RD_BEFORE_WR_CC; + ps_iso_15693_con->current_block = 0; + + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_READ_COMMAND, NULL, 0); + + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + + +void +phFriNfc_ISO15693_Process ( + void *pContext, + NFCSTATUS Status) +{ + phFriNfc_NdefMap_t *psNdefMap = + (phFriNfc_NdefMap_t *)pContext; + + if ((NFCSTATUS_SUCCESS & PHNFCSTBLOWER) == (Status & PHNFCSTBLOWER)) + { + switch (psNdefMap->State) + { + case ISO15693_CHECK_NDEF: + { + /* State = CHECK NDEF in progress */ + Status = phFriNfc_ISO15693_H_ProcessCheckNdef (psNdefMap); + break; + } + + case ISO15693_READ_NDEF: + { + /* State = READ NDEF in progress */ + Status = phFriNfc_ISO15693_H_ProcessReadNdef (psNdefMap); + break; + } + + case ISO15693_WRITE_NDEF: + { + /* State = WRITE NDEF in progress */ + Status = phFriNfc_ISO15693_H_ProcessWriteNdef (psNdefMap); + break; + } + +#ifdef FRINFC_READONLY_NDEF + case ISO15693_READ_ONLY_NDEF: + { + /* State = RAD ONLY NDEF in progress */ + Status = phFriNfc_ISO15693_H_ProcessReadOnly (psNdefMap); + break; + } +#endif /* #ifdef FRINFC_READONLY_NDEF */ + + default: + { + break; + } + } + } + + /* Call for the Completion Routine*/ + if (NFCSTATUS_PENDING != Status) + { + phFriNfc_ISO15693_H_Complete(psNdefMap, Status); + } +} + +/************************** END external functions *********************/ + +#endif /* #ifndef PH_FRINFC_MAP_ISO15693_DISABLED */ diff --git a/libnfc-nxp/phFriNfc_ISO15693Map.h b/libnfc-nxp/phFriNfc_ISO15693Map.h new file mode 100644 index 0000000..f4c0c08 --- /dev/null +++ b/libnfc-nxp/phFriNfc_ISO15693Map.h @@ -0,0 +1,219 @@ +/* + * + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* + * \file phFriNfc_ISO15693Map.h + * \brief NFC Ndef Mapping For ISO-15693 Smart Card. + * + * Project: NFC-FRI + * + * $Date: $ + * $Author: ing02260 $ + * $Revision: $ + * $Aliases: $ + * + */ + +#ifndef PHFRINFC_ISO15693MAP_H +#define PHFRINFC_ISO15693MAP_H + +/************************** START MACROS definition *********************/ +/* BYTES in a BLOCK */ +#define ISO15693_BYTES_PER_BLOCK 0x04U +/* BLOCKS per page */ +#define ISO15693_BLOCKS_PER_PAGE 0x04U +/* 3 BYTE value identifier for NDEF TLV */ +#define ISO15693_THREE_BYTE_LENGTH_ID 0xFFU + +/* Get the NDEF TLV VALUE field block and byte address */ +#define ISO15693_GET_VALUE_FIELD_BLOCK_NO(blk, byte_addr, ndef_size) \ + (((byte_addr + 1 + ((ndef_size >= ISO15693_THREE_BYTE_LENGTH_ID) ? 3 : 1)) > \ + (ISO15693_BYTES_PER_BLOCK - 1)) ? (blk + 1) : blk) + +#define ISO15693_GET_VALUE_FIELD_BYTE_NO(blk, byte_addr, ndef_size) \ + (((byte_addr + 1 + ((ndef_size >= ISO15693_THREE_BYTE_LENGTH_ID) ? 3 : 1)) % \ + ISO15693_BYTES_PER_BLOCK)) + +/************************** END MACROS definition *********************/ + +/************************** START Functions declaration *********************/ +/*! + * \brief \copydoc page_ovr Initiates Reading of NDEF information from the Remote Device. + * + * The function initiates the reading of NDEF information from a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that receives the NDEF Packet. + * + * \param[in,out] PacketDataLength Pointer to a variable receiving the length of the NDEF packet. + * + * \param[in] Offset Indicates whether the read operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start reading from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start reading + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED No Space in the File to read. + * \retval NFCSTATUS_MORE_INFORMATION There are more bytes to read in the card. + * \retval NFCSTATUS_SUCCESS Last Byte of the card read. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS +phFriNfc_ISO15693_RdNdef ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *pPacketData, + uint32_t *pPacketDataLength, + uint8_t Offset); + +/*! + * \brief \copydoc page_ovr Initiates Writing of NDEF information to the Remote Device. + * + * The function initiates the writing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that holds the prepared NDEF Packet. + * + * \param[in,out] PacketDataLength Variable specifying the length of the prepared NDEF packet. + * + * \param[in] Offset Indicates whether the write operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start writing from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start writing + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED Last byte is written to the card after this + * no further writing is possible. + * \retval NFCSTATUS_SUCCESS Buffer provided by the user is completely written + * into the card. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS +phFriNfc_ISO15693_WrNdef ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *pPacketData, + uint32_t *pPacketDataLength, + uint8_t Offset); + +/*! + * \brief \copydoc page_ovr Check whether a particulat Remote Device is NDEF compliant. + * + * The function checks whether the peer device is NDEF compliant. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS +phFriNfc_ISO15693_ChkNdef ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_cb Completion Routine, Processing function, needed to avoid long blocking. + * + * The function call scheme is according to \ref grp_interact. No State reset is performed during operation. + * + * \copydoc pphFriNfc_Cr_t + * + * \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion + * Routine in order to be able to notify the component that an I/O has finished and data are + * ready to be processed. + * + */ + +void +phFriNfc_ISO15693_Process ( + void *pContext, + NFCSTATUS Status); + +#ifdef FRINFC_READONLY_NDEF + +/*! + * \brief \copydoc page_ovr Initiates Writing of NDEF information to the Remote Device. + * + * The function initiates the writing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] psNdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED Last byte is written to the card after this + * no further writing is possible. + * \retval NFCSTATUS_SUCCESS Buffer provided by the user is completely written + * into the card. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ +NFCSTATUS +phFriNfc_ISO15693_ConvertToReadOnly ( + phFriNfc_NdefMap_t *psNdefMap); + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/************************** END Functions declaration *********************/ + +#endif /* #ifndef PHFRINFC_ISO15693MAP_H */ diff --git a/libnfc-nxp/phFriNfc_IntNdefMap.c b/libnfc-nxp/phFriNfc_IntNdefMap.c new file mode 100644 index 0000000..8962fc6 --- /dev/null +++ b/libnfc-nxp/phFriNfc_IntNdefMap.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc_IntNdef.c + * \brief NFC Ndef Internal Mapping File. + * + * Project: NFC-FRI + * + * $Date: Mon Sep 15 15:09:33 2008 $ + * $Author: ing08205 $ + * $Revision: 1.5 $ + * $Aliases: NFC_FRI1.1_WK838_R9_PREP2,NFC_FRI1.1_WK838_R9_1,NFC_FRI1.1_WK840_R10_PREP1,NFC_FRI1.1_WK840_R10_1,NFC_FRI1.1_WK842_R11_PREP1,NFC_FRI1.1_WK842_R11_PREP2,NFC_FRI1.1_WK842_R11_1,NFC_FRI1.1_WK844_PREP1,NFC_FRI1.1_WK844_R12_1,NFC_FRI1.1_WK846_PREP1,NFC_FRI1.1_WK846_R13_1,NFC_FRI1.1_WK848_PREP1,NFC_FRI1.1_WK848_R14_1,NFC_FRI1.1_WK850_PACK1,NFC_FRI1.1_WK851_PREP1,NFC_FRI1.1_WK850_R15_1,NFC_FRI1.1_WK902_PREP1,NFC_FRI1.1_WK902_R16_1,NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#include +#include + +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED +#include +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED*/ + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED +#include +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED +#include +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED +#include +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + +#include + +/*! \ingroup grp_file_attributes + * \name NDEF Mapping + * + * File: \ref phFri_IntNdefMap.c + * This file has functions which are used common across all the + * typ1/type2/type3/type4 tags. + * + */ +/*@{*/ +#define PHFRINFCNDEFMAP_FILEREVISION "$Revision: 1.5 $" +#define PHFRINFCNDEFMAP_FILEALIASES "$Aliases: NFC_FRI1.1_WK838_R9_PREP2,NFC_FRI1.1_WK838_R9_1,NFC_FRI1.1_WK840_R10_PREP1,NFC_FRI1.1_WK840_R10_1,NFC_FRI1.1_WK842_R11_PREP1,NFC_FRI1.1_WK842_R11_PREP2,NFC_FRI1.1_WK842_R11_1,NFC_FRI1.1_WK844_PREP1,NFC_FRI1.1_WK844_R12_1,NFC_FRI1.1_WK846_PREP1,NFC_FRI1.1_WK846_R13_1,NFC_FRI1.1_WK848_PREP1,NFC_FRI1.1_WK848_R14_1,NFC_FRI1.1_WK850_PACK1,NFC_FRI1.1_WK851_PREP1,NFC_FRI1.1_WK850_R15_1,NFC_FRI1.1_WK902_PREP1,NFC_FRI1.1_WK902_R16_1,NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" +/*@}*/ + + +/* \note This function has to be called at the beginning, after creating an + * instance of \ref phFriNfc_NdefMap_t . Use this function to reset + * the instance and/or switch to a different underlying device ( + * different NFC device or device mode, or different Remote Device). + */ + + +#if 0 +NFCSTATUS phFriNfc_ChkAndParseTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + switch ( NdefMap->CardType ) + { + #ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED + case PH_FRINFC_NDEFMAP_MIFARE_UL_CARD : + + + break; +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED */ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED + case PH_FRINFC_NDEFMAP_ISO14443_4A_CARD : + status = phFriNfc_Desf_ChkAndParseTLV(NdefMap,PH_FRINFC_NDEFMAP_DESF_TLV_INDEX); + return (status); + + break; +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED + case PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD : + case PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD : + + break; +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED + case PH_FRINFC_NDEFMAP_FELICA_SMART_CARD : + ; + break; +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + + default : + /* Unknown card type. Return error */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_REMOTE_DEVICE); + + break; + } + + return ( status); +} +#endif + +NFCSTATUS phFriNfc_NdefMap_SetCardState(phFriNfc_NdefMap_t *NdefMap, + uint16_t Length) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + if(Length == PH_FRINFC_NDEFMAP_MFUL_VAL0) + { + NdefMap->CardState =(uint8_t) (((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_READ_ONLY) || + (NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID))? + PH_NDEFMAP_CARD_STATE_INVALID: + NdefMap->CardState); + } + else + { + switch(NdefMap->CardState) + { + case PH_NDEFMAP_CARD_STATE_INITIALIZED: + NdefMap->CardState =(uint8_t) ((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID)? + NdefMap->CardState: + PH_NDEFMAP_CARD_STATE_READ_WRITE); + break; + + case PH_NDEFMAP_CARD_STATE_READ_ONLY: + NdefMap->CardState =(uint8_t) ((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID)? + NdefMap->CardState: + PH_NDEFMAP_CARD_STATE_READ_ONLY); + break; + + case PH_NDEFMAP_CARD_STATE_READ_WRITE: + NdefMap->CardState =(uint8_t) ((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID)? + NdefMap->CardState: + PH_NDEFMAP_CARD_STATE_READ_WRITE); + break; + + default: + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + Result = ((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID)? + PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT): + Result); + return Result; +} + +NFCSTATUS phFriNfc_NdefMap_CheckSpecVersion(phFriNfc_NdefMap_t *NdefMap, + uint8_t VersionIndex) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + uint8_t T3TVerNo = NdefMap->SendRecvBuf[VersionIndex]; + + if ( T3TVerNo == 0 ) + { + /*Return Status Error “ Invalid Format”*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT); + } + else + { + /* calculate the major and minor version number of T3VerNo */ + if( (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM == + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(T3TVerNo ) )&& + ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM >= + PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(T3TVerNo))) || + (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM == + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(T3TVerNo ) )&& + ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM < + PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(T3TVerNo) ))) + { + status = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS); + } + else + { + if (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM < + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(T3TVerNo) ) || + ( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM > + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(T3TVerNo))) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT); + } + } + } + return (status); +} diff --git a/libnfc-nxp/phFriNfc_IntNdefMap.h b/libnfc-nxp/phFriNfc_IntNdefMap.h new file mode 100644 index 0000000..1951000 --- /dev/null +++ b/libnfc-nxp/phFriNfc_IntNdefMap.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* + * \file phFriNfc_IntNdefMap.h + * \brief NFC Internal Ndef Mapping File. + * + * Project: NFC-FRI + * + * $Date: Mon Sep 15 15:10:49 2008 $ + * $Author: ing08205 $ + * $Revision: 1.5 $ + * $Aliases: NFC_FRI1.1_WK838_R9_PREP2,NFC_FRI1.1_WK838_R9_1,NFC_FRI1.1_WK840_R10_PREP1,NFC_FRI1.1_WK840_R10_1,NFC_FRI1.1_WK842_R11_PREP1,NFC_FRI1.1_WK842_R11_PREP2,NFC_FRI1.1_WK842_R11_1,NFC_FRI1.1_WK844_PREP1,NFC_FRI1.1_WK844_R12_1,NFC_FRI1.1_WK846_PREP1,NFC_FRI1.1_WK846_R13_1,NFC_FRI1.1_WK848_PREP1,NFC_FRI1.1_WK848_R14_1,NFC_FRI1.1_WK850_PACK1,NFC_FRI1.1_WK851_PREP1,NFC_FRI1.1_WK850_R15_1,NFC_FRI1.1_WK902_PREP1,NFC_FRI1.1_WK902_R16_1,NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PHFRINFC_INTNDEFMAP_H +#define PHFRINFC_INTNDEFMAP_H + +#include +#ifdef PH_HAL4_ENABLE + #include +#else + #include +#endif +#include +#include +#include + + + +/*! + * \name phFriNfc_IntNdefMap.h + * This file has functions which are used common across all the + typ1/type2/type3/type4 tags. + * + */ +/*@{*/ + +#define PH_FRINFC_NDEFMAP_TLVLEN_ZERO 0 + +/* NFC Device Major and Minor Version numbers*/ +/* !!CAUTION!! these needs to be updated periodically.Major and Minor version numbers + should be compatible to the version number of currently implemented mapping document. + Example : NFC Device version Number : 1.0 , specifies + Major VNo is 1, + Minor VNo is 0 */ +#define PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM 0x01 +#define PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM 0x00 + +/* Macros to find major and minor TAG : Ex:Type1/Type2/Type3/Type4 version numbers*/ +#define PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(a) (((a) & (0xf0))>>(4)) +#define PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(a) ((a) & (0x0f)) + + +/*! + * \name NDEF Mapping - states of the Finite State machine + * + */ +/*@{*/ + +NFCSTATUS phFriNfc_NdefMap_CheckSpecVersion(phFriNfc_NdefMap_t *NdefMap, + uint8_t VersionIndex); + +NFCSTATUS phFriNfc_NdefMap_SetCardState(phFriNfc_NdefMap_t *NdefMap, + uint16_t Length); + +#endif /* PHFRINFC_INTNDEFMAP_H */ diff --git a/libnfc-nxp/phFriNfc_Llcp.c b/libnfc-nxp/phFriNfc_Llcp.c new file mode 100644 index 0000000..bf80722 --- /dev/null +++ b/libnfc-nxp/phFriNfc_Llcp.c @@ -0,0 +1,1486 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_Llcp.c + * \brief NFC LLCP core + * + * Project: NFC-FRI + * + */ + +/*include files*/ +#include +#include + +#include +#include + +/** + * \internal + * \name States of the LLC state machine. + * + */ +/*@{*/ +#define PHFRINFC_LLCP_STATE_RESET_INIT 0 /**< \internal Initial state.*/ +#define PHFRINFC_LLCP_STATE_CHECKED 1 /**< \internal The tag has been checked for LLCP compliance.*/ +#define PHFRINFC_LLCP_STATE_ACTIVATION 2 /**< \internal The deactivation phase.*/ +#define PHFRINFC_LLCP_STATE_PAX 3 /**< \internal Parameter exchange phase.*/ +#define PHFRINFC_LLCP_STATE_OPERATION_RECV 4 /**< \internal Normal operation phase (ready to receive).*/ +#define PHFRINFC_LLCP_STATE_OPERATION_SEND 5 /**< \internal Normal operation phase (ready to send).*/ +#define PHFRINFC_LLCP_STATE_DEACTIVATION 6 /**< \internal The deactivation phase.*/ +/*@}*/ + +/** + * \internal + * \name Masks used for VERSION parsing. + * + */ +/*@{*/ +#define PHFRINFC_LLCP_VERSION_MAJOR_MASK 0xF0 /**< \internal Mask to apply to get major version number.*/ +#define PHFRINFC_LLCP_VERSION_MINOR_MASK 0x0F /**< \internal Mask to apply to get major version number.*/ +/*@}*/ + +/** + * \internal + * \name Invalid values for parameters. + * + */ +/*@{*/ +#define PHFRINFC_LLCP_INVALID_VERSION 0x00 /**< \internal Invalid VERSION value.*/ +/*@}*/ + +/** + * \internal + * \name Internal constants. + * + */ +/*@{*/ +#define PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH \ + (( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_VERSION ) + \ + ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_MIUX ) + \ + ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_WKS ) + \ + ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_LTO ) + \ + ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_OPT )) /**< \internal Maximum size of link params TLV.*/ +/*@}*/ + + + +/* --------------------------- Internal functions ------------------------------ */ + +static void phFriNfc_Llcp_Receive_CB( void *pContext, + NFCSTATUS status, + phNfc_sData_t *psData); +static NFCSTATUS phFriNfc_Llcp_HandleIncomingPacket( phFriNfc_Llcp_t *Llcp, + phNfc_sData_t *psPacket ); +static void phFriNfc_Llcp_ResetLTO( phFriNfc_Llcp_t *Llcp ); +static NFCSTATUS phFriNfc_Llcp_InternalSend( phFriNfc_Llcp_t *Llcp, + phFriNfc_Llcp_sPacketHeader_t *psHeader, + phFriNfc_Llcp_sPacketSequence_t *psSequence, + phNfc_sData_t *psInfo ); +static bool_t phFriNfc_Llcp_HandlePendingSend ( phFriNfc_Llcp_t *Llcp ); + +static phNfc_sData_t * phFriNfc_Llcp_AllocateAndCopy(phNfc_sData_t * pOrig) +{ + phNfc_sData_t * pDest = NULL; + + if (pOrig == NULL) + { + return NULL; + } + + pDest = phOsalNfc_GetMemory(sizeof(phNfc_sData_t)); + if (pDest == NULL) + { + goto error; + } + + pDest->buffer = phOsalNfc_GetMemory(pOrig->length); + if (pDest->buffer == NULL) + { + goto error; + } + + memcpy(pDest->buffer, pOrig->buffer, pOrig->length); + pDest->length = pOrig->length; + + return pDest; + +error: + if (pDest != NULL) + { + if (pDest->buffer != NULL) + { + phOsalNfc_FreeMemory(pDest->buffer); + } + phOsalNfc_FreeMemory(pDest); + } + return NULL; +} + +static void phFriNfc_Llcp_Deallocate(phNfc_sData_t * pData) +{ + if (pData != NULL) + { + if (pData->buffer != NULL) + { + phOsalNfc_FreeMemory(pData->buffer); + } + else + { + LLCP_PRINT("Warning, deallocating empty buffer"); + } + phOsalNfc_FreeMemory(pData); + } +} + +static NFCSTATUS phFriNfc_Llcp_InternalDeactivate( phFriNfc_Llcp_t *Llcp ) +{ + phFriNfc_Llcp_Send_CB_t pfSendCB; + void * pSendContext; + if ((Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) || + (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) || + (Llcp->state == PHFRINFC_LLCP_STATE_PAX) || + (Llcp->state == PHFRINFC_LLCP_STATE_ACTIVATION)) + { + /* Update state */ + Llcp->state = PHFRINFC_LLCP_STATE_DEACTIVATION; + + /* Stop timer */ + phOsalNfc_Timer_Stop(Llcp->hSymmTimer); + + Llcp->psSendHeader = NULL; + Llcp->psSendSequence = NULL; + /* Return delayed send operation in error, in any */ + if (Llcp->psSendInfo != NULL) + { + phFriNfc_Llcp_Deallocate(Llcp->psSendInfo); + Llcp->psSendInfo = NULL; + } + if (Llcp->pfSendCB != NULL) + { + /* Get Callback params */ + pfSendCB = Llcp->pfSendCB; + pSendContext = Llcp->pSendContext; + /* Reset callback params */ + Llcp->pfSendCB = NULL; + Llcp->pSendContext = NULL; + /* Call the callback */ + (pfSendCB)(pSendContext, NFCSTATUS_FAILED); + } + + /* Notify service layer */ + Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkDeactivated); + + /* Forward check request to MAC layer */ + return phFriNfc_LlcpMac_Deactivate(&Llcp->MAC); + } + + return NFCSTATUS_SUCCESS; +} + + +static NFCSTATUS phFriNfc_Llcp_SendSymm( phFriNfc_Llcp_t *Llcp ) +{ + phFriNfc_Llcp_sPacketHeader_t sHeader; + + sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; + sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; + sHeader.ptype = PHFRINFC_LLCP_PTYPE_SYMM; + return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, NULL); +} + + +static NFCSTATUS phFriNfc_Llcp_SendPax( phFriNfc_Llcp_t *Llcp, phFriNfc_Llcp_sLinkParameters_t *psLinkParams) +{ + uint8_t pTLVBuffer[PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH]; + phNfc_sData_t sParamsTLV; + phFriNfc_Llcp_sPacketHeader_t sHeader; + NFCSTATUS result; + + /* Prepare link parameters TLV */ + sParamsTLV.buffer = pTLVBuffer; + sParamsTLV.length = PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH; + result = phFriNfc_Llcp_EncodeLinkParams(&sParamsTLV, psLinkParams, PHFRINFC_LLCP_VERSION); + if (result != NFCSTATUS_SUCCESS) + { + /* Error while encoding */ + return NFCSTATUS_FAILED; + } + + /* Check if ready to send */ + if (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) + { + /* No send pending, send the PAX packet */ + sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; + sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; + sHeader.ptype = PHFRINFC_LLCP_PTYPE_PAX; + return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, &sParamsTLV); + } + else + { + /* Error: A send is already pending, cannot send PAX */ + /* NOTE: this should not happen since PAX are sent before any other packet ! */ + return NFCSTATUS_FAILED; + } +} + + +static NFCSTATUS phFriNfc_Llcp_SendDisconnect( phFriNfc_Llcp_t *Llcp ) +{ + phFriNfc_Llcp_sPacketHeader_t sHeader; + + /* Check if ready to send */ + if (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) + { + /* No send pending, send the DISC packet */ + sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; + sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; + sHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC; + return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, NULL); + } + else + { + /* A send is already pending, raise a flag to send DISC as soon as possible */ + Llcp->bDiscPendingFlag = TRUE; + return NFCSTATUS_PENDING; + } +} + + +static void phFriNfc_Llcp_Timer_CB(uint32_t TimerId, void *pContext) +{ + phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; + + PHNFC_UNUSED_VARIABLE(TimerId); + + /* Check current state */ + if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) + { + /* No data is coming before LTO, disconnecting */ + phFriNfc_Llcp_InternalDeactivate(Llcp); + } + else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) + { + /* Send SYMM */ + phFriNfc_Llcp_SendSymm(Llcp); + } + else + { + /* Nothing to do if not in Normal Operation state */ + } +} + + +static NFCSTATUS phFriNfc_Llcp_HandleAggregatedPacket( phFriNfc_Llcp_t *Llcp, + phNfc_sData_t *psRawPacket ) +{ + phNfc_sData_t sInfo; + phNfc_sData_t sCurrentInfo; + uint16_t length; + NFCSTATUS status; + + /* Get info field */ + sInfo.buffer = psRawPacket->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE; + sInfo.length = psRawPacket->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE; + + /* Check for empty info field */ + if (sInfo.length == 0) + { + return NFCSTATUS_FAILED; + } + + /* Check consistency */ + while (sInfo.length != 0) + { + /* Check if enough room to read length */ + if (sInfo.length < sizeof(sInfo.length)) + { + return NFCSTATUS_FAILED; + } + /* Read length */ + length = (sInfo.buffer[0] << 8) | sInfo.buffer[1]; + /* Update info buffer */ + sInfo.buffer += 2; /*Size of length field is 2*/ + sInfo.length -= 2; /*Size of length field is 2*/ + /* Check if declared length fits in remaining space */ + if (length > sInfo.length) + { + return NFCSTATUS_FAILED; + } + /* Update info buffer */ + sInfo.buffer += length; + sInfo.length -= length; + } + + /* Get info field */ + sInfo.buffer = psRawPacket->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE; + sInfo.length = psRawPacket->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE; + + /* Handle aggregated packets */ + while (sInfo.length != 0) + { + /* Read length */ + length = (sInfo.buffer[0] << 8) | sInfo.buffer[1]; + /* Update info buffer */ + sInfo.buffer += 2; /* Size of length field is 2 */ + sInfo.length -= 2; /*Size of length field is 2*/ + /* Handle aggregated packet */ + sCurrentInfo.buffer=sInfo.buffer; + sCurrentInfo.length=length; + status = phFriNfc_Llcp_HandleIncomingPacket(Llcp, &sCurrentInfo); + if ( (status != NFCSTATUS_SUCCESS) && + (status != NFCSTATUS_PENDING) ) + { + /* TODO: Error: invalid frame */ + } + /* Update info buffer */ + sInfo.buffer += length; + sInfo.length -= length; + } + return NFCSTATUS_SUCCESS; +} + + +static NFCSTATUS phFriNfc_Llcp_ParseLinkParams( phNfc_sData_t *psParamsTLV, + phFriNfc_Llcp_sLinkParameters_t *psParsedParams, + uint8_t *pnParsedVersion ) +{ + NFCSTATUS status; + uint8_t type; + phFriNfc_Llcp_sLinkParameters_t sParams; + phNfc_sData_t sValueBuffer; + uint32_t offset = 0; + uint8_t version = PHFRINFC_LLCP_INVALID_VERSION; + + /* Check for NULL pointers */ + if ((psParamsTLV == NULL) || (psParsedParams == NULL) || (pnParsedVersion == NULL)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Prepare default param structure */ + sParams.miu = PHFRINFC_LLCP_MIU_DEFAULT; + sParams.wks = PHFRINFC_LLCP_WKS_DEFAULT; + sParams.lto = PHFRINFC_LLCP_LTO_DEFAULT; + sParams.option = PHFRINFC_LLCP_OPTION_DEFAULT; + + /* Decode TLV */ + while (offset < psParamsTLV->length) + { + status = phFriNfc_Llcp_DecodeTLV(psParamsTLV, &offset, &type, &sValueBuffer); + if (status != NFCSTATUS_SUCCESS) + { + /* Error: Ill-formed TLV */ + return status; + } + switch(type) + { + case PHFRINFC_LLCP_TLV_TYPE_VERSION: + { + /* Check length */ + if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_VERSION) + { + /* Error : Ill-formed VERSION parameter TLV */ + break; + } + /* Get VERSION */ + version = sValueBuffer.buffer[0]; + break; + } + case PHFRINFC_LLCP_TLV_TYPE_MIUX: + { + /* Check length */ + if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_MIUX) + { + /* Error : Ill-formed MIUX parameter TLV */ + break; + } + /* Get MIU */ + sParams.miu = (PHFRINFC_LLCP_MIU_DEFAULT + ((sValueBuffer.buffer[0] << 8) | sValueBuffer.buffer[1])) & PHFRINFC_LLCP_TLV_MIUX_MASK; + break; + } + case PHFRINFC_LLCP_TLV_TYPE_WKS: + { + /* Check length */ + if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_WKS) + { + /* Error : Ill-formed MIUX parameter TLV */ + break; + } + /* Get WKS */ + sParams.wks = (sValueBuffer.buffer[0] << 8) | sValueBuffer.buffer[1]; + /* Ignored bits must always be set */ + sParams.wks |= PHFRINFC_LLCP_TLV_WKS_MASK; + break; + } + case PHFRINFC_LLCP_TLV_TYPE_LTO: + { + /* Check length */ + if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_LTO) + { + /* Error : Ill-formed LTO parameter TLV */ + break; + } + /* Get LTO */ + sParams.lto = sValueBuffer.buffer[0]; + break; + } + case PHFRINFC_LLCP_TLV_TYPE_OPT: + { + /* Check length */ + if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_OPT) + { + /* Error : Ill-formed OPT parameter TLV */ + break;; + } + /* Get OPT */ + sParams.option = sValueBuffer.buffer[0] & PHFRINFC_LLCP_TLV_OPT_MASK; + break; + } + default: + { + /* Error : Unknown Type */ + break; + } + } + } + + /* Check if a VERSION parameter has been provided */ + if (version == PHFRINFC_LLCP_INVALID_VERSION) + { + /* Error : Mandatory VERSION parameter not provided */ + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Save response */ + *pnParsedVersion = version; + memcpy(psParsedParams, &sParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); + + return NFCSTATUS_SUCCESS; +} + + +static NFCSTATUS phFriNfc_Llcp_VersionAgreement( uint8_t localVersion, + uint8_t remoteVersion, + uint8_t *pNegociatedVersion ) +{ + uint8_t localMajor = localVersion & PHFRINFC_LLCP_VERSION_MAJOR_MASK; + uint8_t localMinor = localVersion & PHFRINFC_LLCP_VERSION_MINOR_MASK; + uint8_t remoteMajor = remoteVersion & PHFRINFC_LLCP_VERSION_MAJOR_MASK; + uint8_t remoteMinor = remoteVersion & PHFRINFC_LLCP_VERSION_MINOR_MASK; + uint8_t negociatedVersion; + + /* Check for NULL pointers */ + if (pNegociatedVersion == NULL) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Compare Major numbers */ + if (localMajor == remoteMajor) + { + /* Version agreement succeed : use lowest version */ + negociatedVersion = localMajor | ((remoteMinor remoteMajor) + { + /* Decide if versions are compatible */ + /* Currently, there is no backward compatibility to handle */ + return NFCSTATUS_FAILED; + } + else /* if (localMajor < remoteMajor) */ + { + /* It is up to the remote host to decide if versions are compatible */ + /* Set negociated version to our local version, the remote will + deacivate the link if its own version agreement fails */ + negociatedVersion = localVersion; + } + + /* Save response */ + *pNegociatedVersion = negociatedVersion; + + return NFCSTATUS_SUCCESS; +} + + +static NFCSTATUS phFriNfc_Llcp_InternalActivate( phFriNfc_Llcp_t *Llcp, + phNfc_sData_t *psParamsTLV) +{ + NFCSTATUS status; + phFriNfc_Llcp_sLinkParameters_t sRemoteParams; + uint8_t remoteVersion; + uint8_t negociatedVersion; + const uint16_t nMaxHeaderSize = PHFRINFC_LLCP_PACKET_HEADER_SIZE + + PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE; + + /* Parse parameters */ + status = phFriNfc_Llcp_ParseLinkParams(psParamsTLV, &sRemoteParams, &remoteVersion); + if (status != NFCSTATUS_SUCCESS) + { + /* Error: invalid parameters TLV */ + status = NFCSTATUS_FAILED; + } + else + { + /* Version agreement procedure */ + status = phFriNfc_Llcp_VersionAgreement(PHFRINFC_LLCP_VERSION , remoteVersion, &negociatedVersion); + if (status != NFCSTATUS_SUCCESS) + { + /* Error: version agreement failed */ + status = NFCSTATUS_FAILED; + } + else + { + /* Save parameters */ + Llcp->version = negociatedVersion; + memcpy(&Llcp->sRemoteParams, &sRemoteParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); + + /* Update remote MIU to match local Tx buffer size */ + if (Llcp->nTxBufferLength < (Llcp->sRemoteParams.miu + nMaxHeaderSize)) + { + Llcp->sRemoteParams.miu = Llcp->nTxBufferLength - nMaxHeaderSize; + } + + /* Initiate Symmetry procedure by resetting LTO timer */ + /* NOTE: this also updates current state */ + phFriNfc_Llcp_ResetLTO(Llcp); + } + } + /* Notify upper layer, if Activation failed CB called by Deactivate */ + if (status == NFCSTATUS_SUCCESS) + { + /* Link activated ! */ + Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkActivated); + } + + return status; +} + + +static NFCSTATUS phFriNfc_Llcp_HandleMACLinkActivated( phFriNfc_Llcp_t *Llcp, + phNfc_sData_t *psParamsTLV) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Create the timer */ + Llcp->hSymmTimer = phOsalNfc_Timer_Create(); + if (Llcp->hSymmTimer == PH_OSALNFC_INVALID_TIMER_ID) + { + /* Error: unable to create timer */ + return NFCSTATUS_INSUFFICIENT_RESOURCES; + } + + /* Check if params received from MAC activation procedure */ + if (psParamsTLV == NULL) + { + /* No params with selected MAC mapping, enter PAX mode for parameter exchange */ + Llcp->state = PHFRINFC_LLCP_STATE_PAX; + /* Set default MIU for PAX exchange */ + Llcp->sRemoteParams.miu = PHFRINFC_LLCP_MIU_DEFAULT; + /* If the local device is the initiator, it must initiate PAX exchange */ + if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator) + { + /* Send PAX */ + status = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams); + } + } + else + { + /* Params exchanged during MAX activation, try LLC activation */ + status = phFriNfc_Llcp_InternalActivate(Llcp, psParamsTLV); + } + + if (status == NFCSTATUS_SUCCESS) + { + /* Start listening for incoming packets */ + Llcp->sRxBuffer.length = Llcp->nRxBufferLength; + phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp); + } + + return status; +} + + +static void phFriNfc_Llcp_HandleMACLinkDeactivated( phFriNfc_Llcp_t *Llcp ) +{ + uint8_t state = Llcp->state; + + /* Delete the timer */ + if (Llcp->hSymmTimer != PH_OSALNFC_INVALID_TIMER_ID) + { + phOsalNfc_Timer_Delete(Llcp->hSymmTimer); + } + + /* Reset state */ + Llcp->state = PHFRINFC_LLCP_STATE_RESET_INIT; + + switch (state) + { + case PHFRINFC_LLCP_STATE_DEACTIVATION: + { + /* The service layer has already been notified, nothing more to do */ + break; + } + default: + { + /* Notify service layer of link failure */ + Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkDeactivated); + break; + } + } +} + + +static void phFriNfc_Llcp_ChkLlcp_CB( void *pContext, + NFCSTATUS status ) +{ + /* Get monitor from context */ + phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; + + /* Update state */ + Llcp->state = PHFRINFC_LLCP_STATE_CHECKED; + + /* Invoke callback */ + Llcp->pfChk_CB(Llcp->pChkContext, status); +} + +static void phFriNfc_Llcp_LinkStatus_CB( void *pContext, + phFriNfc_LlcpMac_eLinkStatus_t eLinkStatus, + phNfc_sData_t *psParamsTLV, + phFriNfc_LlcpMac_ePeerType_t PeerRemoteDevType) +{ + NFCSTATUS status; + + /* Get monitor from context */ + phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; + + /* Save the local peer role (initiator/target) */ + Llcp->eRole = PeerRemoteDevType; + + /* Check new link status */ + switch(eLinkStatus) + { + case phFriNfc_LlcpMac_eLinkActivated: + { + /* Handle MAC link activation */ + status = phFriNfc_Llcp_HandleMACLinkActivated(Llcp, psParamsTLV); + if (status != NFCSTATUS_SUCCESS) + { + /* Error: LLC link activation procedure failed, deactivate MAC link */ + status = phFriNfc_Llcp_InternalDeactivate(Llcp); + } + break; + } + case phFriNfc_LlcpMac_eLinkDeactivated: + { + /* Handle MAC link deactivation (cannot fail) */ + phFriNfc_Llcp_HandleMACLinkDeactivated(Llcp); + break; + } + default: + { + /* Warning: Unknown link status, should not happen */ + } + } +} + + +static void phFriNfc_Llcp_ResetLTO( phFriNfc_Llcp_t *Llcp ) +{ + uint32_t nDuration = 0; + uint8_t bIsReset = 0; + + /* Stop timer */ + phOsalNfc_Timer_Stop(Llcp->hSymmTimer); + + + /* Update state */ + if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) + { + Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_SEND; + } + else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) + { + Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_RECV; + } + else if (Llcp->state != PHFRINFC_LLCP_STATE_DEACTIVATION && + Llcp->state != PHFRINFC_LLCP_STATE_RESET_INIT) + { + bIsReset = 1; + /* Not yet in OPERATION state, perform first reset */ + if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator) + { + Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_SEND; + } + else + { + Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_RECV; + } + } + + /* Calculate timer duration */ + /* NOTE: nDuration is in 1/100s, and timer system takes values in 1/1000s */ + if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) + { + /* Response must be received before LTO announced by remote peer */ + nDuration = Llcp->sRemoteParams.lto * 10; + } + else + { + if (bIsReset) + { + /* Immediately bounce SYMM back - it'll take + * a while for the host to come up with something, + * and maybe the remote is faster. + */ + nDuration = 1; + } + else + { + /* Must answer before the local announced LTO */ + /* NOTE: to ensure the answer is completely sent before LTO, the + timer is triggered _before_ LTO expiration */ + /* TODO: make sure time scope is enough, and avoid use of magic number */ + nDuration = (Llcp->sLocalParams.lto * 10) / 2; + } + } + + LLCP_DEBUG("Starting LLCP timer with duration %d", nDuration); + + /* Restart timer */ + phOsalNfc_Timer_Start( + Llcp->hSymmTimer, + nDuration, + phFriNfc_Llcp_Timer_CB, + Llcp); +} + + +static NFCSTATUS phFriNfc_Llcp_HandleLinkPacket( phFriNfc_Llcp_t *Llcp, + phNfc_sData_t *psPacket ) +{ + NFCSTATUS result; + phFriNfc_Llcp_sPacketHeader_t sHeader; + + /* Parse header */ + phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader); + + /* Check packet type */ + switch (sHeader.ptype) + { + case PHFRINFC_LLCP_PTYPE_SYMM: + { + /* Nothing to do, the LTO is handled upon all packet reception */ + result = NFCSTATUS_SUCCESS; + break; + } + + case PHFRINFC_LLCP_PTYPE_AGF: + { + /* Handle the aggregated packet */ + result = phFriNfc_Llcp_HandleAggregatedPacket(Llcp, psPacket); + if (result != NFCSTATUS_SUCCESS) + { + /* Error: invalid info field, dropping frame */ + } + break; + } + + case PHFRINFC_LLCP_PTYPE_DISC: + { + /* Handle link disconnection request */ + result = phFriNfc_Llcp_InternalDeactivate(Llcp); + break; + } + + + case PHFRINFC_LLCP_PTYPE_FRMR: + { + /* TODO: what to do upon reception of FRMR on Link SAP ? */ + result = NFCSTATUS_SUCCESS; + break; + } + + case PHFRINFC_LLCP_PTYPE_PAX: + { + /* Ignore PAX when in Normal Operation */ + result = NFCSTATUS_SUCCESS; + break; + } + + default: + { + /* Error: invalid ptype field, dropping packet */ + result = NFCSTATUS_FAILED; + break; + } + } + + return result; +} + + +static NFCSTATUS phFriNfc_Llcp_HandleTransportPacket( phFriNfc_Llcp_t *Llcp, + phNfc_sData_t *psPacket ) +{ + phFriNfc_Llcp_Recv_CB_t pfRecvCB; + void *pContext; + NFCSTATUS result = NFCSTATUS_SUCCESS; + + /* Forward to upper layer */ + if (Llcp->pfRecvCB != NULL) + { + /* Get callback details */ + pfRecvCB = Llcp->pfRecvCB; + pContext = Llcp->pRecvContext; + /* Reset callback details */ + Llcp->pfRecvCB = NULL; + Llcp->pRecvContext = NULL; + /* Call the callback */ + (pfRecvCB)(pContext, psPacket, NFCSTATUS_SUCCESS); + } + + return result; +} + + +static bool_t phFriNfc_Llcp_HandlePendingSend ( phFriNfc_Llcp_t *Llcp ) +{ + phFriNfc_Llcp_sPacketHeader_t sHeader; + phNfc_sData_t sInfoBuffer; + phFriNfc_Llcp_sPacketHeader_t *psSendHeader = NULL; + phFriNfc_Llcp_sPacketSequence_t *psSendSequence = NULL; + phNfc_sData_t *psSendInfo = NULL; + NFCSTATUS result; + uint8_t bDeallocate = FALSE; + uint8_t return_value = FALSE; + /* Handle pending disconnection request */ + if (Llcp->bDiscPendingFlag == TRUE) + { + /* Last send si acheived, send the pending DISC packet */ + sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; + sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; + sHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC; + /* Set send params */ + psSendHeader = &sHeader; + /* Reset flag */ + Llcp->bDiscPendingFlag = FALSE; + } + /* Handle pending frame reject request */ + else if (Llcp->bFrmrPendingFlag == TRUE) + { + /* Last send si acheived, send the pending FRMR packet */ + sInfoBuffer.buffer = Llcp->pFrmrInfo; + sInfoBuffer.length = sizeof(Llcp->pFrmrInfo); + /* Set send params */ + psSendHeader = &Llcp->sFrmrHeader; + psSendInfo = &sInfoBuffer; + /* Reset flag */ + Llcp->bFrmrPendingFlag = FALSE; + } + /* Handle pending service frame */ + else if (Llcp->pfSendCB != NULL) + { + /* Set send params */ + psSendHeader = Llcp->psSendHeader; + psSendSequence = Llcp->psSendSequence; + psSendInfo = Llcp->psSendInfo; + /* Reset pending send infos */ + Llcp->psSendHeader = NULL; + Llcp->psSendSequence = NULL; + Llcp->psSendInfo = NULL; + bDeallocate = TRUE; + } + + /* Perform send, if needed */ + if (psSendHeader != NULL) + { + result = phFriNfc_Llcp_InternalSend(Llcp, psSendHeader, psSendSequence, psSendInfo); + if ((result != NFCSTATUS_SUCCESS) && (result != NFCSTATUS_PENDING)) + { + /* Error: send failed, impossible to recover */ + phFriNfc_Llcp_InternalDeactivate(Llcp); + } + return_value = TRUE; + } else if (Llcp->pfSendCB == NULL) { + // Nothing to send, send SYMM instead to allow peer to send something + // if it wants. + phFriNfc_Llcp_SendSymm(Llcp); + return_value = TRUE; + } + + if (bDeallocate) + { + phFriNfc_Llcp_Deallocate(psSendInfo); + } + + return return_value; +} + +static NFCSTATUS phFriNfc_Llcp_HandleIncomingPacket( phFriNfc_Llcp_t *Llcp, + phNfc_sData_t *psPacket ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phFriNfc_Llcp_sPacketHeader_t sHeader; + + /* Parse header */ + phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader); + + /* Check destination */ + if (sHeader.dsap == PHFRINFC_LLCP_SAP_LINK) + { + /* Handle packet as destinated to the Link SAP */ + status = phFriNfc_Llcp_HandleLinkPacket(Llcp, psPacket); + } + else if (sHeader.dsap >= PHFRINFC_LLCP_SAP_NUMBER) + { + /* NOTE: this cannot happen since "psHeader->dsap" is only 6-bit wide */ + status = NFCSTATUS_FAILED; + } + else + { + /* Handle packet as destinated to the SDP and transport SAPs */ + status = phFriNfc_Llcp_HandleTransportPacket(Llcp, psPacket); + } + return status; +} + + +static void phFriNfc_Llcp_Receive_CB( void *pContext, + NFCSTATUS status, + phNfc_sData_t *psData) +{ + /* Get monitor from context */ + phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_Llcp_sPacketHeader_t sPacketHeader; + + /* Check reception status and for pending disconnection */ + if ((status != NFCSTATUS_SUCCESS) || (Llcp->bDiscPendingFlag == TRUE)) + { + LLCP_DEBUG("\nReceived LLCP packet error - status = 0x%04x", status); + /* Reset disconnection operation */ + Llcp->bDiscPendingFlag = FALSE; + /* Deactivate the link */ + phFriNfc_Llcp_InternalDeactivate(Llcp); + return; + } + + /* Parse header */ + phFriNfc_Llcp_Buffer2Header(psData->buffer, 0, &sPacketHeader); + + if (sPacketHeader.ptype != PHFRINFC_LLCP_PTYPE_SYMM) + { + LLCP_PRINT_BUFFER("\nReceived LLCP packet :", psData->buffer, psData->length); + } + else + { + LLCP_PRINT("?"); + } + + + /* Check new link status */ + switch(Llcp->state) + { + /* Handle packets in PAX-waiting state */ + case PHFRINFC_LLCP_STATE_PAX: + { + /* Check packet type */ + if (sPacketHeader.ptype == PHFRINFC_LLCP_PTYPE_PAX) + { + /* Params exchanged during MAC activation, try LLC activation */ + result = phFriNfc_Llcp_InternalActivate(Llcp, psData+PHFRINFC_LLCP_PACKET_HEADER_SIZE); + /* If the local LLC is the target, it must answer the PAX */ + if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeTarget) + { + /* Send PAX */ + result = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams); + } + } + else + { + /* Warning: Received packet with unhandled type in PAX-waiting state, drop it */ + } + break; + } + + /* Handle normal operation packets */ + case PHFRINFC_LLCP_STATE_OPERATION_RECV: + case PHFRINFC_LLCP_STATE_OPERATION_SEND: + { + /* Handle Symmetry procedure by resetting LTO timer */ + phFriNfc_Llcp_ResetLTO(Llcp); + /* Handle packet */ + result = phFriNfc_Llcp_HandleIncomingPacket(Llcp, psData); + if ( (result != NFCSTATUS_SUCCESS) && + (result != NFCSTATUS_PENDING) ) + { + /* TODO: Error: invalid frame */ + } + /* Perform pending send request, if any */ + phFriNfc_Llcp_HandlePendingSend(Llcp); + break; + } + + default: + { + /* Warning: Should not receive packets in other states, drop them */ + } + } + + /* Restart reception */ + Llcp->sRxBuffer.length = Llcp->nRxBufferLength; + phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp); +} + + +static void phFriNfc_Llcp_Send_CB( void *pContext, + NFCSTATUS status ) +{ + /* Get monitor from context */ + phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; + phFriNfc_Llcp_Send_CB_t pfSendCB; + void *pSendContext; + + /* Call the upper layer callback if last packet sent was */ + /* NOTE: if Llcp->psSendHeader is not NULL, this means that the send operation is still not initiated */ + if (Llcp->psSendHeader == NULL) + { + if (Llcp->pfSendCB != NULL) + { + /* Get Callback params */ + pfSendCB = Llcp->pfSendCB; + pSendContext = Llcp->pSendContext; + /* Reset callback params */ + Llcp->pfSendCB = NULL; + Llcp->pSendContext = NULL; + /* Call the callback */ + (pfSendCB)(pSendContext, status); + } + } + + /* Check reception status */ + if (status != NFCSTATUS_SUCCESS) + { + /* Error: Reception failed, link must be down */ + phFriNfc_Llcp_InternalDeactivate(Llcp); + } +} + + +static NFCSTATUS phFriNfc_Llcp_InternalSend( phFriNfc_Llcp_t *Llcp, + phFriNfc_Llcp_sPacketHeader_t *psHeader, + phFriNfc_Llcp_sPacketSequence_t *psSequence, + phNfc_sData_t *psInfo ) +{ + NFCSTATUS status; + phNfc_sData_t *psRawPacket = &Llcp->sTxBuffer; /* Use internal Tx buffer */ + + /* Handle Symmetry procedure */ + phFriNfc_Llcp_ResetLTO(Llcp); + + /* Generate raw packet to send (aggregate header + sequence + info fields) */ + psRawPacket->length = 0; + psRawPacket->length += phFriNfc_Llcp_Header2Buffer(psHeader, psRawPacket->buffer, psRawPacket->length); + if (psSequence != NULL) + { + psRawPacket->length += phFriNfc_Llcp_Sequence2Buffer(psSequence, psRawPacket->buffer, psRawPacket->length); + } + if (psInfo != NULL) + { + memcpy(psRawPacket->buffer + psRawPacket->length, psInfo->buffer, psInfo->length); + psRawPacket->length += psInfo->length; + } + + if (psHeader->ptype != PHFRINFC_LLCP_PTYPE_SYMM) + { + LLCP_PRINT_BUFFER("\nSending LLCP packet :", psRawPacket->buffer, psRawPacket->length); + } + else + { + LLCP_PRINT("!"); + } + + /* Send raw packet */ + status = phFriNfc_LlcpMac_Send ( + &Llcp->MAC, + psRawPacket, + phFriNfc_Llcp_Send_CB, + Llcp ); + + return status; +} + +/* ---------------------------- Public functions ------------------------------- */ + +NFCSTATUS phFriNfc_Llcp_EncodeLinkParams( phNfc_sData_t *psRawBuffer, + phFriNfc_Llcp_sLinkParameters_t *psLinkParams, + uint8_t nVersion ) +{ + uint32_t nOffset = 0; + uint16_t miux; + uint16_t wks; + uint8_t pValue[2]; + NFCSTATUS result = NFCSTATUS_SUCCESS; + + /* Check parameters */ + if ((psRawBuffer == NULL) || (psLinkParams == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Encode mandatory VERSION field */ + if (result == NFCSTATUS_SUCCESS) + { + result = phFriNfc_Llcp_EncodeTLV( + psRawBuffer, + &nOffset, + PHFRINFC_LLCP_TLV_TYPE_VERSION, + PHFRINFC_LLCP_TLV_LENGTH_VERSION, + &nVersion); + } + + /* Encode mandatory VERSION field */ + if (result == NFCSTATUS_SUCCESS) + { + /* Encode MIUX field, if needed */ + if (psLinkParams->miu != PHFRINFC_LLCP_MIU_DEFAULT) + { + miux = (psLinkParams->miu - PHFRINFC_LLCP_MIU_DEFAULT) & PHFRINFC_LLCP_TLV_MIUX_MASK; + pValue[0] = (miux >> 8) & 0xFF; + pValue[1] = miux & 0xFF; + result = phFriNfc_Llcp_EncodeTLV( + psRawBuffer, + &nOffset, + PHFRINFC_LLCP_TLV_TYPE_MIUX, + PHFRINFC_LLCP_TLV_LENGTH_MIUX, + pValue); + } + } + + /* Encode WKS field */ + if (result == NFCSTATUS_SUCCESS) + { + wks = psLinkParams->wks | PHFRINFC_LLCP_TLV_WKS_MASK; + pValue[0] = (wks >> 8) & 0xFF; + pValue[1] = wks & 0xFF; + result = phFriNfc_Llcp_EncodeTLV( + psRawBuffer, + &nOffset, + PHFRINFC_LLCP_TLV_TYPE_WKS, + PHFRINFC_LLCP_TLV_LENGTH_WKS, + pValue); + } + + /* Encode LTO field, if needed */ + if (result == NFCSTATUS_SUCCESS) + { + if (psLinkParams->lto != PHFRINFC_LLCP_LTO_DEFAULT) + { + result = phFriNfc_Llcp_EncodeTLV( + psRawBuffer, + &nOffset, + PHFRINFC_LLCP_TLV_TYPE_LTO, + PHFRINFC_LLCP_TLV_LENGTH_LTO, + &psLinkParams->lto); + } + } + + /* Encode OPT field, if needed */ + if (result == NFCSTATUS_SUCCESS) + { + if (psLinkParams->option != PHFRINFC_LLCP_OPTION_DEFAULT) + { + result = phFriNfc_Llcp_EncodeTLV( + psRawBuffer, + &nOffset, + PHFRINFC_LLCP_TLV_TYPE_OPT, + PHFRINFC_LLCP_TLV_LENGTH_OPT, + &psLinkParams->option); + } + } + + if (result != NFCSTATUS_SUCCESS) + { + /* Error: failed to encode TLV */ + return NFCSTATUS_FAILED; + } + + /* Save new buffer size */ + psRawBuffer->length = nOffset; + + return result; +} + + +NFCSTATUS phFriNfc_Llcp_Reset( phFriNfc_Llcp_t *Llcp, + void *LowerDevice, + phFriNfc_Llcp_sLinkParameters_t *psLinkParams, + void *pRxBuffer, + uint16_t nRxBufferLength, + void *pTxBuffer, + uint16_t nTxBufferLength, + phFriNfc_Llcp_LinkStatus_CB_t pfLink_CB, + void *pContext ) +{ + const uint16_t nMaxHeaderSize = PHFRINFC_LLCP_PACKET_HEADER_SIZE + + PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE; + NFCSTATUS result; + + /* Check parameters presence */ + if ((Llcp == NULL) || (LowerDevice == NULL) || (pfLink_CB == NULL) || + (pRxBuffer == NULL) || (pTxBuffer == NULL) ) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check parameters value */ + if (psLinkParams->miu < PHFRINFC_LLCP_MIU_DEFAULT) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check if buffers are large enough to support minimal MIU */ + if ((nRxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) || + (nTxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) ) + { + return NFCSTATUS_BUFFER_TOO_SMALL; + } + + /* Check compatibility between reception buffer size and announced MIU */ + if (nRxBufferLength < (nMaxHeaderSize + psLinkParams->miu)) + { + return NFCSTATUS_BUFFER_TOO_SMALL; + } + + /* Start with a zero-filled monitor */ + memset(Llcp, 0x00, sizeof(phFriNfc_Llcp_t)); + + /* Reset the MAC Mapping layer */ + result = phFriNfc_LlcpMac_Reset(&Llcp->MAC, LowerDevice, phFriNfc_Llcp_LinkStatus_CB, Llcp); + if (result != NFCSTATUS_SUCCESS) { + return result; + } + + /* Save the working buffers */ + Llcp->sRxBuffer.buffer = pRxBuffer; + Llcp->sRxBuffer.length = nRxBufferLength; + Llcp->nRxBufferLength = nRxBufferLength; + Llcp->sTxBuffer.buffer = pTxBuffer; + Llcp->sTxBuffer.length = nTxBufferLength; + Llcp->nTxBufferLength = nTxBufferLength; + + /* Save the link status callback references */ + Llcp->pfLink_CB = pfLink_CB; + Llcp->pLinkContext = pContext; + + /* Save the local link parameters */ + memcpy(&Llcp->sLocalParams, psLinkParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); + + return NFCSTATUS_SUCCESS; +} + + +NFCSTATUS phFriNfc_Llcp_ChkLlcp( phFriNfc_Llcp_t *Llcp, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phFriNfc_Llcp_Check_CB_t pfCheck_CB, + void *pContext ) +{ + /* Check parameters */ + if ( (Llcp == NULL) || (psRemoteDevInfo == NULL) || (pfCheck_CB == NULL) ) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check current state */ + if( Llcp->state != PHFRINFC_LLCP_STATE_RESET_INIT ) { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE); + } + + /* Save the compliance check callback */ + Llcp->pfChk_CB = pfCheck_CB; + Llcp->pChkContext = pContext; + + /* Forward check request to MAC layer */ + return phFriNfc_LlcpMac_ChkLlcp(&Llcp->MAC, psRemoteDevInfo, phFriNfc_Llcp_ChkLlcp_CB, (void*)Llcp); +} + + +NFCSTATUS phFriNfc_Llcp_Activate( phFriNfc_Llcp_t *Llcp ) +{ + /* Check parameters */ + if (Llcp == NULL) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check current state */ + if( Llcp->state != PHFRINFC_LLCP_STATE_CHECKED ) { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE); + } + + /* Update state */ + Llcp->state = PHFRINFC_LLCP_STATE_ACTIVATION; + + /* Reset any headers to send */ + Llcp->psSendHeader = NULL; + Llcp->psSendSequence = NULL; + + /* Forward check request to MAC layer */ + return phFriNfc_LlcpMac_Activate(&Llcp->MAC); +} + + +NFCSTATUS phFriNfc_Llcp_Deactivate( phFriNfc_Llcp_t *Llcp ) +{ + NFCSTATUS status; + + /* Check parameters */ + if (Llcp == NULL) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check current state */ + if( (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_RECV) && + (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) ) { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE); + } + + /* Send DISC packet */ + status = phFriNfc_Llcp_SendDisconnect(Llcp); + if (status == NFCSTATUS_PENDING) + { + /* Wait for packet to be sent before deactivate link */ + return status; + } + + /* Perform actual deactivation */ + return phFriNfc_Llcp_InternalDeactivate(Llcp); +} + + +NFCSTATUS phFriNfc_Llcp_GetLocalInfo( phFriNfc_Llcp_t *Llcp, + phFriNfc_Llcp_sLinkParameters_t *pParams ) +{ + /* Check parameters */ + if ((Llcp == NULL) || (pParams == NULL)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Copy response */ + memcpy(pParams, &Llcp->sLocalParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); + + return NFCSTATUS_SUCCESS; +} + + +NFCSTATUS phFriNfc_Llcp_GetRemoteInfo( phFriNfc_Llcp_t *Llcp, + phFriNfc_Llcp_sLinkParameters_t *pParams ) +{ + /* Check parameters */ + if ((Llcp == NULL) || (pParams == NULL)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Copy response */ + memcpy(pParams, &Llcp->sRemoteParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); + + return NFCSTATUS_SUCCESS; +} + + +NFCSTATUS phFriNfc_Llcp_Send( phFriNfc_Llcp_t *Llcp, + phFriNfc_Llcp_sPacketHeader_t *psHeader, + phFriNfc_Llcp_sPacketSequence_t *psSequence, + phNfc_sData_t *psInfo, + phFriNfc_Llcp_Send_CB_t pfSend_CB, + void *pContext ) +{ + NFCSTATUS result; + /* Check parameters */ + if ((Llcp == NULL) || (psHeader == NULL) || (pfSend_CB == NULL)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check if previous phFriNfc_Llcp_Send() has finished */ + if (Llcp->pfSendCB != NULL) + { + /* Error: a send operation is already running */ + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED); + } + + /* Save the callback parameters */ + Llcp->pfSendCB = pfSend_CB; + Llcp->pSendContext = pContext; + + if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) + { + /* Ready to send */ + result = phFriNfc_Llcp_InternalSend(Llcp, psHeader, psSequence, psInfo); + } + else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) + { + /* Not ready to send, save send params for later use */ + Llcp->psSendHeader = psHeader; + Llcp->psSendSequence = psSequence; + Llcp->psSendInfo = phFriNfc_Llcp_AllocateAndCopy(psInfo); + result = NFCSTATUS_PENDING; + } + else + { + /* Incorrect state for sending ! */ + result = PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);; + } + + if (result != NFCSTATUS_PENDING) { + Llcp->pfSendCB = NULL; + } + return result; +} + + +NFCSTATUS phFriNfc_Llcp_Recv( phFriNfc_Llcp_t *Llcp, + phFriNfc_Llcp_Recv_CB_t pfRecv_CB, + void *pContext ) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + + /* Check parameters */ + if ((Llcp == NULL) || (pfRecv_CB == NULL)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check if previous phFriNfc_Llcp_Recv() has finished */ + if (Llcp->pfRecvCB != NULL) + { + /* Error: a send operation is already running */ + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED); + } + + /* Save the callback parameters */ + Llcp->pfRecvCB = pfRecv_CB; + Llcp->pRecvContext = pContext; + + /* NOTE: nothing more to do, the receive function is called in background */ + + return result; +} diff --git a/libnfc-nxp/phFriNfc_Llcp.h b/libnfc-nxp/phFriNfc_Llcp.h new file mode 100644 index 0000000..728697f --- /dev/null +++ b/libnfc-nxp/phFriNfc_Llcp.h @@ -0,0 +1,463 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_Llcp.h + * \brief NFC LLCP core + * + * Project: NFC-FRI + * + */ + +#ifndef PHFRINFC_LLCP_H +#define PHFRINFC_LLCP_H + +/*include files*/ +#include +#include +#include +#include + +#include + +/** + * \name NFC Forum Logical Link Control Protocol + * + * File: \ref phFriNfc_Llcp.h + * + */ + + +/** \defgroup grp_fri_nfc_llcp NFC Forum Logical Link Control Protocol Component + * + * TODO + * + */ + +/*=========== DEBUG MACROS ===========*/ + +/* LLCP TRACE Macros */ +#if defined(LLCP_TRACE) +#include +#include +extern char phOsalNfc_DbgTraceBuffer[]; +#define LLCP_MAX_TRACE_BUFFER 150 +#define LLCP_PRINT( str ) phOsalNfc_DbgString(str) +#define LLCP_DEBUG(str, arg) \ + { \ + snprintf(phOsalNfc_DbgTraceBuffer,LLCP_MAX_TRACE_BUFFER,str,arg); \ + phOsalNfc_DbgString(phOsalNfc_DbgTraceBuffer); \ + } +#define LLCP_PRINT_BUFFER(msg,buf,len) \ + { \ + snprintf(phOsalNfc_DbgTraceBuffer,LLCP_MAX_TRACE_BUFFER,"\n\t %s:",msg); \ + phOsalNfc_DbgString(phOsalNfc_DbgTraceBuffer); \ + phOsalNfc_DbgTrace(buf,len); \ + phOsalNfc_DbgString("\r"); \ + } +#else +#define LLCP_PRINT( str ) +#define LLCP_DEBUG(str, arg) +#define LLCP_PRINT_BUFFER(msg,buf,len) +#endif + + +/*=========== CONSTANTS ===========*/ + +/** + * \name LLCP local protocol version. + * + */ + /*@{*/ +#define PHFRINFC_LLCP_VERSION_MAJOR 0x01 /**< Major number of local LLCP version.*/ +#define PHFRINFC_LLCP_VERSION_MINOR 0x01 /**< Minor number of local LLCP version.*/ +#define PHFRINFC_LLCP_VERSION ((PHFRINFC_LLCP_VERSION_MAJOR << 4) | PHFRINFC_LLCP_VERSION_MINOR) /**< Local LLCP version.*/ +/*@}*/ + +/** + * \name LLCP packet types. + * + */ + /*@{*/ +#define PHFRINFC_LLCP_PTYPE_SYMM 0x00 /**< Symmetry.*/ +#define PHFRINFC_LLCP_PTYPE_PAX 0x01 /**< PArameter Exchange.*/ +#define PHFRINFC_LLCP_PTYPE_AGF 0x02 /**< AGgregated Frame.*/ +#define PHFRINFC_LLCP_PTYPE_UI 0x03 /**< Unnumbered Information.*/ +#define PHFRINFC_LLCP_PTYPE_CONNECT 0x04 /**< Connect.*/ +#define PHFRINFC_LLCP_PTYPE_DISC 0x05 /**< Disconnect.*/ +#define PHFRINFC_LLCP_PTYPE_CC 0x06 /**< Connection Complete.*/ +#define PHFRINFC_LLCP_PTYPE_DM 0x07 /**< Disconnected Mode.*/ +#define PHFRINFC_LLCP_PTYPE_FRMR 0x08 /**< FRaMe Reject.*/ +#define PHFRINFC_LLCP_PTYPE_SNL 0x09 /**< Service Name Lookup.*/ +#define PHFRINFC_LLCP_PTYPE_RESERVED1 0x0A /**< Reserved.*/ +#define PHFRINFC_LLCP_PTYPE_RESERVED2 0x0B /**< Reserved.*/ +#define PHFRINFC_LLCP_PTYPE_I 0x0C /**< Information.*/ +#define PHFRINFC_LLCP_PTYPE_RR 0x0D /**< Receive Ready.*/ +#define PHFRINFC_LLCP_PTYPE_RNR 0x0E /**< Receive Not Ready.*/ +#define PHFRINFC_LLCP_PTYPE_RESERVED3 0x0F /**< Reserved.*/ +/*@}*/ + +/** + * \name LLCP well-known SAPs. + * + */ + /*@{*/ +#define PHFRINFC_LLCP_SAP_LINK 0x00 /**< Link SAP.*/ +#define PHFRINFC_LLCP_SAP_SDP 0x01 /**< Service Discovery Protocol SAP.*/ +#define PHFRINFC_LLCP_SAP_WKS_FIRST 0x02 /**< Other Well-Known Services defined by the NFC Forum.*/ +#define PHFRINFC_LLCP_SAP_SDP_ADVERTISED_FIRST 0x10 /**< First SAP number from SDP-avertised SAP range.*/ +#define PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST 0x20 /**< First SAP number from SDP-unavertised SAP range.*/ +#define PHFRINFC_LLCP_SAP_NUMBER 0x40 /**< Number of possible SAP values (also first invalid value).*/ +#define PHFRINFC_LLCP_SAP_DEFAULT 0xFF /**< Default number when a socket is created or reset */ +#define PHFRINFC_LLCP_SDP_ADVERTISED_NB 0x10 /**< Number of SDP advertised SAP slots */ +/*@}*/ + +/** + * \name LLCP well-known SAPs. + * + */ + /*@{*/ +#define PHFRINFC_LLCP_SERVICENAME_SDP "urn:nfc:sn:sdp" /**< Service Discovery Protocol name.*/ +/*@}*/ + +/** + * \name Length value for DM opCode + * + */ + /*@{*/ +#define PHFRINFC_LLCP_DM_LENGTH 0x01 /**< Length value for DM opCode */ +/*@}*/ + + +/** + * \internal + * \name Masks used with parameters value. + * + */ +/*@{*/ +#define PHFRINFC_LLCP_TLV_MIUX_MASK 0x07FF /**< \internal Mask to apply to MIUX TLV Value.*/ +#define PHFRINFC_LLCP_TLV_WKS_MASK 0x0001 /**< \internal Minimal bits to be set in WKS TLV Value.*/ +#define PHFRINFC_LLCP_TLV_RW_MASK 0x0F /**< \internal Mask to apply to RW TLV Value.*/ +#define PHFRINFC_LLCP_TLV_OPT_MASK 0x03 /**< \internal Mask to apply to OPT TLV Value.*/ +/*@}*/ + +/** + * \internal + * \name Type codes for parameters in TLV. + * + */ +/*@{*/ +#define PHFRINFC_LLCP_TLV_TYPE_VERSION 0x01 /**< \internal VERSION parameter Type code.*/ +#define PHFRINFC_LLCP_TLV_TYPE_MIUX 0x02 /**< \internal MIUX parameter Type code.*/ +#define PHFRINFC_LLCP_TLV_TYPE_WKS 0x03 /**< \internal WKS parameter Type code.*/ +#define PHFRINFC_LLCP_TLV_TYPE_LTO 0x04 /**< \internal LTO parameter Type code.*/ +#define PHFRINFC_LLCP_TLV_TYPE_RW 0x05 /**< \internal RW parameter Type code.*/ +#define PHFRINFC_LLCP_TLV_TYPE_SN 0x06 /**< \internal SN parameter Type code.*/ +#define PHFRINFC_LLCP_TLV_TYPE_OPT 0x07 /**< \internal OPT parameter Type code.*/ +#define PHFRINFC_LLCP_TLV_TYPE_SDREQ 0x08 /**< \internal SDREQ parameter Type code.*/ +#define PHFRINFC_LLCP_TLV_TYPE_SDRES 0x09 /**< \internal SDRES parameter Type code.*/ +/*@}*/ + +/** + * \internal + * \name Fixed Value length for parameters in TLV. + * + */ +/*@{*/ +#define PHFRINFC_LLCP_TLV_LENGTH_HEADER 2 /**< \internal Fixed length of Type and Length fields in TLV.*/ +#define PHFRINFC_LLCP_TLV_LENGTH_VERSION 1 /**< \internal Fixed length of VERSION parameter Value.*/ +#define PHFRINFC_LLCP_TLV_LENGTH_MIUX 2 /**< \internal Fixed length of MIUX parameter Value.*/ +#define PHFRINFC_LLCP_TLV_LENGTH_WKS 2 /**< \internal Fixed length of WKS parameter Value.*/ +#define PHFRINFC_LLCP_TLV_LENGTH_LTO 1 /**< \internal Fixed length of LTO parameter Value.*/ +#define PHFRINFC_LLCP_TLV_LENGTH_RW 1 /**< \internal Fixed length of RW parameter Value.*/ +#define PHFRINFC_LLCP_TLV_LENGTH_OPT 1 /**< \internal Fixed length of OPT parameter Value.*/ +/*@}*/ + +/** + * \name LLCP packet field sizes. + * + */ + /*@{*/ +#define PHFRINFC_LLCP_PACKET_HEADER_SIZE 2 /**< Size of the general packet header (DSAP+PTYPE+SSAP).*/ +#define PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE 1 /**< Size of the sequence field, if present.*/ +#define PHFRINFC_LLCP_PACKET_MAX_SIZE (PHFRINFC_LLCP_PACKET_HEADER_SIZE + \ + PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE + \ + PHFRINFC_LLCP_MIU_DEFAULT + \ + PHFRINFC_LLCP_TLV_MIUX_MASK) /**< Maximum size of a packet */ +/*@}*/ + +/*========== MACROS ===========*/ + +#define CHECK_SEND_RW(socket) ( (((socket)->socket_VS - (socket)->socket_VSA) % 16) < (socket)->remoteRW ) + +/*========== ENUMERATES ===========*/ + +typedef phFriNfc_LlcpMac_ePeerType_t phFriNfc_Llcp_eRole_t; + +typedef phFriNfc_LlcpMac_eLinkStatus_t phFriNfc_Llcp_eLinkStatus_t; + +/*========== CALLBACKS ===========*/ + +typedef void (*phFriNfc_Llcp_Check_CB_t) ( + void *pContext, + NFCSTATUS status +); + +typedef void (*phFriNfc_Llcp_LinkStatus_CB_t) ( + void *pContext, + phFriNfc_Llcp_eLinkStatus_t eLinkStatus +); + +typedef void (*phFriNfc_Llcp_LinkSend_CB_t) ( + void *pContext, + uint8_t socketIndex, + NFCSTATUS status +); + +typedef void (*phFriNfc_Llcp_Send_CB_t) ( + void *pContext, + NFCSTATUS status +); + +typedef void (*phFriNfc_Llcp_Recv_CB_t) ( + void *pContext, + phNfc_sData_t *psData, + NFCSTATUS status +); + +/*========== STRUCTURES ===========*/ + +typedef struct phFriNfc_Llcp_sPacketHeader +{ + /**< The destination service access point*/ + unsigned dsap : 6; + + /**< The packet type*/ + unsigned ptype : 4; + + /**< The source service access point*/ + unsigned ssap : 6; + +} phFriNfc_Llcp_sPacketHeader_t; + +typedef struct phFriNfc_Llcp_sPacketSequence +{ + /**< Sequence number for sending*/ + unsigned ns : 4; + + /**< Sequence number for reception*/ + unsigned nr : 4; + +} phFriNfc_Llcp_sPacketSequence_t; + +typedef struct phFriNfc_Llcp_sSendOperation +{ + /**< Sequence number for sending*/ + phFriNfc_Llcp_sPacketHeader_t *psHeader; + + /**< Sequence number for sending*/ + phFriNfc_Llcp_sPacketSequence_t *psSequence; + + /**< Sequence number for sending*/ + phNfc_sData_t *psInfo; + + /**< Sequence number for sending*/ + phFriNfc_Llcp_Send_CB_t pfSend_CB; + + /**< Sequence number for sending*/ + void *pContext; + +} phFriNfc_Llcp_sSendOperation_t; + +typedef struct phFriNfc_Llcp_sRecvOperation +{ + /**< Sequence number for sending*/ + uint8_t nSap; + + /**< Sequence number for sending*/ + phNfc_sData_t *psBuffer; + + /**< Sequence number for sending*/ + phFriNfc_Llcp_Recv_CB_t pfRecv_CB; + + /**< Sequence number for sending*/ + void *pContext; + +} phFriNfc_Llcp_sRecvOperation_t; + +typedef struct phFriNfc_Llcp +{ + /**< The current state*/ + uint8_t state; + + /**< MAC mapping instance*/ + phFriNfc_LlcpMac_t MAC; + + /**< Local LLC role*/ + phFriNfc_LlcpMac_ePeerType_t eRole; + + /**< Local link parameters*/ + phFriNfc_Llcp_sLinkParameters_t sLocalParams; + + /**< Remote link parameters*/ + phFriNfc_Llcp_sLinkParameters_t sRemoteParams; + + /**< Negociated protocol version (major number on MSB, minor on LSB)*/ + uint8_t version; + + /**< Internal reception buffer, its size may vary during time but not exceed nRxBufferSize*/ + phNfc_sData_t sRxBuffer; + + /**< Actual size of reception buffer*/ + uint16_t nRxBufferLength; + + /**< Internal emission buffer, its size may vary during time but not exceed nTxBufferSize*/ + phNfc_sData_t sTxBuffer; + + /**< Actual size of emission buffer*/ + uint16_t nTxBufferLength; + + /**< Callback function for link status notification*/ + phFriNfc_Llcp_LinkStatus_CB_t pfLink_CB; + + /**< Callback context for link status notification*/ + void *pLinkContext; + + /**< Callback function for compliance checking*/ + phFriNfc_Llcp_Check_CB_t pfChk_CB; + + /**< Callback context for compliance checking*/ + void *pChkContext; + + /**< Symmetry timer*/ + uint32_t hSymmTimer; + + /**< Control frames buffer*/ + uint8_t pCtrlTxBuffer[10]; + + /**< Control frames buffer size*/ + uint8_t pCtrlTxBufferLength; + + /**< DISC packet send pending flag*/ + bool_t bDiscPendingFlag; + + /**< FRMR packet send pending flag*/ + bool_t bFrmrPendingFlag; + + /**< Header of pending FRMR packet*/ + phFriNfc_Llcp_sPacketHeader_t sFrmrHeader; + + /**< Info field of pending FRMR packet*/ + uint8_t pFrmrInfo[4]; + + /**< Send callback*/ + phFriNfc_Llcp_Send_CB_t pfSendCB; + + /**< Send callback*/ + void *pSendContext; + + /**< Pending send header*/ + phFriNfc_Llcp_sPacketHeader_t *psSendHeader; + + /**< Pending send sequence*/ + phFriNfc_Llcp_sPacketSequence_t *psSendSequence; + + /**< Pending send info*/ + phNfc_sData_t *psSendInfo; + + /**< Receive callback*/ + phFriNfc_Llcp_Recv_CB_t pfRecvCB; + + /**< Receive callback*/ + void *pRecvContext; + +} phFriNfc_Llcp_t; + +/*========== UNIONS ===========*/ + + +/*========== FUNCTIONS ===========*/ + +/*! + * \brief TODO + */ +NFCSTATUS phFriNfc_Llcp_EncodeLinkParams( phNfc_sData_t *psRawBuffer, + phFriNfc_Llcp_sLinkParameters_t *psLinkParams, + uint8_t nVersion ); + + +/*! + * \brief TODO + */ +NFCSTATUS phFriNfc_Llcp_Reset( phFriNfc_Llcp_t *Llcp, + void *LowerDevice, + phFriNfc_Llcp_sLinkParameters_t *psLinkParams, + void *pRxBuffer, + uint16_t nRxBufferLength, + void *pTxBuffer, + uint16_t nTxBufferLength, + phFriNfc_Llcp_LinkStatus_CB_t pfLink_CB, + void *pContext ); + +/*! + * \brief TODO + */ +NFCSTATUS phFriNfc_Llcp_ChkLlcp( phFriNfc_Llcp_t *Llcp, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phFriNfc_Llcp_Check_CB_t pfCheck_CB, + void *pContext ); + +/*! + * \brief TODO + */ +NFCSTATUS phFriNfc_Llcp_Activate( phFriNfc_Llcp_t *Llcp ); + +/*! + * \brief TODO + */ +NFCSTATUS phFriNfc_Llcp_Deactivate( phFriNfc_Llcp_t *Llcp ); + +/*! + * \brief TODO + */ +NFCSTATUS phFriNfc_Llcp_GetLocalInfo( phFriNfc_Llcp_t *Llcp, + phFriNfc_Llcp_sLinkParameters_t *pParams ); + +/*! + * \brief TODO + */ +NFCSTATUS phFriNfc_Llcp_GetRemoteInfo( phFriNfc_Llcp_t *Llcp, + phFriNfc_Llcp_sLinkParameters_t *pParams ); + +/*! + * \brief TODO + */ +NFCSTATUS phFriNfc_Llcp_Send( phFriNfc_Llcp_t *Llcp, + phFriNfc_Llcp_sPacketHeader_t *psHeader, + phFriNfc_Llcp_sPacketSequence_t *psSequence, + phNfc_sData_t *psInfo, + phFriNfc_Llcp_Send_CB_t pfSend_CB, + void *pContext ); + +/*! + * \brief TODO + */ +NFCSTATUS phFriNfc_Llcp_Recv( phFriNfc_Llcp_t *Llcp, + phFriNfc_Llcp_Recv_CB_t pfRecv_CB, + void *pContext ); + + +#endif /* PHFRINFC_LLCP_H */ diff --git a/libnfc-nxp/phFriNfc_LlcpMac.c b/libnfc-nxp/phFriNfc_LlcpMac.c new file mode 100644 index 0000000..e68f5db --- /dev/null +++ b/libnfc-nxp/phFriNfc_LlcpMac.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_LlcpMac.c + * \brief NFC LLCP MAC Mappings For Different RF Technologies. + * + * Project: NFC-FRI + * + */ + + +/*include files*/ +#include +#include +#include +#include +#include + +NFCSTATUS phFriNfc_LlcpMac_Reset (phFriNfc_LlcpMac_t *LlcpMac, + void *LowerDevice, + phFriNfc_LlcpMac_LinkStatus_CB_t LinkStatus_Cb, + void *pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + /* Store the Linkstatus callback function of the upper layer */ + LlcpMac->LinkStatus_Cb = LinkStatus_Cb; + + /* Store a pointer to the upper layer context */ + LlcpMac->LinkStatus_Context = pContext; + + /* Set the LinkStatus variable to the default state */ + LlcpMac->LinkState = phFriNfc_LlcpMac_eLinkDefault; + + /* Store a pointer to the lower layer */ + LlcpMac->LowerDevice = LowerDevice; + + LlcpMac->psRemoteDevInfo = NULL; + LlcpMac->PeerRemoteDevType = 0; + LlcpMac->MacType = 0; + LlcpMac->MacReceive_Cb = NULL; + LlcpMac->MacSend_Cb = NULL; + LlcpMac->psSendBuffer = NULL; + LlcpMac->RecvPending = 0; + LlcpMac->SendPending = 0; + + return status; +} + +NFCSTATUS phFriNfc_LlcpMac_ChkLlcp (phFriNfc_LlcpMac_t *LlcpMac, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phFriNfc_LlcpMac_Chk_CB_t ChkLlcpMac_Cb, + void *pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if (NULL == LlcpMac || NULL == psRemoteDevInfo) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Store the Remote Device info received from Device Discovery */ + LlcpMac->psRemoteDevInfo = psRemoteDevInfo; + + if(LlcpMac->psRemoteDevInfo->RemDevType == phHal_eNfcIP1_Initiator) + { + /* Set the PeerRemoteDevType variable to the Target type */ + LlcpMac->PeerRemoteDevType = phFriNfc_LlcpMac_ePeerTypeTarget; + } + else if(LlcpMac->psRemoteDevInfo->RemDevType == phHal_eNfcIP1_Target) + { + /* Set the PeerRemoteDevType variable to the Initiator type */ + LlcpMac->PeerRemoteDevType = phFriNfc_LlcpMac_ePeerTypeInitiator; + } + + switch(LlcpMac->psRemoteDevInfo->RemDevType) + { + case phHal_eNfcIP1_Initiator: + case phHal_eNfcIP1_Target: + { + /* Set the MAC mapping type detected */ + LlcpMac->MacType = phFriNfc_LlcpMac_eTypeNfcip; + + /* Register the lower layer to the MAC mapping component */ + status = phFriNfc_LlcpMac_Nfcip_Register (LlcpMac); + if(status == NFCSTATUS_SUCCESS) + { + status = LlcpMac->LlcpMacInterface.chk(LlcpMac,ChkLlcpMac_Cb,pContext); + } + else + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_FAILED); + } + }break; + default: + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_DEVICE); + }break; + } + } + + return status; +} + +NFCSTATUS phFriNfc_LlcpMac_Activate (phFriNfc_LlcpMac_t *LlcpMac) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if(LlcpMac->LlcpMacInterface.activate == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = LlcpMac->LlcpMacInterface.activate(LlcpMac); + } + return status; +} + +NFCSTATUS phFriNfc_LlcpMac_Deactivate (phFriNfc_LlcpMac_t *LlcpMac) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if(LlcpMac->LlcpMacInterface.deactivate == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = LlcpMac->LlcpMacInterface.deactivate(LlcpMac); + } + return status; +} + +NFCSTATUS phFriNfc_LlcpMac_Send (phFriNfc_LlcpMac_t *LlcpMac, + phNfc_sData_t *psData, + phFriNfc_LlcpMac_Send_CB_t LlcpMacSend_Cb, + void *pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if(NULL== LlcpMac->LlcpMacInterface.send || NULL==psData || NULL==LlcpMacSend_Cb || NULL==pContext) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = LlcpMac->LlcpMacInterface.send(LlcpMac,psData,LlcpMacSend_Cb,pContext); + } + return status; +} + +NFCSTATUS phFriNfc_LlcpMac_Receive (phFriNfc_LlcpMac_t *LlcpMac, + phNfc_sData_t *psData, + phFriNfc_LlcpMac_Reveive_CB_t ReceiveLlcpMac_Cb, + void *pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if(LlcpMac->LlcpMacInterface.receive == NULL || NULL==psData || NULL==ReceiveLlcpMac_Cb || NULL==pContext) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = LlcpMac->LlcpMacInterface.receive(LlcpMac,psData,ReceiveLlcpMac_Cb,pContext); + } + return status; + +} + + diff --git a/libnfc-nxp/phFriNfc_LlcpMac.h b/libnfc-nxp/phFriNfc_LlcpMac.h new file mode 100644 index 0000000..8cd4373 --- /dev/null +++ b/libnfc-nxp/phFriNfc_LlcpMac.h @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/** + * \file phFriNfc_LlcpMac.h + * \brief NFC LLCP MAC Mappings For Different RF Technologies. + * + * Project: NFC-FRI + * + */ + +#ifndef PHFRINFC_LLCPMAC_H +#define PHFRINFC_LLCPMAC_H + + +/*include files*/ +#include +#include +#include +#include + +#include + +/** + * \name LLCP MAC Mapping + * + * File: \ref phFriNfc_LlcpMac.h + * + */ + + +/** \defgroup grp_fri_nfc_llcp_mac LLCP MAC Mapping Component + * + * This component implements the different MAC mapping for a Logical Link Control Protocol communication, + * as defined by the NFC Forum LLCP specifications.\n + * The MAC component handles the mapping for the different technologies supported by LLCP + *..This component provides an API to the upper layer with the following features:\n\n + * - Reset the MAC mapping component + * - \ref phFriNfc_LlcpMac_ChkLlcp + * . + * - Check the LLCP Compliancy + * - \ref phFriNfc_LlcpMac_ChkLlcp + * . + * - Activate the LLCP link + * - \ref phFriNfc_LlcpMac_Activate + * . + * - Deactivate the LLCP link + * - \ref phFriNfc_LlcpMac_Deactivate + * . + * - Register the MAC component Interface with a specific technologie (NFCIP/ISO14443) + * - \ref phFriNfc_LlcpMac_Register + * . + * - Send packets through the LLCP link + * - \ref phFriNfc_LlcpMac_Send + * . + * - Receive packets through the LLCP link + * - \ref phFriNfc_LlcpMac_Receive + * + */ + +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief Declaration of a MAC type + */ +struct phFriNfc_LlcpMac; +typedef struct phFriNfc_LlcpMac phFriNfc_LlcpMac_t; + +/** + * \ingroup grp_fri_nfc_llcp_mac + * + */ +/*========== ENUMERATES ===========*/ + +/* Enum reperesents the different MAC mapping*/ +typedef enum phFriNfc_LlcpMac_eType +{ + phFriNfc_LlcpMac_eTypeNfcip, + phFriNfc_LlcpMac_eTypeIso14443 +}phFriNfc_LlcpMac_eType_t; + +/* Enum reperesents the different Peer type for a LLCP communication*/ +typedef enum phFriNfc_LlcpMac_ePeerType +{ + phFriNfc_LlcpMac_ePeerTypeInitiator, + phFriNfc_LlcpMac_ePeerTypeTarget +}phFriNfc_LlcpMac_ePeerType_t; + + + + + + +/*========== CALLBACKS ===========*/ + +typedef void (*phFriNfc_LlcpMac_Chk_CB_t) (void *pContext, + NFCSTATUS status); + +typedef void (*phFriNfc_LlcpMac_LinkStatus_CB_t) (void *pContext, + phFriNfc_LlcpMac_eLinkStatus_t eLinkStatus, + phNfc_sData_t *psData, + phFriNfc_LlcpMac_ePeerType_t PeerRemoteDevType); + +typedef void (*phFriNfc_LlcpMac_Send_CB_t) (void *pContext, + NFCSTATUS status); + + +typedef void (*phFriNfc_LlcpMac_Reveive_CB_t) (void *pContext, + NFCSTATUS status, + phNfc_sData_t *psData); + + +/*========== FUNCTIONS TYPES ===========*/ + +typedef NFCSTATUS (*pphFriNfcLlpcMac_Chk_t) ( phFriNfc_LlcpMac_t *LlcpMac, + phFriNfc_LlcpMac_Chk_CB_t ChkLlcpMac_Cb, + void *pContext); + +typedef NFCSTATUS (*pphFriNfcLlpcMac_Activate_t) (phFriNfc_LlcpMac_t *LlcpMac); + +typedef NFCSTATUS (*pphFriNfcLlpcMac_Deactivate_t) (phFriNfc_LlcpMac_t *LlcpMac); + +typedef NFCSTATUS (*pphFriNfcLlpcMac_Send_t) (phFriNfc_LlcpMac_t *LlcpMac, + phNfc_sData_t *psData, + phFriNfc_LlcpMac_Send_CB_t LlcpMacSend_Cb, + void *pContext); + +typedef NFCSTATUS (*pphFriNfcLlpcMac_Receive_t) (phFriNfc_LlcpMac_t *LlcpMac, + phNfc_sData_t *psData, + phFriNfc_LlcpMac_Reveive_CB_t LlcpMacReceive_Cb, + void *pContext); + +/*========== STRUCTURES ===========*/ + +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief Generic Interface structure with the Lower Layer + */ +typedef struct phFriNfc_LlcpMac_Interface +{ + pphFriNfcLlpcMac_Chk_t chk; + pphFriNfcLlpcMac_Activate_t activate; + pphFriNfcLlpcMac_Deactivate_t deactivate; + pphFriNfcLlpcMac_Send_t send; + pphFriNfcLlpcMac_Receive_t receive; +} phFriNfc_LlcpMac_Interface_t; + +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief Definition of the MAC type + */ +struct phFriNfc_LlcpMac +{ + phFriNfc_LlcpMac_eLinkStatus_t LinkState; + phHal_sRemoteDevInformation_t *psRemoteDevInfo; + phFriNfc_LlcpMac_LinkStatus_CB_t LinkStatus_Cb; + void *LinkStatus_Context; + phFriNfc_LlcpMac_Interface_t LlcpMacInterface; + phFriNfc_LlcpMac_ePeerType_t PeerRemoteDevType; + phFriNfc_LlcpMac_eType_t MacType; + + /**<\internal Holds the completion routine informations of the Map Layer*/ + phFriNfc_CplRt_t MacCompletionInfo; + void *LowerDevice; + phFriNfc_LlcpMac_Send_CB_t MacSend_Cb; + void *MacSend_Context; + phFriNfc_LlcpMac_Reveive_CB_t MacReceive_Cb; + void *MacReceive_Context; + phNfc_sData_t *psReceiveBuffer; + phNfc_sData_t *psSendBuffer; + phNfc_sData_t sConfigParam; + uint8_t RecvPending; + uint8_t SendPending; + uint8_t RecvStatus; + phHal_uCmdList_t Cmd; + phHal_sDepAdditionalInfo_t psDepAdditionalInfo; +} ; + + +/* +################################################################################ +********************** MAC Interface Function Prototype *********************** +################################################################################ +*/ + +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief + */ +NFCSTATUS phFriNfc_LlcpMac_Reset (phFriNfc_LlcpMac_t *LlcpMac, + void *LowerDevice, + phFriNfc_LlcpMac_LinkStatus_CB_t LinkStatus_Cb, + void *pContext); +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief + */ +NFCSTATUS phFriNfc_LlcpMac_ChkLlcp (phFriNfc_LlcpMac_t *LlcpMac, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phFriNfc_LlcpMac_Chk_CB_t ChkLlcpMac_Cb, + void *pContext); + +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief + */ +NFCSTATUS phFriNfc_LlcpMac_Activate (phFriNfc_LlcpMac_t *LlcpMac); + +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief + */ +NFCSTATUS phFriNfc_LlcpMac_Deactivate (phFriNfc_LlcpMac_t *LlcpMac); + +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief + */ +NFCSTATUS phFriNfc_LlcpMac_Send (phFriNfc_LlcpMac_t *LlcpMac, + phNfc_sData_t *psData, + phFriNfc_LlcpMac_Send_CB_t LlcpMacSend_Cb, + void *pContext); + +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief + */ +NFCSTATUS phFriNfc_LlcpMac_Receive (phFriNfc_LlcpMac_t *LlcpMac, + phNfc_sData_t *psData, + phFriNfc_LlcpMac_Reveive_CB_t ReceiveLlcpMac_Cb, + void *pContext); + +#endif /* PHFRINFC_LLCPMAC_H */ diff --git a/libnfc-nxp/phFriNfc_LlcpMacNfcip.c b/libnfc-nxp/phFriNfc_LlcpMacNfcip.c new file mode 100644 index 0000000..611571a --- /dev/null +++ b/libnfc-nxp/phFriNfc_LlcpMacNfcip.c @@ -0,0 +1,455 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/** + * \file phFriNfc_LlcpMacNfcip.c + * \brief NFC LLCP MAC Mappings For Different RF Technologies. + * + * Project: NFC-FRI + * + */ + + +/*include files*/ +#include +#include +#include +#include +#include +#include + +static NFCSTATUS phFriNfc_LlcpMac_Nfcip_Send(phFriNfc_LlcpMac_t *LlcpMac, + phNfc_sData_t *psData, + phFriNfc_LlcpMac_Send_CB_t LlcpMacSend_Cb, + void *pContext); + + +static void phFriNfc_LlcpMac_Nfcip_TriggerRecvCb(phFriNfc_LlcpMac_t *LlcpMac, + NFCSTATUS status) +{ + phFriNfc_LlcpMac_Reveive_CB_t pfReceiveCB; + void *pReceiveContext; + + if (LlcpMac->MacReceive_Cb != NULL) + { + /* Save callback params */ + pfReceiveCB = LlcpMac->MacReceive_Cb; + pReceiveContext = LlcpMac->MacReceive_Context; + + /* Reset the pointer to the Receive Callback and Context*/ + LlcpMac->MacReceive_Cb = NULL; + LlcpMac->MacReceive_Context = NULL; + + /* Call the receive callback */ + pfReceiveCB(pReceiveContext, status, LlcpMac->psReceiveBuffer); + } +} + +static void phFriNfc_LlcpMac_Nfcip_TriggerSendCb(phFriNfc_LlcpMac_t *LlcpMac, + NFCSTATUS status) +{ + phFriNfc_LlcpMac_Send_CB_t pfSendCB; + void *pSendContext; + + if (LlcpMac->MacSend_Cb != NULL) + { + /* Save context in local variables */ + pfSendCB = LlcpMac->MacSend_Cb; + pSendContext = LlcpMac->MacSend_Context; + + /* Reset the pointer to the Send Callback */ + LlcpMac->MacSend_Cb = NULL; + LlcpMac->MacSend_Context = NULL; + + /* Call Send callback */ + pfSendCB(pSendContext, status); + } +} + +static NFCSTATUS phFriNfc_LlcpMac_Nfcip_Chk(phFriNfc_LlcpMac_t *LlcpMac, + phFriNfc_LlcpMac_Chk_CB_t ChkLlcpMac_Cb, + void *pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t Llcp_Magic_Number[] = {0x46,0x66,0x6D}; + + if(NULL == LlcpMac || NULL == ChkLlcpMac_Cb || NULL == pContext) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = (NFCSTATUS)memcmp(Llcp_Magic_Number,LlcpMac->psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo,3); + if(!status) + { + LlcpMac->sConfigParam.buffer = &LlcpMac->psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo[3] ; + LlcpMac->sConfigParam.length = (LlcpMac->psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo_Length - 3); + status = NFCSTATUS_SUCCESS; + } + else + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_FAILED); + } + ChkLlcpMac_Cb(pContext,status); + } + + return status; +} + +static NFCSTATUS phFriNfc_LlcpMac_Nfcip_Activate (phFriNfc_LlcpMac_t *LlcpMac) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if(LlcpMac == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER); + } + else + { + LlcpMac->LinkState = phFriNfc_LlcpMac_eLinkActivated; + LlcpMac->LinkStatus_Cb(LlcpMac->LinkStatus_Context, + LlcpMac->LinkState, + &LlcpMac->sConfigParam, + LlcpMac->PeerRemoteDevType); + } + + return status; +} + +static NFCSTATUS phFriNfc_LlcpMac_Nfcip_Deactivate (phFriNfc_LlcpMac_t *LlcpMac) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if(NULL == LlcpMac) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Set the flag of LinkStatus to deactivate */ + LlcpMac->LinkState = phFriNfc_LlcpMac_eLinkDeactivated; + + if (LlcpMac->SendPending) + { + /* Reset Flag */ + LlcpMac->SendPending = FALSE; + phFriNfc_LlcpMac_Nfcip_TriggerSendCb(LlcpMac, NFCSTATUS_FAILED); + } + + if (LlcpMac->RecvPending) + { + /* Reset Flag */ + LlcpMac->RecvPending = FALSE; + phFriNfc_LlcpMac_Nfcip_TriggerRecvCb(LlcpMac, NFCSTATUS_FAILED); + } + + LlcpMac->LinkStatus_Cb(LlcpMac->LinkStatus_Context, + LlcpMac->LinkState, + NULL, + LlcpMac->PeerRemoteDevType); + } + + return status; +} + +static void phFriNfc_LlcpMac_Nfcip_Send_Cb(void *pContext, + NFCSTATUS Status) +{ + phFriNfc_LlcpMac_t *LlcpMac = (phFriNfc_LlcpMac_t *)pContext; + +#ifdef LLCP_CHANGES + if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + phLibNfc_Pending_Shutdown(); + Status = NFCSTATUS_SHUTDOWN; + } +#endif /* #ifdef LLCP_CHANGES */ + + /* Reset Send and Receive Flag */ + LlcpMac->SendPending = FALSE; + LlcpMac->RecvPending = FALSE; + + phFriNfc_LlcpMac_Nfcip_TriggerSendCb(LlcpMac, Status); + +} + +static void phFriNfc_LlcpMac_Nfcip_Receive_Cb(void *pContext, + NFCSTATUS Status) +{ + phFriNfc_LlcpMac_t *LlcpMac = (phFriNfc_LlcpMac_t *)pContext; +#ifdef LLCP_CHANGES + + phFriNfc_LlcpMac_Send_CB_t pfSendCB; + void *pSendContext; + + + if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + phLibNfc_Pending_Shutdown(); + Status = NFCSTATUS_SHUTDOWN; + } + + if (NFCSTATUS_SHUTDOWN == Status) + { + /* Save context in local variables */ + pfSendCB = LlcpMac->MacSend_Cb; + pSendContext = LlcpMac->MacSend_Context; + + /* Reset the pointer to the Send Callback */ + LlcpMac->MacSend_Cb = NULL; + LlcpMac->MacSend_Context = NULL; + + /* Reset Send and Receive Flag */ + LlcpMac->SendPending = FALSE; + LlcpMac->RecvPending = FALSE; + } + +#endif /* #ifdef LLCP_CHANGES */ + + phFriNfc_LlcpMac_Nfcip_TriggerRecvCb(LlcpMac, Status); + +#ifdef LLCP_CHANGES + + if (NFCSTATUS_SHUTDOWN == Status) + { + if ((LlcpMac->SendPending) && (NULL != pfSendCB)) + { + pfSendCB(pSendContext, Status); + } + } + else + +#endif /* #ifdef LLCP_CHANGES */ + { + /* Test if a send is pending */ + if(LlcpMac->SendPending) + { + Status = phFriNfc_LlcpMac_Nfcip_Send(LlcpMac,LlcpMac->psSendBuffer,LlcpMac->MacSend_Cb,LlcpMac->MacSend_Context); + } +} +} + +static void phFriNfc_LlcpMac_Nfcip_Transceive_Cb(void *pContext, + NFCSTATUS Status) +{ + phFriNfc_LlcpMac_t *LlcpMac = (phFriNfc_LlcpMac_t *)pContext; + +#ifdef LLCP_CHANGES + if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + phLibNfc_Pending_Shutdown(); + Status = NFCSTATUS_SHUTDOWN; + } +#endif /* #ifdef LLCP_CHANGES */ + + /* Reset Send and Receive Flag */ + LlcpMac->SendPending = FALSE; + LlcpMac->RecvPending = FALSE; + + /* Call the callbacks */ + phFriNfc_LlcpMac_Nfcip_TriggerSendCb(LlcpMac, Status); + phFriNfc_LlcpMac_Nfcip_TriggerRecvCb(LlcpMac, Status); +} + +static NFCSTATUS phFriNfc_LlcpMac_Nfcip_Send(phFriNfc_LlcpMac_t *LlcpMac, + phNfc_sData_t *psData, + phFriNfc_LlcpMac_Send_CB_t LlcpMacSend_Cb, + void *pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if(NULL == LlcpMac || NULL == psData || NULL == LlcpMacSend_Cb || NULL == pContext) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER); + } + else if(LlcpMac->MacSend_Cb != NULL && LlcpMac->PeerRemoteDevType == phFriNfc_LlcpMac_ePeerTypeInitiator) + { + /*Previous callback is pending */ + status = NFCSTATUS_REJECTED; + } + else + { + /* Save the LlcpMacSend_Cb */ + LlcpMac->MacSend_Cb = LlcpMacSend_Cb; + LlcpMac->MacSend_Context = pContext; + + switch(LlcpMac->PeerRemoteDevType) + { + case phFriNfc_LlcpMac_ePeerTypeInitiator: + { + if(LlcpMac->RecvPending) + { + /*set the completion routines for the LLCP Transceive function*/ + LlcpMac->MacCompletionInfo.CompletionRoutine = phFriNfc_LlcpMac_Nfcip_Transceive_Cb; + LlcpMac->MacCompletionInfo.Context = LlcpMac; + + /* set the command type*/ + LlcpMac->Cmd.NfcIP1Cmd = phHal_eNfcIP1_Raw; + + /* set the Additional Info*/ + LlcpMac->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + LlcpMac->psDepAdditionalInfo.DepFlags.NADPresent = 0; + LlcpMac->SendPending = TRUE; + + status = phFriNfc_OvrHal_Transceive(LlcpMac->LowerDevice, + &LlcpMac->MacCompletionInfo, + LlcpMac->psRemoteDevInfo, + LlcpMac->Cmd, + &LlcpMac->psDepAdditionalInfo, + psData->buffer, + (uint16_t)psData->length, + LlcpMac->psReceiveBuffer->buffer, + (uint16_t*)&LlcpMac->psReceiveBuffer->length); + } + else + { + LlcpMac->SendPending = TRUE; + LlcpMac->psSendBuffer = psData; + return status = NFCSTATUS_PENDING; + } + }break; + case phFriNfc_LlcpMac_ePeerTypeTarget: + { + if(!LlcpMac->RecvPending) + { + LlcpMac->SendPending = TRUE; + LlcpMac->psSendBuffer = psData; + return status = NFCSTATUS_PENDING; + } + else + { + /*set the completion routines for the LLCP Send function*/ + LlcpMac->MacCompletionInfo.CompletionRoutine = phFriNfc_LlcpMac_Nfcip_Send_Cb; + LlcpMac->MacCompletionInfo.Context = LlcpMac; + status = phFriNfc_OvrHal_Send(LlcpMac->LowerDevice, + &LlcpMac->MacCompletionInfo, + LlcpMac->psRemoteDevInfo, + psData->buffer, + (uint16_t)psData->length); + } + }break; + default: + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_DEVICE); + }break; + } + } + return status; +} + +static NFCSTATUS phFriNfc_LlcpMac_Nfcip_Receive(phFriNfc_LlcpMac_t *LlcpMac, + phNfc_sData_t *psData, + phFriNfc_LlcpMac_Reveive_CB_t LlcpMacReceive_Cb, + void *pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if(NULL == LlcpMac || NULL==psData || NULL == LlcpMacReceive_Cb || NULL == pContext) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER); + } + else if(LlcpMac->MacReceive_Cb != NULL) + { + /*Previous callback is pending */ + status = NFCSTATUS_REJECTED; + } + else + { + /* Save the LlcpMacReceive_Cb */ + LlcpMac->MacReceive_Cb = LlcpMacReceive_Cb; + LlcpMac->MacReceive_Context = pContext; + + /* Save the pointer to the receive buffer */ + LlcpMac->psReceiveBuffer= psData; + + switch(LlcpMac->PeerRemoteDevType) + { + case phFriNfc_LlcpMac_ePeerTypeInitiator: + { + if(LlcpMac->SendPending) + { + /*set the completion routines for the LLCP Transceive function*/ + LlcpMac->MacCompletionInfo.CompletionRoutine = phFriNfc_LlcpMac_Nfcip_Transceive_Cb; + LlcpMac->MacCompletionInfo.Context = LlcpMac; + /* set the command type*/ + LlcpMac->Cmd.NfcIP1Cmd = phHal_eNfcIP1_Raw; + /* set the Additional Info*/ + LlcpMac->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + LlcpMac->psDepAdditionalInfo.DepFlags.NADPresent = 0; + LlcpMac->RecvPending = TRUE; + + status = phFriNfc_OvrHal_Transceive(LlcpMac->LowerDevice, + &LlcpMac->MacCompletionInfo, + LlcpMac->psRemoteDevInfo, + LlcpMac->Cmd, + &LlcpMac->psDepAdditionalInfo, + LlcpMac->psSendBuffer->buffer, + (uint16_t)LlcpMac->psSendBuffer->length, + psData->buffer, + (uint16_t*)&psData->length); + } + else + { + LlcpMac->RecvPending = TRUE; + return status = NFCSTATUS_PENDING; + } + }break; + case phFriNfc_LlcpMac_ePeerTypeTarget: + { + /*set the completion routines for the LLCP Receive function*/ + LlcpMac->MacCompletionInfo.CompletionRoutine = phFriNfc_LlcpMac_Nfcip_Receive_Cb; + /* save the context of LlcpMacNfcip */ + LlcpMac->MacCompletionInfo.Context = LlcpMac; + LlcpMac->RecvPending = TRUE; + + status = phFriNfc_OvrHal_Receive(LlcpMac->LowerDevice, + &LlcpMac->MacCompletionInfo, + LlcpMac->psRemoteDevInfo, + LlcpMac->psReceiveBuffer->buffer, + (uint16_t*)&LlcpMac->psReceiveBuffer->length); + }break; + default: + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_DEVICE); + }break; + } + } + return status; +} + + +NFCSTATUS phFriNfc_LlcpMac_Nfcip_Register (phFriNfc_LlcpMac_t *LlcpMac) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if(NULL != LlcpMac) + { + LlcpMac->LlcpMacInterface.chk = phFriNfc_LlcpMac_Nfcip_Chk; + LlcpMac->LlcpMacInterface.activate = phFriNfc_LlcpMac_Nfcip_Activate; + LlcpMac->LlcpMacInterface.deactivate = phFriNfc_LlcpMac_Nfcip_Deactivate; + LlcpMac->LlcpMacInterface.send = phFriNfc_LlcpMac_Nfcip_Send; + LlcpMac->LlcpMacInterface.receive = phFriNfc_LlcpMac_Nfcip_Receive; + + return NFCSTATUS_SUCCESS; + } + else + { + return status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_FAILED); + } +} diff --git a/libnfc-nxp/phFriNfc_LlcpMacNfcip.h b/libnfc-nxp/phFriNfc_LlcpMacNfcip.h new file mode 100644 index 0000000..945ddc9 --- /dev/null +++ b/libnfc-nxp/phFriNfc_LlcpMacNfcip.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_LlcpMacNfcip.h + * \brief NFC LLCP MAC Mapping for NFCIP. + * + * Project: NFC-FRI + * + */ + +#ifndef PHFRINFC_LLCPMACNFCIP_H +#define PHFRINFC_LLCPMACNFCIP_H + + +/*include files*/ +#include +#include +#include +#include + +/** + * \name MAC Mapping for NFCIP + * + * File: \ref phFriNfc_LlcpMacNfcip.h + * + */ + + +/** \defgroup grp_fri_nfc_llcp_macnfcip NFCIP MAC Mapping + * + * TODO + * + */ +NFCSTATUS phFriNfc_LlcpMac_Nfcip_Register (phFriNfc_LlcpMac_t *LlcpMac); + +#endif /* PHFRINFC_LLCPMACNFCIP_H */ diff --git a/libnfc-nxp/phFriNfc_LlcpTransport.c b/libnfc-nxp/phFriNfc_LlcpTransport.c new file mode 100644 index 0000000..51f520e --- /dev/null +++ b/libnfc-nxp/phFriNfc_LlcpTransport.c @@ -0,0 +1,2293 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_LlcpTransport.c + * \brief + * + * Project: NFC-FRI + * + */ + +/*include files*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* local macros */ + +/* Check if (a <= x < b) */ +#define IS_BETWEEN(x, a, b) (((x)>=(a)) && ((x)<(b))) + +static NFCSTATUS phFriNfc_LlcpTransport_RegisterName(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + uint8_t nSap, + phNfc_sData_t *psServiceName); + +static NFCSTATUS phFriNfc_LlcpTransport_DiscoverServicesEx(phFriNfc_LlcpTransport_t *psTransport); + +static void phFriNfc_LlcpTransport_Send_CB(void *pContext, + NFCSTATUS status); + +static NFCSTATUS phFriNfc_LlcpTransport_GetFreeSap(phFriNfc_LlcpTransport_t * psTransport, phNfc_sData_t *psServiceName, uint8_t * pnSap) +{ + uint8_t i; + uint8_t sap; + uint8_t min_sap_range, max_sap_range; + phFriNfc_LlcpTransport_Socket_t* pSocketTable = psTransport->pSocketTable; + + /* Calculate authorized SAP range */ + if ((psServiceName != NULL) && (psServiceName->length > 0)) + { + /* Make sure that we will return the same SAP if service name was already used in the past */ + for(i=0 ; ipCachedServiceNames[i].sServiceName.length > 0) && + (memcmp(psTransport->pCachedServiceNames[i].sServiceName.buffer, psServiceName->buffer, psServiceName->length) == 0)) + { + /* Service name matched in cached service names list */ + *pnSap = psTransport->pCachedServiceNames[i].nSap; + return NFCSTATUS_SUCCESS; + } + } + + /* SDP advertised service */ + min_sap_range = PHFRINFC_LLCP_SAP_SDP_ADVERTISED_FIRST; + max_sap_range = PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST; + } + else + { + /* Non-SDP advertised service */ + min_sap_range = PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST; + max_sap_range = PHFRINFC_LLCP_SAP_NUMBER; + } + + /* Try all possible SAPs */ + for(sap=min_sap_range ; sap= phFriNfc_LlcpTransportSocket_eSocketBound) && + (pSocketTable[i].socket_sSap == sap)) + { + /* SAP is already in use */ + break; + } + } + + if (i >= PHFRINFC_LLCP_NB_SOCKET_MAX) + { + /* No socket is using current SAP, proceed with binding */ + *pnSap = sap; + return NFCSTATUS_SUCCESS; + } + } + + /* If we reach this point, it means that no SAP is free */ + return NFCSTATUS_INSUFFICIENT_RESOURCES; +} + +static NFCSTATUS phFriNfc_LlcpTransport_EncodeSdreqTlv(phNfc_sData_t *psTlvData, + uint32_t *pOffset, + uint8_t nTid, + phNfc_sData_t *psServiceName) +{ + NFCSTATUS result; + uint32_t nTlvOffset = *pOffset; + uint32_t nTlvStartOffset = nTlvOffset; + + /* Encode the TID */ + result = phFriNfc_Llcp_EncodeTLV(psTlvData, + &nTlvOffset, + PHFRINFC_LLCP_TLV_TYPE_SDREQ, + 1, + &nTid); + if (result != NFCSTATUS_SUCCESS) + { + goto clean_and_return; + } + + /* Encode the service name itself */ + result = phFriNfc_Llcp_AppendTLV(psTlvData, + nTlvStartOffset, + &nTlvOffset, + psServiceName->length, + psServiceName->buffer); + if (result != NFCSTATUS_SUCCESS) + { + goto clean_and_return; + } + +clean_and_return: + /* Save offset if no error occured */ + if (result == NFCSTATUS_SUCCESS) + { + *pOffset = nTlvOffset; + } + + return result; +} + +static NFCSTATUS phFriNfc_LlcpTransport_EncodeSdresTlv(phNfc_sData_t *psTlvData, + uint32_t *pOffset, + uint8_t nTid, + uint8_t nSap) +{ + NFCSTATUS result; + uint32_t nTlvStartOffset = *pOffset; + + /* Encode the TID */ + result = phFriNfc_Llcp_EncodeTLV(psTlvData, + pOffset, + PHFRINFC_LLCP_TLV_TYPE_SDRES, + 1, + &nTid); + if (result != NFCSTATUS_SUCCESS) + { + goto clean_and_return; + } + + /* Encode the service name itself */ + result = phFriNfc_Llcp_AppendTLV(psTlvData, + nTlvStartOffset, + pOffset, + 1, + &nSap); + if (result != NFCSTATUS_SUCCESS) + { + goto clean_and_return; + } + +clean_and_return: + /* Restore previous offset if an error occured */ + if (result != NFCSTATUS_SUCCESS) + { + *pOffset = nTlvStartOffset; + } + + return result; +} + +static phFriNfc_LlcpTransport_Socket_t* phFriNfc_LlcpTransport_ServiceNameLoockup(phFriNfc_LlcpTransport_t *psTransport, + phNfc_sData_t *pServiceName) +{ + uint32_t index; + uint8_t cacheIndex; + phFriNfc_Llcp_CachedServiceName_t * pCachedServiceName; + phFriNfc_LlcpTransport_Socket_t * pSocket; + + /* Search a socket with the SN */ + for(index=0;indexpSocketTable[index]; + /* Test if the CO socket is in Listen state or the CL socket is bound + and if its SN is the good one */ + if((((pSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionOriented) + && (pSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketRegistered)) + || ((pSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionLess) + && (pSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketBound))) + && + (pServiceName->length == pSocket->sServiceName.length) + && !memcmp(pServiceName->buffer, pSocket->sServiceName.buffer, pServiceName->length)) + { + /* Add new entry to cached service name/sap if not already in table */ + for(cacheIndex=0;cacheIndexpCachedServiceNames[cacheIndex]; + if (pCachedServiceName->sServiceName.buffer != NULL) + { + if ((pCachedServiceName->sServiceName.length == pServiceName->length) && + (memcmp(pCachedServiceName->sServiceName.buffer, pServiceName->buffer, pServiceName->length) == 0)) + { + /* Already registered */ + break; + } + } + else + { + /* Reached end of existing entries and not found the service name, + * => Add the new entry + */ + pCachedServiceName->nSap = pSocket->socket_sSap; + pCachedServiceName->sServiceName.buffer = phOsalNfc_GetMemory(pServiceName->length); + if (pCachedServiceName->sServiceName.buffer == NULL) + { + /* Unable to cache this entry, so report this service as not found */ + return NULL; + } + memcpy(pCachedServiceName->sServiceName.buffer, pServiceName->buffer, pServiceName->length); + pCachedServiceName->sServiceName.length = pServiceName->length; + break; + } + } + + return pSocket; + } + } + + return NULL; +} + + +static NFCSTATUS phFriNfc_LlcpTransport_DiscoveryAnswer(phFriNfc_LlcpTransport_t *psTransport) +{ + NFCSTATUS result = NFCSTATUS_PENDING; + phNfc_sData_t sInfoBuffer; + uint32_t nTlvOffset; + uint8_t index; + uint8_t nTid, nSap; + + /* Test if a send is pending */ + if(!testAndSetSendPending(psTransport)) + { + /* Set the header */ + psTransport->sLlcpHeader.dsap = PHFRINFC_LLCP_SAP_SDP; + psTransport->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_SNL; + psTransport->sLlcpHeader.ssap = PHFRINFC_LLCP_SAP_SDP; + + /* Prepare the info buffer */ + sInfoBuffer.buffer = psTransport->pDiscoveryBuffer; + sInfoBuffer.length = sizeof(psTransport->pDiscoveryBuffer); + + /* Encode as many requests as possible */ + nTlvOffset = 0; + for(index=0 ; indexnDiscoveryResListSize ; index++) + { + /* Get current TID/SAP and try to encode them in SNL frame */ + nTid = psTransport->nDiscoveryResTidList[index]; + nSap = psTransport->nDiscoveryResSapList[index]; + /* Encode response */ + result = phFriNfc_LlcpTransport_EncodeSdresTlv(&sInfoBuffer, + &nTlvOffset, + nTid, + nSap); + if (result != NFCSTATUS_SUCCESS) + { + /* Impossible to fit the entire response */ + /* TODO: support reponse framgentation */ + break; + } + } + + /* Reset list size to be able to handle a new request */ + psTransport->nDiscoveryResListSize = 0; + + /* Update buffer length to match real TLV size */ + sInfoBuffer.length = nTlvOffset; + + /* Send SNL frame */ + result = phFriNfc_Llcp_Send(psTransport->pLlcp, + &psTransport->sLlcpHeader, + NULL, + &sInfoBuffer, + phFriNfc_LlcpTransport_Send_CB, + psTransport); + } + else + { + /* Impossible to send now, this function will be called again on next opportunity */ + } + + return result; +} + + +static void Handle_Discovery_IncomingFrame(phFriNfc_LlcpTransport_t *psTransport, + phNfc_sData_t *psData) +{ + NFCSTATUS result; + phNfc_sData_t sValue; + phNfc_sData_t sResponseData; + phNfc_sData_t sServiceName; + uint32_t nInTlvOffset; + uint8_t nType; + uint8_t nTid; + uint8_t nSap; + pphFriNfc_Cr_t pfSavedCb; + void *pfSavedContext; + phFriNfc_LlcpTransport_Socket_t *pSocket; + + + /* Prepare buffer */ + sResponseData.buffer = psTransport->pDiscoveryBuffer; + sResponseData.length = sizeof(psTransport->pDiscoveryBuffer); + + /* Parse all TLVs in frame */ + nInTlvOffset = 0; + while(nInTlvOffset < psData->length) + { + result = phFriNfc_Llcp_DecodeTLV(psData, + &nInTlvOffset, + &nType, + &sValue ); + switch(nType) + { + case PHFRINFC_LLCP_TLV_TYPE_SDREQ: + if (sValue.length < 2) + { + /* Erroneous request, ignore */ + break; + } + /* Decode TID */ + nTid = sValue.buffer[0]; + /* Decode service name */ + sServiceName.buffer = sValue.buffer + 1; + sServiceName.length = sValue.length - 1; + + /* Handle SDP service name */ + if((sServiceName.length == sizeof(PHFRINFC_LLCP_SERVICENAME_SDP)-1) + && !memcmp(sServiceName.buffer, PHFRINFC_LLCP_SERVICENAME_SDP, sServiceName.length)) + { + nSap = PHFRINFC_LLCP_SAP_SDP; + } + else + { + /* Match service name in socket list */ + pSocket = phFriNfc_LlcpTransport_ServiceNameLoockup(psTransport, &sServiceName); + if (pSocket != NULL) + { + nSap = pSocket->socket_sSap; + } + else + { + nSap = 0; + } + } + + /* Encode response */ + if (psTransport->nDiscoveryResListSize < PHFRINFC_LLCP_SNL_RESPONSE_MAX) + { + psTransport->nDiscoveryResSapList[psTransport->nDiscoveryResListSize] = nSap; + psTransport->nDiscoveryResTidList[psTransport->nDiscoveryResListSize] = nTid; + psTransport->nDiscoveryResListSize++; + } + else + { + /* Remote peer is sending more than max. allowed requests (max. 256 + different TID values), drop invalid requests to avoid buffer overflow + */ + } + break; + + case PHFRINFC_LLCP_TLV_TYPE_SDRES: + if (psTransport->pfDiscover_Cb == NULL) + { + /* Ignore response when no requests are pending */ + break; + } + if (sValue.length != 2) + { + /* Erroneous response, ignore it */ + break; + } + /* Decode TID and SAP */ + nTid = sValue.buffer[0]; + if (nTid >= psTransport->nDiscoveryListSize) + { + /* Unkown TID, ignore it */ + break; + } + nSap = sValue.buffer[1]; + /* Save response */ + psTransport->pnDiscoverySapList[nTid] = nSap; + /* Update response counter */ + psTransport->nDiscoveryResOffset++; + break; + + default: + /* Ignored */ + break; + } + } + + /* If discovery requests have been received, send response */ + if (psTransport->nDiscoveryResListSize > 0) + { + phFriNfc_LlcpTransport_DiscoveryAnswer(psTransport); + } + + /* If all discovery responses have been received, trigger callback (if any) */ + if ((psTransport->pfDiscover_Cb != NULL) && + (psTransport->nDiscoveryResOffset >= psTransport->nDiscoveryListSize)) + { + pfSavedCb = psTransport->pfDiscover_Cb; + pfSavedContext = psTransport->pDiscoverContext; + + psTransport->pfDiscover_Cb = NULL; + psTransport->pDiscoverContext = NULL; + + pfSavedCb(pfSavedContext, NFCSTATUS_SUCCESS); + } +} + + +/* TODO: comment function Transport recv CB */ +static void phFriNfc_LlcpTransport__Recv_CB(void *pContext, + phNfc_sData_t *psData, + NFCSTATUS status) +{ + phFriNfc_Llcp_sPacketHeader_t sLlcpLocalHeader; + uint8_t dsap; + uint8_t ptype; + uint8_t ssap; + + phFriNfc_LlcpTransport_t* pLlcpTransport = (phFriNfc_LlcpTransport_t*)pContext; + + if(status != NFCSTATUS_SUCCESS) + { + pLlcpTransport->LinkStatusError = TRUE; + } + else + { + phFriNfc_Llcp_Buffer2Header( psData->buffer,0x00, &sLlcpLocalHeader); + + dsap = (uint8_t)sLlcpLocalHeader.dsap; + ptype = (uint8_t)sLlcpLocalHeader.ptype; + ssap = (uint8_t)sLlcpLocalHeader.ssap; + + /* Update the length value (without the header length) */ + psData->length = psData->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE; + + /* Update the buffer pointer */ + psData->buffer = psData->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE; + + switch(ptype) + { + /* Connectionless */ + case PHFRINFC_LLCP_PTYPE_UI: + { + Handle_Connectionless_IncommingFrame(pLlcpTransport, + psData, + dsap, + ssap); + }break; + + /* Service Discovery Protocol */ + case PHFRINFC_LLCP_PTYPE_SNL: + { + if ((ssap == PHFRINFC_LLCP_SAP_SDP) && (dsap == PHFRINFC_LLCP_SAP_SDP)) + { + Handle_Discovery_IncomingFrame(pLlcpTransport, + psData); + } + else + { + /* Ignore frame if source and destination are not the SDP service */ + } + }break; + + /* Connection oriented */ + /* NOTE: forward reserved PTYPE to enable FRMR sending */ + case PHFRINFC_LLCP_PTYPE_CONNECT: + case PHFRINFC_LLCP_PTYPE_CC: + case PHFRINFC_LLCP_PTYPE_DISC: + case PHFRINFC_LLCP_PTYPE_DM: + case PHFRINFC_LLCP_PTYPE_I: + case PHFRINFC_LLCP_PTYPE_RR: + case PHFRINFC_LLCP_PTYPE_RNR: + case PHFRINFC_LLCP_PTYPE_FRMR: + case PHFRINFC_LLCP_PTYPE_RESERVED1: + case PHFRINFC_LLCP_PTYPE_RESERVED2: + case PHFRINFC_LLCP_PTYPE_RESERVED3: + { + Handle_ConnectionOriented_IncommingFrame(pLlcpTransport, + psData, + dsap, + ptype, + ssap); + }break; + default: + { + + }break; + } + + /*Restart the Receive Loop */ + status = phFriNfc_Llcp_Recv(pLlcpTransport->pLlcp, + phFriNfc_LlcpTransport__Recv_CB, + pLlcpTransport); + } +} + +bool_t testAndSetSendPending(phFriNfc_LlcpTransport_t* transport) { + bool_t currentValue; + pthread_mutex_lock(&transport->mutex); + currentValue = transport->bSendPending; + transport->bSendPending = TRUE; + pthread_mutex_unlock(&transport->mutex); + return currentValue; +} + +void clearSendPending(phFriNfc_LlcpTransport_t* transport) { + pthread_mutex_lock(&transport->mutex); + transport->bSendPending = FALSE; + pthread_mutex_unlock(&transport->mutex); +} + +/* TODO: comment function Transport recv CB */ +static void phFriNfc_LlcpTransport_Send_CB(void *pContext, + NFCSTATUS status) +{ + phFriNfc_LlcpTransport_t *psTransport = (phFriNfc_LlcpTransport_t*)pContext; + NFCSTATUS result = NFCSTATUS_FAILED; + phNfc_sData_t sFrmrBuffer; + phFriNfc_Llcp_LinkSend_CB_t pfSavedCb; + void *pSavedContext; + phFriNfc_LlcpTransport_Socket_t *pCurrentSocket = NULL; + uint8_t index; + + // Store callbacks and socket index, so they can safely be + // overwritten by any code in the callback itself. + pfSavedCb = psTransport->pfLinkSendCb; + pSavedContext = psTransport->pLinkSendContext; + psTransport->pfLinkSendCb = NULL; + psTransport->pLinkSendContext = NULL; + index = psTransport->socketIndex; + + /* 1 - Reset the FLAG send pending*/ + clearSendPending(psTransport); + + /* 2 - Handle pending error responses */ + if(psTransport->bFrmrPending) + { + if (!testAndSetSendPending(psTransport)) { + /* Reset FRMR pending */ + psTransport->bFrmrPending = FALSE; + + /* Send Frmr */ + sFrmrBuffer.buffer = psTransport->FrmrInfoBuffer; + sFrmrBuffer.length = 0x04; /* Size of FRMR Information field */ + + result = phFriNfc_Llcp_Send(psTransport->pLlcp, + &psTransport->sLlcpHeader, + NULL, + &sFrmrBuffer, + phFriNfc_LlcpTransport_Send_CB, + psTransport); + } + } + else if(psTransport->bDmPending) + { + /* Reset DM pending */ + psTransport->bDmPending = FALSE; + + /* Send DM pending */ + result = phFriNfc_LlcpTransport_SendDisconnectMode(psTransport, + psTransport->DmInfoBuffer[0], + psTransport->DmInfoBuffer[1], + psTransport->DmInfoBuffer[2]); + } + + /* 3 - Call the original callback */ + if (pfSavedCb != NULL) + { + (*pfSavedCb)(pSavedContext, index, status); + } + + + /* 4 - Handle pending send operations */ + + /* Check for pending discovery requests/responses */ + if (psTransport->nDiscoveryResListSize > 0) + { + phFriNfc_LlcpTransport_DiscoveryAnswer(psTransport); + } + if ( (psTransport->pfDiscover_Cb != NULL) && + (psTransport->nDiscoveryReqOffset < psTransport->nDiscoveryListSize) ) + { + result = phFriNfc_LlcpTransport_DiscoverServicesEx(psTransport); + } + + /* Init index */ + index = psTransport->socketIndex; + + /* Check all sockets for pending operation */ + do + { + /* Modulo-increment index */ + index = (index + 1) % PHFRINFC_LLCP_NB_SOCKET_MAX; + + pCurrentSocket = &psTransport->pSocketTable[index]; + + /* Dispatch to the corresponding transport layer */ + if (pCurrentSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionOriented) + { + result = phFriNfc_LlcpTransport_ConnectionOriented_HandlePendingOperations(pCurrentSocket); + } + else if (pCurrentSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionLess) + { + result = phFriNfc_LlcpTransport_Connectionless_HandlePendingOperations(pCurrentSocket); + } + + if (result != NFCSTATUS_FAILED) + { + /* Stop looping if pending operation has been found */ + break; + } + + } while(index != psTransport->socketIndex); +} + + +/* TODO: comment function Transport reset */ +NFCSTATUS phFriNfc_LlcpTransport_Reset (phFriNfc_LlcpTransport_t *pLlcpTransport, + phFriNfc_Llcp_t *pLlcp) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t i; + + /* Check for NULL pointers */ + if(pLlcpTransport == NULL || pLlcp == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Reset Transport structure */ + pLlcpTransport->pLlcp = pLlcp; + pLlcpTransport->LinkStatusError = FALSE; + pLlcpTransport->bSendPending = FALSE; + pLlcpTransport->bRecvPending = FALSE; + pLlcpTransport->bDmPending = FALSE; + pLlcpTransport->bFrmrPending = FALSE; + pLlcpTransport->socketIndex = FALSE; + pLlcpTransport->LinkStatusError = 0; + pLlcpTransport->pfDiscover_Cb = NULL; + + /* Initialize cached service name/sap table */ + memset(pLlcpTransport->pCachedServiceNames, 0x00, sizeof(phFriNfc_Llcp_CachedServiceName_t)*PHFRINFC_LLCP_SDP_ADVERTISED_NB); + + /* Reset all the socket info in the table */ + for(i=0;ipSocketTable[i].eSocket_State = phFriNfc_LlcpTransportSocket_eSocketDefault; + pLlcpTransport->pSocketTable[i].eSocket_Type = phFriNfc_LlcpTransport_eDefaultType; + pLlcpTransport->pSocketTable[i].index = i; + pLlcpTransport->pSocketTable[i].pContext = NULL; + pLlcpTransport->pSocketTable[i].pListenContext = NULL; + pLlcpTransport->pSocketTable[i].pAcceptContext = NULL; + pLlcpTransport->pSocketTable[i].pRejectContext = NULL; + pLlcpTransport->pSocketTable[i].pConnectContext = NULL; + pLlcpTransport->pSocketTable[i].pDisconnectContext = NULL; + pLlcpTransport->pSocketTable[i].pSendContext = NULL; + pLlcpTransport->pSocketTable[i].pRecvContext = NULL; + pLlcpTransport->pSocketTable[i].pSocketErrCb = NULL; + pLlcpTransport->pSocketTable[i].bufferLinearLength = 0; + pLlcpTransport->pSocketTable[i].bufferSendMaxLength = 0; + pLlcpTransport->pSocketTable[i].bufferRwMaxLength = 0; + pLlcpTransport->pSocketTable[i].ReceiverBusyCondition = FALSE; + pLlcpTransport->pSocketTable[i].RemoteBusyConditionInfo = FALSE; + pLlcpTransport->pSocketTable[i].socket_sSap = PHFRINFC_LLCP_SAP_DEFAULT; + pLlcpTransport->pSocketTable[i].socket_dSap = PHFRINFC_LLCP_SAP_DEFAULT; + pLlcpTransport->pSocketTable[i].bSocketRecvPending = FALSE; + pLlcpTransport->pSocketTable[i].bSocketSendPending = FALSE; + pLlcpTransport->pSocketTable[i].bSocketListenPending = FALSE; + pLlcpTransport->pSocketTable[i].bSocketDiscPending = FALSE; + pLlcpTransport->pSocketTable[i].bSocketConnectPending = FALSE; + pLlcpTransport->pSocketTable[i].bSocketAcceptPending = FALSE; + pLlcpTransport->pSocketTable[i].bSocketRRPending = FALSE; + pLlcpTransport->pSocketTable[i].bSocketRNRPending = FALSE; + pLlcpTransport->pSocketTable[i].psTransport = pLlcpTransport; + pLlcpTransport->pSocketTable[i].pfSocketSend_Cb = NULL; + pLlcpTransport->pSocketTable[i].pfSocketRecv_Cb = NULL; + pLlcpTransport->pSocketTable[i].pfSocketRecvFrom_Cb = NULL; + pLlcpTransport->pSocketTable[i].pfSocketListen_Cb = NULL; + pLlcpTransport->pSocketTable[i].pfSocketConnect_Cb = NULL; + pLlcpTransport->pSocketTable[i].pfSocketDisconnect_Cb = NULL; + pLlcpTransport->pSocketTable[i].socket_VS = 0; + pLlcpTransport->pSocketTable[i].socket_VSA = 0; + pLlcpTransport->pSocketTable[i].socket_VR = 0; + pLlcpTransport->pSocketTable[i].socket_VRA = 0; + pLlcpTransport->pSocketTable[i].remoteRW = 0; + pLlcpTransport->pSocketTable[i].localRW = 0; + pLlcpTransport->pSocketTable[i].remoteMIU = 0; + pLlcpTransport->pSocketTable[i].localMIUX = 0; + pLlcpTransport->pSocketTable[i].index = 0; + pLlcpTransport->pSocketTable[i].indexRwRead = 0; + pLlcpTransport->pSocketTable[i].indexRwWrite = 0; + + memset(&pLlcpTransport->pSocketTable[i].sSocketOption, 0x00, sizeof(phFriNfc_LlcpTransport_sSocketOptions_t)); + + if (pLlcpTransport->pSocketTable[i].sServiceName.buffer != NULL) { + phOsalNfc_FreeMemory(pLlcpTransport->pSocketTable[i].sServiceName.buffer); + } + pLlcpTransport->pSocketTable[i].sServiceName.buffer = NULL; + pLlcpTransport->pSocketTable[i].sServiceName.length = 0; + } + + /* Start The Receive Loop */ + status = phFriNfc_Llcp_Recv(pLlcpTransport->pLlcp, + phFriNfc_LlcpTransport__Recv_CB, + pLlcpTransport); + } + return status; +} + +/* TODO: comment function Transport CloseAll */ +NFCSTATUS phFriNfc_LlcpTransport_CloseAll (phFriNfc_LlcpTransport_t *pLlcpTransport) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phFriNfc_Llcp_CachedServiceName_t * pCachedServiceName; + uint8_t i; + + /* Check for NULL pointers */ + if(pLlcpTransport == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + + /* Close all sockets */ + for(i=0;ipSocketTable[i].eSocket_Type == phFriNfc_LlcpTransport_eConnectionOriented) + { + switch(pLlcpTransport->pSocketTable[i].eSocket_State) + { + case phFriNfc_LlcpTransportSocket_eSocketConnected: + case phFriNfc_LlcpTransportSocket_eSocketConnecting: + case phFriNfc_LlcpTransportSocket_eSocketAccepted: + case phFriNfc_LlcpTransportSocket_eSocketDisconnected: + case phFriNfc_LlcpTransportSocket_eSocketDisconnecting: + case phFriNfc_LlcpTransportSocket_eSocketRejected: + phFriNfc_LlcpTransport_Close(&pLlcpTransport->pSocketTable[i]); + break; + default: + /* Do nothing */ + break; + } + } + else + { + phFriNfc_LlcpTransport_Close(&pLlcpTransport->pSocketTable[i]); + } + } + + /* Reset cached service name/sap table */ + for(i=0;ipCachedServiceNames[i]; + + pCachedServiceName->nSap = 0; + if (pCachedServiceName->sServiceName.buffer != NULL) + { + phOsalNfc_FreeMemory(pCachedServiceName->sServiceName.buffer); + pCachedServiceName->sServiceName.buffer = NULL; + } + pCachedServiceName->sServiceName.length = 0; + } + + return status; +} + + +/* TODO: comment function Transport LinkSend */ +NFCSTATUS phFriNfc_LlcpTransport_LinkSend( phFriNfc_LlcpTransport_t *LlcpTransport, + phFriNfc_Llcp_sPacketHeader_t *psHeader, + phFriNfc_Llcp_sPacketSequence_t *psSequence, + phNfc_sData_t *psInfo, + phFriNfc_Llcp_LinkSend_CB_t pfSend_CB, + uint8_t socketIndex, + void *pContext ) +{ + NFCSTATUS status; + /* Check if a send is already ongoing */ + if (LlcpTransport->pfLinkSendCb != NULL) + { + return NFCSTATUS_BUSY; + } + /* Save callback details */ + LlcpTransport->pfLinkSendCb = pfSend_CB; + LlcpTransport->pLinkSendContext = pContext; + LlcpTransport->socketIndex = socketIndex; + + /* Call the link-level send function */ + status = phFriNfc_Llcp_Send(LlcpTransport->pLlcp, psHeader, psSequence, psInfo, phFriNfc_LlcpTransport_Send_CB, (void*)LlcpTransport); + if (status != NFCSTATUS_PENDING && status != NFCSTATUS_SUCCESS) { + // Clear out callbacks + LlcpTransport->pfLinkSendCb = NULL; + LlcpTransport->pLinkSendContext = NULL; + } + return status; +} + + +/* TODO: comment function Transport SendFrameReject */ +NFCSTATUS phFriNfc_LlcpTransport_SendFrameReject(phFriNfc_LlcpTransport_t *psTransport, + uint8_t dsap, + uint8_t rejectedPTYPE, + uint8_t ssap, + phFriNfc_Llcp_sPacketSequence_t* sLlcpSequence, + uint8_t WFlag, + uint8_t IFlag, + uint8_t RFlag, + uint8_t SFlag, + uint8_t vs, + uint8_t vsa, + uint8_t vr, + uint8_t vra) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phNfc_sData_t sFrmrBuffer; + uint8_t flagValue; + uint8_t sequence = 0; + uint8_t index; + uint8_t socketFound = FALSE; + + /* Search a socket waiting for a FRAME */ + for(index=0;indexpSocketTable[index].socket_sSap == dsap + && psTransport->pSocketTable[index].socket_dSap == ssap) + { + /* socket found */ + socketFound = TRUE; + break; + } + } + + /* Test if a socket has been found */ + if(socketFound) + { + /* Set socket state to disconnected */ + psTransport->pSocketTable[index].eSocket_State = phFriNfc_LlcpTransportSocket_eSocketDefault; + + /* Call ErrCB due to a FRMR*/ + psTransport->pSocketTable[index].pSocketErrCb( psTransport->pSocketTable[index].pContext,PHFRINFC_LLCP_ERR_FRAME_REJECTED); + + /* Close the socket */ + status = phFriNfc_LlcpTransport_ConnectionOriented_Close(&psTransport->pSocketTable[index]); + + /* Set FRMR Header */ + psTransport->sLlcpHeader.dsap = ssap; + psTransport->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_FRMR; + psTransport->sLlcpHeader.ssap = dsap; + + /* Set FRMR Information Field */ + flagValue = (WFlag<<7) | (IFlag<<6) | (RFlag<<5) | (SFlag<<4) | rejectedPTYPE; + if (sLlcpSequence != NULL) + { + sequence = (uint8_t)((sLlcpSequence->ns<<4)|(sLlcpSequence->nr)); + } + + psTransport->FrmrInfoBuffer[0] = flagValue; + psTransport->FrmrInfoBuffer[1] = sequence; + psTransport->FrmrInfoBuffer[2] = (vs<<4)|vr ; + psTransport->FrmrInfoBuffer[3] = (vsa<<4)|vra ; + + /* Test if a send is pending */ + if(testAndSetSendPending(psTransport)) + { + psTransport->bFrmrPending = TRUE; + status = NFCSTATUS_PENDING; + } + else + { + sFrmrBuffer.buffer = psTransport->FrmrInfoBuffer; + sFrmrBuffer.length = 0x04; /* Size of FRMR Information field */ + + /* Send FRMR frame */ + status = phFriNfc_Llcp_Send(psTransport->pLlcp, + &psTransport->sLlcpHeader, + NULL, + &sFrmrBuffer, + phFriNfc_LlcpTransport_Send_CB, + psTransport); + } + } + else + { + /* No active socket*/ + /* FRMR Frame not handled*/ + } + return status; +} + + +/* TODO: comment function Transport SendDisconnectMode (NOTE: used only + * for requests not bound to a socket, like "service not found") + */ +NFCSTATUS phFriNfc_LlcpTransport_SendDisconnectMode(phFriNfc_LlcpTransport_t* psTransport, + uint8_t dsap, + uint8_t ssap, + uint8_t dmOpCode) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Test if a send is pending */ + if(testAndSetSendPending(psTransport)) + { + /* DM pending */ + psTransport->bDmPending = TRUE; + + /* Store DM Info */ + psTransport->DmInfoBuffer[0] = dsap; + psTransport->DmInfoBuffer[1] = ssap; + psTransport->DmInfoBuffer[2] = dmOpCode; + + status = NFCSTATUS_PENDING; + } + else + { + /* Set the header */ + psTransport->sDmHeader.dsap = dsap; + psTransport->sDmHeader.ptype = PHFRINFC_LLCP_PTYPE_DM; + psTransport->sDmHeader.ssap = ssap; + + /* Save Operation Code to be provided in DM frame payload */ + psTransport->DmInfoBuffer[2] = dmOpCode; + psTransport->sDmPayload.buffer = &psTransport->DmInfoBuffer[2]; + psTransport->sDmPayload.length = PHFRINFC_LLCP_DM_LENGTH; + + /* Send DM frame */ + status = phFriNfc_Llcp_Send(psTransport->pLlcp, + &psTransport->sDmHeader, + NULL, + &psTransport->sDmPayload, + phFriNfc_LlcpTransport_Send_CB, + psTransport); + } + + return status; +} + + +/** +* \ingroup grp_lib_nfc +* \brief Get the local options of a socket. +* +* This function returns the local options (maximum packet size and receive window size) used +* for a given connection-oriented socket. This function shall not be used with connectionless +* sockets. +* +* \param[out] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psLocalOptions A pointer to be filled with the local options of the socket. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_SocketGetLocalOptions(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + phLibNfc_Llcp_sSocketOptions_t *psLocalOptions) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Check for NULL pointers */ + if (pLlcpSocket == NULL || psLocalOptions == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test the socket type */ + else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test the socket state */ + else if(pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketDefault) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE); + } + else + { + status = phFriNfc_LlcpTransport_ConnectionOriented_SocketGetLocalOptions(pLlcpSocket, + psLocalOptions); + } + + return status; +} + + +/** +* \ingroup grp_lib_nfc +* \brief Get the local options of a socket. +* +* This function returns the remote options (maximum packet size and receive window size) used +* for a given connection-oriented socket. This function shall not be used with connectionless +* sockets. +* +* \param[out] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psRemoteOptions A pointer to be filled with the remote options of the socket. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_SocketGetRemoteOptions(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phLibNfc_Llcp_sSocketOptions_t* psRemoteOptions) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Check for NULL pointers */ + if (pLlcpSocket == NULL || psRemoteOptions == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test the socket type */ + else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test the socket state */ + else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketConnected) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE); + } + else + { + status = phFriNfc_LlcpTransport_ConnectionOriented_SocketGetRemoteOptions(pLlcpSocket, + psRemoteOptions); + } + + return status; +} + + +static NFCSTATUS phFriNfc_LlcpTransport_DiscoverServicesEx(phFriNfc_LlcpTransport_t *psTransport) +{ + NFCSTATUS result = NFCSTATUS_PENDING; + phNfc_sData_t sInfoBuffer; + phNfc_sData_t *psServiceName; + uint32_t nTlvOffset; + + /* Test if a send is pending */ + if(!testAndSetSendPending(psTransport)) + { + /* Set the header */ + psTransport->sLlcpHeader.dsap = PHFRINFC_LLCP_SAP_SDP; + psTransport->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_SNL; + psTransport->sLlcpHeader.ssap = PHFRINFC_LLCP_SAP_SDP; + + /* Prepare the info buffer */ + sInfoBuffer.buffer = psTransport->pDiscoveryBuffer; + sInfoBuffer.length = sizeof(psTransport->pDiscoveryBuffer); + + /* Encode as many requests as possible */ + nTlvOffset = 0; + while(psTransport->nDiscoveryReqOffset < psTransport->nDiscoveryListSize) + { + /* Get current service name and try to encode it in SNL frame */ + psServiceName = &psTransport->psDiscoveryServiceNameList[psTransport->nDiscoveryReqOffset]; + result = phFriNfc_LlcpTransport_EncodeSdreqTlv(&sInfoBuffer, + &nTlvOffset, + psTransport->nDiscoveryReqOffset, + psServiceName); + if (result != NFCSTATUS_SUCCESS) + { + /* Impossible to fit more requests in a single frame, + * will be continued on next opportunity + */ + break; + } + + /* Update request counter */ + psTransport->nDiscoveryReqOffset++; + } + + /* Update buffer length to match real TLV size */ + sInfoBuffer.length = nTlvOffset; + + /* Send SNL frame */ + result = phFriNfc_Llcp_Send(psTransport->pLlcp, + &psTransport->sLlcpHeader, + NULL, + &sInfoBuffer, + phFriNfc_LlcpTransport_Send_CB, + psTransport); + } + else + { + /* Impossible to send now, this function will be called again on next opportunity */ + } + + return result; +} + +/*! +* \ingroup grp_fri_nfc +* \brief Discover remote services SAP using SDP protocol. + */ +NFCSTATUS phFriNfc_LlcpTransport_DiscoverServices( phFriNfc_LlcpTransport_t *pLlcpTransport, + phNfc_sData_t *psServiceNameList, + uint8_t *pnSapList, + uint8_t nListSize, + pphFriNfc_Cr_t pDiscover_Cb, + void *pContext ) +{ + NFCSTATUS result = NFCSTATUS_FAILED; + + /* Save request details */ + pLlcpTransport->psDiscoveryServiceNameList = psServiceNameList; + pLlcpTransport->pnDiscoverySapList = pnSapList; + pLlcpTransport->nDiscoveryListSize = nListSize; + pLlcpTransport->pfDiscover_Cb = pDiscover_Cb; + pLlcpTransport->pDiscoverContext = pContext; + + /* Reset internal counters */ + pLlcpTransport->nDiscoveryReqOffset = 0; + pLlcpTransport->nDiscoveryResOffset = 0; + + /* Perform request */ + result = phFriNfc_LlcpTransport_DiscoverServicesEx(pLlcpTransport); + + return result; +} + + + /** +* \ingroup grp_fri_nfc +* \brief Create a socket on a LLCP-connected device. +* +* This function creates a socket for a given LLCP link. Sockets can be of two types : +* connection-oriented and connectionless. If the socket is connection-oriented, the caller +* must provide a working buffer to the socket in order to handle incoming data. This buffer +* must be large enough to fit the receive window (RW * MIU), the remaining space being +* used as a linear buffer to store incoming data as a stream. Data will be readable later +* using the phLibNfc_LlcpTransport_Recv function. +* The options and working buffer are not required if the socket is used as a listening socket, +* since it cannot be directly used for communication. +* +* \param[in] pLlcpSocketTable A pointer to a table of PHFRINFC_LLCP_NB_SOCKET_DEFAULT sockets. +* \param[in] eType The socket type. +* \param[in] psOptions The options to be used with the socket. +* \param[in] psWorkingBuffer A working buffer to be used by the library. +* \param[out] pLlcpSocket A pointer on the socket to be filled with a + socket found on the socket table. +* \param[in] pErr_Cb The callback to be called each time the socket +* is in error. +* \param[in] pContext Upper layer context to be returned in the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_BUFFER_TOO_SMALL The working buffer is too small for the MIU and RW +* declared in the options. +* \retval NFCSTATUS_INSUFFICIENT_RESOURCES No more socket handle available. +* \retval NFCSTATUS_FAILED Operation failed. +* */ +NFCSTATUS phFriNfc_LlcpTransport_Socket(phFriNfc_LlcpTransport_t *pLlcpTransport, + phFriNfc_LlcpTransport_eSocketType_t eType, + phFriNfc_LlcpTransport_sSocketOptions_t *psOptions, + phNfc_sData_t *psWorkingBuffer, + phFriNfc_LlcpTransport_Socket_t **pLlcpSocket, + pphFriNfc_LlcpTransportSocketErrCb_t pErr_Cb, + void *pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phFriNfc_Llcp_sLinkParameters_t LlcpLinkParamInfo; + uint8_t index=0; + uint8_t cpt; + + /* Check for NULL pointers */ + if ( ((psOptions == NULL) && (eType == phFriNfc_LlcpTransport_eConnectionOriented)) + || ((psWorkingBuffer == NULL) && (eType == phFriNfc_LlcpTransport_eConnectionOriented)) + || (pLlcpSocket == NULL) + || (pErr_Cb == NULL) + || (pContext == NULL) + || (pLlcpTransport == NULL)) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + return status; + } + /* Test the socket type*/ + else if(eType != phFriNfc_LlcpTransport_eConnectionOriented && eType != phFriNfc_LlcpTransport_eConnectionLess) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + return status; + } + /* Connectionless sockets don't support options */ + else if ((psOptions != NULL) && (eType == phFriNfc_LlcpTransport_eConnectionLess)) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + return status; + } + + /* Get the local parameters of the LLCP Link */ + status = phFriNfc_Llcp_GetLocalInfo(pLlcpTransport->pLlcp,&LlcpLinkParamInfo); + if(status != NFCSTATUS_SUCCESS) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_FAILED); + return status; + } + else + { + /* Search a socket free in the Socket Table*/ + do + { + if(pLlcpTransport->pSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketDefault) + { + /* Set the socket pointer to socket of the table */ + *pLlcpSocket = &pLlcpTransport->pSocketTable[index]; + + /* Store the socket info in the socket pointer */ + pLlcpTransport->pSocketTable[index].eSocket_Type = eType; + pLlcpTransport->pSocketTable[index].pSocketErrCb = pErr_Cb; + + /* Store the context of the upper layer */ + pLlcpTransport->pSocketTable[index].pContext = pContext; + + /* Set the pointers to the different working buffers */ + if (eType == phFriNfc_LlcpTransport_eConnectionOriented) + { + /* Test the socket options */ + if (psOptions->rw > PHFRINFC_LLCP_RW_MAX) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + return status; + } + + /* Set socket options */ + memcpy(&pLlcpTransport->pSocketTable[index].sSocketOption, psOptions, sizeof(phFriNfc_LlcpTransport_sSocketOptions_t)); + + /* Set socket local params (MIUX & RW) */ + pLlcpTransport->pSocketTable[index].localMIUX = (pLlcpTransport->pSocketTable[index].sSocketOption.miu - PHFRINFC_LLCP_MIU_DEFAULT) & PHFRINFC_LLCP_TLV_MIUX_MASK; + pLlcpTransport->pSocketTable[index].localRW = pLlcpTransport->pSocketTable[index].sSocketOption.rw & PHFRINFC_LLCP_TLV_RW_MASK; + + /* Set the Max length for the Send and Receive Window Buffer */ + pLlcpTransport->pSocketTable[index].bufferSendMaxLength = pLlcpTransport->pSocketTable[index].sSocketOption.miu; + pLlcpTransport->pSocketTable[index].bufferRwMaxLength = pLlcpTransport->pSocketTable[index].sSocketOption.miu * ((pLlcpTransport->pSocketTable[index].sSocketOption.rw & PHFRINFC_LLCP_TLV_RW_MASK)); + pLlcpTransport->pSocketTable[index].bufferLinearLength = psWorkingBuffer->length - pLlcpTransport->pSocketTable[index].bufferSendMaxLength - pLlcpTransport->pSocketTable[index].bufferRwMaxLength; + + /* Test the connection oriented buffers length */ + if((pLlcpTransport->pSocketTable[index].bufferSendMaxLength + pLlcpTransport->pSocketTable[index].bufferRwMaxLength) > psWorkingBuffer->length + || ((pLlcpTransport->pSocketTable[index].bufferLinearLength < PHFRINFC_LLCP_MIU_DEFAULT) && (pLlcpTransport->pSocketTable[index].bufferLinearLength != 0))) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_BUFFER_TOO_SMALL); + return status; + } + + /* Set the pointer and the length for the Receive Window Buffer */ + for(cpt=0;cptpSocketTable[index].localRW;cpt++) + { + pLlcpTransport->pSocketTable[index].sSocketRwBufferTable[cpt].buffer = psWorkingBuffer->buffer + (cpt*pLlcpTransport->pSocketTable[index].sSocketOption.miu); + pLlcpTransport->pSocketTable[index].sSocketRwBufferTable[cpt].length = 0; + } + + /* Set the pointer and the length for the Send Buffer */ + pLlcpTransport->pSocketTable[index].sSocketSendBuffer.buffer = psWorkingBuffer->buffer + pLlcpTransport->pSocketTable[index].bufferRwMaxLength; + pLlcpTransport->pSocketTable[index].sSocketSendBuffer.length = pLlcpTransport->pSocketTable[index].bufferSendMaxLength; + + /** Set the pointer and the length for the Linear Buffer */ + pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.buffer = psWorkingBuffer->buffer + pLlcpTransport->pSocketTable[index].bufferRwMaxLength + pLlcpTransport->pSocketTable[index].bufferSendMaxLength; + pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.length = pLlcpTransport->pSocketTable[index].bufferLinearLength; + + if(pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.length != 0) + { + /* Init Cyclic Fifo */ + phFriNfc_Llcp_CyclicFifoInit(&pLlcpTransport->pSocketTable[index].sCyclicFifoBuffer, + pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.buffer, + pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.length); + } + } + /* Handle connectionless socket with buffering option */ + else if (eType == phFriNfc_LlcpTransport_eConnectionLess) + { + /* Determine how many packets can be bufferized in working buffer */ + if (psWorkingBuffer != NULL) + { + /* NOTE: the extra byte is used to store SSAP */ + pLlcpTransport->pSocketTable[index].localRW = psWorkingBuffer->length / (pLlcpTransport->pLlcp->sLocalParams.miu + 1); + } + else + { + pLlcpTransport->pSocketTable[index].localRW = 0; + } + + if (pLlcpTransport->pSocketTable[index].localRW > PHFRINFC_LLCP_RW_MAX) + { + pLlcpTransport->pSocketTable[index].localRW = PHFRINFC_LLCP_RW_MAX; + } + + /* Set the pointers and the lengths for buffering */ + for(cpt=0 ; cptpSocketTable[index].localRW ; cpt++) + { + pLlcpTransport->pSocketTable[index].sSocketRwBufferTable[cpt].buffer = psWorkingBuffer->buffer + (cpt*(pLlcpTransport->pLlcp->sLocalParams.miu + 1)); + pLlcpTransport->pSocketTable[index].sSocketRwBufferTable[cpt].length = 0; + } + + /* Set other socket internals */ + pLlcpTransport->pSocketTable[index].indexRwRead = 0; + pLlcpTransport->pSocketTable[index].indexRwWrite = 0; + } + + /* Store index of the socket */ + pLlcpTransport->pSocketTable[index].index = index; + + /* Set the socket into created state */ + pLlcpTransport->pSocketTable[index].eSocket_State = phFriNfc_LlcpTransportSocket_eSocketCreated; + return status; + } + else + { + index++; + } + }while(indexClose a socket on a LLCP-connected device. +* +* This function closes a LLCP socket previously created using phFriNfc_LlcpTransport_Socket. +* If the socket was connected, it is first disconnected, and then closed. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. + +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Close(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Check for NULL pointers */ + if( pLlcpSocket == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + else if(pLlcpSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionOriented) + { + status = phFriNfc_LlcpTransport_ConnectionOriented_Close(pLlcpSocket); + } + else if(pLlcpSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionLess) + { + status = phFriNfc_LlcpTransport_Connectionless_Close(pLlcpSocket); + } + else + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + + return status; +} + +/** +* \ingroup grp_fri_nfc +* \brief Bind a socket to a local SAP. +* +* This function binds the socket to a local Service Access Point. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] nSap The SAP number to bind with, or 0 for auto-bind to a free SAP. +* \param[in] psServiceName A pointer to Service Name, or NULL if no service name. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_ALREADY_REGISTERED The selected SAP is already bound to another + socket. +* \retval NFCSTATUS_FAILED Operation failed. +*/ + +NFCSTATUS phFriNfc_LlcpTransport_Bind(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + uint8_t nSap, + phNfc_sData_t *psServiceName) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t i; + uint8_t min_sap_range; + uint8_t max_sap_range; + + /* Check for NULL pointers */ + if(pLlcpSocket == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketCreated) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE); + } + else + { + /* Calculate authorized SAP range */ + if ((psServiceName != NULL) && (psServiceName->length > 0)) + { + /* SDP advertised service */ + min_sap_range = PHFRINFC_LLCP_SAP_SDP_ADVERTISED_FIRST; + max_sap_range = PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST; + } + else + { + /* Non-SDP advertised service */ + min_sap_range = PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST; + max_sap_range = PHFRINFC_LLCP_SAP_NUMBER; + } + + /* Handle dynamic SAP allocation */ + if (nSap == 0) + { + status = phFriNfc_LlcpTransport_GetFreeSap(pLlcpSocket->psTransport, psServiceName, &nSap); + if (status != NFCSTATUS_SUCCESS) + { + return status; + } + } + + /* Test the SAP range */ + if(!IS_BETWEEN(nSap, min_sap_range, max_sap_range) && + !IS_BETWEEN(nSap, PHFRINFC_LLCP_SAP_WKS_FIRST, PHFRINFC_LLCP_SAP_SDP_ADVERTISED_FIRST)) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Test if the nSap it is used by another socket */ + for(i=0;ipsTransport->pSocketTable[i].socket_sSap == nSap) + { + return status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_ALREADY_REGISTERED); + } + } + /* Set service name */ + status = phFriNfc_LlcpTransport_RegisterName(pLlcpSocket, nSap, psServiceName); + if (status != NFCSTATUS_SUCCESS) + { + return status; + } + /* Set the nSap value of the socket */ + pLlcpSocket->socket_sSap = nSap; + /* Set the socket state */ + pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketBound; + } + } + return status; +} + +/*********************************************/ +/* ConnectionOriented */ +/*********************************************/ + +/** +* \ingroup grp_fri_nfc +* \brief Listen for incoming connection requests on a socket. +* +* This function switches a socket into a listening state and registers a callback on +* incoming connection requests. In this state, the socket is not able to communicate +* directly. The listening state is only available for connection-oriented sockets +* which are still not connected. The socket keeps listening until it is closed, and +* thus can trigger several times the pListen_Cb callback. +* +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] pListen_Cb The callback to be called each time the +* socket receive a connection request. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state to switch +* to listening state. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Listen(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + pphFriNfc_LlcpTransportSocketListenCb_t pListen_Cb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Check for NULL pointers */ + if(pLlcpSocket == NULL || pListen_Cb == NULL|| pContext == NULL ) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Check for socket state */ + else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE); + } + /* Check for socket type */ + else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if a listen is not pending with this socket */ + else if(pLlcpSocket->bSocketListenPending) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = phFriNfc_LlcpTransport_ConnectionOriented_Listen(pLlcpSocket, + pListen_Cb, + pContext); + } + return status; +} + + +/** +* \ingroup grp_fri_nfc +* \brief Register the socket service name. +* +* This function changes the service name of the corresponding socket. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] nSap SAP number associated to the service name. +* \param[in] psServiceName A pointer to a Service Name. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +static NFCSTATUS phFriNfc_LlcpTransport_RegisterName(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + uint8_t nSap, + phNfc_sData_t *psServiceName) +{ + phFriNfc_LlcpTransport_t * psTransport = pLlcpSocket->psTransport; + uint8_t index; + uint8_t bSnMatch, bSapMatch; + + /* Check in cache if sap has been used for different service name */ + for(index=0 ; indexpCachedServiceNames[index].sServiceName.length == 0) + { + /* Reached end of table */ + break; + } + + bSnMatch = (memcmp(psTransport->pCachedServiceNames[index].sServiceName.buffer, psServiceName->buffer, psServiceName->length) == 0); + bSapMatch = psTransport->pCachedServiceNames[index].nSap == nSap; + if(bSnMatch && bSapMatch) + { + /* Request match cache */ + break; + } + else if((bSnMatch && !bSapMatch) || (!bSnMatch && bSapMatch)) + { + /* Request mismatch with cache */ + return NFCSTATUS_INVALID_PARAMETER; + } + } + + /* Handle service with no name */ + if (psServiceName == NULL) + { + if (pLlcpSocket->sServiceName.buffer != NULL) + { + phOsalNfc_FreeMemory(pLlcpSocket->sServiceName.buffer); + } + pLlcpSocket->sServiceName.buffer = NULL; + pLlcpSocket->sServiceName.length = 0; + } + else + { + /* Check if name already in use */ + for(index=0;indexpsTransport->pSocketTable[index]; + + if( (pCurrentSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound) + && (pCurrentSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketRegistered)) + { + /* Only bound or listening sockets may have a service name */ + continue; + } + if(pCurrentSocket->sServiceName.length != psServiceName->length) { + /* Service name do not match, check next */ + continue; + } + if(memcmp(pCurrentSocket->sServiceName.buffer, psServiceName->buffer, psServiceName->length) == 0) + { + /* Service name already in use */ + return NFCSTATUS_INVALID_PARAMETER; + } + } + + /* Store the listen socket SN */ + pLlcpSocket->sServiceName.length = psServiceName->length; + pLlcpSocket->sServiceName.buffer = phOsalNfc_GetMemory(psServiceName->length); + if (pLlcpSocket->sServiceName.buffer == NULL) + { + return NFCSTATUS_NOT_ENOUGH_MEMORY; + } + memcpy(pLlcpSocket->sServiceName.buffer, psServiceName->buffer, psServiceName->length); + } + + return NFCSTATUS_SUCCESS; +} + +/** +* \ingroup grp_fri_nfc +* \brief Accept an incoming connection request for a socket. +* +* This functions allows the client to accept an incoming connection request. +* It must be used with the socket provided within the listen callback. The socket +* is implicitly switched to the connected state when the function is called. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psOptions The options to be used with the socket. +* \param[in] psWorkingBuffer A working buffer to be used by the library. +* \param[in] pErr_Cb The callback to be called each time the accepted socket +* is in error. +* \param[in] pContext Upper layer context to be returned in the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_BUFFER_TOO_SMALL The working buffer is too small for the MIU and RW +* declared in the options. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Accept(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phFriNfc_LlcpTransport_sSocketOptions_t* psOptions, + phNfc_sData_t* psWorkingBuffer, + pphFriNfc_LlcpTransportSocketErrCb_t pErr_Cb, + pphFriNfc_LlcpTransportSocketAcceptCb_t pAccept_RspCb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Check for NULL pointers */ + if(pLlcpSocket == NULL || psOptions == NULL || psWorkingBuffer == NULL || pErr_Cb == NULL || pContext == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Check for socket state */ + else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE); + } + /* Check for socket type */ + else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test the socket options */ + else if(psOptions->rw > PHFRINFC_LLCP_RW_MAX) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Set the Max length for the Send and Receive Window Buffer */ + pLlcpSocket->bufferSendMaxLength = psOptions->miu; + pLlcpSocket->bufferRwMaxLength = psOptions->miu * ((psOptions->rw & PHFRINFC_LLCP_TLV_RW_MASK)); + pLlcpSocket->bufferLinearLength = psWorkingBuffer->length - pLlcpSocket->bufferSendMaxLength - pLlcpSocket->bufferRwMaxLength; + + /* Test the buffers length */ + if((pLlcpSocket->bufferSendMaxLength + pLlcpSocket->bufferRwMaxLength) > psWorkingBuffer->length + || ((pLlcpSocket->bufferLinearLength < PHFRINFC_LLCP_MIU_DEFAULT) && (pLlcpSocket->bufferLinearLength != 0))) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_BUFFER_TOO_SMALL); + } + else + { + pLlcpSocket->psTransport->socketIndex = pLlcpSocket->index; + + status = phFriNfc_LlcpTransport_ConnectionOriented_Accept(pLlcpSocket, + psOptions, + psWorkingBuffer, + pErr_Cb, + pAccept_RspCb, + pContext); + } + } + return status; +} + + /** +* \ingroup grp_fri_nfc +* \brief Reject an incoming connection request for a socket. +* +* This functions allows the client to reject an incoming connection request. +* It must be used with the socket provided within the listen callback. The socket +* is implicitly closed when the function is called. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] pReject_RspCb The callback to be call when the Reject operation is completed +* \param[in] pContext Upper layer context to be returned in the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Reject( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + pphFriNfc_LlcpTransportSocketRejectCb_t pReject_RspCb, + void *pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Check for NULL pointers */ + if(pLlcpSocket == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Check for socket state */ + else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE); + } + /* Check for socket type */ + else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = phLibNfc_LlcpTransport_ConnectionOriented_Reject(pLlcpSocket, + pReject_RspCb, + pContext); + } + + return status; +} + +/** +* \ingroup grp_fri_nfc +* \brief Try to establish connection with a socket on a remote SAP. +* +* This function tries to connect to a given SAP on the remote peer. If the +* socket is not bound to a local SAP, it is implicitly bound to a free SAP. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] nSap The destination SAP to connect to. +* \param[in] pConnect_RspCb The callback to be called when the connection +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Connection operation is in progress, +* pConnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Connect( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + uint8_t nSap, + pphFriNfc_LlcpTransportSocketConnectCb_t pConnect_RspCb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t nLocalSap; + + /* Check for NULL pointers */ + if(pLlcpSocket == NULL || pConnect_RspCb == NULL || pContext == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test the port number value */ + else if(nSap<02 || nSap>63) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is a connectionOriented socket */ + else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket has a service name */ + else if(pLlcpSocket->sServiceName.length != 0) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE); + } + /* Test if the socket is not in connecting or connected state*/ + else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketCreated && pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE); + } + else + { + /* Implicit bind if socket is not already bound */ + if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound) + { + /* Bind to a free sap */ + status = phFriNfc_LlcpTransport_GetFreeSap(pLlcpSocket->psTransport, NULL, &nLocalSap); + if (status != NFCSTATUS_SUCCESS) + { + return status; + } + pLlcpSocket->socket_sSap = nLocalSap; + } + + /* Test the SAP range for non SDP-advertised services */ + if(!IS_BETWEEN(pLlcpSocket->socket_sSap, PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST, PHFRINFC_LLCP_SAP_NUMBER)) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = phFriNfc_LlcpTransport_ConnectionOriented_Connect(pLlcpSocket, + nSap, + NULL, + pConnect_RspCb, + pContext); + } + } + + return status; +} + +/** +* \ingroup grp_fri_nfc +* \brief Try to establish connection with a socket on a remote service, given its URI. +* +* This function tries to connect to a SAP designated by an URI. If the +* socket is not bound to a local SAP, it is implicitly bound to a free SAP. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psUri The URI corresponding to the destination SAP to connect to. +* \param[in] pConnect_RspCb The callback to be called when the connection +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Connection operation is in progress, +* pConnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectByUri(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phNfc_sData_t* psUri, + pphFriNfc_LlcpTransportSocketConnectCb_t pConnect_RspCb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t nLocalSap; + + /* Check for NULL pointers */ + if(pLlcpSocket == NULL || pConnect_RspCb == NULL || pContext == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is a connectionOriented socket */ + else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is not in connect pending or connected state*/ + else if(pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnecting || pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnected) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test the length of the SN */ + else if(psUri->length > PHFRINFC_LLCP_SN_MAX_LENGTH) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Implicit bind if socket is not already bound */ + if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound) + { + /* Bind to a free sap */ + status = phFriNfc_LlcpTransport_GetFreeSap(pLlcpSocket->psTransport, NULL, &nLocalSap); + if (status != NFCSTATUS_SUCCESS) + { + return status; + } + pLlcpSocket->socket_sSap = nLocalSap; + } + + /* Test the SAP range for non SDP-advertised services */ + if(!IS_BETWEEN(pLlcpSocket->socket_sSap, PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST, PHFRINFC_LLCP_SAP_NUMBER)) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = phFriNfc_LlcpTransport_ConnectionOriented_Connect(pLlcpSocket, + PHFRINFC_LLCP_SAP_DEFAULT, + psUri, + pConnect_RspCb, + pContext); + } + } + + return status; +} + +/** +* \ingroup grp_lib_nfc +* \brief Disconnect a currently connected socket. +* +* This function initiates the disconnection of a previously connected socket. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] pDisconnect_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Disconnection operation is in progress, +* pDisconnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Disconnect(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + pphLibNfc_LlcpSocketDisconnectCb_t pDisconnect_RspCb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Check for NULL pointers */ + if(pLlcpSocket == NULL || pDisconnect_RspCb == NULL || pContext == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is a connectionOriented socket */ + else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is connected state*/ + else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketConnected) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = phLibNfc_LlcpTransport_ConnectionOriented_Disconnect(pLlcpSocket, + pDisconnect_RspCb, + pContext); + } + + return status; +} + +/** +* \ingroup grp_fri_nfc +* \brief Send data on a socket. +* +* This function is used to write data on a socket. This function +* can only be called on a connection-oriented socket which is already +* in a connected state. +* +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psBuffer The buffer containing the data to send. +* \param[in] pSend_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pSend_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Send(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Check for NULL pointers */ + if(pLlcpSocket == NULL || psBuffer == NULL || pSend_RspCb == NULL || pContext == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is a connectionOriented socket */ + else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is in connected state */ + else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketConnected) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE); + } + /* Test the length of the buffer */ + else if(psBuffer->length > pLlcpSocket->remoteMIU ) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if a send is pending */ + else if(pLlcpSocket->pfSocketSend_Cb != NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED); + } + else + { + status = phFriNfc_LlcpTransport_ConnectionOriented_Send(pLlcpSocket, + psBuffer, + pSend_RspCb, + pContext); + } + + return status; +} + + /** +* \ingroup grp_fri_nfc +* \brief Read data on a socket. +* +* This function is used to read data from a socket. It reads at most the +* size of the reception buffer, but can also return less bytes if less bytes +* are available. If no data is available, the function will be pending until +* more data comes, and the response will be sent by the callback. This function +* can only be called on a connection-oriented socket. +* +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psBuffer The buffer receiving the data. +* \param[in] pRecv_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pRecv_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Recv( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketRecvCb_t pRecv_RspCb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Check for NULL pointers */ + if(pLlcpSocket == NULL || psBuffer == NULL || pRecv_RspCb == NULL || pContext == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is a connectionOriented socket */ + else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is in connected state */ + else if(pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketDefault) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if a receive is pending */ + else if(pLlcpSocket->bSocketRecvPending == TRUE) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED); + } + else + { + status = phFriNfc_LlcpTransport_ConnectionOriented_Recv(pLlcpSocket, + psBuffer, + pRecv_RspCb, + pContext); + } + + return status; +} + +/*****************************************/ +/* ConnectionLess */ +/*****************************************/ + +/** +* \ingroup grp_fri_nfc +* \brief Send data on a socket to a given destination SAP. +* +* This function is used to write data on a socket to a given destination SAP. +* This function can only be called on a connectionless socket. +* +* +* \param[in] pLlcpSocket A pointer to a LlcpSocket created. +* \param[in] nSap The destination SAP. +* \param[in] psBuffer The buffer containing the data to send. +* \param[in] pSend_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pSend_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_SendTo( phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + uint8_t nSap, + phNfc_sData_t *psBuffer, + pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phFriNfc_Llcp_sLinkParameters_t LlcpRemoteLinkParamInfo; + + if(pLlcpSocket == NULL || psBuffer == NULL || pSend_RspCb == NULL || pContext == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test the port number value */ + else if(nSap<2 || nSap>63) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is a connectionless socket */ + else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionLess) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is in an updated state */ + else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE); + } + /* Test if a send is pending */ + else if(pLlcpSocket->pfSocketSend_Cb != NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED); + } + else + { + /* Get the local parameters of the LLCP Link */ + status = phFriNfc_Llcp_GetRemoteInfo(pLlcpSocket->psTransport->pLlcp,&LlcpRemoteLinkParamInfo); + if(status != NFCSTATUS_SUCCESS) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_FAILED); + } + /* Test the length of the socket buffer for ConnectionLess mode*/ + else if(psBuffer->length > LlcpRemoteLinkParamInfo.miu) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the link is in error state */ + else if(pLlcpSocket->psTransport->LinkStatusError) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED); + } + else + { + status = phFriNfc_LlcpTransport_Connectionless_SendTo(pLlcpSocket, + nSap, + psBuffer, + pSend_RspCb, + pContext); + } + } + + return status; +} + + + /** +* \ingroup grp_lib_nfc +* \brief Read data on a socket and get the source SAP. +* +* This function is the same as phLibNfc_Llcp_Recv, except that the callback includes +* the source SAP. This functions can only be called on a connectionless socket. +* +* +* \param[in] pLlcpSocket A pointer to a LlcpSocket created. +* \param[in] psBuffer The buffer receiving the data. +* \param[in] pRecv_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pRecv_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_RecvFrom( phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketRecvFromCb_t pRecv_Cb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if(pLlcpSocket == NULL || psBuffer == NULL || pRecv_Cb == NULL || pContext == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is a connectionless socket */ + else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionLess) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER); + } + /* Test if the socket is in an updated state */ + else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE); + } + else + { + if(pLlcpSocket->bSocketRecvPending) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED); + } + else + { + status = phLibNfc_LlcpTransport_Connectionless_RecvFrom(pLlcpSocket, + psBuffer, + pRecv_Cb, + pContext); + } + } + + return status; +} diff --git a/libnfc-nxp/phFriNfc_LlcpTransport.h b/libnfc-nxp/phFriNfc_LlcpTransport.h new file mode 100644 index 0000000..2f83439 --- /dev/null +++ b/libnfc-nxp/phFriNfc_LlcpTransport.h @@ -0,0 +1,794 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_LlcpTransport.h + * \brief + * + * Project: NFC-FRI + * + */ + +#ifndef PHFRINFC_LLCP_TRANSPORT_H +#define PHFRINFC_LLCP_TRANSPORT_H +#include +#include +#include +#include +#include +#include +#ifdef ANDROID +#include +#include +#endif + + +typedef uint32_t phFriNfc_Socket_Handle; + +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief Declaration of a TRANSPORT type + */ +struct phFriNfc_LlcpTransport; +typedef struct phFriNfc_LlcpTransport phFriNfc_LlcpTransport_t; + +struct phFriNfc_LlcpTransport_Socket; +typedef struct phFriNfc_LlcpTransport_Socket phFriNfc_LlcpTransport_Socket_t; + +struct phFriNfc_Llcp_CachedServiceName; +typedef struct phFriNfc_Llcp_CachedServiceName phFriNfc_Llcp_CachedServiceName_t; + +/*========== ENUMERATES ===========*/ + +/* Enum reperesents the different LLCP Link status*/ +typedef enum phFriNfc_LlcpTransportSocket_eSocketState +{ + phFriNfc_LlcpTransportSocket_eSocketDefault, + phFriNfc_LlcpTransportSocket_eSocketCreated, + phFriNfc_LlcpTransportSocket_eSocketBound, + phFriNfc_LlcpTransportSocket_eSocketRegistered, + phFriNfc_LlcpTransportSocket_eSocketConnected, + phFriNfc_LlcpTransportSocket_eSocketConnecting, + phFriNfc_LlcpTransportSocket_eSocketAccepted, + phFriNfc_LlcpTransportSocket_eSocketDisconnected, + phFriNfc_LlcpTransportSocket_eSocketDisconnecting, + phFriNfc_LlcpTransportSocket_eSocketRejected, +}phFriNfc_LlcpTransportSocket_eSocketState_t; + + + +/*========== CALLBACKS ===========*/ + +/** +*\ingroup grp_fri_nfc +* +* \brief LLCP socket error notification callback definition +*/ +typedef void (*pphFriNfc_LlcpTransportSocketErrCb_t) ( void* pContext, + uint8_t nErrCode); + + +/** +*\ingroup grp_fri_nfc +* +* \brief LLCP socket listen callback definition +*/ +typedef void (*pphFriNfc_LlcpTransportSocketListenCb_t) (void* pContext, + phFriNfc_LlcpTransport_Socket_t *IncomingSocket); + +/** +*\ingroup grp_fri_nfc +* +* \brief LLCP socket connect callback definition +*/ +typedef void (*pphFriNfc_LlcpTransportSocketConnectCb_t) ( void* pContext, + uint8_t nErrCode, + NFCSTATUS status); + +/** +*\ingroup grp_fri_nfc +* +* \brief LLCP socket disconnect callback definition +*/ +typedef void (*pphFriNfc_LlcpTransportSocketDisconnectCb_t) (void* pContext, + NFCSTATUS status); + +/** +*\ingroup grp_fri_nfc +* +* \brief LLCP socket accept callback definition +*/ +typedef void (*pphFriNfc_LlcpTransportSocketAcceptCb_t) (void* pContext, + NFCSTATUS status); + +/** +*\ingroup grp_fri_nfc +* +* \brief LLCP socket reject callback definition +*/ +typedef void (*pphFriNfc_LlcpTransportSocketRejectCb_t) (void* pContext, + NFCSTATUS status); + +/** +*\ingroup grp_fri_nfc +* +* \brief LLCP socket reception callback definition +*/ +typedef void (*pphFriNfc_LlcpTransportSocketRecvCb_t) (void* pContext, + NFCSTATUS status); + +/** +*\ingroup grp_fri_nfc +* +* \brief LLCP socket reception with SSAP callback definition +*/ +typedef void (*pphFriNfc_LlcpTransportSocketRecvFromCb_t) (void* pContext, + uint8_t ssap, + NFCSTATUS status); + +/** +*\ingroup grp_fri_nfc +* +* \brief LLCP socket emission callback definition +*/ +typedef void (*pphFriNfc_LlcpTransportSocketSendCb_t) (void* pContext, + NFCSTATUS status); + + +/*========== STRUCTURES ===========*/ +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief Declaration of a SOCKET type + */ +struct phFriNfc_LlcpTransport_Socket +{ + phFriNfc_LlcpTransportSocket_eSocketState_t eSocket_State; + phFriNfc_LlcpTransport_eSocketType_t eSocket_Type; + phFriNfc_LlcpTransport_sSocketOptions_t sSocketOption; + pphFriNfc_LlcpTransportSocketErrCb_t pSocketErrCb; + + /* Remote and local socket info */ + uint8_t socket_sSap; + uint8_t socket_dSap; + // TODO: copy service name (could be deallocated by upper layer) + phNfc_sData_t sServiceName; + uint8_t remoteRW; + uint8_t localRW; + uint16_t remoteMIU; + uint16_t localMIUX; + uint8_t index; + + /* SDP related fields */ + uint8_t nTid; + + /* Information Flags */ + bool_t bSocketRecvPending; + bool_t bSocketSendPending; + bool_t bSocketListenPending; + bool_t bSocketDiscPending; + bool_t bSocketConnectPending; + bool_t bSocketAcceptPending; + bool_t bSocketRRPending; + bool_t bSocketRNRPending; + + /* Buffers */ + phNfc_sData_t sSocketSendBuffer; + phNfc_sData_t sSocketLinearBuffer; + phNfc_sData_t* sSocketRecvBuffer; + uint32_t *receivedLength; + uint32_t bufferLinearLength; + uint32_t bufferSendMaxLength; + uint32_t bufferRwMaxLength; + bool_t ReceiverBusyCondition; + bool_t RemoteBusyConditionInfo; + UTIL_FIFO_BUFFER sCyclicFifoBuffer; + uint32_t indexRwRead; + uint32_t indexRwWrite; + + /* Construction Frame */ + phFriNfc_Llcp_sPacketHeader_t sLlcpHeader; + phFriNfc_Llcp_sPacketSequence_t sSequence; + uint8_t socket_VS; + uint8_t socket_VSA; + uint8_t socket_VR; + uint8_t socket_VRA; + + /* Callbacks */ + pphFriNfc_LlcpTransportSocketAcceptCb_t pfSocketAccept_Cb; + pphFriNfc_LlcpTransportSocketSendCb_t pfSocketSend_Cb; + pphFriNfc_LlcpTransportSocketRecvFromCb_t pfSocketRecvFrom_Cb; + pphFriNfc_LlcpTransportSocketRecvCb_t pfSocketRecv_Cb; + pphFriNfc_LlcpTransportSocketListenCb_t pfSocketListen_Cb; + pphFriNfc_LlcpTransportSocketConnectCb_t pfSocketConnect_Cb; + pphFriNfc_LlcpTransportSocketDisconnectCb_t pfSocketDisconnect_Cb; + + /* Table of PHFRINFC_LLCP_RW_MAX Receive Windows Buffers */ + phNfc_sData_t sSocketRwBufferTable[PHFRINFC_LLCP_RW_MAX]; + + /* Pointer a the socket table */ + phFriNfc_LlcpTransport_t *psTransport; + /* Context */ + void *pListenContext; + void *pAcceptContext; + void *pRejectContext; + void *pConnectContext; + void *pDisconnectContext; + void *pSendContext; + void *pRecvContext; + void *pContext; +}; + +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief TODO + */ +struct phFriNfc_Llcp_CachedServiceName +{ + phNfc_sData_t sServiceName; + uint8_t nSap; +}; + + +/** + * \ingroup grp_fri_nfc_llcp_mac + * \brief Declaration of a TRANSPORT Type with a table of PHFRINFC_LLCP_NB_SOCKET_DEFAULT sockets + * and a pointer a Llcp layer + */ +struct phFriNfc_LlcpTransport +{ + phFriNfc_LlcpTransport_Socket_t pSocketTable[PHFRINFC_LLCP_NB_SOCKET_MAX]; + phFriNfc_Llcp_CachedServiceName_t pCachedServiceNames[PHFRINFC_LLCP_SDP_ADVERTISED_NB]; + phFriNfc_Llcp_t *pLlcp; + pthread_mutex_t mutex; + bool_t bSendPending; + bool_t bRecvPending; + bool_t bDmPending; + bool_t bFrmrPending; + + phFriNfc_Llcp_LinkSend_CB_t pfLinkSendCb; + void *pLinkSendContext; + + uint8_t socketIndex; + + /**< Info field of pending FRMR packet*/ + uint8_t FrmrInfoBuffer[4]; + phFriNfc_Llcp_sPacketHeader_t sLlcpHeader; + phFriNfc_Llcp_sPacketSequence_t sSequence; + + /**< Info field of pending DM packet*/ + phFriNfc_Llcp_sPacketHeader_t sDmHeader; + phNfc_sData_t sDmPayload; + uint8_t DmInfoBuffer[3]; + + uint8_t LinkStatusError; + + /**< Service discovery related infos */ + phNfc_sData_t *psDiscoveryServiceNameList; + uint8_t *pnDiscoverySapList; + uint8_t nDiscoveryListSize; + uint8_t nDiscoveryReqOffset; + uint8_t nDiscoveryResOffset; + + uint8_t nDiscoveryResTidList[PHFRINFC_LLCP_SNL_RESPONSE_MAX]; + uint8_t nDiscoveryResSapList[PHFRINFC_LLCP_SNL_RESPONSE_MAX]; + uint8_t nDiscoveryResListSize; + + uint8_t pDiscoveryBuffer[PHFRINFC_LLCP_MIU_DEFAULT]; + pphFriNfc_Cr_t pfDiscover_Cb; + void *pDiscoverContext; + +}; + +/* +################################################################################ +********************** TRANSPORT Interface Function Prototype ***************** +################################################################################ +*/ + +bool_t testAndSetSendPending(phFriNfc_LlcpTransport_t* transport); + +void clearSendPending(phFriNfc_LlcpTransport_t* transport); + + /** +* \ingroup grp_fri_nfc +* \brief Create a socket on a LLCP-connected device. +* +*/ +NFCSTATUS phFriNfc_LlcpTransport_Reset (phFriNfc_LlcpTransport_t *pLlcpSocketTable, + phFriNfc_Llcp_t *pLlcp); + + +/** +* \ingroup grp_fri_nfc +* \brief Close all existing sockets. +* +*/ +NFCSTATUS phFriNfc_LlcpTransport_CloseAll (phFriNfc_LlcpTransport_t *pLlcpSocketTable); + + +/** +* \ingroup grp_fri_nfc +* \brief Used by transport layers to request a send on link layer. +* +*/ +NFCSTATUS phFriNfc_LlcpTransport_LinkSend( phFriNfc_LlcpTransport_t *LlcpTransport, + phFriNfc_Llcp_sPacketHeader_t *psHeader, + phFriNfc_Llcp_sPacketSequence_t *psSequence, + phNfc_sData_t *psInfo, + phFriNfc_Llcp_LinkSend_CB_t pfSend_CB, + uint8_t socketIndex, + void *pContext ); + + +/** +* \ingroup grp_fri_nfc +* \brief Used by transport layers to send a DM frame. +* +* This function is only used when the DM is not related to a DISC on a socket. +*/ +NFCSTATUS phFriNfc_LlcpTransport_SendDisconnectMode(phFriNfc_LlcpTransport_t* psTransport, + uint8_t dsap, + uint8_t ssap, + uint8_t dmOpCode); + +/** +* \ingroup grp_fri_nfc +* \brief Used by transport layers to send a FRMR frame. +* +*/ +NFCSTATUS phFriNfc_LlcpTransport_SendFrameReject(phFriNfc_LlcpTransport_t *psTransport, + uint8_t dsap, + uint8_t rejectedPTYPE, + uint8_t ssap, + phFriNfc_Llcp_sPacketSequence_t* sLlcpSequence, + uint8_t WFlag, + uint8_t IFlag, + uint8_t RFlag, + uint8_t SFlag, + uint8_t vs, + uint8_t vsa, + uint8_t vr, + uint8_t vra); + +/*! +* \ingroup grp_fri_nfc +* \brief Discover remote services SAP using SDP protocol. + */ +NFCSTATUS phFriNfc_LlcpTransport_DiscoverServices( phFriNfc_LlcpTransport_t *pLlcpTransport, + phNfc_sData_t *psServiceNameList, + uint8_t *pnSapList, + uint8_t nListSize, + pphFriNfc_Cr_t pDiscover_Cb, + void *pContext ); + +/** +* \ingroup grp_lib_nfc +* \brief Get the local options of a socket. +* +* This function returns the local options (maximum packet size and receive window size) used +* for a given connection-oriented socket. This function shall not be used with connectionless +* sockets. +* +* \param[out] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psLocalOptions A pointer to be filled with the local options of the socket. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_SocketGetLocalOptions(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + phLibNfc_Llcp_sSocketOptions_t *psLocalOptions); + + +/** +* \ingroup grp_lib_nfc +* \brief Get the local options of a socket. +* +* This function returns the remote options (maximum packet size and receive window size) used +* for a given connection-oriented socket. This function shall not be used with connectionless +* sockets. +* +* \param[out] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psRemoteOptions A pointer to be filled with the remote options of the socket. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_SocketGetRemoteOptions(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phLibNfc_Llcp_sSocketOptions_t* psRemoteOptions); + + + /** +* \ingroup grp_fri_nfc +* \brief Create a socket on a LLCP-connected device. +* +* This function creates a socket for a given LLCP link. Sockets can be of two types : +* connection-oriented and connectionless. If the socket is connection-oriented, the caller +* must provide a working buffer to the socket in order to handle incoming data. This buffer +* must be large enough to fit the receive window (RW * MIU), the remaining space being +* used as a linear buffer to store incoming data as a stream. Data will be readable later +* using the phLibNfc_LlcpTransport_Recv function. +* The options and working buffer are not required if the socket is used as a listening socket, +* since it cannot be directly used for communication. +* +* \param[in] pLlcpSocketTable A pointer to a table of PHFRINFC_LLCP_NB_SOCKET_DEFAULT sockets. +* \param[in] eType The socket type. +* \param[in] psOptions The options to be used with the socket. +* \param[in] psWorkingBuffer A working buffer to be used by the library. +* \param[out] pLlcpSocket A pointer to a socket pointer to be filled with a + socket found on the socket table. +* \param[in] pErr_Cb The callback to be called each time the socket +* is in error. +* \param[in] pContext Upper layer context to be returned in the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_BUFFER_TOO_SMALL The working buffer is too small for the MIU and RW +* declared in the options. +* \retval NFCSTATUS_INSUFFICIENT_RESOURCES No more socket handle available. +* \retval NFCSTATUS_FAILED Operation failed. +* */ +NFCSTATUS phFriNfc_LlcpTransport_Socket(phFriNfc_LlcpTransport_t *pLlcpSocketTable, + phFriNfc_LlcpTransport_eSocketType_t eType, + phFriNfc_LlcpTransport_sSocketOptions_t* psOptions, + phNfc_sData_t* psWorkingBuffer, + phFriNfc_LlcpTransport_Socket_t **pLlcpSocket, + pphFriNfc_LlcpTransportSocketErrCb_t pErr_Cb, + void* pContext); + +/** +* \ingroup grp_fri_nfc +* \brief Close a socket on a LLCP-connected device. +* +* This function closes a LLCP socket previously created using phFriNfc_LlcpTransport_Socket. +* If the socket was connected, it is first disconnected, and then closed. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. + +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Close(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket); + + +/** +* \ingroup grp_fri_nfc +* \brief Bind a socket to a local SAP. +* +* This function binds the socket to a local Service Access Point. +* +* \param[out] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] pConfigInfo A port number for a specific socket +* \param TODO +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_ALREADY_REGISTERED The selected SAP is already bound to another + socket. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Bind(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + uint8_t nSap, + phNfc_sData_t *psServiceName); + +/** +* \ingroup grp_fri_nfc +* \brief Listen for incoming connection requests on a socket. +* +* This function switches a socket into a listening state and registers a callback on +* incoming connection requests. In this state, the socket is not able to communicate +* directly. The listening state is only available for connection-oriented sockets +* which are still not connected. The socket keeps listening until it is closed, and +* thus can trigger several times the pListen_Cb callback. +* +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] pListen_Cb The callback to be called each time the +* socket receive a connection request. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state to switch +* to listening state. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Listen(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + pphFriNfc_LlcpTransportSocketListenCb_t pListen_Cb, + void* pContext); + +/** +* \ingroup grp_fri_nfc +* \brief Accept an incoming connection request for a socket. +* +* This functions allows the client to accept an incoming connection request. +* It must be used with the socket provided within the listen callback. The socket +* is implicitly switched to the connected state when the function is called. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psOptions The options to be used with the socket. +* \param[in] psWorkingBuffer A working buffer to be used by the library. +* \param[in] pErr_Cb The callback to be called each time the accepted socket +* is in error. +* \param[in] pAccept_RspCb The callback to be called when the Accept operation is completed +* \param[in] pContext Upper layer context to be returned in the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_BUFFER_TOO_SMALL The working buffer is too small for the MIU and RW +* declared in the options. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Accept(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phFriNfc_LlcpTransport_sSocketOptions_t* psOptions, + phNfc_sData_t* psWorkingBuffer, + pphFriNfc_LlcpTransportSocketErrCb_t pErr_Cb, + pphFriNfc_LlcpTransportSocketAcceptCb_t pAccept_RspCb, + void* pContext); + + /** +* \ingroup grp_fri_nfc +* \brief Reject an incoming connection request for a socket. +* +* This functions allows the client to reject an incoming connection request. +* It must be used with the socket provided within the listen callback. The socket +* is implicitly closed when the function is called. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] pReject_RspCb The callback to be called when the Reject operation is completed +* \param[in] pContext Upper layer context to be returned in the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Reject( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + pphFriNfc_LlcpTransportSocketRejectCb_t pReject_RspCb, + void *pContext); +/** +* \ingroup grp_fri_nfc +* \brief Try to establish connection with a socket on a remote SAP. +* +* This function tries to connect to a given SAP on the remote peer. If the +* socket is not bound to a local SAP, it is implicitly bound to a free SAP. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] nSap The destination SAP to connect to. +* \param[in] pConnect_RspCb The callback to be called when the connection +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Connection operation is in progress, +* pConnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Connect( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + uint8_t nSap, + pphFriNfc_LlcpTransportSocketConnectCb_t pConnect_RspCb, + void* pContext); + +/** +* \ingroup grp_fri_nfc +* \brief Try to establish connection with a socket on a remote service, given its URI. +* +* This function tries to connect to a SAP designated by an URI. If the +* socket is not bound to a local SAP, it is implicitly bound to a free SAP. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psUri The URI corresponding to the destination SAP to connect to. +* \param[in] pConnect_RspCb The callback to be called when the connection +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Connection operation is in progress, +* pConnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectByUri(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phNfc_sData_t* psUri, + pphFriNfc_LlcpTransportSocketConnectCb_t pConnect_RspCb, + void* pContext); + +/** +* \ingroup grp_lib_nfc +* \brief Disconnect a currently connected socket. +* +* This function initiates the disconnection of a previously connected socket. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] pDisconnect_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Disconnection operation is in progress, +* pDisconnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Disconnect(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + pphLibNfc_LlcpSocketDisconnectCb_t pDisconnect_RspCb, + void* pContext); + +/** +* \ingroup grp_fri_nfc +* \brief Send data on a socket. +* +* This function is used to write data on a socket. This function +* can only be called on a connection-oriented socket which is already +* in a connected state. +* +* +* \param[in] hSocket Socket handle obtained during socket creation. +* \param[in] psBuffer The buffer containing the data to send. +* \param[in] pSend_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pSend_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Send(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb, + void* pContext); + +/** +* \ingroup grp_fri_nfc +* \brief Read data on a socket. +* +* This function is used to read data from a socket. It reads at most the +* size of the reception buffer, but can also return less bytes if less bytes +* are available. If no data is available, the function will be pending until +* more data comes, and the response will be sent by the callback. This function +* can only be called on a connection-oriented socket. +* +* +* \param[in] hSocket Socket handle obtained during socket creation. +* \param[in] psBuffer The buffer receiving the data. +* \param[in] pRecv_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pRecv_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Recv( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketRecvCb_t pRecv_RspCb, + void* pContext); + + + + /** +* \ingroup grp_lib_nfc +* \brief Read data on a socket and get the source SAP. +* +* This function is the same as phLibNfc_Llcp_Recv, except that the callback includes +* the source SAP. This functions can only be called on a connectionless socket. +* +* +* \param[in] pLlcpSocket A pointer to a LlcpSocket created. +* \param[in] psBuffer The buffer receiving the data. +* \param[in] pRecv_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pRecv_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_RecvFrom( phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketRecvFromCb_t pRecv_Cb, + void *pContext); + +/** +* \ingroup grp_fri_nfc +* \brief Send data on a socket to a given destination SAP. +* +* This function is used to write data on a socket to a given destination SAP. +* This function can only be called on a connectionless socket. +* +* +* \param[in] pLlcpSocket A pointer to a LlcpSocket created. +* \param[in] nSap The destination SAP. +* \param[in] psBuffer The buffer containing the data to send. +* \param[in] pSend_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pSend_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_SendTo( phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + uint8_t nSap, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb, + void* pContext); +#endif /* PHFRINFC_LLCP_TRANSPORT_H */ diff --git a/libnfc-nxp/phFriNfc_LlcpTransport_Connection.c b/libnfc-nxp/phFriNfc_LlcpTransport_Connection.c new file mode 100644 index 0000000..4fb50ab --- /dev/null +++ b/libnfc-nxp/phFriNfc_LlcpTransport_Connection.c @@ -0,0 +1,2481 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_LlcpTransport_Connection.c + * \brief + * + * Project: NFC-FRI + * + */ +/*include files*/ +#define LOG_TAG "NFC" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Function definition */ +static NFCSTATUS phFriNfc_Llcp_Send_ReceiveReady_Frame(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket); +static NFCSTATUS phFriNfc_Llcp_Send_ReceiveNotReady_Frame(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket); + +static NFCSTATUS static_performSendInfo(phFriNfc_LlcpTransport_Socket_t * psLlcpSocket); +/********** End Function definition ***********/ + +/* TODO: comment functionphFriNfc_LlcpTransport_ConnectionOriented_SendLlcp_CB */ +static void phFriNfc_LlcpTransport_ConnectionOriented_SendLlcp_CB(void* pContext, + uint8_t socketIndex, + NFCSTATUS status) +{ + phFriNfc_LlcpTransport_t *psTransport; + phFriNfc_LlcpTransport_Socket_t psTempLlcpSocket; + NFCSTATUS result; + /* Get Send CB context */ + psTransport = (phFriNfc_LlcpTransport_t*)pContext; + + if(status == NFCSTATUS_SUCCESS) + { + /* Test the socket */ + switch(psTransport->pSocketTable[socketIndex].eSocket_State) + { + case phFriNfc_LlcpTransportSocket_eSocketAccepted: + { + /* Set socket state to Connected */ + psTransport->pSocketTable[socketIndex].eSocket_State = phFriNfc_LlcpTransportSocket_eSocketConnected; + /* Call the Accept Callback */ + psTransport->pSocketTable[socketIndex].pfSocketAccept_Cb(psTransport->pSocketTable[socketIndex].pAcceptContext,status); + psTransport->pSocketTable[socketIndex].pfSocketAccept_Cb = NULL; + psTransport->pSocketTable[socketIndex].pAcceptContext = NULL; + }break; + + case phFriNfc_LlcpTransportSocket_eSocketRejected: + { + /* Store the Llcp socket in a local Llcp socket */ + psTempLlcpSocket = psTransport->pSocketTable[socketIndex]; + + /* Reset the socket and set the socket state to default */ + result = phFriNfc_LlcpTransport_Close(&psTransport->pSocketTable[socketIndex]); + + /* Call the Reject Callback */ + psTempLlcpSocket.pfSocketSend_Cb(psTempLlcpSocket.pRejectContext,status); + psTempLlcpSocket.pfSocketSend_Cb = NULL; + }break; + + case phFriNfc_LlcpTransportSocket_eSocketConnected: + { + if(!psTransport->pSocketTable[socketIndex].bSocketSendPending && psTransport->pSocketTable[socketIndex].pfSocketSend_Cb != NULL) + { + psTransport->pSocketTable[socketIndex].pfSocketSend_Cb(psTransport->pSocketTable[socketIndex].pSendContext,status); + psTransport->pSocketTable[socketIndex].pfSocketSend_Cb = NULL; + } + }break; + default: + /* Nothing to do */ + break; + } + } + else + { + /* Send CB error */ + if(!psTransport->pSocketTable[socketIndex].bSocketSendPending && psTransport->pSocketTable[socketIndex].pfSocketSend_Cb != NULL) + { + psTransport->pSocketTable[socketIndex].pfSocketSend_Cb(psTransport->pSocketTable[socketIndex].pSendContext,status); + psTransport->pSocketTable[socketIndex].pfSocketSend_Cb = NULL; + } + } +} + + +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_HandlePendingOperations(phFriNfc_LlcpTransport_Socket_t *pSocket) +{ + NFCSTATUS result = NFCSTATUS_FAILED; + phFriNfc_LlcpTransport_t *psTransport = pSocket->psTransport; + /* I FRAME */ + if(pSocket->bSocketSendPending == TRUE) + { + /* Test the RW window */ + if(CHECK_SEND_RW(pSocket)) + { + if (!testAndSetSendPending(psTransport)) { + result = static_performSendInfo(pSocket); + if (result != NFCSTATUS_SUCCESS && result != NFCSTATUS_PENDING) { + clearSendPending(psTransport); + } + } + } + } + /* RR FRAME */ + else if(pSocket->bSocketRRPending == TRUE) + { + /* Reset RR pending */ + pSocket->bSocketRRPending = FALSE; + + /* Send RR Frame */ + result = phFriNfc_Llcp_Send_ReceiveReady_Frame(pSocket); + } + /* RNR Frame */ + else if(pSocket->bSocketRNRPending == TRUE) + { + /* Reset RNR pending */ + pSocket->bSocketRNRPending = FALSE; + + /* Send RNR Frame */ + result = phFriNfc_Llcp_Send_ReceiveNotReady_Frame(pSocket); + } + /* CC Frame */ + else if(pSocket->bSocketAcceptPending == TRUE) + { + if (!testAndSetSendPending(psTransport)) + { + /* Reset Accept pending */ + pSocket->bSocketAcceptPending = FALSE; + + /* Fill the psLlcpHeader stuture with the DSAP,CC PTYPE and the SSAP */ + pSocket->sLlcpHeader.dsap = pSocket->socket_dSap; + pSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_CC; + pSocket->sLlcpHeader.ssap = pSocket->socket_sSap; + + /* Set the socket state to accepted */ + pSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketAccepted; + + /* Send a CC Frame */ + result = phFriNfc_LlcpTransport_LinkSend(psTransport, + &pSocket->sLlcpHeader, + NULL, + &pSocket->sSocketSendBuffer, + phFriNfc_LlcpTransport_ConnectionOriented_SendLlcp_CB, + pSocket->index, + psTransport); + + if (result != NFCSTATUS_SUCCESS && result != NFCSTATUS_PENDING) { + clearSendPending(psTransport); + } + } + } + /* CONNECT FRAME */ + else if(pSocket->bSocketConnectPending == TRUE) + { + if (!testAndSetSendPending(psTransport)) + { + /* Reset Accept pending */ + pSocket->bSocketConnectPending = FALSE; + + /* Set the socket in connecting state */ + pSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketConnecting; + + /* send CONNECT */ + result = phFriNfc_LlcpTransport_LinkSend(psTransport, + &pSocket->sLlcpHeader, + NULL, + &pSocket->sSocketSendBuffer, + phFriNfc_LlcpTransport_ConnectionOriented_SendLlcp_CB, + pSocket->index, + psTransport); + + if (result != NFCSTATUS_SUCCESS && result != NFCSTATUS_PENDING) { + clearSendPending(psTransport); + } + } + } + /* DISC FRAME */ + else if(pSocket->bSocketDiscPending == TRUE) + { + if (!testAndSetSendPending(psTransport)) + { + /* Reset Disc Pending */ + pSocket->bSocketDiscPending = FALSE; + + /* Set the socket in connecting state */ + pSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketDisconnecting; + + /* Send DISC */ + result = phFriNfc_LlcpTransport_LinkSend(psTransport, + &pSocket->sLlcpHeader, + NULL, + &pSocket->sSocketSendBuffer, + phFriNfc_LlcpTransport_ConnectionOriented_SendLlcp_CB, + pSocket->index, + psTransport); + + if (result != NFCSTATUS_SUCCESS && result != NFCSTATUS_PENDING) { + clearSendPending(psTransport); + } + /* Call ErrCB due to a DISC */ + pSocket->pSocketErrCb(pSocket->pContext, PHFRINFC_LLCP_ERR_DISCONNECTED); + } + } + return result; +} + +static NFCSTATUS static_performSendInfo(phFriNfc_LlcpTransport_Socket_t * psLlcpSocket) +{ + phFriNfc_LlcpTransport_t *psTransport = psLlcpSocket->psTransport; + NFCSTATUS status; + + /* Set the Header */ + psLlcpSocket->sLlcpHeader.dsap = psLlcpSocket->socket_dSap; + psLlcpSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_I; + psLlcpSocket->sLlcpHeader.ssap = psLlcpSocket->socket_sSap; + + /* Set Sequence Numbers */ + psLlcpSocket->sSequence.ns = psLlcpSocket->socket_VS; + psLlcpSocket->sSequence.nr = psLlcpSocket->socket_VR; + + /* Update the VRA */ + psLlcpSocket->socket_VRA = psLlcpSocket->socket_VR; + + + /* Send I_PDU */ + status = phFriNfc_LlcpTransport_LinkSend(psTransport, + &psLlcpSocket->sLlcpHeader, + &psLlcpSocket->sSequence, + &psLlcpSocket->sSocketSendBuffer, + phFriNfc_LlcpTransport_ConnectionOriented_SendLlcp_CB, + psLlcpSocket->index, + psLlcpSocket->psTransport); + if (status == NFCSTATUS_SUCCESS || status == NFCSTATUS_PENDING) { + /* Update VS */ + psLlcpSocket->socket_VS = (psLlcpSocket->socket_VS+1)%16; + + /* Reset Send Pending */ + psLlcpSocket->bSocketSendPending = FALSE; + } + + return status; +} + +static void phFriNfc_LlcpTransport_ConnectionOriented_Abort(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket) +{ + if (pLlcpSocket->pfSocketSend_Cb != NULL) + { + pLlcpSocket->pfSocketSend_Cb(pLlcpSocket->pSendContext, NFCSTATUS_ABORTED); + pLlcpSocket->pfSocketSend_Cb = NULL; + } + pLlcpSocket->pSendContext = NULL; + if (pLlcpSocket->pfSocketRecv_Cb != NULL) + { + pLlcpSocket->pfSocketRecv_Cb(pLlcpSocket->pRecvContext, NFCSTATUS_ABORTED); + pLlcpSocket->pfSocketRecv_Cb = NULL; + } + pLlcpSocket->pRecvContext = NULL; + if (pLlcpSocket->pfSocketAccept_Cb != NULL) + { + pLlcpSocket->pfSocketAccept_Cb(pLlcpSocket->pAcceptContext, NFCSTATUS_ABORTED); + pLlcpSocket->pfSocketAccept_Cb = NULL; + } + pLlcpSocket->pAcceptContext = NULL; + if (pLlcpSocket->pfSocketConnect_Cb != NULL) + { + pLlcpSocket->pfSocketConnect_Cb(pLlcpSocket->pConnectContext, 0, NFCSTATUS_ABORTED); + pLlcpSocket->pfSocketConnect_Cb = NULL; + } + pLlcpSocket->pConnectContext = NULL; + if (pLlcpSocket->pfSocketDisconnect_Cb != NULL) + { + pLlcpSocket->pfSocketDisconnect_Cb(pLlcpSocket->pDisconnectContext, NFCSTATUS_ABORTED); + pLlcpSocket->pfSocketDisconnect_Cb = NULL; + } + pLlcpSocket->pDisconnectContext = NULL; + + pLlcpSocket->pfSocketRecvFrom_Cb = NULL; + pLlcpSocket->pfSocketListen_Cb = NULL; + pLlcpSocket->pListenContext = NULL; +} + + +static NFCSTATUS phFriNfc_Llcp_Send_ReceiveReady_Frame(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Test if a send is pending */ + if(testAndSetSendPending(pLlcpSocket->psTransport)) + { + pLlcpSocket->bSocketRRPending = TRUE; + status = NFCSTATUS_PENDING; + } + else + { + /* Set the header of the RR frame */ + pLlcpSocket->sLlcpHeader.dsap = pLlcpSocket->socket_dSap; + pLlcpSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_RR; + pLlcpSocket->sLlcpHeader.ssap = pLlcpSocket->socket_sSap; + + /* Set sequence number for RR Frame */ + pLlcpSocket->sSequence.ns = 0; + pLlcpSocket->sSequence.nr = pLlcpSocket->socket_VR; + + /* Update VRA */ + pLlcpSocket->socket_VRA = (uint8_t)pLlcpSocket->sSequence.nr; + + /* Send RR frame */ + status = phFriNfc_LlcpTransport_LinkSend(pLlcpSocket->psTransport, + &pLlcpSocket->sLlcpHeader, + &pLlcpSocket->sSequence, + NULL, + phFriNfc_LlcpTransport_ConnectionOriented_SendLlcp_CB, + pLlcpSocket->index, + pLlcpSocket->psTransport); + if (status != NFCSTATUS_SUCCESS && status != NFCSTATUS_PENDING) { + clearSendPending(pLlcpSocket->psTransport); + } + } + + return status; +} + +static NFCSTATUS phFriNfc_Llcp_Send_ReceiveNotReady_Frame(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + + /* Test if a send is pending */ + if(testAndSetSendPending(pLlcpSocket->psTransport)) + { + pLlcpSocket->bSocketRNRPending = TRUE; + status = NFCSTATUS_PENDING; + } + else + { + /* Set the header of the RNR frame */ + pLlcpSocket->sLlcpHeader.dsap = pLlcpSocket->socket_dSap; + pLlcpSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_RNR; + pLlcpSocket->sLlcpHeader.ssap = pLlcpSocket->socket_sSap; + + /* Set sequence number for RNR Frame */ + pLlcpSocket->sSequence.ns = 0x00; + pLlcpSocket->sSequence.nr = pLlcpSocket->socket_VR; + + /* Update VRA */ + pLlcpSocket->socket_VRA = (uint8_t)pLlcpSocket->sSequence.nr; + + /* Send RNR frame */ + status = phFriNfc_LlcpTransport_LinkSend(pLlcpSocket->psTransport, + &pLlcpSocket->sLlcpHeader, + &pLlcpSocket->sSequence, + NULL, + phFriNfc_LlcpTransport_ConnectionOriented_SendLlcp_CB, + pLlcpSocket->index, + pLlcpSocket->psTransport); + if (status != NFCSTATUS_SUCCESS && status != NFCSTATUS_PENDING) { + clearSendPending(pLlcpSocket->psTransport); + } + } + return status; +} + +static NFCSTATUS phFriNfc_Llcp_GetSocket_Params(phNfc_sData_t *psParamsTLV, + phNfc_sData_t *psServiceName, + uint8_t *pRemoteRW_Size, + uint16_t *pRemoteMIU) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phNfc_sData_t sValueBuffer; + uint32_t offset = 0; + uint8_t type; + + /* Check for NULL pointers */ + if ((psParamsTLV == NULL) || (pRemoteRW_Size == NULL) || (pRemoteMIU == NULL)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Decode TLV */ + while (offset < psParamsTLV->length) + { + status = phFriNfc_Llcp_DecodeTLV(psParamsTLV, &offset, &type,&sValueBuffer); + if (status != NFCSTATUS_SUCCESS) + { + /* Error: Ill-formed TLV */ + return status; + } + switch(type) + { + case PHFRINFC_LLCP_TLV_TYPE_SN: + { + /* Test if a SN is present in the TLV */ + if(sValueBuffer.length == 0) + { + /* Error : Ill-formed SN parameter TLV */ + break; + } + /* Get the Service Name */ + *psServiceName = sValueBuffer; + }break; + + case PHFRINFC_LLCP_TLV_TYPE_RW: + { + /* Check length */ + if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_RW) + { + /* Error : Ill-formed MIUX parameter TLV */ + break; + } + *pRemoteRW_Size = sValueBuffer.buffer[0]; + }break; + + case PHFRINFC_LLCP_TLV_TYPE_MIUX: + { + /* Check length */ + if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_MIUX) + { + /* Error : Ill-formed MIUX parameter TLV */ + break; + } + *pRemoteMIU = PHFRINFC_LLCP_MIU_DEFAULT + (((sValueBuffer.buffer[0] << 8) | sValueBuffer.buffer[1]) & PHFRINFC_LLCP_TLV_MIUX_MASK); + }break; + + default: + { + /* Error : Unknown type */ + break; + } + } + } + } + return status; +} + + +/* TODO: comment function Handle_ConnectFrame */ +static void Handle_ConnectionFrame(phFriNfc_LlcpTransport_t *psTransport, + phNfc_sData_t *psData, + uint8_t dsap, + uint8_t ssap) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + uint8_t index; + uint8_t socketFound = FALSE; + phFriNfc_LlcpTransport_Socket_t *pLlcpSocket = NULL; + phFriNfc_LlcpTransport_Socket_t *psLocalLlcpSocket = NULL; + pphFriNfc_LlcpTransportSocketListenCb_t pListen_Cb = NULL; + void *pListenContext = NULL; + + phNfc_sData_t sServiceName; + uint8_t remoteRW = PHFRINFC_LLCP_RW_DEFAULT; + uint16_t remoteMIU = PHFRINFC_LLCP_MIU_DEFAULT; + + status = phFriNfc_Llcp_GetSocket_Params(psData, + &sServiceName, + &remoteRW, + &remoteMIU); + + if(status != NFCSTATUS_SUCCESS) + { + /* Incorrect TLV */ + /* send FRMR */ + status = phFriNfc_LlcpTransport_SendFrameReject(psTransport, + dsap, + PHFRINFC_LLCP_PTYPE_CONNECT, + ssap, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00); + } + else + { + if(dsap == PHFRINFC_LLCP_SAP_SDP) + { + /* Search a socket with the SN */ + for(index=0;indexpSocketTable[index].bSocketListenPending + && (sServiceName.length == psTransport->pSocketTable[index].sServiceName.length) + && !memcmp(sServiceName.buffer,psTransport->pSocketTable[index].sServiceName.buffer,sServiceName.length)) + { + /* socket with the SN found */ + socketFound = TRUE; + + psLocalLlcpSocket = &psTransport->pSocketTable[index]; + + /* Get the new ssap number, it is the ssap number of the socket found */ + dsap = psLocalLlcpSocket->socket_sSap; + /* Get the ListenCB of the socket */ + pListen_Cb = psLocalLlcpSocket->pfSocketListen_Cb; + pListenContext = psLocalLlcpSocket->pListenContext; + break; + } + } + } + else + { + /* Search a socket with the DSAP */ + for(index=0;indexpSocketTable[index].bSocketListenPending && psTransport->pSocketTable[index].socket_sSap == dsap) + { + /* socket with the SN found */ + socketFound = TRUE; + + psLocalLlcpSocket = &psTransport->pSocketTable[index]; + + /* Get the Listen CB and the Context of the socket */ + pListen_Cb = psLocalLlcpSocket->pfSocketListen_Cb; + pListenContext = psLocalLlcpSocket->pListenContext; + break; + } + } + } + } + + /* Test if a socket has beeen found */ + if(socketFound) + { + /* Reset the FLAG socketFound*/ + socketFound = FALSE; + + /* Search a socket free and no socket connect on this DSAP*/ + for(index=0;indexpSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketDefault && socketFound != TRUE) + { + socketFound = TRUE; + + psTransport->pSocketTable[index].index = index; + + /* Create a communication socket */ + pLlcpSocket = &psTransport->pSocketTable[index]; + + /* Set the communication option of the Remote Socket */ + pLlcpSocket->remoteMIU = remoteMIU; + pLlcpSocket->remoteRW = remoteRW; + + /* Set SSAP/DSAP of the new socket created for the communication with the remote */ + pLlcpSocket->socket_dSap = ssap; + pLlcpSocket->socket_sSap = dsap; + + /* Set the state and the type of the new socket */ + pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketBound; + pLlcpSocket->eSocket_Type = phFriNfc_LlcpTransport_eConnectionOriented; + + } + else if(((psTransport->pSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnected) + || (psTransport->pSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketAccepted)) + && ((psTransport->pSocketTable[index].socket_sSap == ssap)&&(psTransport->pSocketTable[index].socket_dSap == dsap))) + + { + socketFound = FALSE; + + if(pLlcpSocket != NULL) + { + /* Reset Socket Information */ + pLlcpSocket->remoteMIU = 0; + pLlcpSocket->remoteRW = 0; + + /* Set SSAP/DSAP of the new socket created for the communication with the remote */ + pLlcpSocket->socket_dSap = 0; + pLlcpSocket->socket_sSap = 0; + + /* Set the state and the type of the new socket */ + pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketDefault; + pLlcpSocket->eSocket_Type = phFriNfc_LlcpTransport_eDefaultType; + break; + } + } + } + + + + /* Test if a socket has been found */ + if(socketFound) + { + /* Call the Listen CB */ + pListen_Cb(pListenContext,pLlcpSocket); + } + else + { + /* No more socket are available */ + /* Send a DM (0x21) */ + status = phFriNfc_LlcpTransport_SendDisconnectMode (psTransport, + ssap, + dsap, + PHFRINFC_LLCP_DM_OPCODE_SOCKET_NOT_AVAILABLE); + } + } + else + { + /* Service Name not found or Port number not found */ + /* Send a DM (0x02) */ + status = phFriNfc_LlcpTransport_SendDisconnectMode (psTransport, + ssap, + dsap, + PHFRINFC_LLCP_DM_OPCODE_SAP_NOT_FOUND); + } +} + +/* TODO: comment function Handle_ConnectFrame */ +static void Handle_ConnectionCompleteFrame(phFriNfc_LlcpTransport_t *psTransport, + phNfc_sData_t *psData, + uint8_t dsap, + uint8_t ssap) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t index; + uint8_t remoteRW = PHFRINFC_LLCP_RW_DEFAULT; + uint16_t remoteMIU = PHFRINFC_LLCP_MIU_DEFAULT; + uint8_t socketFound = FALSE; + phFriNfc_LlcpTransport_Socket_t* psLocalLlcpSocket = NULL; + + status = phFriNfc_Llcp_GetSocket_Params(psData, + NULL, + &remoteRW, + &remoteMIU); + + if(status != NFCSTATUS_SUCCESS) + { + /* Incorrect TLV */ + /* send FRMR */ + status = phFriNfc_LlcpTransport_SendFrameReject(psTransport, + dsap, + PHFRINFC_LLCP_PTYPE_CC, + ssap, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00); + } + else + { + /* Search a socket in connecting state and with the good SSAP */ + for(index=0;indexpSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnecting + && psTransport->pSocketTable[index].socket_sSap == dsap) + { + /* socket with the SN found */ + socketFound = TRUE; + + /* Update the DSAP value with the incomming Socket sSap */ + psTransport->pSocketTable[index].socket_dSap = ssap; + + /* Store a pointer to the socket found */ + psLocalLlcpSocket = &psTransport->pSocketTable[index]; + break; + } + } + /* Test if a socket has been found */ + if(socketFound) + { + /* Set the socket state to connected */ + psLocalLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketConnected; + + /* Reset the socket_VS,socket_VR,socket_VSA and socket_VRA variables */ + psLocalLlcpSocket->socket_VR = 0; + psLocalLlcpSocket->socket_VRA = 0; + psLocalLlcpSocket->socket_VS = 0; + psLocalLlcpSocket->socket_VSA = 0; + + /* Store the Remote parameters (MIU,RW) */ + psLocalLlcpSocket->remoteMIU = remoteMIU; + psLocalLlcpSocket->remoteRW = remoteRW; + + /* Call the Connect CB and reset callback info */ + psLocalLlcpSocket->pfSocketConnect_Cb(psLocalLlcpSocket->pConnectContext,0x00,NFCSTATUS_SUCCESS); + psLocalLlcpSocket->pfSocketConnect_Cb = NULL; + psLocalLlcpSocket->pConnectContext = NULL; + } + else + { + /* No socket Active */ + /* CC Frame not handled */ + } + } +} + +/* TODO: comment function Handle_DisconnectFrame */ +static void Handle_DisconnectFrame(phFriNfc_LlcpTransport_t *psTransport, + uint8_t dsap, + uint8_t ssap) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t index; + uint8_t socketFound = FALSE; + phFriNfc_LlcpTransport_Socket_t* psLocalLlcpSocket = NULL; + + /* Search a socket in connected state and the good SSAP */ + for(index=0;indexpSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnected + && psTransport->pSocketTable[index].socket_sSap == dsap) + { + /* socket found */ + socketFound = TRUE; + + /* Store a pointer to the socket found */ + psLocalLlcpSocket = &psTransport->pSocketTable[index]; + break; + } + } + + /* Test if a socket has been found */ + if(socketFound) + { + /* Test if a send IFRAME is pending with this socket */ + if((psLocalLlcpSocket->bSocketSendPending == TRUE) || (psLocalLlcpSocket->bSocketRecvPending == TRUE)) + { + /* Call the send CB, a disconnect abort the send request */ + if (psLocalLlcpSocket->pfSocketSend_Cb != NULL && psLocalLlcpSocket->bSocketSendPending == TRUE) + { + /* Copy CB + context in local variables */ + pphFriNfc_LlcpTransportSocketSendCb_t pfSendCb = psLocalLlcpSocket->pfSocketSend_Cb; + void* pSendContext = psLocalLlcpSocket->pSendContext; + /* Reset CB + context */ + psLocalLlcpSocket->pfSocketSend_Cb = NULL; + psLocalLlcpSocket->pSendContext = NULL; + /* Perform callback */ + pfSendCb(pSendContext, NFCSTATUS_FAILED); + } + /* Call the send CB, a disconnect abort the receive request */ + if (psLocalLlcpSocket->pfSocketRecv_Cb != NULL && psLocalLlcpSocket->bSocketRecvPending == TRUE) + { + /* Copy CB + context in local variables */ + pphFriNfc_LlcpTransportSocketRecvCb_t pfRecvCb = psLocalLlcpSocket->pfSocketRecv_Cb; + void* pRecvContext = psLocalLlcpSocket->pRecvContext; + /* Reset CB + context */ + psLocalLlcpSocket->pfSocketRecv_Cb = NULL; + psLocalLlcpSocket->pRecvContext = NULL; + /* Perform callback */ + pfRecvCb(pRecvContext, NFCSTATUS_FAILED); + } + psLocalLlcpSocket->bSocketRecvPending = FALSE; + psLocalLlcpSocket->bSocketSendPending = FALSE; + } + + /* Update the socket state */ + psLocalLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketDisconnecting; + + /* Send a DM*/ + /* TODO: use a socket internal flag to save */ + status = phFriNfc_LlcpTransport_SendDisconnectMode(psTransport, + ssap, + dsap, + PHFRINFC_LLCP_DM_OPCODE_DISCONNECTED); + + /* Call ErrCB due to a DISC */ + psTransport->pSocketTable[index].pSocketErrCb(psTransport->pSocketTable[index].pContext, PHFRINFC_LLCP_ERR_DISCONNECTED); + } + else + { + /* No socket Active */ + /* DISC Frame not handled */ + } +} + +/* TODO: comment function Handle_ConnectFrame */ +static void Handle_DisconnetModeFrame(phFriNfc_LlcpTransport_t *psTransport, + phNfc_sData_t *psData, + uint8_t dsap, + uint8_t ssap) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t index; + uint8_t socketFound = FALSE; + uint8_t dmOpCode; + phFriNfc_LlcpTransport_Socket_t *psLocalLlcpSocket = NULL; + + /* Test if the DM buffer is correct */ + if(psData->length != PHFRINFC_LLCP_DM_LENGTH) + { + /* send FRMR */ + status = phFriNfc_LlcpTransport_SendFrameReject(psTransport, + dsap, + PHFRINFC_LLCP_PTYPE_DM, + ssap, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00); + } + else + { + /* Search a socket waiting for a DM (Disconnecting State) */ + for(index=0;indexpSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketDisconnecting + || psTransport->pSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnecting) + && psTransport->pSocketTable[index].socket_sSap == dsap) + { + /* socket found */ + socketFound = TRUE; + + /* Store a pointer to the socket found */ + psLocalLlcpSocket = &psTransport->pSocketTable[index]; + break; + } + } + + /* Test if a socket has been found */ + if(socketFound) + { + /* Set dmOpcode */ + dmOpCode = psData->buffer[0]; + + switch(dmOpCode) + { + case PHFRINFC_LLCP_DM_OPCODE_DISCONNECTED: + { + /* Set the socket state to disconnected */ + psLocalLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketCreated; + + /* Call Disconnect CB */ + if (psLocalLlcpSocket->pfSocketDisconnect_Cb != NULL) + { + psLocalLlcpSocket->pfSocketDisconnect_Cb(psLocalLlcpSocket->pDisconnectContext,NFCSTATUS_SUCCESS); + psLocalLlcpSocket->pfSocketDisconnect_Cb = NULL; + } + + }break; + + case PHFRINFC_LLCP_DM_OPCODE_CONNECT_REJECTED: + case PHFRINFC_LLCP_DM_OPCODE_CONNECT_NOT_ACCEPTED: + case PHFRINFC_LLCP_DM_OPCODE_SAP_NOT_ACTIVE: + case PHFRINFC_LLCP_DM_OPCODE_SAP_NOT_FOUND: + case PHFRINFC_LLCP_DM_OPCODE_SOCKET_NOT_AVAILABLE: + { + /* Set the socket state to bound */ + psLocalLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketCreated; + if(psLocalLlcpSocket->pfSocketConnect_Cb != NULL) + { + /* Call Connect CB */ + psLocalLlcpSocket->pfSocketConnect_Cb(psLocalLlcpSocket->pConnectContext,dmOpCode,NFCSTATUS_FAILED); + psLocalLlcpSocket->pfSocketConnect_Cb = NULL; + } + }break; + } + } + } +} + +/* TODO: comment function Handle_Receive_IFrame */ +static void Handle_Receive_IFrame(phFriNfc_LlcpTransport_t *psTransport, + phNfc_sData_t *psData, + uint8_t dsap, + uint8_t ssap) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + phFriNfc_LlcpTransport_Socket_t* psLocalLlcpSocket = NULL; + phFriNfc_Llcp_sPacketSequence_t sLlcpLocalSequence; + + uint32_t dataLengthAvailable = 0; + uint32_t dataLengthWrite = 0; + uint8_t index; + uint8_t socketFound = FALSE; + uint8_t WFlag = 0; + uint8_t IFlag = 0; + uint8_t RFlag = 0; + uint8_t SFlag = 0; + uint8_t nr_val; + uint32_t offset = 0; + uint32_t rw_offset; + + /* Get NS and NR Value of the I Frame*/ + phFriNfc_Llcp_Buffer2Sequence( psData->buffer, offset, &sLlcpLocalSequence); + + + /* Update the buffer pointer */ + psData->buffer = psData->buffer + PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE; + + /* Update the length value (without the header length) */ + psData->length = psData->length - PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE; + + /* Search a socket waiting for an I FRAME (Connected State) */ + for(index=0;indexpSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnected) + || (psTransport->pSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketAccepted)) + && psTransport->pSocketTable[index].socket_sSap == dsap + && psTransport->pSocketTable[index].socket_dSap == ssap) + { + /* socket found */ + socketFound = TRUE; + + /* Store a pointer to the socket found */ + psLocalLlcpSocket = &psTransport->pSocketTable[index]; + break; + } + } + + /* Test if a socket has been found */ + if(socketFound) + { + /* Test NS */ + /*if(sLlcpLocalSequence.ns != psLocalLlcpSocket->socket_VR) + { + SFlag = TRUE; + }*/ + + /* Calculate offset of current frame in RW, and check validity */ + if(sLlcpLocalSequence.ns >= psLocalLlcpSocket->socket_VRA) + { + rw_offset = sLlcpLocalSequence.ns - psLocalLlcpSocket->socket_VRA; + } + else + { + rw_offset = 16 - (psLocalLlcpSocket->socket_VRA - sLlcpLocalSequence.ns); + } + if(rw_offset >= psLocalLlcpSocket->localRW) + { + /* FRMR 0x01 */ + SFlag = TRUE; + } + + /* Check Info length */ + if(psData->length > (uint32_t)(psLocalLlcpSocket->localMIUX + PHFRINFC_LLCP_MIU_DEFAULT)) + { + IFlag = TRUE; + } + + + /* Test NR */ + nr_val = (uint8_t)sLlcpLocalSequence.nr; + do + { + if(nr_val == psLocalLlcpSocket->socket_VS) + { + break; + } + + nr_val = (nr_val+1)%16; + + if(nr_val == psLocalLlcpSocket->socket_VSA) + { + /* FRMR 0x02 */ + RFlag = TRUE; + break; + } + }while(nr_val != sLlcpLocalSequence.nr); + + + if( WFlag != 0 || IFlag != 0 || RFlag != 0 || SFlag != 0) + { + /* Send FRMR */ + status = phFriNfc_LlcpTransport_SendFrameReject(psTransport, + dsap, + PHFRINFC_LLCP_PTYPE_I, + ssap, + &sLlcpLocalSequence, + WFlag, + IFlag, + RFlag, + SFlag, + psLocalLlcpSocket->socket_VS, + psLocalLlcpSocket->socket_VSA, + psLocalLlcpSocket->socket_VR, + psLocalLlcpSocket->socket_VRA); + + } + else + { + /* Update VSA */ + psLocalLlcpSocket->socket_VSA = (uint8_t)sLlcpLocalSequence.nr; + + /* Test if the Linear Buffer length is null */ + if(psLocalLlcpSocket->bufferLinearLength == 0) + { + /* Test if a Receive is pending and RW empty */ + if(psLocalLlcpSocket->bSocketRecvPending == TRUE && (psLocalLlcpSocket->indexRwWrite == psLocalLlcpSocket->indexRwRead)) + { + /* Reset Flag */ + psLocalLlcpSocket->bSocketRecvPending = FALSE; + + /* Save I_FRAME into the Receive Buffer */ + memcpy(psLocalLlcpSocket->sSocketRecvBuffer->buffer,psData->buffer,psData->length); + psLocalLlcpSocket->sSocketRecvBuffer->length = psData->length; + + /* Update VR */ + psLocalLlcpSocket->socket_VR = (psLocalLlcpSocket->socket_VR+1)%16; + + /* Call the Receive CB */ + psLocalLlcpSocket->pfSocketRecv_Cb(psLocalLlcpSocket->pRecvContext, NFCSTATUS_SUCCESS); + psLocalLlcpSocket->pfSocketRecv_Cb = NULL; + + /* Test if a send is pending with this socket */ + if(psLocalLlcpSocket->bSocketSendPending == TRUE && CHECK_SEND_RW(psLocalLlcpSocket)) + { + /* Test if a send is pending at LLC layer */ + if(!testAndSetSendPending(psLocalLlcpSocket->psTransport)) + { + status = static_performSendInfo(psLocalLlcpSocket); + if (status != NFCSTATUS_SUCCESS && status != NFCSTATUS_PENDING) { + clearSendPending(psTransport); + } + } + } + else + { + /* RR */ + status = phFriNfc_Llcp_Send_ReceiveReady_Frame(psLocalLlcpSocket); + } + } + else + { + /* Test if RW is full */ + if((psLocalLlcpSocket->indexRwWrite - psLocalLlcpSocket->indexRwRead)localRW) + { + if(psLocalLlcpSocket->sSocketRwBufferTable[(psLocalLlcpSocket->indexRwWrite%psLocalLlcpSocket->localRW)].length == 0) + { + /* Save I_FRAME into the RW Buffers */ + memcpy(psLocalLlcpSocket->sSocketRwBufferTable[(psLocalLlcpSocket->indexRwWrite%psLocalLlcpSocket->localRW)].buffer,psData->buffer,psData->length); + psLocalLlcpSocket->sSocketRwBufferTable[(psLocalLlcpSocket->indexRwWrite%psLocalLlcpSocket->localRW)].length = psData->length; + + if(psLocalLlcpSocket->ReceiverBusyCondition != TRUE) + { + /* Receiver Busy condition */ + psLocalLlcpSocket->ReceiverBusyCondition = TRUE; + + /* Send RNR */ + status = phFriNfc_Llcp_Send_ReceiveNotReady_Frame(psLocalLlcpSocket); + } + /* Update the RW write index */ + psLocalLlcpSocket->indexRwWrite++; + } + } + } + } + else + { + /* Copy the buffer into the RW buffer */ + memcpy(psLocalLlcpSocket->sSocketRwBufferTable[(psLocalLlcpSocket->indexRwWrite%psLocalLlcpSocket->localRW)].buffer,psData->buffer,psData->length); + + /* Update the length */ + psLocalLlcpSocket->sSocketRwBufferTable[(psLocalLlcpSocket->indexRwWrite%psLocalLlcpSocket->localRW)].length = psData->length; + + /* Test the length of the available place in the linear buffer */ + dataLengthAvailable = phFriNfc_Llcp_CyclicFifoAvailable(&psLocalLlcpSocket->sCyclicFifoBuffer); + + if(dataLengthAvailable >= psLocalLlcpSocket->sSocketRwBufferTable[(psLocalLlcpSocket->indexRwWrite%psLocalLlcpSocket->localRW)].length) + { + /* Store Data into the linear buffer */ + dataLengthWrite = phFriNfc_Llcp_CyclicFifoWrite(&psLocalLlcpSocket->sCyclicFifoBuffer, + psLocalLlcpSocket->sSocketRwBufferTable[(psLocalLlcpSocket->indexRwWrite%psLocalLlcpSocket->localRW)].buffer, + psLocalLlcpSocket->sSocketRwBufferTable[(psLocalLlcpSocket->indexRwWrite%psLocalLlcpSocket->localRW)].length); + + /* Update VR */ + psLocalLlcpSocket->socket_VR = (psLocalLlcpSocket->socket_VR+1)%16; + + /* Update the length */ + psLocalLlcpSocket->sSocketRwBufferTable[(psLocalLlcpSocket->indexRwWrite%psLocalLlcpSocket->localRW)].length = 0x00; + + /* Test if a Receive Pending*/ + if(psLocalLlcpSocket->bSocketRecvPending == TRUE) + { + /* Reset Flag */ + psLocalLlcpSocket->bSocketRecvPending = FALSE; + + phFriNfc_LlcpTransport_ConnectionOriented_Recv(psLocalLlcpSocket, + psLocalLlcpSocket->sSocketRecvBuffer, + psLocalLlcpSocket->pfSocketRecv_Cb, + psLocalLlcpSocket->pRecvContext); + } + + /* Test if a send is pending with this socket */ + if((psLocalLlcpSocket->bSocketSendPending == TRUE) && CHECK_SEND_RW(psLocalLlcpSocket)) + { + /* Test if a send is pending at LLC layer */ + if(!testAndSetSendPending(psLocalLlcpSocket->psTransport)) + { + status = static_performSendInfo(psLocalLlcpSocket); + if (status != NFCSTATUS_SUCCESS && status != NFCSTATUS_PENDING) { + clearSendPending(psTransport); + } + } + } + else + { + /* RR */ + status = phFriNfc_Llcp_Send_ReceiveReady_Frame(psLocalLlcpSocket); + } + } + else + { + if(psLocalLlcpSocket->ReceiverBusyCondition != TRUE) + { + /* Receiver Busy condition */ + psLocalLlcpSocket->ReceiverBusyCondition = TRUE; + + /* Send RNR */ + status = phFriNfc_Llcp_Send_ReceiveNotReady_Frame(psLocalLlcpSocket); + } + + /* Update the RW write index */ + psLocalLlcpSocket->indexRwWrite++; + } + } + } + } + else + { + /* No active socket*/ + /* I FRAME not Handled */ + } +} + +static void Handle_ReceiveReady_Frame(phFriNfc_LlcpTransport_t *psTransport, + phNfc_sData_t *psData, + uint8_t dsap, + uint8_t ssap) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t index; + uint8_t socketFound = FALSE; + uint8_t WFlag = 0; + uint8_t IFlag = 0; + uint8_t RFlag = 0; + uint8_t SFlag = 0; + uint32_t offset = 0; + uint8_t nr_val; + + phFriNfc_LlcpTransport_Socket_t* psLocalLlcpSocket = NULL; + phFriNfc_Llcp_sPacketSequence_t sLlcpLocalSequence; + + /* Get NS and NR Value of the I Frame*/ + phFriNfc_Llcp_Buffer2Sequence( psData->buffer, offset, &sLlcpLocalSequence); + + /* Search a socket waiting for an RR FRAME (Connected State) */ + for(index=0;indexpSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnected + && psTransport->pSocketTable[index].socket_sSap == dsap + && psTransport->pSocketTable[index].socket_dSap == ssap) + { + /* socket found */ + socketFound = TRUE; + + /* Store a pointer to the socket found */ + psLocalLlcpSocket = &psTransport->pSocketTable[index]; + psLocalLlcpSocket->index = psTransport->pSocketTable[index].index; + break; + } + } + + /* Test if a socket has been found */ + if(socketFound) + { + /* Test NR */ + nr_val = (uint8_t)sLlcpLocalSequence.nr; + do + { + if(nr_val == psLocalLlcpSocket->socket_VS) + { + break; + } + + nr_val = (nr_val+1)%16; + + if(nr_val == psLocalLlcpSocket->socket_VSA) + { + RFlag = TRUE; + break; + } + + }while(nr_val != sLlcpLocalSequence.nr); + + + /* Test if Info field present */ + if(psData->length > 1) + { + WFlag = TRUE; + IFlag = TRUE; + } + + if (WFlag || IFlag || RFlag || SFlag) + { + /* Send FRMR */ + status = phFriNfc_LlcpTransport_SendFrameReject(psTransport, + dsap, PHFRINFC_LLCP_PTYPE_RR, ssap, + &sLlcpLocalSequence, + WFlag, IFlag, RFlag, SFlag, + psLocalLlcpSocket->socket_VS, + psLocalLlcpSocket->socket_VSA, + psLocalLlcpSocket->socket_VR, + psLocalLlcpSocket->socket_VRA); + } + else + { + /* Test Receiver Busy condition */ + if(psLocalLlcpSocket->RemoteBusyConditionInfo == TRUE) + { + /* Notify the upper layer */ + psLocalLlcpSocket->pSocketErrCb(psLocalLlcpSocket->pContext,PHFRINFC_LLCP_ERR_NOT_BUSY_CONDITION); + psLocalLlcpSocket->RemoteBusyConditionInfo = FALSE; + } + /* Update VSA */ + psLocalLlcpSocket->socket_VSA = (uint8_t)sLlcpLocalSequence.nr; + + /* Test if a send is pendind */ + if(psLocalLlcpSocket->bSocketSendPending == TRUE) + { + /* Test the RW window */ + if(CHECK_SEND_RW(psLocalLlcpSocket)) + { + /* Test if a send is pending at LLC layer */ + if(!testAndSetSendPending(psLocalLlcpSocket->psTransport)) + { + status = static_performSendInfo(psLocalLlcpSocket); + if (status != NFCSTATUS_SUCCESS && status != NFCSTATUS_PENDING) { + clearSendPending(psTransport); + } + } + } + } + } + } + else + { + /* No active socket*/ + /* RR Frame not handled*/ + } +} + +static void Handle_ReceiveNotReady_Frame(phFriNfc_LlcpTransport_t *psTransport, + phNfc_sData_t *psData, + uint8_t dsap, + uint8_t ssap) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t index; + uint8_t socketFound = FALSE; + bool_t bWFlag = 0; + bool_t bIFlag = 0; + bool_t bRFlag = 0; + bool_t bSFlag = 0; + uint32_t offset = 0; + uint8_t nr_val; + + phFriNfc_LlcpTransport_Socket_t* psLocalLlcpSocket = NULL; + phFriNfc_Llcp_sPacketSequence_t sLlcpLocalSequence; + + /* Get NS and NR Value of the I Frame*/ + phFriNfc_Llcp_Buffer2Sequence( psData->buffer, offset, &sLlcpLocalSequence); + + /* Search a socket waiting for an RNR FRAME (Connected State) */ + for(index=0;indexpSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnected + && psTransport->pSocketTable[index].socket_sSap == dsap + && psTransport->pSocketTable[index].socket_dSap == ssap) + { + /* socket found */ + socketFound = TRUE; + + /* Store a pointer to the socket found */ + psLocalLlcpSocket = &psTransport->pSocketTable[index]; + break; + } + } + + /* Test if a socket has been found */ + if(socketFound) + { + /* Test NR */ + nr_val = (uint8_t)sLlcpLocalSequence.nr; + do + { + + if(nr_val == psLocalLlcpSocket->socket_VS) + { + break; + } + + nr_val = (nr_val+1)%16; + + if(nr_val == psLocalLlcpSocket->socket_VSA) + { + /* FRMR 0x02 */ + bRFlag = TRUE; + break; + } + }while(nr_val != sLlcpLocalSequence.nr); + + /* Test if Info field present */ + if(psData->length > 1) + { + /* Send FRMR */ + bWFlag = TRUE; + bIFlag = TRUE; + } + + if( bWFlag != 0 || bIFlag != 0 || bRFlag != 0 || bSFlag != 0) + { + /* Send FRMR */ + status = phFriNfc_LlcpTransport_SendFrameReject(psTransport, + dsap, PHFRINFC_LLCP_PTYPE_RNR, ssap, + &sLlcpLocalSequence, + bWFlag, bIFlag, bRFlag, bSFlag, + psLocalLlcpSocket->socket_VS, + psLocalLlcpSocket->socket_VSA, + psLocalLlcpSocket->socket_VR, + psLocalLlcpSocket->socket_VRA); + } + else + { + /* Notify the upper layer */ + psLocalLlcpSocket->pSocketErrCb(psTransport->pSocketTable[index].pContext,PHFRINFC_LLCP_ERR_BUSY_CONDITION); + psLocalLlcpSocket->RemoteBusyConditionInfo = TRUE; + + /* Update VSA */ + psLocalLlcpSocket->socket_VSA = (uint8_t)sLlcpLocalSequence.nr; + + /* Test if a send is pendind */ + if(psLocalLlcpSocket->bSocketSendPending == TRUE && CHECK_SEND_RW(psLocalLlcpSocket)) + { + /* Test if a send is pending at LLC layer */ + if(!testAndSetSendPending(psLocalLlcpSocket->psTransport)) + { + status = static_performSendInfo(psLocalLlcpSocket); + if (status != NFCSTATUS_SUCCESS && status != NFCSTATUS_PENDING) { + clearSendPending(psTransport); + } + } + } + } + } + else + { + /* No active socket*/ + /* RNR Frame not handled*/ + } +} + +static void Handle_FrameReject_Frame(phFriNfc_LlcpTransport_t *psTransport, + uint8_t dsap, + uint8_t ssap) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t index; + uint8_t socketFound = FALSE; + + /* Search a socket waiting for a FRAME */ + for(index=0;indexpSocketTable[index].socket_sSap == dsap + && psTransport->pSocketTable[index].socket_dSap == ssap) + { + /* socket found */ + socketFound = TRUE; + break; + } + } + + /* Test if a socket has been found */ + if(socketFound) + { + /* Set socket state to disconnected */ + psTransport->pSocketTable[index].eSocket_State = phFriNfc_LlcpTransportSocket_eSocketDisconnected; + + /* Call ErrCB due to a FRMR*/ + psTransport->pSocketTable[index].pSocketErrCb( psTransport->pSocketTable[index].pContext,PHFRINFC_LLCP_ERR_FRAME_REJECTED); + + /* Close the socket */ + status = phFriNfc_LlcpTransport_ConnectionOriented_Close(&psTransport->pSocketTable[index]); + } + else + { + /* No active socket*/ + /* FRMR Frame not handled*/ + } +} + +/* TODO: comment function Handle_ConnectionOriented_IncommingFrame */ +void Handle_ConnectionOriented_IncommingFrame(phFriNfc_LlcpTransport_t *psTransport, + phNfc_sData_t *psData, + uint8_t dsap, + uint8_t ptype, + uint8_t ssap) +{ + phFriNfc_Llcp_sPacketSequence_t sSequence = {0,0}; + + switch(ptype) + { + case PHFRINFC_LLCP_PTYPE_CONNECT: + { + Handle_ConnectionFrame(psTransport, + psData, + dsap, + ssap); + }break; + + case PHFRINFC_LLCP_PTYPE_DISC: + { + Handle_DisconnectFrame(psTransport, + dsap, + ssap); + }break; + + case PHFRINFC_LLCP_PTYPE_CC: + { + Handle_ConnectionCompleteFrame(psTransport, + psData, + dsap, + ssap); + }break; + + case PHFRINFC_LLCP_PTYPE_DM: + { + Handle_DisconnetModeFrame(psTransport, + psData, + dsap, + ssap); + }break; + + case PHFRINFC_LLCP_PTYPE_FRMR: + { + Handle_FrameReject_Frame(psTransport, + dsap, + ssap); + }break; + + case PHFRINFC_LLCP_PTYPE_I: + { + Handle_Receive_IFrame(psTransport, + psData, + dsap, + ssap); + }break; + + case PHFRINFC_LLCP_PTYPE_RR: + { + Handle_ReceiveReady_Frame(psTransport, + psData, + dsap, + ssap); + }break; + + case PHFRINFC_LLCP_PTYPE_RNR: + { + Handle_ReceiveNotReady_Frame(psTransport, + psData, + dsap, + ssap); + }break; + + case PHFRINFC_LLCP_PTYPE_RESERVED1: + case PHFRINFC_LLCP_PTYPE_RESERVED2: + case PHFRINFC_LLCP_PTYPE_RESERVED3: + { + phFriNfc_LlcpTransport_SendFrameReject( psTransport, + dsap, ptype, ssap, + &sSequence, + TRUE, FALSE, FALSE, FALSE, + 0, 0, 0, 0); + }break; + } +} + +/** +* \ingroup grp_lib_nfc +* \brief Get the local options of a socket. +* +* This function returns the local options (maximum packet size and receive window size) used +* for a given connection-oriented socket. This function shall not be used with connectionless +* sockets. +* +* \param[out] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psLocalOptions A pointer to be filled with the local options of the socket. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_SocketGetLocalOptions(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + phLibNfc_Llcp_sSocketOptions_t *psLocalOptions) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Get Local MIUX */ + psLocalOptions->miu = pLlcpSocket->sSocketOption.miu; + + /* Get Local Receive Window */ + psLocalOptions->rw = pLlcpSocket->sSocketOption.rw; + + return status; +} + +/** +* \ingroup grp_lib_nfc +* \brief Get the local options of a socket. +* +* This function returns the remote options (maximum packet size and receive window size) used +* for a given connection-oriented socket. This function shall not be used with connectionless +* sockets. +* +* \param[out] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psRemoteOptions A pointer to be filled with the remote options of the socket. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_SocketGetRemoteOptions(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phLibNfc_Llcp_sSocketOptions_t* psRemoteOptions) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Get Remote MIUX */ + psRemoteOptions->miu = pLlcpSocket->remoteMIU; + + /* Get Remote Receive Window */ + psRemoteOptions->rw = pLlcpSocket->remoteRW; + + return status; +} + + +/** +* \ingroup grp_fri_nfc +* \brief Listen for incoming connection requests on a socket. +* +* This function switches a socket into a listening state and registers a callback on +* incoming connection requests. In this state, the socket is not able to communicate +* directly. The listening state is only available for connection-oriented sockets +* which are still not connected. The socket keeps listening until it is closed, and +* thus can trigger several times the pListen_Cb callback. +* +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] pListen_Cb The callback to be called each time the +* socket receive a connection request. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state to switch +* to listening state. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_Listen(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + pphFriNfc_LlcpTransportSocketListenCb_t pListen_Cb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Store the listen callback */ + pLlcpSocket->pfSocketListen_Cb = pListen_Cb; + + /* store the context */ + pLlcpSocket->pListenContext = pContext; + + /* Set RecvPending to TRUE */ + pLlcpSocket->bSocketListenPending = TRUE; + + /* Set the socket state*/ + pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketRegistered; + + return status; +} + +/** +* \ingroup grp_fri_nfc +* \brief Accept an incoming connection request for a socket. +* +* This functions allows the client to accept an incoming connection request. +* It must be used with the socket provided within the listen callback. The socket +* is implicitly switched to the connected state when the function is called. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psOptions The options to be used with the socket. +* \param[in] psWorkingBuffer A working buffer to be used by the library. +* \param[in] pErr_Cb The callback to be called each time the accepted socket +* is in error. +* \param[in] pAccept_RspCb The callback to be called when the Accept operation is completed +* \param[in] pContext Upper layer context to be returned in the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_BUFFER_TOO_SMALL The working buffer is too small for the MIU and RW +* declared in the options. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_Accept(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phFriNfc_LlcpTransport_sSocketOptions_t* psOptions, + phNfc_sData_t* psWorkingBuffer, + pphFriNfc_LlcpTransportSocketErrCb_t pErr_Cb, + pphFriNfc_LlcpTransportSocketAcceptCb_t pAccept_RspCb, + void* pContext) + +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + uint32_t offset = 0; + uint8_t miux[2]; + uint8_t i; + /* Store the options in the socket */ + memcpy(&pLlcpSocket->sSocketOption, psOptions, sizeof(phFriNfc_LlcpTransport_sSocketOptions_t)); + + /* Set socket local params (MIUX & RW) */ + pLlcpSocket ->localMIUX = (pLlcpSocket->sSocketOption.miu - PHFRINFC_LLCP_MIU_DEFAULT) & PHFRINFC_LLCP_TLV_MIUX_MASK; + pLlcpSocket ->localRW = pLlcpSocket->sSocketOption.rw & PHFRINFC_LLCP_TLV_RW_MASK; + + /* Set the pointer and the length for the Receive Window Buffer */ + for(i=0;ilocalRW;i++) + { + pLlcpSocket->sSocketRwBufferTable[i].buffer = psWorkingBuffer->buffer + (i*pLlcpSocket->sSocketOption.miu); + pLlcpSocket->sSocketRwBufferTable[i].length = 0; + } + + /* Set the pointer and the length for the Send Buffer */ + pLlcpSocket->sSocketSendBuffer.buffer = psWorkingBuffer->buffer + pLlcpSocket->bufferRwMaxLength; + pLlcpSocket->sSocketSendBuffer.length = pLlcpSocket->bufferSendMaxLength; + + /* Set the pointer and the length for the Linear Buffer */ + pLlcpSocket->sSocketLinearBuffer.buffer = psWorkingBuffer->buffer + pLlcpSocket->bufferRwMaxLength + pLlcpSocket->bufferSendMaxLength; + pLlcpSocket->sSocketLinearBuffer.length = pLlcpSocket->bufferLinearLength; + + if(pLlcpSocket->sSocketLinearBuffer.length != 0) + { + /* Init Cyclic Fifo */ + phFriNfc_Llcp_CyclicFifoInit(&pLlcpSocket->sCyclicFifoBuffer, + pLlcpSocket->sSocketLinearBuffer.buffer, + pLlcpSocket->sSocketLinearBuffer.length); + } + + pLlcpSocket->pSocketErrCb = pErr_Cb; + pLlcpSocket->pContext = pContext; + + /* store the pointer to the Accept callback */ + pLlcpSocket->pfSocketAccept_Cb = pAccept_RspCb; + pLlcpSocket->pAcceptContext = pContext; + + /* Reset the socket_VS,socket_VR,socket_VSA and socket_VRA variables */ + pLlcpSocket->socket_VR = 0; + pLlcpSocket->socket_VRA = 0; + pLlcpSocket->socket_VS = 0; + pLlcpSocket->socket_VSA = 0; + + /* MIUX */ + if(pLlcpSocket->localMIUX != PHFRINFC_LLCP_MIUX_DEFAULT) + { + /* Encode MIUX value */ + phFriNfc_Llcp_EncodeMIUX(pLlcpSocket->localMIUX, + miux); + + /* Encode MIUX in TLV format */ + status = phFriNfc_Llcp_EncodeTLV(&pLlcpSocket->sSocketSendBuffer, + &offset, + PHFRINFC_LLCP_TLV_TYPE_MIUX, + PHFRINFC_LLCP_TLV_LENGTH_MIUX, + miux); + if(status != NFCSTATUS_SUCCESS) + { + /* Call the CB */ + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_FAILED); + goto clean_and_return; + } + } + + /* Receive Window */ + if(pLlcpSocket->sSocketOption.rw != PHFRINFC_LLCP_RW_DEFAULT) + { + /* Encode RW value */ + phFriNfc_Llcp_EncodeRW(&pLlcpSocket->sSocketOption.rw); + + /* Encode RW in TLV format */ + status = phFriNfc_Llcp_EncodeTLV(&pLlcpSocket->sSocketSendBuffer, + &offset, + PHFRINFC_LLCP_TLV_TYPE_RW, + PHFRINFC_LLCP_TLV_LENGTH_RW, + &pLlcpSocket->sSocketOption.rw); + if(status != NFCSTATUS_SUCCESS) + { + /* Call the CB */ + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_FAILED); + goto clean_and_return; + } + } + + + /* Test if a send is pending */ + if(testAndSetSendPending(pLlcpSocket->psTransport)) + { + pLlcpSocket->bSocketAcceptPending = TRUE; + + /* Update Send Buffer length value */ + pLlcpSocket->sSocketSendBuffer.length = offset; + + status = NFCSTATUS_PENDING; + } + else + { + /* Fill the psLlcpHeader stuture with the DSAP,CC PTYPE and the SSAP */ + pLlcpSocket->sLlcpHeader.dsap = pLlcpSocket->socket_dSap; + pLlcpSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_CC; + pLlcpSocket->sLlcpHeader.ssap = pLlcpSocket->socket_sSap; + + /* Set the socket state to accepted */ + pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketAccepted; + + /* Update Send Buffer length value */ + pLlcpSocket->sSocketSendBuffer.length = offset; + + /* Send a CC Frame */ + status = phFriNfc_LlcpTransport_LinkSend(pLlcpSocket->psTransport, + &pLlcpSocket->sLlcpHeader, + NULL, + &pLlcpSocket->sSocketSendBuffer, + phFriNfc_LlcpTransport_ConnectionOriented_SendLlcp_CB, + pLlcpSocket->index, + pLlcpSocket->psTransport); + if (status != NFCSTATUS_SUCCESS && status != NFCSTATUS_PENDING) { + clearSendPending(pLlcpSocket->psTransport); + } + } + +clean_and_return: + if(status != NFCSTATUS_PENDING) + { + LLCP_PRINT("Release Accept callback"); + pLlcpSocket->pfSocketAccept_Cb = NULL; + pLlcpSocket->pAcceptContext = NULL; + } + + return status; +} + + /** +* \ingroup grp_fri_nfc +* \brief Reject an incoming connection request for a socket. +* +* This functions allows the client to reject an incoming connection request. +* It must be used with the socket provided within the listen callback. The socket +* is implicitly closed when the function is called. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phLibNfc_LlcpTransport_ConnectionOriented_Reject( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + pphFriNfc_LlcpTransportSocketRejectCb_t pReject_RspCb, + void *pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Set the state of the socket */ + pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketRejected; + + /* Store the Reject callback */ + pLlcpSocket->pfSocketSend_Cb = pReject_RspCb; + pLlcpSocket->pRejectContext = pContext; + + /* Send a DM*/ + status = phFriNfc_LlcpTransport_SendDisconnectMode(pLlcpSocket->psTransport, + pLlcpSocket->socket_dSap, + pLlcpSocket->socket_sSap, + PHFRINFC_LLCP_DM_OPCODE_CONNECT_REJECTED); + + return status; +} + +/** +* \ingroup grp_fri_nfc +* \brief Try to establish connection with a socket on a remote SAP. +* +* This function tries to connect to a given SAP on the remote peer. If the +* socket is not bound to a local SAP, it is implicitly bound to a free SAP. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] nSap The destination SAP to connect to. +* \param[in] psUri The URI corresponding to the destination SAP to connect to. +* \param[in] pConnect_RspCb The callback to be called when the connection +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Connection operation is in progress, +* pConnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_Connect( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + uint8_t nSap, + phNfc_sData_t* psUri, + pphFriNfc_LlcpTransportSocketConnectCb_t pConnect_RspCb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint32_t offset = 0; + uint8_t miux[2]; + + /* Test if a nSap is present */ + if(nSap != PHFRINFC_LLCP_SAP_DEFAULT) + { + /* Set DSAP port number with the nSap value */ + pLlcpSocket->socket_dSap = nSap; + } + else + { + /* Set DSAP port number with the SDP port number */ + pLlcpSocket->socket_dSap = PHFRINFC_LLCP_SAP_SDP; + } + + /* Store the Connect callback and context */ + pLlcpSocket->pfSocketConnect_Cb = pConnect_RspCb; + pLlcpSocket->pConnectContext = pContext; + + /* Set the socket Header */ + pLlcpSocket->sLlcpHeader.dsap = pLlcpSocket->socket_dSap; + pLlcpSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_CONNECT; + pLlcpSocket->sLlcpHeader.ssap = pLlcpSocket->socket_sSap; + + /* MIUX */ + if(pLlcpSocket->localMIUX != PHFRINFC_LLCP_MIUX_DEFAULT) + { + /* Encode MIUX value */ + phFriNfc_Llcp_EncodeMIUX(pLlcpSocket->localMIUX, + miux); + + /* Encode MIUX in TLV format */ + status = phFriNfc_Llcp_EncodeTLV(&pLlcpSocket->sSocketSendBuffer, + &offset, + PHFRINFC_LLCP_TLV_TYPE_MIUX, + PHFRINFC_LLCP_TLV_LENGTH_MIUX, + miux); + if(status != NFCSTATUS_SUCCESS) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_FAILED); + goto clean_and_return; + } + } + + /* Receive Window */ + if(pLlcpSocket->sSocketOption.rw != PHFRINFC_LLCP_RW_DEFAULT) + { + /* Encode RW value */ + phFriNfc_Llcp_EncodeRW(&pLlcpSocket->sSocketOption.rw); + + /* Encode RW in TLV format */ + status = phFriNfc_Llcp_EncodeTLV(&pLlcpSocket->sSocketSendBuffer, + &offset, + PHFRINFC_LLCP_TLV_TYPE_RW, + PHFRINFC_LLCP_TLV_LENGTH_RW, + &pLlcpSocket->sSocketOption.rw); + if(status != NFCSTATUS_SUCCESS) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_FAILED); + goto clean_and_return; + } + } + + /* Test if a Service Name is present */ + if(psUri != NULL) + { + /* Encode SN in TLV format */ + status = phFriNfc_Llcp_EncodeTLV(&pLlcpSocket->sSocketSendBuffer, + &offset, + PHFRINFC_LLCP_TLV_TYPE_SN, + (uint8_t)psUri->length, + psUri->buffer); + if(status != NFCSTATUS_SUCCESS) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_FAILED); + goto clean_and_return; + } + } + + /* Test if a send is pending */ + if(testAndSetSendPending(pLlcpSocket->psTransport)) + { + pLlcpSocket->bSocketConnectPending = TRUE; + + /* Update Send Buffer length value */ + pLlcpSocket->sSocketSendBuffer.length = offset; + + status = NFCSTATUS_PENDING; + } + else + { + /* Update Send Buffer length value */ + pLlcpSocket->sSocketSendBuffer.length = offset; + + /* Set the socket in connecting state */ + pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketConnecting; + + status = phFriNfc_LlcpTransport_LinkSend(pLlcpSocket->psTransport, + &pLlcpSocket->sLlcpHeader, + NULL, + &pLlcpSocket->sSocketSendBuffer, + phFriNfc_LlcpTransport_ConnectionOriented_SendLlcp_CB, + pLlcpSocket->index, + pLlcpSocket->psTransport); + if (status != NFCSTATUS_SUCCESS && status != NFCSTATUS_PENDING) { + clearSendPending(pLlcpSocket->psTransport); + } + } + +clean_and_return: + if(status != NFCSTATUS_PENDING) + { + LLCP_PRINT("Release Connect callback"); + pLlcpSocket->pfSocketConnect_Cb = NULL; + pLlcpSocket->pConnectContext = NULL; + } + + return status; +} + + +/** +* \ingroup grp_lib_nfc +* \brief Disconnect a currently connected socket. +* +* This function initiates the disconnection of a previously connected socket. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] pDisconnect_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Disconnection operation is in progress, +* pDisconnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phLibNfc_LlcpTransport_ConnectionOriented_Disconnect(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + pphLibNfc_LlcpSocketDisconnectCb_t pDisconnect_RspCb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Store the Disconnect callback and context*/ + pLlcpSocket->pfSocketDisconnect_Cb = pDisconnect_RspCb; + pLlcpSocket->pDisconnectContext = pContext; + + /* Set the socket in connecting state */ + pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketDisconnecting; + + /* Test if a send IFRAME is pending with this socket */ + if((pLlcpSocket->bSocketSendPending == TRUE) || (pLlcpSocket->bSocketRecvPending == TRUE)) + { + pLlcpSocket->bSocketSendPending = FALSE; + pLlcpSocket->bSocketRecvPending = FALSE; + + /* Call the send CB, a disconnect abort the send request */ + if (pLlcpSocket->pfSocketSend_Cb != NULL) + { + /* Copy CB + context in local variables */ + pphFriNfc_LlcpTransportSocketSendCb_t pfSendCb = pLlcpSocket->pfSocketSend_Cb; + void* pSendContext = pLlcpSocket->pSendContext; + /* Reset CB + context */ + pLlcpSocket->pfSocketSend_Cb = NULL; + pLlcpSocket->pSendContext = NULL; + /* Perform callback */ + pfSendCb(pSendContext, NFCSTATUS_FAILED); + } + /* Call the send CB, a disconnect abort the receive request */ + if (pLlcpSocket->pfSocketRecv_Cb != NULL) + { + /* Copy CB + context in local variables */ + pphFriNfc_LlcpTransportSocketRecvCb_t pfRecvCb = pLlcpSocket->pfSocketRecv_Cb; + void* pRecvContext = pLlcpSocket->pRecvContext; + /* Reset CB + context */ + pLlcpSocket->pfSocketRecv_Cb = NULL; + pLlcpSocket->pRecvContext = NULL; + /* Perform callback */ + pfRecvCb(pRecvContext, NFCSTATUS_FAILED); + } + } + + /* Test if a send is pending */ + if( testAndSetSendPending(pLlcpSocket->psTransport)) + { + pLlcpSocket->bSocketDiscPending = TRUE; + status = NFCSTATUS_PENDING; + } + else + { + /* Set the socket Header */ + pLlcpSocket->sLlcpHeader.dsap = pLlcpSocket->socket_dSap; + pLlcpSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC; + pLlcpSocket->sLlcpHeader.ssap = pLlcpSocket->socket_sSap; + + status = phFriNfc_LlcpTransport_LinkSend(pLlcpSocket->psTransport, + &pLlcpSocket->sLlcpHeader, + NULL, + NULL, + phFriNfc_LlcpTransport_ConnectionOriented_SendLlcp_CB, + pLlcpSocket->index, + pLlcpSocket->psTransport); + if(status != NFCSTATUS_SUCCESS && status != NFCSTATUS_PENDING) + { + clearSendPending(pLlcpSocket->psTransport); + LLCP_PRINT("Release Disconnect callback"); + pLlcpSocket->pfSocketDisconnect_Cb = NULL; + pLlcpSocket->pDisconnectContext = NULL; + } + } + + return status; +} + +/* TODO: comment function phFriNfc_LlcpTransport_Connectionless_SendTo_CB */ +static void phFriNfc_LlcpTransport_ConnectionOriented_DisconnectClose_CB(void* pContext, + NFCSTATUS status) +{ + phFriNfc_LlcpTransport_Socket_t *pLlcpSocket = (phFriNfc_LlcpTransport_Socket_t*)pContext; + + if(status == NFCSTATUS_SUCCESS) + { + /* Reset the pointer to the socket closed */ + pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketDefault; + pLlcpSocket->eSocket_Type = phFriNfc_LlcpTransport_eDefaultType; + pLlcpSocket->pContext = NULL; + pLlcpSocket->pSocketErrCb = NULL; + pLlcpSocket->socket_sSap = PHFRINFC_LLCP_SAP_DEFAULT; + pLlcpSocket->socket_dSap = PHFRINFC_LLCP_SAP_DEFAULT; + pLlcpSocket->bSocketRecvPending = FALSE; + pLlcpSocket->bSocketSendPending = FALSE; + pLlcpSocket->bSocketListenPending = FALSE; + pLlcpSocket->bSocketDiscPending = FALSE; + pLlcpSocket->socket_VS = 0; + pLlcpSocket->socket_VSA = 0; + pLlcpSocket->socket_VR = 0; + pLlcpSocket->socket_VRA = 0; + + pLlcpSocket->indexRwRead = 0; + pLlcpSocket->indexRwWrite = 0; + + phFriNfc_LlcpTransport_ConnectionOriented_Abort(pLlcpSocket); + + memset(&pLlcpSocket->sSocketOption, 0x00, sizeof(phFriNfc_LlcpTransport_sSocketOptions_t)); + + if (pLlcpSocket->sServiceName.buffer != NULL) { + phOsalNfc_FreeMemory(pLlcpSocket->sServiceName.buffer); + } + pLlcpSocket->sServiceName.buffer = NULL; + pLlcpSocket->sServiceName.length = 0; + } + else + { + /* Disconnect close Error */ + } +} + +/** +* \ingroup grp_fri_nfc +* \brief Close a socket on a LLCP-connected device. +* +* This function closes a LLCP socket previously created using phFriNfc_LlcpTransport_Socket. +* If the socket was connected, it is first disconnected, and then closed. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. + +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_Close(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if(pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnected) + { + status = phLibNfc_LlcpTransport_ConnectionOriented_Disconnect(pLlcpSocket, + phFriNfc_LlcpTransport_ConnectionOriented_DisconnectClose_CB, + pLlcpSocket); + } + else + { + LLCP_PRINT("Socket not connected, no need to disconnect"); + /* Reset the pointer to the socket closed */ + pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketDefault; + pLlcpSocket->eSocket_Type = phFriNfc_LlcpTransport_eDefaultType; + pLlcpSocket->pContext = NULL; + pLlcpSocket->pSocketErrCb = NULL; + pLlcpSocket->socket_sSap = PHFRINFC_LLCP_SAP_DEFAULT; + pLlcpSocket->socket_dSap = PHFRINFC_LLCP_SAP_DEFAULT; + pLlcpSocket->bSocketRecvPending = FALSE; + pLlcpSocket->bSocketSendPending = FALSE; + pLlcpSocket->bSocketListenPending = FALSE; + pLlcpSocket->bSocketDiscPending = FALSE; + pLlcpSocket->RemoteBusyConditionInfo = FALSE; + pLlcpSocket->ReceiverBusyCondition = FALSE; + pLlcpSocket->socket_VS = 0; + pLlcpSocket->socket_VSA = 0; + pLlcpSocket->socket_VR = 0; + pLlcpSocket->socket_VRA = 0; + + pLlcpSocket->indexRwRead = 0; + pLlcpSocket->indexRwWrite = 0; + + phFriNfc_LlcpTransport_ConnectionOriented_Abort(pLlcpSocket); + + memset(&pLlcpSocket->sSocketOption, 0x00, sizeof(phFriNfc_LlcpTransport_sSocketOptions_t)); + + if (pLlcpSocket->sServiceName.buffer != NULL) { + phOsalNfc_FreeMemory(pLlcpSocket->sServiceName.buffer); + } + pLlcpSocket->sServiceName.buffer = NULL; + pLlcpSocket->sServiceName.length = 0; + } + return NFCSTATUS_SUCCESS; +} + + +/** +* \ingroup grp_fri_nfc +* \brief Send data on a socket. +* +* This function is used to write data on a socket. This function +* can only be called on a connection-oriented socket which is already +* in a connected state. +* +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psBuffer The buffer containing the data to send. +* \param[in] pSend_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pSend_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_Send(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + + /* Test the RW window */ + if(!CHECK_SEND_RW(pLlcpSocket)) + { + /* Store the Send CB and context */ + pLlcpSocket->pfSocketSend_Cb = pSend_RspCb; + pLlcpSocket->pSendContext = pContext; + + /* Set Send pending */ + pLlcpSocket->bSocketSendPending = TRUE; + + /* Store send buffer pointer */ + pLlcpSocket->sSocketSendBuffer = *psBuffer; + + /* Set status */ + status = NFCSTATUS_PENDING; + } + else + { + /* Store send buffer pointer */ + pLlcpSocket->sSocketSendBuffer = *psBuffer; + + /* Store the Send CB and context */ + pLlcpSocket->pfSocketSend_Cb = pSend_RspCb; + pLlcpSocket->pSendContext = pContext; + + /* Test if a send is pending */ + if(testAndSetSendPending(pLlcpSocket->psTransport)) + { + /* Set Send pending */ + pLlcpSocket->bSocketSendPending = TRUE; + + /* Set status */ + status = NFCSTATUS_PENDING; + } + else + { + /* Store the Send CB and context */ + pLlcpSocket->pfSocketSend_Cb = pSend_RspCb; + pLlcpSocket->pSendContext = pContext; + + status = static_performSendInfo(pLlcpSocket); + + if(status != NFCSTATUS_SUCCESS && status != NFCSTATUS_PENDING) + { + clearSendPending(pLlcpSocket->psTransport); + LLCP_PRINT("Release Send callback"); + pLlcpSocket->pfSocketSend_Cb = NULL; + pLlcpSocket->pSendContext = NULL; + } + } + + } + return status; +} + + + /** +* \ingroup grp_fri_nfc +* \brief Read data on a socket. +* +* This function is used to read data from a socket. It reads at most the +* size of the reception buffer, but can also return less bytes if less bytes +* are available. If no data is available, the function will be pending until +* more data comes, and the response will be sent by the callback. This function +* can only be called on a connection-oriented socket. +* +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psBuffer The buffer receiving the data. +* \param[in] pRecv_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pRecv_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_Recv( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketRecvCb_t pRecv_RspCb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint32_t dataLengthStored = 0; + uint32_t dataLengthAvailable = 0; + uint32_t dataLengthRead = 0; + uint32_t dataLengthWrite = 0; + bool_t dataBufferized = FALSE; + + /* Test if the WorkingBuffer Length is null */ + if(pLlcpSocket->bufferLinearLength == 0) + { + if (pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketConnected) + { + return NFCSTATUS_FAILED; + } + + /* Test If data is present in the RW Buffer */ + if(pLlcpSocket->indexRwRead != pLlcpSocket->indexRwWrite) + { + if(pLlcpSocket->sSocketRwBufferTable[(pLlcpSocket->indexRwRead%pLlcpSocket->localRW)].length != 0) + { + /* Save I_FRAME into the Receive Buffer */ + memcpy(psBuffer->buffer,pLlcpSocket->sSocketRwBufferTable[(pLlcpSocket->indexRwRead%pLlcpSocket->localRW)].buffer,pLlcpSocket->sSocketRwBufferTable[(pLlcpSocket->indexRwRead%pLlcpSocket->localRW)].length); + psBuffer->length = pLlcpSocket->sSocketRwBufferTable[(pLlcpSocket->indexRwRead%pLlcpSocket->localRW)].length; + + dataBufferized = TRUE; + + /* Update VR */ + pLlcpSocket->socket_VR = (pLlcpSocket->socket_VR+1)%16; + + /* Update RW Buffer length */ + pLlcpSocket->sSocketRwBufferTable[(pLlcpSocket->indexRwRead%pLlcpSocket->localRW)].length = 0; + + /* Update Value Rw Read Index*/ + pLlcpSocket->indexRwRead++; + } + } + + if(dataBufferized == TRUE) + { + /* Call the Receive CB */ + pRecv_RspCb(pContext,NFCSTATUS_SUCCESS); + + if(pLlcpSocket->ReceiverBusyCondition == TRUE) + { + /* Reset the ReceiverBusyCondition Flag */ + pLlcpSocket->ReceiverBusyCondition = FALSE; + /* RR */ + /* TODO: report status? */ + phFriNfc_Llcp_Send_ReceiveReady_Frame(pLlcpSocket); + } + } + else + { + /* Set Receive pending */ + pLlcpSocket->bSocketRecvPending = TRUE; + + /* Store the buffer pointer */ + pLlcpSocket->sSocketRecvBuffer = psBuffer; + + /* Store the Recv CB and context */ + pLlcpSocket->pfSocketRecv_Cb = pRecv_RspCb; + pLlcpSocket->pRecvContext = pContext; + + /* Set status */ + status = NFCSTATUS_PENDING; + } + } + else + { + /* Test if data is present in the linear buffer*/ + dataLengthStored = phFriNfc_Llcp_CyclicFifoUsage(&pLlcpSocket->sCyclicFifoBuffer); + + if(dataLengthStored != 0) + { + if(psBuffer->length > dataLengthStored) + { + psBuffer->length = dataLengthStored; + } + + /* Read data from the linear buffer */ + dataLengthRead = phFriNfc_Llcp_CyclicFifoFifoRead(&pLlcpSocket->sCyclicFifoBuffer, + psBuffer->buffer, + psBuffer->length); + + if(dataLengthRead != 0) + { + /* Test If data is present in the RW Buffer */ + while(pLlcpSocket->indexRwRead != pLlcpSocket->indexRwWrite) + { + /* Get the data length available in the linear buffer */ + dataLengthAvailable = phFriNfc_Llcp_CyclicFifoAvailable(&pLlcpSocket->sCyclicFifoBuffer); + + /* Exit if not enough memory available in linear buffer */ + if(dataLengthAvailable < pLlcpSocket->sSocketRwBufferTable[(pLlcpSocket->indexRwRead%pLlcpSocket->localRW)].length) + { + break; + } + + /* Write data into the linear buffer */ + dataLengthWrite = phFriNfc_Llcp_CyclicFifoWrite(&pLlcpSocket->sCyclicFifoBuffer, + pLlcpSocket->sSocketRwBufferTable[(pLlcpSocket->indexRwRead%pLlcpSocket->localRW)].buffer, + pLlcpSocket->sSocketRwBufferTable[(pLlcpSocket->indexRwRead%pLlcpSocket->localRW)].length); + /* Update VR */ + pLlcpSocket->socket_VR = (pLlcpSocket->socket_VR+1)%16; + + /* Set flag bufferized to TRUE */ + dataBufferized = TRUE; + + /* Update RW Buffer length */ + pLlcpSocket->sSocketRwBufferTable[(pLlcpSocket->indexRwRead%pLlcpSocket->localRW)].length = 0; + + /* Update Value Rw Read Index*/ + pLlcpSocket->indexRwRead++; + } + + /* Test if data has been bufferized after a read access */ + if(dataBufferized == TRUE) + { + /* Get the data length available in the linear buffer */ + dataLengthAvailable = phFriNfc_Llcp_CyclicFifoAvailable(&pLlcpSocket->sCyclicFifoBuffer); + if((dataLengthAvailable >= pLlcpSocket->sSocketOption.miu) && (pLlcpSocket->ReceiverBusyCondition == TRUE)) + { + /* Reset the ReceiverBusyCondition Flag */ + pLlcpSocket->ReceiverBusyCondition = FALSE; + /* RR */ + /* TODO: report status? */ + phFriNfc_Llcp_Send_ReceiveReady_Frame(pLlcpSocket); + } + } + + /* Call the Receive CB */ + pRecv_RspCb(pContext,NFCSTATUS_SUCCESS); + } + else + { + /* Call the Receive CB */ + status = NFCSTATUS_FAILED; + } + } + else + { + if (pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketConnected) + { + status = NFCSTATUS_FAILED; + } + else + { + /* Set Receive pending */ + pLlcpSocket->bSocketRecvPending = TRUE; + + /* Store the buffer pointer */ + pLlcpSocket->sSocketRecvBuffer = psBuffer; + + /* Store the Recv CB and context */ + pLlcpSocket->pfSocketRecv_Cb = pRecv_RspCb; + pLlcpSocket->pRecvContext = pContext; + + /* Set status */ + status = NFCSTATUS_PENDING; + } + } + } + + if(status != NFCSTATUS_PENDING) + { + /* Note: The receive callback must be released to avoid being called at abort */ + LLCP_PRINT("Release Receive callback"); + pLlcpSocket->pfSocketRecv_Cb = NULL; + pLlcpSocket->pRecvContext = NULL; + } + + return status; +} + + diff --git a/libnfc-nxp/phFriNfc_LlcpTransport_Connection.h b/libnfc-nxp/phFriNfc_LlcpTransport_Connection.h new file mode 100644 index 0000000..07ec1fb --- /dev/null +++ b/libnfc-nxp/phFriNfc_LlcpTransport_Connection.h @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_LlcpTransport_Connection.h + * \brief + * + * Project: NFC-FRI + * + */ +#ifndef PHFRINFC_LLCP_TRANSPORT_CONNECTION_H +#define PHFRINFC_LLCP_TRANSPORT_CONNECTION_H +/*include files*/ +#include +#include +#include + +#include + +void Handle_ConnectionOriented_IncommingFrame(phFriNfc_LlcpTransport_t *pLlcpTransport, + phNfc_sData_t *psData, + uint8_t dsap, + uint8_t ptype, + uint8_t ssap); + +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_HandlePendingOperations(phFriNfc_LlcpTransport_Socket_t *pSocket); + +/** +* \ingroup grp_lib_nfc +* \brief Get the local options of a socket. +* +* This function returns the local options (maximum packet size and receive window size) used +* for a given connection-oriented socket. This function shall not be used with connectionless +* sockets. +* +* \param[out] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psLocalOptions A pointer to be filled with the local options of the socket. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_SocketGetLocalOptions(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + phLibNfc_Llcp_sSocketOptions_t *psLocalOptions); + +/** +* \ingroup grp_lib_nfc +* \brief Get the local options of a socket. +* +* This function returns the remote options (maximum packet size and receive window size) used +* for a given connection-oriented socket. This function shall not be used with connectionless +* sockets. +* +* \param[out] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psRemoteOptions A pointer to be filled with the remote options of the socket. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_SocketGetRemoteOptions(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phLibNfc_Llcp_sSocketOptions_t* psRemoteOptions); + +/** +* \ingroup grp_fri_nfc +* \brief Close a socket on a LLCP-connected device. +* +* This function closes a LLCP socket previously created using phFriNfc_LlcpTransport_Socket. +* If the socket was connected, it is first disconnected, and then closed. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. + +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_Close(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket); + +/** +* \ingroup grp_fri_nfc +* \brief Listen for incoming connection requests on a socket. +* +* This function switches a socket into a listening state and registers a callback on +* incoming connection requests. In this state, the socket is not able to communicate +* directly. The listening state is only available for connection-oriented sockets +* which are still not connected. The socket keeps listening until it is closed, and +* thus can trigger several times the pListen_Cb callback. +* +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] pListen_Cb The callback to be called each time the +* socket receive a connection request. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state to switch +* to listening state. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_Listen(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + pphFriNfc_LlcpTransportSocketListenCb_t pListen_Cb, + void* pContext); + + +/** +* \ingroup grp_fri_nfc +* \brief Accept an incoming connection request for a socket. +* +* This functions allows the client to accept an incoming connection request. +* It must be used with the socket provided within the listen callback. The socket +* is implicitly switched to the connected state when the function is called. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psOptions The options to be used with the socket. +* \param[in] psWorkingBuffer A working buffer to be used by the library. +* \param[in] pErr_Cb The callback to be called each time the accepted socket +* is in error. +* \param[in] pAccept_RspCb The callback to be called when the Accept operation is completed +* \param[in] pContext Upper layer context to be returned in the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_BUFFER_TOO_SMALL The working buffer is too small for the MIU and RW +* declared in the options. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_Accept(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phFriNfc_LlcpTransport_sSocketOptions_t* psOptions, + phNfc_sData_t* psWorkingBuffer, + pphFriNfc_LlcpTransportSocketErrCb_t pErr_Cb, + pphFriNfc_LlcpTransportSocketAcceptCb_t pAccept_RspCb, + void* pContext); + + + /** +* \ingroup grp_fri_nfc +* \brief Reject an incoming connection request for a socket. +* +* This functions allows the client to reject an incoming connection request. +* It must be used with the socket provided within the listen callback. The socket +* is implicitly closed when the function is called. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] pReject_RspCb The callback to be called when the Reject operation is completed +* \param[in] pContext Upper layer context to be returned in the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phLibNfc_LlcpTransport_ConnectionOriented_Reject( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + pphFriNfc_LlcpTransportSocketRejectCb_t pReject_RspCb, + void *pContext); + +/** +* \ingroup grp_fri_nfc +* \brief Try to establish connection with a socket on a remote SAP. +* +* This function tries to connect to a given SAP on the remote peer. If the +* socket is not bound to a local SAP, it is implicitly bound to a free SAP. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] nSap The destination SAP to connect to. +* \param[in] psUri The URI corresponding to the destination SAP to connect to. +* \param[in] pConnect_RspCb The callback to be called when the connection +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Connection operation is in progress, +* pConnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_Connect( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + uint8_t nSap, + phNfc_sData_t* psUri, + pphFriNfc_LlcpTransportSocketConnectCb_t pConnect_RspCb, + void* pContext); + +/** +* \ingroup grp_lib_nfc +* \brief Disconnect a currently connected socket. +* +* This function initiates the disconnection of a previously connected socket. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] pDisconnect_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Disconnection operation is in progress, +* pDisconnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phLibNfc_LlcpTransport_ConnectionOriented_Disconnect(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + pphLibNfc_LlcpSocketDisconnectCb_t pDisconnect_RspCb, + void* pContext); + +/** +* \ingroup grp_fri_nfc +* \brief Send data on a socket. +* +* This function is used to write data on a socket. This function +* can only be called on a connection-oriented socket which is already +* in a connected state. +* +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psBuffer The buffer containing the data to send. +* \param[in] pSend_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pSend_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_Send(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb, + void* pContext); + + /** +* \ingroup grp_fri_nfc +* \brief Read data on a socket. +* +* This function is used to read data from a socket. It reads at most the +* size of the reception buffer, but can also return less bytes if less bytes +* are available. If no data is available, the function will be pending until +* more data comes, and the response will be sent by the callback. This function +* can only be called on a connection-oriented socket. +* +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. +* \param[in] psBuffer The buffer receiving the data. +* \param[in] pRecv_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pRecv_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_ConnectionOriented_Recv( phFriNfc_LlcpTransport_Socket_t* pLlcpSocket, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketRecvCb_t pRecv_RspCb, + void* pContext); +#endif /* PHFRINFC_LLCP_TRANSPORT_CONNECTION_H */ diff --git a/libnfc-nxp/phFriNfc_LlcpTransport_Connectionless.c b/libnfc-nxp/phFriNfc_LlcpTransport_Connectionless.c new file mode 100644 index 0000000..37bf14f --- /dev/null +++ b/libnfc-nxp/phFriNfc_LlcpTransport_Connectionless.c @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_LlcpTransport_Connectionless.c + * \brief + * + * Project: NFC-FRI + * + */ +/*include files*/ +#include +#include +#include +#include +#include +#include + +static void phFriNfc_LlcpTransport_Connectionless_SendTo_CB(void* pContext, + uint8_t socketIndex, + NFCSTATUS status); + +NFCSTATUS phFriNfc_LlcpTransport_Connectionless_HandlePendingOperations(phFriNfc_LlcpTransport_Socket_t *pSocket) +{ + NFCSTATUS status = NFCSTATUS_FAILED; + + /* Check if something is pending and if transport layer is ready to send */ + if ((pSocket->pfSocketSend_Cb != NULL) && + (pSocket->psTransport->bSendPending == FALSE)) + { + /* Fill the psLlcpHeader stuture with the DSAP,PTYPE and the SSAP */ + pSocket->sLlcpHeader.dsap = pSocket->socket_dSap; + pSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_UI; + pSocket->sLlcpHeader.ssap = pSocket->socket_sSap; + + /* Send to data to the approiate socket */ + status = phFriNfc_LlcpTransport_LinkSend(pSocket->psTransport, + &pSocket->sLlcpHeader, + NULL, + &pSocket->sSocketSendBuffer, + phFriNfc_LlcpTransport_Connectionless_SendTo_CB, + pSocket->index, + pSocket); + } + else + { + /* Cannot send now, retry later */ + } + + return status; +} + + +/* TODO: comment function Handle_Connectionless_IncommingFrame */ +void Handle_Connectionless_IncommingFrame(phFriNfc_LlcpTransport_t *pLlcpTransport, + phNfc_sData_t *psData, + uint8_t dsap, + uint8_t ssap) +{ + phFriNfc_LlcpTransport_Socket_t * pSocket = NULL; + uint8_t i = 0; + uint8_t writeIndex; + + /* Look through the socket table for a match */ + for(i=0;ipSocketTable[i].socket_sSap == dsap) + { + /* Socket found ! */ + pSocket = &pLlcpTransport->pSocketTable[i]; + + /* Forward directly to application if a read is pending */ + if (pSocket->bSocketRecvPending == TRUE) + { + /* Reset the RecvPending variable */ + pSocket->bSocketRecvPending = FALSE; + + /* Copy the received buffer into the receive buffer */ + memcpy(pSocket->sSocketRecvBuffer->buffer, psData->buffer, psData->length); + + /* Update the received length */ + *pSocket->receivedLength = psData->length; + + /* call the recv callback */ + pSocket->pfSocketRecvFrom_Cb(pSocket->pRecvContext, ssap, NFCSTATUS_SUCCESS); + pSocket->pfSocketRecvFrom_Cb = NULL; + } + /* If no read is pending, try to bufferize for later reading */ + else + { + if((pSocket->indexRwWrite - pSocket->indexRwRead) < pSocket->localRW) + { + writeIndex = pSocket->indexRwWrite % pSocket->localRW; + /* Save SSAP */ + pSocket->sSocketRwBufferTable[writeIndex].buffer[0] = ssap; + /* Save UI frame payload */ + memcpy(pSocket->sSocketRwBufferTable[writeIndex].buffer + 1, + psData->buffer, + psData->length); + pSocket->sSocketRwBufferTable[writeIndex].length = psData->length; + + /* Update the RW write index */ + pSocket->indexRwWrite++; + } + else + { + /* Unable to bufferize the packet, drop it */ + } + } + break; + } + } +} + +/* TODO: comment function phFriNfc_LlcpTransport_Connectionless_SendTo_CB */ +static void phFriNfc_LlcpTransport_Connectionless_SendTo_CB(void* pContext, + uint8_t socketIndex, + NFCSTATUS status) +{ + phFriNfc_LlcpTransport_Socket_t * pLlcpSocket = (phFriNfc_LlcpTransport_Socket_t*)pContext; + pphFriNfc_LlcpTransportSocketSendCb_t pfSavedCallback; + + /* Call the send callback */ + pfSavedCallback = pLlcpSocket->pfSocketSend_Cb; + if (pfSavedCallback != NULL) + { + pLlcpSocket->pfSocketSend_Cb = NULL; + pfSavedCallback(pLlcpSocket->pSendContext, status); + } +} + +static void phFriNfc_LlcpTransport_Connectionless_Abort(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket) +{ + if (pLlcpSocket->pfSocketSend_Cb != NULL) + { + pLlcpSocket->pfSocketSend_Cb(pLlcpSocket->pSendContext, NFCSTATUS_ABORTED); + pLlcpSocket->pSendContext = NULL; + pLlcpSocket->pfSocketSend_Cb = NULL; + } + if (pLlcpSocket->pfSocketRecvFrom_Cb != NULL) + { + pLlcpSocket->pfSocketRecvFrom_Cb(pLlcpSocket->pRecvContext, 0, NFCSTATUS_ABORTED); + pLlcpSocket->pRecvContext = NULL; + pLlcpSocket->pfSocketRecvFrom_Cb = NULL; + pLlcpSocket->pfSocketRecv_Cb = NULL; + } + pLlcpSocket->pAcceptContext = NULL; + pLlcpSocket->pfSocketAccept_Cb = NULL; + pLlcpSocket->pListenContext = NULL; + pLlcpSocket->pfSocketListen_Cb = NULL; + pLlcpSocket->pConnectContext = NULL; + pLlcpSocket->pfSocketConnect_Cb = NULL; + pLlcpSocket->pDisconnectContext = NULL; + pLlcpSocket->pfSocketDisconnect_Cb = NULL; +} + +/** +* \ingroup grp_fri_nfc +* \brief Close a socket on a LLCP-connectionless device. +* +* This function closes a LLCP socket previously created using phFriNfc_LlcpTransport_Socket. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. + +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Connectionless_Close(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket) +{ + /* Reset the pointer to the socket closed */ + pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketDefault; + pLlcpSocket->eSocket_Type = phFriNfc_LlcpTransport_eDefaultType; + pLlcpSocket->pContext = NULL; + pLlcpSocket->pSocketErrCb = NULL; + pLlcpSocket->socket_sSap = PHFRINFC_LLCP_SAP_DEFAULT; + pLlcpSocket->socket_dSap = PHFRINFC_LLCP_SAP_DEFAULT; + pLlcpSocket->bSocketRecvPending = FALSE; + pLlcpSocket->bSocketSendPending = FALSE; + pLlcpSocket->bSocketListenPending = FALSE; + pLlcpSocket->bSocketDiscPending = FALSE; + pLlcpSocket->RemoteBusyConditionInfo = FALSE; + pLlcpSocket->ReceiverBusyCondition = FALSE; + pLlcpSocket->socket_VS = 0; + pLlcpSocket->socket_VSA = 0; + pLlcpSocket->socket_VR = 0; + pLlcpSocket->socket_VRA = 0; + + phFriNfc_LlcpTransport_Connectionless_Abort(pLlcpSocket); + + memset(&pLlcpSocket->sSocketOption, 0x00, sizeof(phFriNfc_LlcpTransport_sSocketOptions_t)); + + if (pLlcpSocket->sServiceName.buffer != NULL) { + phOsalNfc_FreeMemory(pLlcpSocket->sServiceName.buffer); + } + pLlcpSocket->sServiceName.buffer = NULL; + pLlcpSocket->sServiceName.length = 0; + + return NFCSTATUS_SUCCESS; +} + +/** +* \ingroup grp_fri_nfc +* \brief Send data on a socket to a given destination SAP. +* +* This function is used to write data on a socket to a given destination SAP. +* This function can only be called on a connectionless socket. +* +* +* \param[in] pLlcpSocket A pointer to a LlcpSocket created. +* \param[in] nSap The destination SAP. +* \param[in] psBuffer The buffer containing the data to send. +* \param[in] pSend_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pSend_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Connectionless_SendTo(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + uint8_t nSap, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb, + void* pContext) +{ + NFCSTATUS status = NFCSTATUS_FAILED; + + /* Store send callback and context*/ + pLlcpSocket->pfSocketSend_Cb = pSend_RspCb; + pLlcpSocket->pSendContext = pContext; + + /* Test if a send is already pending at transport level */ + if(pLlcpSocket->psTransport->bSendPending == TRUE) + { + /* Save the request so it can be handled in phFriNfc_LlcpTransport_Connectionless_HandlePendingOperations() */ + pLlcpSocket->sSocketSendBuffer = *psBuffer; + pLlcpSocket->socket_dSap = nSap; + status = NFCSTATUS_PENDING; + } + else + { + /* Fill the psLlcpHeader stuture with the DSAP,PTYPE and the SSAP */ + pLlcpSocket->sLlcpHeader.dsap = nSap; + pLlcpSocket->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_UI; + pLlcpSocket->sLlcpHeader.ssap = pLlcpSocket->socket_sSap; + + /* Send to data to the approiate socket */ + status = phFriNfc_LlcpTransport_LinkSend(pLlcpSocket->psTransport, + &pLlcpSocket->sLlcpHeader, + NULL, + psBuffer, + phFriNfc_LlcpTransport_Connectionless_SendTo_CB, + pLlcpSocket->index, + pLlcpSocket); + } + + return status; +} + + + /** +* \ingroup grp_lib_nfc +* \brief Read data on a socket and get the source SAP. +* +* This function is the same as phLibNfc_Llcp_Recv, except that the callback includes +* the source SAP. This functions can only be called on a connectionless socket. +* +* +* \param[in] pLlcpSocket A pointer to a LlcpSocket created. +* \param[in] psBuffer The buffer receiving the data. +* \param[in] pRecv_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pRecv_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phLibNfc_LlcpTransport_Connectionless_RecvFrom(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketRecvFromCb_t pRecv_Cb, + void *pContext) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint8_t readIndex; + uint8_t ssap; + + if(pLlcpSocket->bSocketRecvPending) + { + status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED); + } + else + { + /* Check if pending packets in RW */ + if(pLlcpSocket->indexRwRead != pLlcpSocket->indexRwWrite) + { + readIndex = pLlcpSocket->indexRwRead % pLlcpSocket->localRW; + + /* Extract ssap and buffer from RW buffer */ + ssap = pLlcpSocket->sSocketRwBufferTable[readIndex].buffer[0]; + memcpy(psBuffer->buffer, + pLlcpSocket->sSocketRwBufferTable[readIndex].buffer + 1, + pLlcpSocket->sSocketRwBufferTable[readIndex].length); + psBuffer->length = pLlcpSocket->sSocketRwBufferTable[readIndex].length; + + /* Reset RW buffer length */ + pLlcpSocket->sSocketRwBufferTable[readIndex].length = 0; + + /* Update Value Rw Read Index */ + pLlcpSocket->indexRwRead++; + + /* call the recv callback */ + pRecv_Cb(pContext, ssap, NFCSTATUS_SUCCESS); + + status = NFCSTATUS_SUCCESS; + } + /* Otherwise, wait for a packet to come */ + else + { + /* Store the callback and context*/ + pLlcpSocket->pfSocketRecvFrom_Cb = pRecv_Cb; + pLlcpSocket->pRecvContext = pContext; + + /* Store the pointer to the receive buffer */ + pLlcpSocket->sSocketRecvBuffer = psBuffer; + pLlcpSocket->receivedLength = &psBuffer->length; + + /* Set RecvPending to TRUE */ + pLlcpSocket->bSocketRecvPending = TRUE; + } + } + return status; +} diff --git a/libnfc-nxp/phFriNfc_LlcpTransport_Connectionless.h b/libnfc-nxp/phFriNfc_LlcpTransport_Connectionless.h new file mode 100644 index 0000000..2fa263e --- /dev/null +++ b/libnfc-nxp/phFriNfc_LlcpTransport_Connectionless.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_LlcpTransport_Connectionless.h + * \brief + * + * Project: NFC-FRI + * + */ +#ifndef PHFRINFC_LLCP_TRANSPORT_CONNECTIONLESS_H +#define PHFRINFC_LLCP_TRANSPORT_CONNECTIONLESS_H +/*include files*/ +#include +#include +#include + +#include + + +void Handle_Connectionless_IncommingFrame(phFriNfc_LlcpTransport_t *pLlcpTransport, + phNfc_sData_t *psData, + uint8_t dsap, + uint8_t ssap); + +NFCSTATUS phFriNfc_LlcpTransport_Connectionless_HandlePendingOperations(phFriNfc_LlcpTransport_Socket_t *pSocket); + +/** +* \ingroup grp_fri_nfc +* \brief Close a socket on a LLCP-connectionless device. +* +* This function closes a LLCP socket previously created using phFriNfc_LlcpTransport_Socket. +* +* \param[in] pLlcpSocket A pointer to a phFriNfc_LlcpTransport_Socket_t. + +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Connectionless_Close(phFriNfc_LlcpTransport_Socket_t* pLlcpSocket); + +/** +* \ingroup grp_fri_nfc +* \brief Send data on a socket to a given destination SAP. +* +* This function is used to write data on a socket to a given destination SAP. +* This function can only be called on a connectionless socket. +* +* +* \param[in] pLlcpSocket A pointer to a LlcpSocket created. +* \param[in] nSap The destination SAP. +* \param[in] psBuffer The buffer containing the data to send. +* \param[in] pSend_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pSend_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phFriNfc_LlcpTransport_Connectionless_SendTo(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + uint8_t nSap, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb, + void* pContext); + + /** +* \ingroup grp_lib_nfc +* \brief Read data on a socket and get the source SAP. +* +* This function is the same as phLibNfc_Llcp_Recv, except that the callback includes +* the source SAP. This functions can only be called on a connectionless socket. +* +* +* \param[in] pLlcpSocket A pointer to a LlcpSocket created. +* \param[in] psBuffer The buffer receiving the data. +* \param[in] pRecv_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pRecv_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +NFCSTATUS phLibNfc_LlcpTransport_Connectionless_RecvFrom(phFriNfc_LlcpTransport_Socket_t *pLlcpSocket, + phNfc_sData_t* psBuffer, + pphFriNfc_LlcpTransportSocketRecvFromCb_t pRecv_Cb, + void* pContext); + +#endif /* PHFRINFC_LLCP_TRANSPORT_CONNECTIONLESS_H */ diff --git a/libnfc-nxp/phFriNfc_LlcpUtils.c b/libnfc-nxp/phFriNfc_LlcpUtils.c new file mode 100644 index 0000000..750f513 --- /dev/null +++ b/libnfc-nxp/phFriNfc_LlcpUtils.c @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_Llcp.c + * \brief NFC LLCP core + * + * Project: NFC-FRI + * + */ + +/*include files*/ +#include +#include +#include +#include +#include + +NFCSTATUS phFriNfc_Llcp_DecodeTLV( phNfc_sData_t *psRawData, + uint32_t *pOffset, + uint8_t *pType, + phNfc_sData_t *psValueBuffer ) +{ + uint8_t type; + uint8_t length; + uint32_t offset = *pOffset; + + /* Check for NULL pointers */ + if ((psRawData == NULL) || (pOffset == NULL) || (pType == NULL) || (psValueBuffer == NULL)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check offset */ + if (offset > psRawData->length) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check if enough room for Type and Length (with overflow check) */ + if ((offset+2 > psRawData->length) && (offset+2 > offset)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Get Type and Length from current TLV, and update offset */ + type = psRawData->buffer[offset]; + length = psRawData->buffer[offset+1]; + offset += 2; + + /* Check if enough room for Value with announced Length (with overflow check) */ + if ((offset+length > psRawData->length) && (offset+length > offset)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Save response, and update offset */ + *pType = type; + psValueBuffer->buffer = psRawData->buffer + offset; + psValueBuffer->length = length; + offset += length; + + /* Save updated offset */ + *pOffset = offset; + + return NFCSTATUS_SUCCESS; +} + +NFCSTATUS phFriNfc_Llcp_EncodeTLV( phNfc_sData_t *psValueBuffer, + uint32_t *pOffset, + uint8_t type, + uint8_t length, + uint8_t *pValue) +{ + uint32_t offset = *pOffset; + uint32_t finalOffset = offset + 2 + length; /* 2 stands for Type and Length fields size */ + uint8_t i; + + /* Check for NULL pointers */ + if ((psValueBuffer == NULL) || (pOffset == NULL) || (pValue == NULL)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check offset */ + if (offset > psValueBuffer->length) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check if enough room for Type, Length and Value (with overflow check) */ + if ((finalOffset > psValueBuffer->length) || (finalOffset < offset)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Set the TYPE */ + psValueBuffer->buffer[offset] = type; + offset += 1; + + /* Set the LENGTH */ + psValueBuffer->buffer[offset] = length; + offset += 1; + + /* Set the VALUE */ + for(i=0;ibuffer[offset] = pValue[i]; + } + + /* Save updated offset */ + *pOffset = offset; + + return NFCSTATUS_SUCCESS; +} + +NFCSTATUS phFriNfc_Llcp_AppendTLV( phNfc_sData_t *psValueBuffer, + uint32_t nTlvOffset, + uint32_t *pCurrentOffset, + uint8_t length, + uint8_t *pValue) +{ + uint32_t offset = *pCurrentOffset; + uint32_t finalOffset = offset + length; + + /* Check for NULL pointers */ + if ((psValueBuffer == NULL) || (pCurrentOffset == NULL) || (pValue == NULL)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check offset */ + if (offset > psValueBuffer->length) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Check if enough room for Type and Length (with overflow check) */ + if ((finalOffset > psValueBuffer->length) || (finalOffset < offset)) + { + return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); + } + + /* Update the LENGTH */ + psValueBuffer->buffer[nTlvOffset+1] += length; + + /* Set the VALUE */ + memcpy(psValueBuffer->buffer + offset, pValue, length); + offset += length; + + /* Save updated offset */ + *pCurrentOffset = offset; + + return NFCSTATUS_SUCCESS; +} + + +/* TODO: comment function EncodeMIUX */ +void phFriNfc_Llcp_EncodeMIUX(uint16_t miux, + uint8_t* pMiuxEncoded) +{ + /* MASK */ + miux = miux & PHFRINFC_LLCP_TLV_MIUX_MASK; + + pMiuxEncoded[0] = miux >> 8; + pMiuxEncoded[1] = miux & 0xff; +} + +/* TODO: comment function EncodeRW */ +void phFriNfc_Llcp_EncodeRW(uint8_t *pRw) +{ + /* MASK */ + *pRw = *pRw & PHFRINFC_LLCP_TLV_RW_MASK; +} + +/** + * Initializes a Fifo Cyclic Buffer to point to some allocated memory. + */ +void phFriNfc_Llcp_CyclicFifoInit(P_UTIL_FIFO_BUFFER pUtilFifo, + const uint8_t *pBuffStart, + uint32_t buffLength) +{ + pUtilFifo->pBuffStart = (uint8_t *)pBuffStart; + pUtilFifo->pBuffEnd = (uint8_t *)pBuffStart + buffLength-1; + pUtilFifo->pIn = (uint8_t *)pBuffStart; + pUtilFifo->pOut = (uint8_t *)pBuffStart; + pUtilFifo->bFull = FALSE; +} + +/** + * Clears the Fifo Cyclic Buffer - loosing any data that was in it. + */ +void phFriNfc_Llcp_CyclicFifoClear(P_UTIL_FIFO_BUFFER pUtilFifo) +{ + pUtilFifo->pIn = pUtilFifo->pBuffStart; + pUtilFifo->pOut = pUtilFifo->pBuffStart; + pUtilFifo->bFull = FALSE; +} + +/** + * Attempts to write dataLength bytes to the specified Fifo Cyclic Buffer. + */ +uint32_t phFriNfc_Llcp_CyclicFifoWrite(P_UTIL_FIFO_BUFFER pUtilFifo, + uint8_t *pData, + uint32_t dataLength) +{ + uint32_t dataLengthWritten = 0; + uint8_t * pNext; + + while(dataLengthWritten < dataLength) + { + pNext = (uint8_t*)pUtilFifo->pIn+1; + + if(pNext > pUtilFifo->pBuffEnd) + { + //Wrap around + pNext = pUtilFifo->pBuffStart; + } + + if(pUtilFifo->bFull) + { + //Full + break; + } + + if(pNext == pUtilFifo->pOut) + { + // Trigger Full flag + pUtilFifo->bFull = TRUE; + } + + dataLengthWritten++; + *pNext = *pData++; + pUtilFifo->pIn = pNext; + } + + return dataLengthWritten; +} + +/** + * Attempts to read dataLength bytes from the specified Fifo Cyclic Buffer. + */ +uint32_t phFriNfc_Llcp_CyclicFifoFifoRead(P_UTIL_FIFO_BUFFER pUtilFifo, + uint8_t *pBuffer, + uint32_t dataLength) +{ + uint32_t dataLengthRead = 0; + uint8_t * pNext; + + while(dataLengthRead < dataLength) + { + if((pUtilFifo->pOut == pUtilFifo->pIn) && (pUtilFifo->bFull == FALSE)) + { + //No more bytes in buffer + break; + } + else + { + dataLengthRead++; + + if(pUtilFifo->pOut == pUtilFifo->pBuffEnd) + { + /* Wrap around */ + pNext = pUtilFifo->pBuffStart; + } + else + { + pNext = (uint8_t*)pUtilFifo->pOut + 1; + } + + *pBuffer++ = *pNext; + + pUtilFifo->pOut = pNext; + + pUtilFifo->bFull = FALSE; + } + } + + return dataLengthRead; +} + +/** + * Returns the number of bytes currently stored in Fifo Cyclic Buffer. + */ +uint32_t phFriNfc_Llcp_CyclicFifoUsage(P_UTIL_FIFO_BUFFER pUtilFifo) +{ + uint32_t dataLength; + uint8_t * pIn = (uint8_t *)pUtilFifo->pIn; + uint8_t * pOut = (uint8_t *)pUtilFifo->pOut; + + if (pUtilFifo->bFull) + { + dataLength = pUtilFifo->pBuffEnd - pUtilFifo->pBuffStart + 1; + } + else + { + if(pIn >= pOut) + { + dataLength = pIn - pOut; + } + else + { + dataLength = pUtilFifo->pBuffEnd - pOut; + dataLength += (pIn+1) - pUtilFifo->pBuffStart; + } + } + + return dataLength; +} + + +/** + * Returns the available room for writing in Fifo Cyclic Buffer. + */ +uint32_t phFriNfc_Llcp_CyclicFifoAvailable(P_UTIL_FIFO_BUFFER pUtilFifo) +{ + uint32_t dataLength; + uint32_t size; + uint8_t * pIn = (uint8_t *)pUtilFifo->pIn; + uint8_t * pOut = (uint8_t *)pUtilFifo->pOut; + + if (pUtilFifo->bFull) + { + dataLength = 0; + } + else + { + if(pIn >= pOut) + { + size = pUtilFifo->pBuffEnd - pUtilFifo->pBuffStart + 1; + dataLength = size - (pIn - pOut); + } + else + { + dataLength = pOut - pIn; + } + } + + return dataLength; +} + + + +uint32_t phFriNfc_Llcp_Header2Buffer( phFriNfc_Llcp_sPacketHeader_t *psHeader, uint8_t *pBuffer, uint32_t nOffset ) +{ + uint32_t nOriginalOffset = nOffset; + pBuffer[nOffset++] = (uint8_t)((psHeader->dsap << 2) | (psHeader->ptype >> 2)); + pBuffer[nOffset++] = (uint8_t)((psHeader->ptype << 6) | psHeader->ssap); + return nOffset - nOriginalOffset; +} + +uint32_t phFriNfc_Llcp_Sequence2Buffer( phFriNfc_Llcp_sPacketSequence_t *psSequence, uint8_t *pBuffer, uint32_t nOffset ) +{ + uint32_t nOriginalOffset = nOffset; + pBuffer[nOffset++] = (uint8_t)((psSequence->ns << 4) | (psSequence->nr)); + return nOffset - nOriginalOffset; +} + +uint32_t phFriNfc_Llcp_Buffer2Header( uint8_t *pBuffer, uint32_t nOffset, phFriNfc_Llcp_sPacketHeader_t *psHeader ) +{ + psHeader->dsap = (pBuffer[nOffset] & 0xFC) >> 2; + psHeader->ptype = ((pBuffer[nOffset] & 0x03) << 2) | ((pBuffer[nOffset+1] & 0xC0) >> 6); + psHeader->ssap = pBuffer[nOffset+1] & 0x3F; + return PHFRINFC_LLCP_PACKET_HEADER_SIZE; +} + +uint32_t phFriNfc_Llcp_Buffer2Sequence( uint8_t *pBuffer, uint32_t nOffset, phFriNfc_Llcp_sPacketSequence_t *psSequence ) +{ + psSequence->ns = pBuffer[nOffset] >> 4; + psSequence->nr = pBuffer[nOffset] & 0x0F; + return PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE; +} + + diff --git a/libnfc-nxp/phFriNfc_LlcpUtils.h b/libnfc-nxp/phFriNfc_LlcpUtils.h new file mode 100644 index 0000000..9dcb95a --- /dev/null +++ b/libnfc-nxp/phFriNfc_LlcpUtils.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_LlcpUtils.h + * \brief NFC LLCP utils + * + * Project: NFC-FRI + * + */ + +#ifndef PHFRINFC_LLCPUTILS_H +#define PHFRINFC_LLCPUTILS_H + +/*include files*/ +#include +#include +#include +#include +#include + +/** + * \name NFC Forum Logical Link Control Protocol Utils + * + * File: \ref phFriNfc_LlcpUtils.h + * + */ + +/** + * UTIL_FIFO_BUFFER - A Cyclic FIFO buffer + * If pIn == pOut the buffer is empty. + */ +typedef struct UTIL_FIFO_BUFFER +{ + uint8_t *pBuffStart; /* Points to first valid location in buffer */ + uint8_t *pBuffEnd; /* Points to last valid location in buffer */ + volatile uint8_t *pIn; /* Points to 1 before where the next TU1 will enter buffer */ + volatile uint8_t *pOut; /* Points to 1 before where the next TU1 will leave buffer */ + volatile bool_t bFull; /* TRUE if buffer is full */ +}UTIL_FIFO_BUFFER, *P_UTIL_FIFO_BUFFER; + + +/** \defgroup grp_fri_nfc_llcp NFC Forum Logical Link Control Protocol Component + * + * TODO + * + */ + +NFCSTATUS phFriNfc_Llcp_DecodeTLV( phNfc_sData_t *psRawData, + uint32_t *pOffset, + uint8_t *pType, + phNfc_sData_t *psValueBuffer ); + +NFCSTATUS phFriNfc_Llcp_EncodeTLV( phNfc_sData_t *psValueBuffer, + uint32_t *pOffset, + uint8_t type, + uint8_t length, + uint8_t *pValue); + +NFCSTATUS phFriNfc_Llcp_AppendTLV( phNfc_sData_t *psValueBuffer, + uint32_t nTlvOffset, + uint32_t *pCurrentOffset, + uint8_t length, + uint8_t *pValue); + +void phFriNfc_Llcp_EncodeMIUX(uint16_t pMiux, + uint8_t* pMiuxEncoded); + +void phFriNfc_Llcp_EncodeRW(uint8_t *pRw); + +/** + * Initializes a Fifo Cyclic Buffer to point to some allocated memory. + */ +void phFriNfc_Llcp_CyclicFifoInit(P_UTIL_FIFO_BUFFER sUtilFifo, + const uint8_t *pBuffStart, + uint32_t buffLength); + +/** + * Clears the Fifo Cyclic Buffer - loosing any data that was in it. + */ +void phFriNfc_Llcp_CyclicFifoClear(P_UTIL_FIFO_BUFFER sUtilFifo); + + +/** + * Attempts to write dataLength bytes to the specified Fifo Cyclic Buffer. + */ +uint32_t phFriNfc_Llcp_CyclicFifoWrite(P_UTIL_FIFO_BUFFER sUtilFifo, + uint8_t *pData, + uint32_t dataLength); + +/** + * Attempts to read dataLength bytes from the specified Fifo Cyclic Buffer. + */ +uint32_t phFriNfc_Llcp_CyclicFifoFifoRead(P_UTIL_FIFO_BUFFER sUtilFifo, + uint8_t *pBuffer, + uint32_t dataLength); + +/** + * Returns the number of bytes currently stored in Fifo Cyclic Buffer. + */ +uint32_t phFriNfc_Llcp_CyclicFifoUsage(P_UTIL_FIFO_BUFFER sUtilFifo); + +/** + * Returns the available room for writing in Fifo Cyclic Buffer. + */ +uint32_t phFriNfc_Llcp_CyclicFifoAvailable(P_UTIL_FIFO_BUFFER sUtilFifo); + +uint32_t phFriNfc_Llcp_Header2Buffer( phFriNfc_Llcp_sPacketHeader_t *psHeader, + uint8_t *pBuffer, + uint32_t nOffset ); + +uint32_t phFriNfc_Llcp_Sequence2Buffer( phFriNfc_Llcp_sPacketSequence_t *psSequence, + uint8_t *pBuffer, + uint32_t nOffset ); + +uint32_t phFriNfc_Llcp_Buffer2Header( uint8_t *pBuffer, + uint32_t nOffset, + phFriNfc_Llcp_sPacketHeader_t *psHeader ); + +uint32_t phFriNfc_Llcp_Buffer2Sequence( uint8_t *pBuffer, + uint32_t nOffset, + phFriNfc_Llcp_sPacketSequence_t *psSequence ); + + +#endif /* PHFRINFC_LLCPUTILS_H */ diff --git a/libnfc-nxp/phFriNfc_MapTools.c b/libnfc-nxp/phFriNfc_MapTools.c new file mode 100644 index 0000000..2e05d33 --- /dev/null +++ b/libnfc-nxp/phFriNfc_MapTools.c @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc_MapTools.c + * \brief NFC Ndef Internal Mapping File. + * + * Project: NFC-FRI + * + * $Date: Fri Oct 15 13:50:54 2010 $ + * $Author: ing02260 $ + * $Revision: 1.6 $ + * $Aliases: $ + * + */ + +#include +#include + +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED +#include +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED*/ + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED +#include +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED +#include +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED +#include +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + +#include + +/*! \ingroup grp_file_attributes + * \name NDEF Mapping + * + * File: \ref phFriNfc_MapTools.c + * This file has functions which are used common across all the + * typ1/type2/type3/type4 tags. + * + */ +/*@{*/ +#define PHFRINFCNDEFMAP_FILEREVISION "$Revision: 1.6 $" +#define PHFRINFCNDEFMAP_FILEALIASES "$Aliases: $" +/*@}*/ + +NFCSTATUS phFriNfc_MapTool_SetCardState(phFriNfc_NdefMap_t *NdefMap, + uint32_t Length) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + if(Length == PH_FRINFC_NDEFMAP_MFUL_VAL0) + { + /* As the NDEF LEN / TLV Len is Zero, irrespective of any state the card + shall be set to INITIALIZED STATE*/ + NdefMap->CardState =(uint8_t) (((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_READ_ONLY) || + (NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID))? + PH_NDEFMAP_CARD_STATE_INVALID: + PH_NDEFMAP_CARD_STATE_INITIALIZED); + } + else + { + switch(NdefMap->CardState) + { + case PH_NDEFMAP_CARD_STATE_INITIALIZED: + NdefMap->CardState =(uint8_t) ((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID)? + NdefMap->CardState: + PH_NDEFMAP_CARD_STATE_READ_WRITE); + break; + + case PH_NDEFMAP_CARD_STATE_READ_ONLY: + NdefMap->CardState = (uint8_t)((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID)? + NdefMap->CardState: + PH_NDEFMAP_CARD_STATE_READ_ONLY); + break; + + case PH_NDEFMAP_CARD_STATE_READ_WRITE: + NdefMap->CardState = (uint8_t)((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID)? + NdefMap->CardState: + PH_NDEFMAP_CARD_STATE_READ_WRITE); + if (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD || + NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD) + { + if(NdefMap->StdMifareContainer.ReadOnlySectorIndex && + NdefMap->StdMifareContainer.SectorTrailerBlockNo == NdefMap->StdMifareContainer.currentBlock ) + { + NdefMap->CardState = (uint8_t)((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID)? + NdefMap->CardState: + PH_NDEFMAP_CARD_STATE_READ_ONLY); + } + } + break; + + default: + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + Result = ((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID)? + PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT): + Result); + return Result; +} + +/* To check mapping spec version */ + +NFCSTATUS phFriNfc_MapTool_ChkSpcVer( const phFriNfc_NdefMap_t *NdefMap, + uint8_t VersionIndex) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + uint8_t TagVerNo = NdefMap->SendRecvBuf[VersionIndex]; + + if ( TagVerNo == 0 ) + { + /*Return Status Error “ Invalid Format”*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT); + } + else + { + switch (NdefMap->CardType) + { + case PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD: + case PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD: + { + /* calculate the major and minor version number of Mifare std version number */ + status = (( (( PH_NFCFRI_MFSTDMAP_NFCDEV_MAJOR_VER_NUM == + PH_NFCFRI_MFSTDMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&& + ( PH_NFCFRI_MFSTDMAP_NFCDEV_MINOR_VER_NUM == + PH_NFCFRI_MFSTDMAP_GET_MINOR_TAG_VERNO(TagVerNo))) || + (( PH_NFCFRI_MFSTDMAP_NFCDEV_MAJOR_VER_NUM == + PH_NFCFRI_MFSTDMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&& + ( PH_NFCFRI_MFSTDMAP_NFCDEV_MINOR_VER_NUM < + PH_NFCFRI_MFSTDMAP_GET_MINOR_TAG_VERNO(TagVerNo) )))? + NFCSTATUS_SUCCESS: + PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT)); + break; + } + +#ifdef DESFIRE_EV1 + case PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1: + { + /* calculate the major and minor version number of T3VerNo */ + if( (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM_2 == + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&& + ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM == + PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo))) || + (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM_2 == + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&& + ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM < + PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo) ))) + { + status = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS); + } + else + { + if (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM_2 < + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo) ) || + ( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM_2 > + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo))) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT); + } + } + break; + } +#endif /* #ifdef DESFIRE_EV1 */ + + default: + { + /* calculate the major and minor version number of T3VerNo */ + if( (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM == + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&& + ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM == + PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo))) || + (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM == + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&& + ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM < + PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo) ))) + { + status = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS); + } + else + { + if (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM < + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo) ) || + ( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM > + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo))) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT); + } + } + break; + } + + + } + } + + return (status); +} diff --git a/libnfc-nxp/phFriNfc_MapTools.h b/libnfc-nxp/phFriNfc_MapTools.h new file mode 100644 index 0000000..e9eda20 --- /dev/null +++ b/libnfc-nxp/phFriNfc_MapTools.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* + * \file phFriNfc_MapTools.h + * \brief NFC Internal Ndef Mapping File. + * + * Project: NFC-FRI + * + * $Date: Fri Oct 15 13:50:54 2010 $ + * $Author: ing02260 $ + * $Revision: 1.6 $ + * $Aliases: $ + * + */ + +#ifndef PHFRINFC_MAPTOOLS_H +#define PHFRINFC_MAPTOOLS_H + +#include +#ifdef PH_HAL4_ENABLE +#include +#else +#include +#endif +#include +#include +#include + +/*! + * \name phFriNfc_MapTools.h + * This file has functions which are used common across all the + typ1/type2/type3/type4 tags. + * + */ +/*@{*/ + +#define PH_FRINFC_NDEFMAP_TLVLEN_ZERO 0 + +/* NFC Device Major and Minor Version numbers*/ +/* !!CAUTION!! these needs to be updated periodically.Major and Minor version numbers + should be compatible to the version number of currently implemented mapping document. + Example : NFC Device version Number : 1.0 , specifies + Major VNo is 1, + Minor VNo is 0 */ +#define PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM 0x01 +#ifdef DESFIRE_EV1 +#define PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM_2 0x02 +#endif /* */ +#define PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM 0x00 + +/* Macros to find major and minor TAG : Ex:Type1/Type2/Type3/Type4 version numbers*/ +#define PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(a) (((a) & (0xf0))>>(4)) +#define PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(a) ((a) & (0x0f)) + +/* NFC Device Major and Minor Version numbers*/ +/* !!CAUTION!! these needs to be updated periodically.Major and Minor version numbers + should be compatible to the version number of currently implemented mapping document. + Example : NFC Device version Number : 1.0 , specifies + Major VNo is 1, + Minor VNo is 0 */ +#define PH_NFCFRI_MFSTDMAP_NFCDEV_MAJOR_VER_NUM 0x40 +#define PH_NFCFRI_MFSTDMAP_NFCDEV_MINOR_VER_NUM 0x00 + +/* Macros to find major and minor TAG : Ex:Type1/Type2/Type3/Type4 version numbers*/ +#define PH_NFCFRI_MFSTDMAP_GET_MAJOR_TAG_VERNO(a) ((a) & (0x40)) // must be 0xC0 +#define PH_NFCFRI_MFSTDMAP_GET_MINOR_TAG_VERNO(a) ((a) & (0x30)) + +/*! + * \name NDEF Mapping - states of the Finite State machine + * + */ +/*@{*/ + + +NFCSTATUS phFriNfc_MapTool_ChkSpcVer( const phFriNfc_NdefMap_t *NdefMap, + uint8_t VersionIndex); + +NFCSTATUS phFriNfc_MapTool_SetCardState(phFriNfc_NdefMap_t *NdefMap, + uint32_t Length); + +#endif //PHFRINFC_MAPTOOLS_H diff --git a/libnfc-nxp/phFriNfc_MifStdFormat.c b/libnfc-nxp/phFriNfc_MifStdFormat.c new file mode 100644 index 0000000..e53c086 --- /dev/null +++ b/libnfc-nxp/phFriNfc_MifStdFormat.c @@ -0,0 +1,1303 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* + * \file phFriNfc_MifStdFormat.c + * \brief NFC Ndef Formatting For Mifare standard card. + * + * Project: NFC-FRI + * + * $Date: Tue Oct 20 20:13:03 2009 $ + * $Author: ing02260 $ + * $Revision: 1.9 $ + * $Aliases: NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#include +#include + +/*! \ingroup grp_file_attributes + * \name NDEF Mapping + * + * File: \ref phFriNfc_MifStdFormat.c + * + */ +/*@{*/ +#define PHFRINFCMIFSTDFMT_FILEREVISION "$Revision: 1.9 $" +#define PHFRINFCMIFSTDFMT_FILEALIASES "$Aliases: NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" +/*@}*/ + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function fills the + * send buffer for transceive function + */ +static void phFriNfc_MfStd_H_FillSendBuf(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint16_t BlockNo); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function authenticates + * a block or a sector from the card. + */ +static NFCSTATUS phFriNfc_MfStd_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function calls + * disconnect. + */ +static NFCSTATUS phFriNfc_MfStd_H_CallDisCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + NFCSTATUS Status); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function calls + * disconnect. + */ +static NFCSTATUS phFriNfc_MfStd_H_CallCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +#ifndef PH_HAL4_ENABLE +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function calls + * disconnect. + */ +static NFCSTATUS phFriNfc_MfStd_H_CallPoll(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); +#endif /* #ifndef PH_HAL4_ENABLE */ + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process the + * poll call. + */ +static NFCSTATUS phFriNfc_MfStd_H_ProCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process the + * authenticate call. + */ +static NFCSTATUS phFriNfc_MfStd_H_ProAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process the + * read access bit call. + */ +static NFCSTATUS phFriNfc_MfStd_H_ProRdSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process the + * write access bit call. + */ +static NFCSTATUS phFriNfc_MfStd_H_ProWrSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function writes the + * sector trailer using the block number. + */ +static NFCSTATUS phFriNfc_MfStd_H_WrRdAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function checks the + * access bits of each sector trailer. + */ +static uint32_t phFriNfc_MfStd_H_ChkAcsBit(uint16_t BlockNo, + const uint8_t *RecvBuf, + const uint8_t AcsBits1[], + const uint8_t AcsBits2[]); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function change the + * authentication state and change the block number if required + */ +static void phFriNfc_MfStd_H_ChangeAuthSt(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function finds the + * contiguous ndef compliant blocks. + */ +static void phFriNfc_MfStd_H_NdefComplSect(uint8_t CardTypes, + uint8_t Sector[]); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare standard. This function writes the + * MAD block values. + */ +static NFCSTATUS phFriNfc_MfStd_H_ProWrMADBlk(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! +* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process +* the error status of the authentication +*/ +static NFCSTATUS phFriNfc_MfStd_H_ProErrAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! +* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process +* the error status of the writing sector trailer +*/ +static NFCSTATUS phFriNfc_MfStd_H_ErrWrSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! +* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process +* the error status of the reading sector trailer +*/ +static NFCSTATUS phFriNfc_MfStd_H_ErrRdSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! +* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall process +* the error status of the writing sector trailer +*/ +static NFCSTATUS phFriNfc_MfStd_H_ProUpdMADBlk(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! +* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall store the +* ndef compliant in the MAD array which will be later used for updating the MAD sector +*/ +static void phFriNfc_MfStd_H_StrNdefData(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! +* \brief \copydoc page_ovr Helper function for Mifare standard. This function shall find the ndef compliant +* and calculate the block number to write the NDEF TLV +*/ +static void phFriNfc_MfStd_H_BlkNoToWrTLV(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +static int phFriNfc_MfStd_MemCompare ( void *s1, void *s2, unsigned int n ); + + +void phFriNfc_MfStd_Reset(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + uint8_t NfcForSectArray[] = PH_FRINFC_SMTCRDFMT_NFCFORUMSECT_KEYA_ACS_BIT, + MADSectArray[] = PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_1K; + + /* Authentication state */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_VAL_1; + + /* Set default key for A or B */ + (void)memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.Default_KeyA_OR_B, + PH_FRINFC_MFSTD_FMT_DEFAULT_KEY, /* 0xFF */ + PH_FRINFC_MFSTD_FMT_VAL_6); + + /* MAD sector key A */ + (void)memcpy(NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_KeyA, + MADSectArray, //PH_FRINFC_MFSTD_FMT_VAL_0, + PH_FRINFC_MFSTD_FMT_VAL_6); + + /* Copy access bits for MAD sectors */ + (void)memcpy(NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_AccessBits, + &MADSectArray[PH_FRINFC_MFSTD_FMT_VAL_6], + PH_FRINFC_MFSTD_FMT_VAL_3); + + /* NFC forum sector key A */ + (void)memcpy(NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_KeyA, + NfcForSectArray, //PH_FRINFC_MFSTD_FMT_VAL_0, + PH_FRINFC_MFSTD_FMT_VAL_6); + + /* Copy access bits for NFC forum sectors */ + (void)memcpy(NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_AccessBits, + &NfcForSectArray[PH_FRINFC_MFSTD_FMT_VAL_6], + PH_FRINFC_MFSTD_FMT_VAL_3); + + /* Sector compliant array initialised to 0 */ + (void)memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl, + PH_FRINFC_MFSTD_FMT_VAL_0, /* 0x00 */ + PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K); + + NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag = (uint8_t)PH_FRINFC_MFSTD_FMT_VAL_0; + NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = (uint8_t)PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK; + +} + +NFCSTATUS phFriNfc_MfStd_Format( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, const uint8_t *ScrtKeyB ) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_PARAMETER); + uint8_t index = PH_FRINFC_MFSTD_FMT_VAL_0; + + if(ScrtKeyB != NULL) + { + NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = + PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK; + /* Store Key B in the context */ + while(index < PH_FRINFC_MFSTD_FMT_VAL_6) + { + NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB[index] = ScrtKeyB[index]; + index++; + } + /* Set the state */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; + /* Initialise current block to the first sector trailer */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = PH_FRINFC_MFSTD_FMT_VAL_3; + /* Set the authenticate state */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY; + /* Start authentication */ + Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); + } + return Result; +} + +void phFriNfc_MfStd_Process(void *Context, + NFCSTATUS Status) +{ + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t *)Context; + /* Copy the formatting status */ + NdefSmtCrdFmt->FmtProcStatus = Status; + if(Status == NFCSTATUS_SUCCESS) + { + switch(NdefSmtCrdFmt->State) + { + case PH_FRINFC_MFSTD_FMT_AUTH_SECT: + Status = phFriNfc_MfStd_H_ProAuth(NdefSmtCrdFmt); + break; + + case PH_FRINFC_MFSTD_FMT_DIS_CON: +#ifndef PH_HAL4_ENABLE + Status = phFriNfc_MfStd_H_CallPoll(NdefSmtCrdFmt); + break; + + case PH_FRINFC_MFSTD_FMT_POLL: +#endif /* #ifndef PH_HAL4_ENABLE */ + Status = phFriNfc_MfStd_H_CallCon(NdefSmtCrdFmt); + break; + + case PH_FRINFC_MFSTD_FMT_CON: + Status = phFriNfc_MfStd_H_ProCon(NdefSmtCrdFmt); + break; + + case PH_FRINFC_MFSTD_FMT_RD_SECT_TR: + Status = phFriNfc_MfStd_H_ProRdSectTr(NdefSmtCrdFmt); + break; + + case PH_FRINFC_MFSTD_FMT_WR_SECT_TR: + Status = phFriNfc_MfStd_H_ProWrSectTr(NdefSmtCrdFmt); + break; + + case PH_FRINFC_MFSTD_FMT_WR_MAD_BLK: + Status = phFriNfc_MfStd_H_ProWrMADBlk(NdefSmtCrdFmt); + break; + + case PH_FRINFC_MFSTD_FMT_WR_TLV: + break; + + case PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK: + Status = phFriNfc_MfStd_H_ProUpdMADBlk(NdefSmtCrdFmt); + break; + + default: + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + else + { + switch(NdefSmtCrdFmt->State) + { + case PH_FRINFC_MFSTD_FMT_AUTH_SECT: + Status = phFriNfc_MfStd_H_ProErrAuth(NdefSmtCrdFmt); + break; + + case PH_FRINFC_MFSTD_FMT_WR_SECT_TR: + Status = phFriNfc_MfStd_H_ErrWrSectTr(NdefSmtCrdFmt); + break; + + case PH_FRINFC_MFSTD_FMT_RD_SECT_TR: + Status = phFriNfc_MfStd_H_ErrRdSectTr(NdefSmtCrdFmt); + break; + + default: + Status = NdefSmtCrdFmt->FmtProcStatus; + break; + } + } + + /* Status is not success then call completion routine */ + if(Status != NFCSTATUS_PENDING) + { + phFriNfc_SmtCrdFmt_HCrHandler(NdefSmtCrdFmt, Status); + } +} + +static void phFriNfc_MfStd_H_FillSendBuf(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint16_t BlockNo) +{ + void *mem = NULL; + uint8_t MADSectTr1k[] = PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_1K, /* MAD key A, + Access bits and GPB of MAD sector */ + MADSectTr4k[] = PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_4K, /* MAD key A, + Access bits and GPB of MAD sector */ + NFCSectTr[] = PH_FRINFC_SMTCRDFMT_NFCFORUMSECT_KEYA_ACS_BIT, /* NFC forum key A, + Access bits and GPB of NFC sector */ + NDEFMsgTLV[16] = {0x03, 0x00, 0xFE, 0x00, 0x00, 0x00, /* NDEF message TLV (INITIALISED state) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, + MADBlk[16] = {0x0F, 0x00, 0x03, 0xE1, 0x03, 0xE1, + 0x03, 0xE1, 0x03, 0xE1, + 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; + /* Block number in send buffer */ + NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_0] = (uint8_t)BlockNo; + /* Initialise send receive length */ + *NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_MFSTD_FMT_MAX_RECV_LENGTH; + + /* Depending on the different state, fill the send buffer */ + switch(NdefSmtCrdFmt->State) + { + case PH_FRINFC_MFSTD_FMT_AUTH_SECT: + /* Depending on the authentication state, fill the send buffer */ + switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState) + { + case PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY: + case PH_FRINFC_MFSTD_FMT_AUTH_KEYB: + /* Fill send buffer with the default key */ + PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_DEF(mem); + break; + + case PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY: + /* Fill send buffer with NFC forum sector key */ + PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_NFCSECT_KEYA(mem); + break; + + case PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB: + /* Fill send buffer with NFC forum sector key */ + PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_SCRT_KEY(mem); + break; + + case PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY: + default: + /* Fill send buffer with MAD sector key */ + PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_MADSECT_KEYA(mem); + break; + } + break; + + case PH_FRINFC_MFSTD_FMT_RD_SECT_TR: +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead; +#else + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead; +#endif /* #ifdef PH_HAL4_ENABLE */ + + /* Send length is always one for read operation */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_1; + break; + + case PH_FRINFC_MFSTD_FMT_WR_SECT_TR: + /* Fill send buffer for writing sector trailer */ +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16; +#else + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite16; +#endif /* #ifdef PH_HAL4_ENABLE */ + /* Copy the relevant sector trailer value in the buffer */ + switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock) + { + case PH_FRINFC_MFSTD_FMT_VAL_3: + if (NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD) + { + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], + MADSectTr1k, + sizeof(MADSectTr1k)); + } + else + { + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], + MADSectTr4k, + sizeof(MADSectTr4k)); + } + break; + case 67: + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], + MADSectTr4k, + sizeof(MADSectTr4k)); + break; + default: + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], + NFCSectTr, + sizeof(NFCSectTr)); + break; + } + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_11], + NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB, + sizeof(NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB)); + + /* Send length is always 17 for write operation */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH; + break; + + case PH_FRINFC_MFSTD_FMT_WR_TLV: + /* Fill send buffer for writing TLV */ +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16; +#else + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite16; +#endif /* #ifdef PH_HAL4_ENABLE */ + /* Copy the NDEF message TLV */ + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], + NDEFMsgTLV, sizeof(NDEFMsgTLV)); + /* Send length is always 17 for write operation */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH; + break; + + case PH_FRINFC_MFSTD_FMT_WR_MAD_BLK: + /* Fill send buffer for writing MAD block */ +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16; +#else + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite16; +#endif /* #ifdef PH_HAL4_ENABLE */ + + if((BlockNo == PH_FRINFC_MFSTD_FMT_VAL_2) || + (BlockNo == 65) || (BlockNo == 66)) + { + /* MAD block number 2, 65 and 66 has 0x03, 0xE1 in the + first two bytes */ + MADBlk[PH_FRINFC_MFSTD_FMT_VAL_0] = 0x03; + MADBlk[PH_FRINFC_MFSTD_FMT_VAL_1] = 0xE1; + } + /* Copy the MAD Block values */ + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], + MADBlk, sizeof(MADBlk)); + /* Send length is always 17 for write operation */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH; + break; + + case PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK: + default: + /* Fill send buffer for writing MAD block */ +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite16; +#else + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite16; +#endif /* #ifdef PH_HAL4_ENABLE */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH; + switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk) + { + case PH_FRINFC_MFSTD_FMT_MAD_BLK_1: + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], + NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk, + (PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1)); + break; + + case PH_FRINFC_MFSTD_FMT_MAD_BLK_2: + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], + &NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[16], + (PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1)); + break; + + case PH_FRINFC_MFSTD_FMT_MAD_BLK_64: + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], + &NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[32], + (PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1)); + break; + + case PH_FRINFC_MFSTD_FMT_MAD_BLK_65: + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], + &NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[48], + (PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1)); + break; + + case PH_FRINFC_MFSTD_FMT_MAD_BLK_66: + default: + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], + &NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[64], + (PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH - PH_FRINFC_MFSTD_FMT_VAL_1)); + break; + } + break; + } + PHNFC_UNUSED_VARIABLE(mem); +} + +static NFCSTATUS phFriNfc_MfStd_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* set the data for additional data exchange*/ + NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.NADPresent = 0; + NdefSmtCrdFmt->psDepAdditionalInfo.NAD = 0; + + /*set the completion routines for the card operations*/ + NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = phFriNfc_NdefSmtCrd_Process; + NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = NdefSmtCrdFmt; + + *NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE; + + /* Call the Overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefSmtCrdFmt->LowerDevice, + &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo, + NdefSmtCrdFmt->psRemoteDevInfo, + NdefSmtCrdFmt->Cmd, + &NdefSmtCrdFmt->psDepAdditionalInfo, + NdefSmtCrdFmt->SendRecvBuf, + NdefSmtCrdFmt->SendLength, + NdefSmtCrdFmt->SendRecvBuf, + NdefSmtCrdFmt->SendRecvLength); + return Result; +} + +static NFCSTATUS phFriNfc_MfStd_H_CallDisCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + NFCSTATUS Status) +{ + NFCSTATUS Result = Status; + + /*Set Ndef State*/ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_DIS_CON; + +#ifdef PH_HAL4_ENABLE + + /*Call the Overlapped HAL POLL function */ + Result = phFriNfc_OvrHal_Reconnect( NdefSmtCrdFmt->LowerDevice, + &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo, + NdefSmtCrdFmt->psRemoteDevInfo); +#else + /*Call the Overlapped HAL POLL function */ + Result = phFriNfc_OvrHal_Disconnect( NdefSmtCrdFmt->LowerDevice, + &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo, + NdefSmtCrdFmt->psRemoteDevInfo); +#endif /* #ifdef PH_HAL4_ENABLE */ + + return Result; +} + +static NFCSTATUS phFriNfc_MfStd_H_CallCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + /*Set Ndef State*/ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_CON; + + /*Call the Overlapped HAL POLL function */ +#ifdef PH_HAL4_ENABLE + Result = phFriNfc_OvrHal_Connect( NdefSmtCrdFmt->LowerDevice, + &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo, + NdefSmtCrdFmt->psRemoteDevInfo, + NdefSmtCrdFmt->AddInfo.MfStdInfo.DevInputParam); +#else + Result = phFriNfc_OvrHal_Connect( NdefSmtCrdFmt->LowerDevice, + &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo, + phHal_eOpModesMifare, + NdefSmtCrdFmt->psRemoteDevInfo, + NdefSmtCrdFmt->AddInfo.MfStdInfo.DevInputParam); +#endif /* #ifdef PH_HAL4_ENABLE */ + + return Result; +} + +#ifndef PH_HAL4_ENABLE + +static NFCSTATUS phFriNfc_MfStd_H_CallPoll(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + /*Set ndef State*/ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_POLL; + /* Opmodes */ + NdefSmtCrdFmt->OpModeType[PH_FRINFC_MFSTD_FMT_VAL_0] = phHal_eOpModesMifare; + NdefSmtCrdFmt->OpModeType[PH_FRINFC_MFSTD_FMT_VAL_1] = phHal_eOpModesArrayTerminator; + + /* Number of devices to poll */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.NoOfDevices = PH_FRINFC_MFSTD_FMT_VAL_1; + + /*Call the Overlapped HAL POLL function */ + Result = phFriNfc_OvrHal_Poll( NdefSmtCrdFmt->LowerDevice, + &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo, + NdefSmtCrdFmt->OpModeType, + NdefSmtCrdFmt->psRemoteDevInfo, + &NdefSmtCrdFmt->AddInfo.MfStdInfo.NoOfDevices, + NdefSmtCrdFmt->AddInfo.MfStdInfo.DevInputParam); + return Result; +} + +#endif /* #ifndef PH_HAL4_ENABLE */ + +static NFCSTATUS phFriNfc_MfStd_H_ProCon(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL}, + index = PH_FRINFC_MFSTD_FMT_VAL_1; + uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1; + + phFriNfc_MfStd_H_ChangeAuthSt(NdefSmtCrdFmt); + if(PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK) + { + PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD(); + } + else + { + /* Set the state */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; + /* Start authentication */ + Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); + } + return Result; +} + +static NFCSTATUS phFriNfc_MfStd_H_ProAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Depending on the authentication key check the */ + switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState) + { + case PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY: + if((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == + PH_FRINFC_MFSTD_FMT_VAL_3) && + (NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag == + PH_FRINFC_MFSTD_FMT_VAL_0)) + { + /* Authenticate with default key for block 3 is successful, + so fill the MAD block of sector 0 */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = + PH_FRINFC_MFSTD_FMT_VAL_1; + /* Write the MAD block */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK; + } + else if((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == 67) + && (NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag == + PH_FRINFC_MFSTD_FMT_VAL_0)) + { + /* Authenticate with default key for block 3 is successful, + so fill the MAD block of sector 64 */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 64; + /* Write the MAD block */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK; + } + else + { + /* Not a MAD sector */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag = + PH_FRINFC_MFSTD_FMT_VAL_0; + /* Write the MAD block */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR; + } + break; + + case PH_FRINFC_MFSTD_FMT_AUTH_KEYB: + if((NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == + PH_FRINFC_MFSTD_FMT_MAD_BLK_1) || + (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == + PH_FRINFC_MFSTD_FMT_MAD_BLK_2) || + (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == + PH_FRINFC_MFSTD_FMT_MAD_BLK_64) || + (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == + PH_FRINFC_MFSTD_FMT_MAD_BLK_65) || + (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == + PH_FRINFC_MFSTD_FMT_MAD_BLK_66)) + { + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = + NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk; + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK; + } + else + { + NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = + PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK; + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR; + } + + break; + + case PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB: + if((NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == + PH_FRINFC_MFSTD_FMT_MAD_BLK_1) || + (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == + PH_FRINFC_MFSTD_FMT_MAD_BLK_2) || + (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == + PH_FRINFC_MFSTD_FMT_MAD_BLK_64) || + (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == + PH_FRINFC_MFSTD_FMT_MAD_BLK_65) || + (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == + PH_FRINFC_MFSTD_FMT_MAD_BLK_66)) + { + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = + NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk; + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK; + } + else + { + NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = + PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK; + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR; + } + break; + + case PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY: + case PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY: + default: + if((NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == + PH_FRINFC_MFSTD_FMT_MAD_BLK_66) || + (NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk == + PH_FRINFC_MFSTD_FMT_MAD_BLK_2)) + { + /* Updating the MAD block is complete */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = + PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK; + /* If Mifare 4k card, write the TLV */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_TLV; + } + else + { + /* Depending on the sector trailer, check the access bit */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_RD_SECT_TR; + } + break; + } + /* Call read, write or authenticate */ + Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); + return Result; +} + +static NFCSTATUS phFriNfc_MfStd_H_ErrWrSectTr( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt ) +{ + NFCSTATUS Result = NdefSmtCrdFmt->FmtProcStatus; + /* If default key A is used for authentication and if write fails, then try to + authenticate using key B*/ + if(NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState == + PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY) + { + /* Change the state to authentication */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; + /* internal authenticate state = key B */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_AUTH_KEYB; + /* Now call authenticate */ + Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); + } + else + { + Result = phFriNfc_MfStd_H_ProWrSectTr(NdefSmtCrdFmt); + } + return Result; +} +static NFCSTATUS phFriNfc_MfStd_H_ProRdSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL}, + index = PH_FRINFC_MFSTD_FMT_VAL_1, + SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0; + uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1; + + /* Calculate sector index */ + SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC; + + /* Depending on the sector trailer, check the access bit */ + memcompare = phFriNfc_MfStd_H_ChkAcsBit(NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock, + NdefSmtCrdFmt->SendRecvBuf, + NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_AccessBits, + NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_AccessBits); + + /* Check the sector for ndef compliance */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] = (uint8_t) + ((memcompare != PH_FRINFC_MFSTD_FMT_VAL_0)? + PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL: + PH_FRINFC_MFSTD_FMT_NDEF_COMPL); + + /* Increment the current block */ + PH_FRINFC_MFSTD_FMT_CUR_BLK_INC(); + SectIndex++; + if(PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK) + { + PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD(); + } + else + { + /* Set the state */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; + /* Set the authenticate state */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = + PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY; + /* Start authentication */ + Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); + } + return Result; +} + +static NFCSTATUS phFriNfc_MfStd_H_ProWrSectTr(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL}, + index = PH_FRINFC_MFSTD_FMT_VAL_1, + SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0; + uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1; + + /* Calculate sector index */ + SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC; + + /* Sector is ndef compliance */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] = (uint8_t) + ((NdefSmtCrdFmt->FmtProcStatus != NFCSTATUS_SUCCESS)? + PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL: + PH_FRINFC_MFSTD_FMT_NDEF_COMPL); + + /* Increment the current block */ + PH_FRINFC_MFSTD_FMT_CUR_BLK_INC(); + SectIndex++; + if(PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK) + { + PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD(); + } + else + { + /* Set the state */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; + /* Set the authenticate state */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = + PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY; + /* Start authentication */ + Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); + } + return Result; +} + +static uint32_t phFriNfc_MfStd_H_ChkAcsBit(uint16_t BlockNo, + const uint8_t *RecvBuf, + const uint8_t AcsBits1[], + const uint8_t AcsBits2[]) +{ + uint32_t mem = PH_FRINFC_MFSTD_FMT_VAL_0; + + /* Compare the access bits read from the sector trailer */ + mem = (uint32_t)(((BlockNo == PH_FRINFC_MFSTD_FMT_VAL_3) || + (BlockNo == 67))? + phFriNfc_MfStd_MemCompare((void*)&RecvBuf[PH_FRINFC_MFSTD_FMT_VAL_6], + (void*)AcsBits1, + PH_FRINFC_MFSTD_FMT_VAL_3): + phFriNfc_MfStd_MemCompare((void*)&RecvBuf[PH_FRINFC_MFSTD_FMT_VAL_6], + (void*)AcsBits2, + PH_FRINFC_MFSTD_FMT_VAL_3)); + + return mem; +} + +static NFCSTATUS phFriNfc_MfStd_H_WrRdAuth(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + /* Fill send buffer and send length */ + phFriNfc_MfStd_H_FillSendBuf(NdefSmtCrdFmt, + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock); + /* Call ovrhal transceive */ + Result = phFriNfc_MfStd_H_Transceive(NdefSmtCrdFmt); + + return Result; +} + +static void phFriNfc_MfStd_H_ChangeAuthSt(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + uint8_t SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0; + + if( NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState == + PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB) + { + /* Calculate sector index */ + SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC; + + /* Check the sector for ndef compliance */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] = + PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL; + + PH_FRINFC_MFSTD_FMT_CUR_BLK_INC(); + } + PH_FRINFC_MFSTD_FMT_NXT_AUTH_STATE(); +} + +static void phFriNfc_MfStd_H_NdefComplSect(uint8_t CardTypes, + uint8_t Sector[]) +{ + uint8_t count = PH_FRINFC_MFSTD_FMT_VAL_0, + NdefComplSectMax = PH_FRINFC_MFSTD_FMT_VAL_0, + NdefComplSectTemp = PH_FRINFC_MFSTD_FMT_VAL_1, + SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0, + MaxCont = PH_FRINFC_MFSTD_FMT_VAL_0, + MaxSect = PH_FRINFC_MFSTD_FMT_VAL_0; + + /* Get the maximum sector depending on the sector */ + MaxSect = ((CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD)? + PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K: + PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K); + /* Sector index */ + NdefComplSectTemp = SectIndex = PH_FRINFC_MFSTD_FMT_VAL_1; + /* Check the sector index depending on the card type */ + while(((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K) && + (CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD)) || + ((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K) && + (CardTypes == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD))) + { + if (Sector[SectIndex] == + PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL) + { + if (MaxCont > count) + { + /* Store the maximum contiguous */ + NdefComplSectMax = NdefComplSectTemp; + count = MaxCont; + } + MaxCont = PH_FRINFC_MFSTD_FMT_VAL_0; + /* Increment the sector index */ + PH_FRINFC_MFSTD_FMT_INCR_SECT; + /* Get the next compliant sector */ + NdefComplSectTemp = SectIndex; + } + else + { + /* Increment the sector index */ + PH_FRINFC_MFSTD_FMT_INCR_SECT; + } + MaxCont ++; + + } + if (MaxCont > count) + { + /* Store the maximum contiguous */ + NdefComplSectMax = NdefComplSectTemp; + count = MaxCont; + } + /* Set the sector value has non ndef compliant which are not present with + contiguous ndef compliant sectors */ + if((((count < (MaxSect - PH_FRINFC_MFSTD_FMT_VAL_1)) && (CardTypes + == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD)) || + ((count < (MaxSect - PH_FRINFC_MFSTD_FMT_VAL_2)) && (CardTypes + == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD))) && + ((NdefComplSectMax > PH_FRINFC_MFSTD_FMT_VAL_0) && + (NdefComplSectMax < (MaxSect - PH_FRINFC_MFSTD_FMT_VAL_2)))) + { + (void)memset(&Sector[PH_FRINFC_MFSTD_FMT_VAL_1], + PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL, + (NdefComplSectMax - PH_FRINFC_MFSTD_FMT_VAL_1)); + + (void)memset(&Sector[(NdefComplSectMax + count)], + PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL, + (MaxSect - (NdefComplSectMax + count))); + } +} + + +static NFCSTATUS phFriNfc_MfStd_H_ProWrMADBlk(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock) + { + case PH_FRINFC_MFSTD_FMT_VAL_1: + /* MAD blocks, still not completed */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK; + /* MAD block number 2 */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = + PH_FRINFC_MFSTD_FMT_VAL_2; + break; + + case PH_FRINFC_MFSTD_FMT_VAL_2: + /* Now write to MAD block is completed */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag = + PH_FRINFC_MFSTD_FMT_VAL_1; + /* Now write the sector trailer, so change the state */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR; + /* MAD block number 3 = Sector trailer */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = + PH_FRINFC_MFSTD_FMT_VAL_3; + break; + + case 64: + /* MAD blocks, still not completed */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK; + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 65; + break; + + case 65: + /* MAD blocks, still not completed */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_MAD_BLK; + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 66; + break; + + case 66: + default: + /* Now write to MAD block is completed */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.WrMADBlkFlag = + PH_FRINFC_MFSTD_FMT_VAL_1; + /* Now write the sector trailer, so change the state */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_WR_SECT_TR; + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = 67; + break; + + } + /* Write the block */ + Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); + + return Result; +} + +static NFCSTATUS phFriNfc_MfStd_H_ProErrAuth( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt ) +{ + NFCSTATUS Result = NdefSmtCrdFmt->FmtProcStatus; + uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL}, + index = PH_FRINFC_MFSTD_FMT_VAL_1; + uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1; + + if ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == 67) && + (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState == + PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB)) + { + /* Error in the MAD sector 16, so the remaining sector + information cant be updated */ + (void)memset(&NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[16], + PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL, + (PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K - 16)); + PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD(); + } + else if(((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock > + PH_FRINFC_MFSTD_FMT_VAL_3) && + (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState != + PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB)) || + ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == + PH_FRINFC_MFSTD_FMT_VAL_3) && + (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState < + PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB))) + { + /* Authenticate failed, so disconnect, poll and connect */ + Result = phFriNfc_MfStd_H_CallDisCon(NdefSmtCrdFmt, + Result); + } + else + { + if (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == + PH_FRINFC_MFSTD_FMT_VAL_3) + { + (void)memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl, + PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL, + PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K); + } + } + + return Result; +} + +static NFCSTATUS phFriNfc_MfStd_H_ProUpdMADBlk(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk) + { + case PH_FRINFC_MFSTD_FMT_MAD_BLK_1: + /* Write the next MAD Block */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = (uint8_t) + PH_FRINFC_MFSTD_FMT_MAD_BLK_2; + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = + PH_FRINFC_MFSTD_FMT_MAD_BLK_2; + break; + + case PH_FRINFC_MFSTD_FMT_MAD_BLK_2: + case PH_FRINFC_MFSTD_FMT_MAD_BLK_66: + if((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD) || + (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock == + PH_FRINFC_MFSTD_FMT_MAD_BLK_66)) + { + /* Get the block from where the TLV has to be written */ + phFriNfc_MfStd_H_BlkNoToWrTLV(NdefSmtCrdFmt); + + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = + PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY; + } + else + { + /* Write the next MAD Block */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = (uint8_t) + PH_FRINFC_MFSTD_FMT_MAD_BLK_64; + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = + PH_FRINFC_MFSTD_FMT_MAD_BLK_64; + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = + PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB; + } + break; + + case PH_FRINFC_MFSTD_FMT_MAD_BLK_64: + /* Write the next MAD Block */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = (uint8_t) + PH_FRINFC_MFSTD_FMT_MAD_BLK_65; + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = + PH_FRINFC_MFSTD_FMT_MAD_BLK_65; + break; + + case PH_FRINFC_MFSTD_FMT_MAD_BLK_65: + default: + /* Write the next MAD Block */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = (uint8_t) + PH_FRINFC_MFSTD_FMT_MAD_BLK_66; + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = + PH_FRINFC_MFSTD_FMT_MAD_BLK_66; + break; + } + Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); + return Result; +} + +static void phFriNfc_MfStd_H_StrNdefData( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt ) +{ + uint8_t SectIndex = PH_FRINFC_MFSTD_FMT_VAL_1, + index = PH_FRINFC_MFSTD_FMT_VAL_0; + + (void)memset(NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk, + 0x00, + PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K); + + /* Zeroth sector of the Mifare card is MAD sector, CRC is 0x14 */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[PH_FRINFC_MFSTD_FMT_VAL_0] = 0x14; + /* Info byte is 0x01, because the NDEF application is written and as per the MAD spec, + the value for miscellaneous application is 0x01 */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[PH_FRINFC_MFSTD_FMT_VAL_1] = 0x01; + + if(NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD) + { + /* If 4k card then sector number 16 is MAD sector, CRC is 0xE8 */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[32] = 0xE8; + /* Info byte is 0x01, because the NDEF application is written and + as per the MAD spec, + the value for miscellaneous application is 0x01 */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[33] = 0x01; + } + /* NDEF information has to be updated from */ + index = PH_FRINFC_MFSTD_FMT_VAL_2; + /* Depending on the card type, check the sector index */ + while (((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K) && + (NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD)) || + ((SectIndex < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K) && + (NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD))) + { + /* Is the sector ndef compliant? */ + if(NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] == + PH_FRINFC_MFSTD_FMT_NDEF_COMPL) + { + /* Ndef compliant sector, update the MAD sector array + in the context with values 0x03 and 0xE1 + 0x03 and 0xE1 is NDEF information in MAD sector */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[index] = + PH_FRINFC_MFSTD_FMT_NDEF_INFO1; + index++; + NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[index] = + PH_FRINFC_MFSTD_FMT_NDEF_INFO2; + index++; + } + else + { + /* Not a Ndef compliant sector, update the MAD sector array + in the context with values 0x00 and 0x00 + 0x00 and 0x00 is NDEF information in MAD sector */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[index] = 0x00; + index++; + NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSectBlk[index] = 0x00; + index++; + } + /* Go to next sector */ + SectIndex++; + /* is the sector, a MAD sector 16? */ + if(SectIndex == PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K) + { + /* MAD sector number 16, so skip this sector */ + SectIndex = SectIndex + PH_FRINFC_MFSTD_FMT_VAL_1; + index = index + PH_FRINFC_MFSTD_FMT_VAL_2; + } + } +} + +static void phFriNfc_MfStd_H_BlkNoToWrTLV( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt ) +{ + uint8_t SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_VAL_1; + while (((SectIndex < (uint8_t)PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K) && + (NdefSmtCrdFmt->CardType == (uint8_t)PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD)) || + ((SectIndex < (uint8_t)PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K) && + (NdefSmtCrdFmt->CardType == (uint8_t)PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD))) + { + if (NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] == + (uint8_t)PH_FRINFC_MFSTD_FMT_NDEF_COMPL) + { + /* Get the first NFC forum sector's block */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = (uint16_t) + (((SectIndex & 0xE0) >= 32)? + (128 + ((SectIndex % 32) * 16)): + (SectIndex * (uint8_t)PH_FRINFC_MFSTD_FMT_VAL_4)); + /* Break out of the loop */ + SectIndex += (uint8_t)PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K; + } + SectIndex++; + } +} + +static NFCSTATUS phFriNfc_MfStd_H_ErrRdSectTr( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt ) +{ + NFCSTATUS Result = NdefSmtCrdFmt->FmtProcStatus; + uint8_t Buffer[1] = {PH_FRINFC_MFSTD_FMT_NDEF_COMPL}, + index = PH_FRINFC_MFSTD_FMT_VAL_1, + SectIndex = PH_FRINFC_MFSTD_FMT_VAL_0; + uint32_t memcompare = PH_FRINFC_MFSTD_FMT_VAL_1; + /* If default key A is used for authentication and if write fails, then try to + authenticate using key B*/ + if(NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState == + PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY) + { + /* Change the state to authentication */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; + /* internal authenticate state = key B */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = PH_FRINFC_MFSTD_FMT_AUTH_KEYB; + /* Now call authenticate */ + Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); + } + else + { + /* Calculate sector index */ + SectIndex = (uint8_t)PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC; + + /* Sector is ndef compliance */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[SectIndex] = (uint8_t) + ((NdefSmtCrdFmt->FmtProcStatus != NFCSTATUS_SUCCESS)? + PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL: + PH_FRINFC_MFSTD_FMT_NDEF_COMPL); + + /* Increment the current block */ + PH_FRINFC_MFSTD_FMT_CUR_BLK_INC(); + SectIndex++; + if(PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK) + { + PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD(); + } + else + { + /* Set the state */ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; + /* Set the authenticate state */ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = + PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY; + /* Start authentication */ + Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); + } + } + return Result; +} + +static int phFriNfc_MfStd_MemCompare( void *s1, void *s2, unsigned int n ) +{ + int8_t diff = 0; + int8_t *char_1 =(int8_t *)s1; + int8_t *char_2 =(int8_t *)s2; + if(NULL == s1 || NULL == s2) + { + PHDBG_CRITICAL_ERROR("NULL pointer passed to memcompare"); + } + else + { + for(;((n>0)&&(diff==0));n--,char_1++,char_2++) + { + diff = *char_1 - *char_2; + } + } + return (int)diff; +} + + + +#ifdef UNIT_TEST +#include +#endif diff --git a/libnfc-nxp/phFriNfc_MifStdFormat.h b/libnfc-nxp/phFriNfc_MifStdFormat.h new file mode 100644 index 0000000..648ec38 --- /dev/null +++ b/libnfc-nxp/phFriNfc_MifStdFormat.h @@ -0,0 +1,461 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* + * \file phFriNfc_MifStdFormat.h + * \brief NFC Ndef Formatting For Mifare standard card. + * + * Project: NFC-FRI + * + * $Date: Fri Sep 25 15:24:17 2009 $ + * $Author: ing07299 $ + * $Revision: 1.4 $ + * $Aliases: NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PHFRINFC_MIFSTDFORMAT_H +#define PHFRINFC_MIFSTDFORMAT_H + +#include +#ifdef PH_HAL4_ENABLE + #include +#else + #include +#endif /* #ifdef PH_HAL4_ENABLE */ +#include +#include +#include + +#define PH_FRINFC_MIFSTD_FORMAT_FILEREVISION "$Revision: 1.4 $" +#define PH_FRINFC_MIFSTD_FORMAT_FILEALIASES "$Aliases: NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" + + +/*! + * \name Mifare standard - constants for the state + * + */ +/*@{*/ +#define PH_FRINFC_MFSTD_FMT_RESET_INIT 0 /*!< Reset state */ +#define PH_FRINFC_MFSTD_FMT_AUTH_SECT 1 /*!< Sector authentication is in progress */ +#define PH_FRINFC_MFSTD_FMT_DIS_CON 2 /*!< Disconnect is in progress */ +#define PH_FRINFC_MFSTD_FMT_CON 3 /*!< Connect is in progress */ +#define PH_FRINFC_MFSTD_FMT_POLL 4 /*!< Poll is in progress */ +#define PH_FRINFC_MFSTD_FMT_RD_SECT_TR 5 /*!< Read sector trailer is in progress */ +#define PH_FRINFC_MFSTD_FMT_WR_SECT_TR 6 /*!< Write sector trailer is in progress */ +#define PH_FRINFC_MFSTD_FMT_WR_TLV 7 /*!< Write sector trailer is in progress */ +#define PH_FRINFC_MFSTD_FMT_WR_MAD_BLK 8 /*!< Write MAD is in progress */ +#define PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK 9 /*!< Write MAD is in progress */ +/*@}*/ + +/*! +* \name Mifare standard - Authenticate states +* +*/ +/*@{*/ +#define PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY 0 /*!< Trying to authenticate with the default key */ +#define PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY 1 /*!< Trying to authenticate with the MAD key */ +#define PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY 2 /*!< Trying to authenticate with the NFC forum key */ +#define PH_FRINFC_MFSTD_FMT_AUTH_KEYB 3 /*!< Trying to authenticate with key B */ +#define PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB 4 /*!< Trying to authenticate with secret key B */ + +/*@}*/ + +/*! +* \name Mifare standard - Update MAD block flag +* +*/ +/*@{*/ +#define PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK 0 /*!< Not a MAD block */ +#define PH_FRINFC_MFSTD_FMT_MAD_BLK_1 1 /*!< MAD block number 1 */ +#define PH_FRINFC_MFSTD_FMT_MAD_BLK_2 2 /*!< MAD block number 2 */ +#define PH_FRINFC_MFSTD_FMT_MAD_BLK_64 64 /*!< MAD block number 64 (only used for Mifare 4k card) */ +#define PH_FRINFC_MFSTD_FMT_MAD_BLK_65 65 /*!< MAD block number 65 (only used for Mifare 4k card) */ +#define PH_FRINFC_MFSTD_FMT_MAD_BLK_66 66 /*!< MAD block number 66 (only used for Mifare 4k card) */ + +/*@}*/ + +/*! +* \name Mifare standard - Update MAD block flag +* +*/ +/*@{*/ +#define PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_1K {0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0x78,0x77,0x88,0xC1} +#define PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_4K {0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0x78,0x77,0x88,0xC2} +#define PH_FRINFC_SMTCRDFMT_NFCFORUMSECT_KEYA_ACS_BIT {0xD3,0xF7,0xD3,0xF7,0xD3,0xF7,0x7F,0x07,0x88,0x40} + +/*@}*/ +/*! + * \name Mifare standard - Key and access bit constants + * + */ +/*@{*/ +#define PH_FRINFC_MFSTD_FMT_NFC_SECT_KEYA0 0xD3 /*!< NFC forum sector key A */ +#define PH_FRINFC_MFSTD_FMT_NFC_SECT_KEYA1 0xF7 /*!< NFC forum sector key A */ + +#define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA0 0xA0 /*!< MAD sector key A */ +#define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA1 0xA1 /*!< MAD sector key A */ +#define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA2 0xA2 /*!< MAD sector key A */ +#define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA3 0xA3 /*!< MAD sector key A */ +#define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA4 0xA4 /*!< MAD sector key A */ +#define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA5 0xA5 /*!< MAD sector key A */ + +#define PH_FRINFC_MFSTD_FMT_DEFAULT_KEY 0xFF /*!< Default key A or B */ + +#define PH_FRINFC_MFSTD_FMT_MAD_SECT_ACS6 0x78 /*!< MAD sector access bits 6 */ +#define PH_FRINFC_MFSTD_FMT_MAD_SECT_ACS7 0x77 /*!< MAD sector access bits 7 */ +#define PH_FRINFC_MFSTD_FMT_MAD_SECT_ACS8 0x88 /*!< MAD sector access bits 8 */ +#define PH_FRINFC_MFSTD_FMT_MAD_SECT_GPB 0xC1 /*!< MAD sector GPB */ + +#define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RW6 0x7F /*!< NFC forum sector access bits 6 for read write */ +#define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RW7 0x07 /*!< NFC forum sector access bits 7 for read write */ +#define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RW8 0x88 /*!< NFC forum sector access bits 8 for read write */ +#define PH_FRINFC_MFSTD_FMT_NFC_SECT_GPB_RW 0x40 /*!< NFC forum sector GPB for read write */ + +#define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RO6 0x07 /*!< NFC forum sector access bits 6 for read only */ +#define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RO7 0x8F /*!< NFC forum sector access bits 7 for read only */ +#define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RO8 0x0F /*!< NFC forum sector access bits 8 for read only */ +#define PH_FRINFC_MFSTD_FMT_NFC_SECT_GPB_R0 0x43 /*!< NFC forum sector GPB for read only */ + +/*@}*/ + +/*! + * \name Mifare standard - enums the values + * + */ +/*@{*/ +typedef enum{ +PH_FRINFC_MFSTD_FMT_VAL_0, +PH_FRINFC_MFSTD_FMT_VAL_1, +PH_FRINFC_MFSTD_FMT_VAL_2, +PH_FRINFC_MFSTD_FMT_VAL_3, +PH_FRINFC_MFSTD_FMT_VAL_4, +PH_FRINFC_MFSTD_FMT_VAL_5, +PH_FRINFC_MFSTD_FMT_VAL_6, +PH_FRINFC_MFSTD_FMT_VAL_7, +PH_FRINFC_MFSTD_FMT_VAL_8, +PH_FRINFC_MFSTD_FMT_VAL_9, +PH_FRINFC_MFSTD_FMT_VAL_10, +PH_FRINFC_MFSTD_FMT_VAL_11 +}phFriNfc_MfStdVal; +/*@}*/ + +/*! + * \name Mifare standard - NDEF information constants + * + */ +/*@{*/ +#define PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL 0 /*!< Sector is not ndef compliant */ +#define PH_FRINFC_MFSTD_FMT_NDEF_COMPL 1 /*!< Sector is ndef compliant */ +#define PH_FRINFC_MFSTD_FMT_NDEF_INFO1 0x03 /*!< If sector is ndef compliant, then one of the MAD + sector byte is 0x03 */ +#define PH_FRINFC_MFSTD_FMT_NDEF_INFO2 0xE1 /*!< If sector is ndef compliant, then one of the MAD + sector byte is 0xE1 */ +/*@}*/ + +/*! + * \name Mifare standard - constants + * + */ +/*@{*/ +#define PH_FRINFC_MFSTD_FMT_MAX_RECV_LENGTH 252 /*!< Maximum receive length */ +#define PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH 17 /*!< Send length for write */ +#define PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K 16 /*!< Maximum sector index for Mifare 1k = 16 */ +#define PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K 40 /*!< Maximum sector index for Mifare 4k = 40 */ +#define PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_1K 64 /*!< Maximum sector index for Mifare 1k = 16 */ +#define PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_4K 256 /*!< Maximum sector index for Mifare 4k = 40 */ +/*@}*/ + +/*! + * \name Mifare standard - constants for filling send buffer, calculating the block number, + * checking the authenticate state + * + */ +/*@{*/ +/* Copy default keyA to send buffer */ +#ifdef PH_HAL4_ENABLE + +#define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_DEF(mem)\ +do \ +{\ + (void)memset(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],\ + PH_FRINFC_MFSTD_FMT_DEFAULT_KEY,\ + PH_FRINFC_MFSTD_FMT_VAL_6);\ + NdefSmtCrdFmt->Cmd.MfCmd = ((NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState == \ + PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY)? \ + phHal_eMifareAuthentA: \ + phHal_eMifareAuthentB); \ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7; \ +}while(0) + +/* Copy NFC forum sector keyA to send buffer */ +#define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_NFCSECT_KEYA(mem)\ +do \ +{\ + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],\ + NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_KeyA,\ + PH_FRINFC_MFSTD_FMT_VAL_6);\ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareAuthentA;\ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7;\ +} while(0) + +/* Copy MAD sector keyA to send buffer */ +#define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_MADSECT_KEYA(mem)\ +do \ +{\ + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],\ + NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_KeyA,\ + PH_FRINFC_MFSTD_FMT_VAL_6);\ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareAuthentA;\ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7;\ +} while(0) + +#define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_SCRT_KEY(mem) \ +do \ +{\ + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],\ + NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB,\ + PH_FRINFC_MFSTD_FMT_VAL_6);\ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareAuthentB;\ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7;\ +} while(0) + +#else + +#define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_DEF(mem)\ +do \ +{\ + (void)memset(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],\ + PH_FRINFC_MFSTD_FMT_DEFAULT_KEY,\ + PH_FRINFC_MFSTD_FMT_VAL_6);\ + NdefSmtCrdFmt->Cmd.MfCmd = ((NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState == \ + PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY)? \ + phHal_eMifareCmdListMifareAuthentA: \ + phHal_eMifareCmdListMifareAuthentB); \ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7; \ +}while(0) + +/* Copy NFC forum sector keyA to send buffer */ +#define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_NFCSECT_KEYA(mem)\ +do \ +{\ + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],\ + NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_KeyA,\ + PH_FRINFC_MFSTD_FMT_VAL_6);\ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareAuthentA;\ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7;\ +} while(0) + +/* Copy MAD sector keyA to send buffer */ +#define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_MADSECT_KEYA(mem)\ +do \ +{\ + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],\ + NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_KeyA,\ + PH_FRINFC_MFSTD_FMT_VAL_6);\ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareAuthentA;\ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7;\ +} while(0) + +#define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_SCRT_KEY(mem) \ +do \ +{\ + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],\ + NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB,\ + PH_FRINFC_MFSTD_FMT_VAL_6);\ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareAuthentB;\ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7;\ +} while(0) + +#endif /* #ifdef PH_HAL4_ENABLE */ + + +/* Get the next block */ +#define PH_FRINFC_MFSTD_FMT_CUR_BLK_INC() \ + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock += \ + ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >= 127)?\ + 16:4) + +/* Get the sector index */ +#define PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC \ + ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >= 128)?\ + (32 + ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock - 128)/16)):\ + (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock/4)) + +#define PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK\ + ((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD) && \ + (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >= \ + PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_1K)) || \ + ((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD) && \ + (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >= \ + PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_4K)) + +/* Get the next authenticate state */ +#define PH_FRINFC_MFSTD_FMT_NXT_AUTH_STATE() \ +do \ +{\ + switch(NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState)\ + {\ + case PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY:\ + {\ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = (uint8_t) \ + ((((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock <= 3) || \ + ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock > 63) && \ + (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock < 67))))? \ + PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY: \ + PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY);\ + }\ + break;\ + case PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY:\ + {\ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = \ + PH_FRINFC_MFSTD_FMT_AUTH_KEYB;\ + }\ + break;\ + case PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY:\ + {\ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = \ + PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY;\ + }\ + break;\ + case PH_FRINFC_MFSTD_FMT_AUTH_KEYB:\ + { \ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = \ + PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB;\ + } \ + break;\ + case PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB:\ + default:\ + { \ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = \ + PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY;\ + }\ + break;\ + }\ +} while(0) + + +/* Increment the sector index */ +#define PH_FRINFC_MFSTD_FMT_INCR_SECT \ +do \ +{\ + SectIndex++;\ + SectIndex = (uint8_t)((SectIndex == 16)?\ + (SectIndex + PH_FRINFC_MFSTD_FMT_VAL_1):\ + SectIndex);\ +} while(0) + + +/* Increment the sector index */ +#define PH_FRINFC_MFSTD_FMT_CHK_SECT_ARRAY \ +do \ +{\ + while ((index < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K) && \ + (memcompare != PH_FRINFC_MFSTD_FMT_VAL_0))\ + {\ + /* Compare any one among the sectors is NDEF COMPLIANT */\ + memcompare = (uint32_t)phFriNfc_MfStd_MemCompare(&Buffer[PH_FRINFC_MFSTD_FMT_VAL_0], \ + &NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[index],\ + PH_FRINFC_MFSTD_FMT_VAL_1);\ + /* increment the index */\ + index += (uint8_t)((index == (PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K - \ + PH_FRINFC_MFSTD_FMT_VAL_1))?\ + PH_FRINFC_MFSTD_FMT_VAL_2:\ + PH_FRINFC_MFSTD_FMT_VAL_1);\ + }\ +} while(0) + +#define PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD() \ +do \ +{ \ + phFriNfc_MfStd_H_NdefComplSect(NdefSmtCrdFmt->CardType, \ + NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl); \ + PH_FRINFC_MFSTD_FMT_CHK_SECT_ARRAY; \ + if(memcompare == PH_FRINFC_MFSTD_FMT_VAL_0) \ + { \ + phFriNfc_MfStd_H_StrNdefData(NdefSmtCrdFmt); \ + NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = \ + PH_FRINFC_MFSTD_FMT_VAL_1; \ + NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = \ + PH_FRINFC_MFSTD_FMT_MAD_BLK_1; \ + NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = \ + PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB; \ + NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; \ + Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); \ + } \ + else \ + { \ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, \ + NFCSTATUS_FORMAT_ERROR); \ + } \ +} while(0) +/*@}*/ + + +/** + * \ingroup grp_fri_smart_card_formatting + * \brief Smart Card Formatting \b Reset function + * + * \copydoc page_reg Resets the component instance to the initial state and initializes the + * internal variables. + */ +void phFriNfc_MfStd_Reset(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! + * \ingroup grp_fri_smart_card_formatting + * + * \brief Initiates the card formatting procedure for Remote Smart Card Type. + * + * \copydoc page_ovr The function initiates and formats the Smart Card.After this formation, remote + * card would be properly initialized and Ndef Compliant. + * Depending upon the different card type, this function handles formatting procedure. + * This function also handles the different recovery procedures for different types of the cards. For both + * Format and Recovery Management same API is used. + * + * \param[in] phFriNfc_sNdefSmartCardFmt_t Pointer to a valid instance of the \ref phFriNfc_sNdefSmartCardFmt_t + * structure describing the component context. + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval Other values An error has occurred. + * + */ +NFCSTATUS phFriNfc_MfStd_Format(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, const uint8_t *ScrtKeyB); + +/** + *\ingroup grp_fri_smart_card_formatting + * + * \brief Smart card Formatting \b Completion \b Routine or \b Process function + * + * \copydoc page_ovr Completion Routine: This function is called by the lower layer (OVR HAL) + * when an I/O operation has finished. The internal state machine decides + * whether to call into the lower device again or to complete the process + * by calling into the upper layer's completion routine, stored within this + * component's context (\ref phFriNfc_sNdefSmtCrdFmt_t). + * + * The function call scheme is according to \ref grp_interact. No State reset is performed during + * operation. + * + * \param[in] Context The context of the current (not the lower/upper) instance, as set by the lower, + * calling layer, upon its completion. + * \param[in] Status The completion status of the lower layer (to be handled by the implementation of + * the state machine of this function like a regular return value of an internally + * called function). + * + * \note For general information about the completion routine interface please see \ref pphFriNfc_Cr_t . * The Different Status Values are as follows + * + */ +void phFriNfc_MfStd_Process(void *Context, + NFCSTATUS Status); +#endif /* PHFRINFC_MIFSTDFMT_H */ diff --git a/libnfc-nxp/phFriNfc_MifULFormat.c b/libnfc-nxp/phFriNfc_MifULFormat.c new file mode 100644 index 0000000..215155e --- /dev/null +++ b/libnfc-nxp/phFriNfc_MifULFormat.c @@ -0,0 +1,1472 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* + * \file phFriNfc_MifULFormat.c + * \brief NFC Ndef Formatting For Mifare ultralight card. + * + * Project: NFC-FRI + * + * $Date: Mon Dec 13 14:14:12 2010 $ + * $Author: ing02260 $ + * $Revision: 1.9 $ + * $Aliases: $ + * + */ + +#include +#include + +/*! \ingroup grp_file_attributes + * \name NDEF Mapping + * + * File: \ref phFriNfc_MifULFormat.c + * + */ +/*@{*/ +#define PHFRINFCMIFULFORMAT_FILEREVISION "$Revision: 1.9 $" +#define PHFRINFCMIFULFORMAT_FILEALIASES "$Aliases: $" +/*@}*/ + +#ifdef FRINFC_READONLY_NDEF + /* Mifare UL OTP block number is 3 */ + #define RD_LOCK_OTP_BLOCK_NUMBER 0x02U + #define OTP_BLOCK_NUMBER 0x03U + /* READ ONLY value that shall be written in the OTP to make the card read only */ + #define READ_ONLY_VALUE_IN_OTP 0x0FU + /* Mifare UL OTP block number is 3 */ + #define MIFARE_UL_READ_MAX_SIZE 16U + /* 1st Lock byte value */ + #define MIFARE_UL_LOCK_BYTE1_VALUE 0xF8U + /* 2nd Lock byte value */ + #define MIFARE_UL_LOCK_BYTE2_VALUE 0xFFU + /* Mifare ULC dynamic lock byte address */ + #define MIFARE_ULC_DYNAMIC_LOCK_BYTES_ADDR 0x28U + /* Type 2 STATIC CARD memory value in the OTP */ + #define TYPE_2_STATIC_MEM_SIZE_VALUE 0x06U + /* Type 2 DYNAMIC CARD memory value in the OTP */ + #define TYPE_2_DYNAMIC_MEM_SIZE_VALUE 0x12U + /* Lock byte 3 value to be ORed with the existing value */ + #define MIFARE_UL_LOCK_BYTE3_VALUE 0xEEU + /* Posiiton of the memory information in the stored OTP bytes */ + #define TYPE_2_MEM_SIZE_POSITION 0x02U + /* 3rd Lock byte position after reading the block number 0x28 */ + #define TYPE_2_LOCK_BYTE3_POS_RD_BLK28 0x00U + +#ifdef PH_NDEF_MIFARE_ULC + + /* Lock control TLVs, TYPE identifier */ + #define LOCK_CTRL_TYPE_IN_TLV 0x01U + /* Lock control TLVs, Length expected */ + #define LOCK_CTRL_LEN_IN_TLV 0x03U + + /* NDEF message TLVs, TYPE identifier */ + #define NDEF_TYPE_IN_TLV 0x03U + + #define MFUL_NULL_TLV 0x00U + #define THREE_BYTE_LENGTH_FIELD 0xFFU + #define TERMINATOR_TLV 0xFEU + #define MIFARE_ULC_SIZE 0xC0U + #define MFUL_NIBBLE_SIZE 0x04U + #define MFUL_NIBBLE_MASK 0x0FU + #define MFUL_BYTE_SIZE_IN_BITS 0x08U + #define MFUL_BLOCK_SIZE_IN_BYTES 0x04U + /* Initial (0 to 3 blocks) 4 blocks are ignored, i.e., 16 bytes */ + #define MFUL_INITIAL_BYTES_IGNORED 0x10U + + #define MFUL_CONVERT_BITS_TO_BYTES(bits_to_bytes) \ + (((bits_to_bytes % MFUL_BYTE_SIZE_IN_BITS) > 0) ? \ + ((bits_to_bytes / MFUL_BYTE_SIZE_IN_BITS) + 1) : \ + (bits_to_bytes / MFUL_BYTE_SIZE_IN_BITS)) + + typedef enum phFriNfc_MfUL_Parse + { + LOCK_TLV_T, + LOCK_TLV_L, + LOCK_TLV_V, + NDEF_TLV_T, + NDEF_TLV_L, + NDEF_TLV_V + }phFriNfc_MfUL_Parse_t; + +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + +#endif /* #ifdef FRINFC_READONLY_NDEF */ +/*! +* \brief \copydoc page_ovr Helper function for Mifare UL. This function calls the +* transceive function +*/ +static NFCSTATUS phFriNfc_MfUL_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! +* \brief \copydoc page_ovr Helper function for Mifare UL. This function calls the +* read or write operation +*/ +static NFCSTATUS phFriNfc_MfUL_H_WrRd(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! +* \brief \copydoc page_ovr Helper function for Mifare UL. This function fills the +* send buffer for transceive function +*/ +static void phFriNfc_MfUL_H_fillSendBuf(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint8_t BlockNo); + +/*! +* \brief \copydoc page_ovr Helper function for Mifare UL. This function shall process +* the read bytes +*/ +static NFCSTATUS phFriNfc_MfUL_H_ProRd16Bytes(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! +* \brief \copydoc page_ovr Helper function for Mifare UL. This function shall process the +* OTP bytes written +*/ +static NFCSTATUS phFriNfc_MfUL_H_ProWrOTPBytes(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +#ifdef FRINFC_READONLY_NDEF + +#ifdef PH_NDEF_MIFARE_ULC + +static +NFCSTATUS +phFriNfc_MfUL_ParseTLVs ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint8_t *data_to_parse, + uint8_t size_to_parse); + +static +NFCSTATUS +phFriNfc_MfUL_GetLockBytesInfo ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +static +NFCSTATUS +phFriNfc_MfUL_GetDefaultLockBytesInfo ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +static +uint8_t +phFriNfc_MfUL_GetSkipSize ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint8_t block_number, + uint8_t byte_number); + +static +NFCSTATUS +phFriNfc_MfUL_ReadWriteLockBytes ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +static +NFCSTATUS +phFriNfc_MfUL_UpdateAndWriteLockBits ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +static +uint8_t +phFriNfc_MfUL_CalcRemainingLockBits ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +static int MemCompare1 ( void *s1, void *s2, unsigned int n ); +/*The function does a comparision of two strings and returns a non zero value +if two strings are unequal*/ +static int MemCompare1 ( void *s1, void *s2, unsigned int n ) +{ + int8_t diff = 0; + int8_t *char_1 =(int8_t *)s1; + int8_t *char_2 =(int8_t *)s2; + if(NULL == s1 || NULL == s2) + { + PHDBG_CRITICAL_ERROR("NULL pointer passed to memcompare"); + } + else + { + for(;((n>0)&&(diff==0));n--,char_1++,char_2++) + { + diff = *char_1 - *char_2; + } + } + return (int)diff; +} + +void phFriNfc_MfUL_Reset(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + uint8_t OTPByte[] = PH_FRINFC_MFUL_FMT_OTP_BYTES; + + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_0; + (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes, + OTPByte, + sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes)); +#ifdef FRINFC_READONLY_NDEF + NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[0] = 0; + NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[1] = 0; + NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[2] = 0; + NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[3] = 0; +#endif /* #ifdef FRINFC_READONLY_NDEF */ +} + +NFCSTATUS phFriNfc_MfUL_Format(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t OTPByte[] = PH_FRINFC_MFUL_FMT_OTP_BYTES; + + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_0; + (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes, + OTPByte, + sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes)); + + /* Set the state */ + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RD_16BYTES; + /* Initialise current block to the lock bits block */ + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = PH_FRINFC_MFUL_FMT_VAL_2; + + /* Start authentication */ + Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt); + return Result; +} + +#ifdef FRINFC_READONLY_NDEF + +NFCSTATUS +phFriNfc_MfUL_ConvertToReadOnly ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + + NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag = TRUE; + NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = 0; + + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_RD_16BYTES; + + result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +void phFriNfc_MfUL_Process(void *Context, + NFCSTATUS Status) +{ + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t *)Context; + + if(Status == NFCSTATUS_SUCCESS) + { + switch(NdefSmtCrdFmt->State) + { + case PH_FRINFC_MFUL_FMT_RD_16BYTES: + Status = phFriNfc_MfUL_H_ProRd16Bytes(NdefSmtCrdFmt); + break; + + case PH_FRINFC_MFUL_FMT_WR_OTPBYTES: + Status = phFriNfc_MfUL_H_ProWrOTPBytes(NdefSmtCrdFmt); + break; + + case PH_FRINFC_MFUL_FMT_WR_TLV: +#ifdef PH_NDEF_MIFARE_ULC + if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD) + { + /* Write NDEF TLV in block number 5 */ + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = + PH_FRINFC_MFUL_FMT_VAL_5; + /* Card already have the OTP bytes so write TLV */ + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV1; + + Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + } +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + + break; + +#ifdef FRINFC_READONLY_NDEF + + case PH_FRINFC_MFUL_FMT_RO_RD_16BYTES: + { + if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength) + { + uint8_t otp_lock_page_size = 0; + uint8_t i = 0; + + otp_lock_page_size = sizeof (NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes); + (void)memcpy ((void *)NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes, + (void *)NdefSmtCrdFmt->SendRecvBuf, + sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes)); + + NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[2] = (uint8_t) + (NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[2] + | MIFARE_UL_LOCK_BYTE1_VALUE); + NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes[3] = MIFARE_UL_LOCK_BYTE2_VALUE; + i = (uint8_t)(i + otp_lock_page_size); + + otp_lock_page_size = sizeof (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes); + + (void)memcpy ((void *)NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes, + (void *)(NdefSmtCrdFmt->SendRecvBuf + i), + sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes)); + + NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[(otp_lock_page_size - 1)] = + READ_ONLY_VALUE_IN_OTP; + + switch (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION]) + { + case TYPE_2_STATIC_MEM_SIZE_VALUE: + { + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES; + Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + break; + } + +#ifdef PH_NDEF_MIFARE_ULC + case TYPE_2_DYNAMIC_MEM_SIZE_VALUE: + { + NdefSmtCrdFmt->State = + PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES; + + /* Start reading from block 4 */ + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = 4; + Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + break; + } +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + + default: + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES: + { + switch (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION]) + { + case TYPE_2_STATIC_MEM_SIZE_VALUE: +#ifdef PH_NDEF_MIFARE_ULC + case TYPE_2_DYNAMIC_MEM_SIZE_VALUE: +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + { + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES; + Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + break; + } + + default: + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + break; + } + +#ifdef PH_NDEF_MIFARE_ULC + + case PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES: + { + if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength) + { + Status = phFriNfc_MfUL_ParseTLVs (NdefSmtCrdFmt, + NdefSmtCrdFmt->SendRecvBuf, + (uint8_t)*NdefSmtCrdFmt->SendRecvLength); + + if (!Status) + { + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = + NdefSmtCrdFmt->AddInfo.Type2Info.LockBlockNumber; + Status = phFriNfc_MfUL_ReadWriteLockBytes (NdefSmtCrdFmt); + } + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES: + { + if (MIFARE_UL_READ_MAX_SIZE == *NdefSmtCrdFmt->SendRecvLength) + { + (void)memcpy ((void *)NdefSmtCrdFmt->AddInfo.Type2Info.ReadData, + (void *)NdefSmtCrdFmt->SendRecvBuf, + sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.ReadData)); + + NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = 0; + + Status = phFriNfc_MfUL_UpdateAndWriteLockBits (NdefSmtCrdFmt); + + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES: + { + NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex = (uint8_t) + (NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex + + MFUL_BLOCK_SIZE_IN_BYTES); + + if (!phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt)) + { + /* There is no lock bits to write, then write OTP bytes */ + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES; + Status = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + } + else if ((NdefSmtCrdFmt->AddInfo.Type2Info.ReadDataIndex < + MIFARE_UL_READ_MAX_SIZE) + && (phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt))) + { + /* If remaining lock bits has to be written and the data is already read */ + Status = phFriNfc_MfUL_UpdateAndWriteLockBits (NdefSmtCrdFmt); + } + else + { + /* Increment current block by 4 because if a data is read then 16 + bytes will be given which is 4 blocks */ + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = (uint8_t) + (NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock + 4); + Status = phFriNfc_MfUL_ReadWriteLockBytes (NdefSmtCrdFmt); + } + break; + } + +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + + case PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES: + { + /* Do nothing */ + break; + } + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +#ifdef PH_NDEF_MIFARE_ULC + case PH_FRINFC_MFUL_FMT_WR_TLV1: + + break; +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + + default: + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + /* Status is not success then call completion routine */ + if(Status != NFCSTATUS_PENDING) + { + phFriNfc_SmtCrdFmt_HCrHandler(NdefSmtCrdFmt, Status); + } +} + +#ifdef FRINFC_READONLY_NDEF + +#ifdef PH_NDEF_MIFARE_ULC + +static +uint8_t +phFriNfc_MfUL_GetSkipSize ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint8_t block_number, + uint8_t byte_number) +{ + uint8_t skip_size = 0; + phFriNfc_Type2_AddInfo_t *ps_type2_info = + &NdefSmtCrdFmt->AddInfo.Type2Info; + + /* This check is added, because the default lock bits is always + present after the DATA AREA. + So, default lock bytes doesnt have any skip size */ + if (!ps_type2_info->DefaultLockBytesFlag) + { + /* Only check for the lock control TLV */ + if ((block_number == ps_type2_info->LockBlockNumber) + && (byte_number == ps_type2_info->LockByteNumber)) + { + skip_size = MFUL_CONVERT_BITS_TO_BYTES(ps_type2_info->NoOfLockBits); + } + } + + return skip_size; +} + +static +NFCSTATUS +phFriNfc_MfUL_GetLockBytesInfo ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_Type2_AddInfo_t *ps_type2_info = + &(NdefSmtCrdFmt->AddInfo.Type2Info); + uint8_t page_address = 0; + uint8_t bytes_offset = 0; + uint8_t lock_index = 0; + + + page_address = (uint8_t)(ps_type2_info->DynLockBytes[lock_index] >> MFUL_NIBBLE_SIZE); + bytes_offset = (uint8_t)(ps_type2_info->DynLockBytes[lock_index] & MFUL_NIBBLE_MASK); + + lock_index = (lock_index + 1); + ps_type2_info->NoOfLockBits = ps_type2_info->DynLockBytes[lock_index]; + + lock_index = (lock_index + 1); + ps_type2_info->LockBytesPerPage = + (ps_type2_info->DynLockBytes[lock_index] & MFUL_NIBBLE_MASK); + ps_type2_info->BytesLockedPerLockBit = + (ps_type2_info->DynLockBytes[lock_index] >> MFUL_NIBBLE_SIZE); + + /* Apply the formula to calculate byte address + ByteAddr = ((PageAddr * (2 ^ BytesPerPage)) + ByteOffset) + */ + ps_type2_info->LockByteNumber = (uint8_t)((page_address + * (1 << ps_type2_info->LockBytesPerPage)) + + bytes_offset); + + ps_type2_info->LockBlockNumber = (uint8_t)(ps_type2_info->LockByteNumber / + MFUL_BLOCK_SIZE_IN_BYTES); + ps_type2_info->LockByteNumber = (uint8_t)(ps_type2_info->LockByteNumber % + MFUL_BLOCK_SIZE_IN_BYTES); + +#if 0 + if ( + /* Out of bound memory check */ + ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size) > + (uint16_t)(psNdefMap->TopazContainer.CCByteBuf[2] * + TOPAZ_BYTES_PER_BLOCK)) || + + /* Check the static lock and reserved areas memory blocks */ + ((ps_locktlv_info->ByteAddr >= TOPAZ_STATIC_LOCK_RES_START) && + (ps_locktlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_END)) || + (((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1) >= + TOPAZ_STATIC_LOCK_RES_START) && + ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1) < + TOPAZ_STATIC_LOCK_RES_END)) + ) + { + ps_locktlv_info->ByteAddr = 0; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + ps_locktlv_info->BlkNum = (ps_locktlv_info->ByteAddr / + TOPAZ_BYTES_PER_BLOCK); + ps_locktlv_info->ByteNum = (ps_locktlv_info->ByteAddr % + TOPAZ_BYTES_PER_BLOCK); + } +#endif /* #if 0 */ + + return result; +} + +static +uint8_t +phFriNfc_MfUL_CalcRemainingLockBits ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + uint8_t lock_bits_remaining = 0; + phFriNfc_Type2_AddInfo_t *ps_type2_info = + &(NdefSmtCrdFmt->AddInfo.Type2Info); + + lock_bits_remaining = (uint8_t)(ps_type2_info->NoOfLockBits - + ps_type2_info->LockBitsWritten); + + return lock_bits_remaining; +} + +static +NFCSTATUS +phFriNfc_MfUL_UpdateAndWriteLockBits ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_Type2_AddInfo_t *ps_type2_info = + &(NdefSmtCrdFmt->AddInfo.Type2Info); + uint8_t byte_index = 0; + uint8_t no_of_bits_left_in_block = 0; + uint8_t remaining_lock_bits = 0; + uint8_t remaining_lock_bytes = 0; + /* Array of 3 is used because the lock bits with 4 bytes in a block + is handled in the function phFriNfc_MfUL_ReadWriteLockBytes + So use this function only if lock bytes doesnt use the entire block */ + uint8_t lock_bytes_value[MFUL_BLOCK_SIZE_IN_BYTES] = {0}; + uint8_t lock_byte_index = 0; + + (void)memcpy ((void *)lock_bytes_value, + (void*)(ps_type2_info->ReadData + ps_type2_info->ReadDataIndex), + sizeof (ps_type2_info->DynLockBytes)); + remaining_lock_bits = phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt); + + if (ps_type2_info->CurrentBlock == ps_type2_info->LockBlockNumber) + { + /* 1st write to lock bits, so byte_index is updated */ + byte_index = ps_type2_info->LockByteNumber; + } + + no_of_bits_left_in_block = (uint8_t)((MFUL_BLOCK_SIZE_IN_BYTES - byte_index) * + MFUL_BYTE_SIZE_IN_BITS); + + if (no_of_bits_left_in_block >= remaining_lock_bits) + { + /* Entire lock bits can be written + if block size is more than number of lock bits. + so allocate the lock bits with value 1b and + dont change the remaining bits */ + if (remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS) + { + /* mod operation has resulted in a value, means lock bits ends in between a byte */ + uint8_t mod_value = 0; + + remaining_lock_bytes = ((remaining_lock_bits / + MFUL_BYTE_SIZE_IN_BITS) + 1); + + /* mod_value is used to fill the only partial bits and + remaining bits shall be untouched */ + mod_value = (uint8_t)(remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS); + if (remaining_lock_bits > MFUL_BYTE_SIZE_IN_BITS) + { + /* lock bits to write is greater than 8 bits */ + while (lock_byte_index < (remaining_lock_bytes - 1)) + { + /* Set 1b to all bits left in the block */ + lock_bytes_value[byte_index] = 0xFF; + lock_byte_index = (uint8_t)(lock_byte_index + 1); + byte_index = (uint8_t)(byte_index + 1); + } + /* Last byte of the lock bits shall be filled partially, + Set only the remaining lock bits and dont change + the other bit value */ + lock_bytes_value[byte_index] = 0; + lock_bytes_value[byte_index] = (uint8_t) + SET_BITS8 (lock_bytes_value[byte_index], 0, + mod_value, 1); + } + else + { + /* lock bits to write is less than 8 bits, so + there is only one byte to write. + Set only the remaining lock bits and dont change + the other bit value */ + lock_bytes_value[0] = (uint8_t)SET_BITS8 (lock_bytes_value[0], 0, + mod_value, 1); + } + } /* if (remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS) */ + else + { + /* MOD operation is 00, that means entire byte value shall be 0xFF, means + every bit shall be to 1 */ + remaining_lock_bytes = (remaining_lock_bits / + MFUL_BYTE_SIZE_IN_BITS); + + while (lock_byte_index < remaining_lock_bytes) + { + /* Set 1b to all bits left in the block */ + lock_bytes_value[byte_index] = 0xFF; + lock_byte_index = (uint8_t)(lock_byte_index + 1); + byte_index = (uint8_t)(byte_index + 1); + } + } /* else of if (remaining_lock_bits % MFUL_BYTE_SIZE_IN_BITS) */ + ps_type2_info->LockBitsWritten = (uint8_t)(ps_type2_info->LockBitsWritten + + remaining_lock_bits); + } /* if (no_of_bits_left_in_block >= remaining_lock_bits) */ + else + { + /* Update till the left bits in the block and then carry + out next operation after this write */ + while (lock_byte_index < (no_of_bits_left_in_block / MFUL_BYTE_SIZE_IN_BITS)) + { + /* Set 1b to all bits left in the block */ + lock_bytes_value[byte_index] = 0xFF; + lock_byte_index = (uint8_t)(lock_byte_index + 1); + byte_index = (uint8_t)(byte_index + 1); + } + ps_type2_info->LockBitsWritten = (uint8_t)(ps_type2_info->LockBitsWritten + + no_of_bits_left_in_block); + } /* else of if (no_of_bits_left_in_block >= remaining_lock_bits) */ + + + /* Copy the values back to the DynLockBytes structure member */ + (void)memcpy ((void*)ps_type2_info->DynLockBytes, + (void *)lock_bytes_value, + sizeof (ps_type2_info->DynLockBytes)); + + + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES; + result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + + return result; +} + +static +NFCSTATUS +phFriNfc_MfUL_ReadWriteLockBytes ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_Type2_AddInfo_t *ps_type2_info = + &(NdefSmtCrdFmt->AddInfo.Type2Info); + uint8_t write_flag = FALSE; + + if (/* Lock bytes starts from the beginning of the block */ + (0 == ps_type2_info->LockByteNumber) + /* To make sure this is the first read */ + && (ps_type2_info->CurrentBlock == ps_type2_info->LockBlockNumber) + /* Lock bytes are greater than or equal to the block size, i.e., 4 bytes */ + && (phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt) + >= (MFUL_BLOCK_SIZE_IN_BYTES * MFUL_BYTE_SIZE_IN_BITS))) + { + /* Then directly write the lock bytes, dont waste time for read */ + (void)memset ((void *)ps_type2_info->DynLockBytes, 0xFF, + sizeof (ps_type2_info->DynLockBytes)); + write_flag = TRUE; + } + else if (ps_type2_info->CurrentBlock == ps_type2_info->LockBlockNumber) + { + /* Read is mandatory, First read and then update the block, + because chances are there that lock byte may start in between + the block */ + } + else if (/* check if remaining bytes exceeds or same as the block size */ + (phFriNfc_MfUL_CalcRemainingLockBits (NdefSmtCrdFmt) + >= (MFUL_BLOCK_SIZE_IN_BYTES * MFUL_BYTE_SIZE_IN_BITS))) + { + /* Then directly write the lock bytes, dont waste time for read */ + (void)memset ((void *)ps_type2_info->DynLockBytes, 0xFF, + sizeof (ps_type2_info->DynLockBytes)); + write_flag = TRUE; + } + else + { + /* Read is mandatory, First read and then update the block */ + } + + if (write_flag) + { + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES; + result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + } + else + { + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES; + result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + } + + return result; +} + +static +NFCSTATUS +phFriNfc_MfUL_GetDefaultLockBytesInfo ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_Type2_AddInfo_t *ps_type2_info = + &(NdefSmtCrdFmt->AddInfo.Type2Info); + uint16_t lock_byte_start_addr = 0; + + /* The position of the dynamic lock bits starts from + the first byte after the data area */ + lock_byte_start_addr = (uint16_t)(MFUL_INITIAL_BYTES_IGNORED + + (ps_type2_info->OTPBytes[TYPE_2_MEM_SIZE_POSITION] * 8)); + + ps_type2_info->LockBlockNumber = (uint8_t)(lock_byte_start_addr / + MFUL_BLOCK_SIZE_IN_BYTES); + ps_type2_info->LockByteNumber = (uint8_t)(lock_byte_start_addr % + MFUL_BLOCK_SIZE_IN_BYTES); + /* Default settings + NoOfLockBits = [(DataAreaSize - 48)/8] */ + ps_type2_info->NoOfLockBits = (uint8_t) + (((ps_type2_info->OTPBytes[TYPE_2_MEM_SIZE_POSITION] * 8) - 48)/8); + + return result; +} + +static +NFCSTATUS +phFriNfc_MfUL_ParseTLVs ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint8_t *data_to_parse, + uint8_t size_to_parse) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + static uint8_t lock_mem_ndef_index = 0; + static uint8_t skip_lock_mem_size = 0; + static uint16_t card_size_remaining = 0; + static uint16_t ndef_data_size = 0; + static phFriNfc_MfUL_Parse_t parse_tlv = LOCK_TLV_T; + uint8_t parse_index = 0; + + if ((0 == card_size_remaining) && (0 == parse_index)) + { + /* card size is calculated only once */ + card_size_remaining = (uint16_t) + (NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION] * 8); + } + + while ((parse_index < size_to_parse) + && (NFCSTATUS_SUCCESS == result) + && (NDEF_TLV_V != parse_tlv) + && (0 != card_size_remaining)) + { + if (0 == skip_lock_mem_size) + { + /* Skip the lock TLVs, so get the lock bits */ + skip_lock_mem_size = phFriNfc_MfUL_GetSkipSize (NdefSmtCrdFmt, + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock, + parse_index); + } + + if (0 != skip_lock_mem_size) + { + if (skip_lock_mem_size >= (size_to_parse - parse_index)) + { + /* if skip size is more than the size to parse, then */ + card_size_remaining = (uint16_t)(card_size_remaining - + (size_to_parse - parse_index)); + skip_lock_mem_size = (uint8_t)(skip_lock_mem_size - + ((size_to_parse - parse_index))); + parse_index = size_to_parse; + } + else + { + card_size_remaining = (uint16_t)(card_size_remaining - + skip_lock_mem_size); + + parse_index = (uint8_t)(parse_index + skip_lock_mem_size); + skip_lock_mem_size = 0; + } + } + else + { + switch (parse_tlv) + { + case LOCK_TLV_T: + { + switch (*(data_to_parse + parse_index)) + { + case MFUL_NULL_TLV: + { + /* Do nothing, parse further */ + break; + } + + case LOCK_CTRL_TYPE_IN_TLV: + { + parse_tlv = LOCK_TLV_L; + break; + } + + case NDEF_TYPE_IN_TLV: + { + parse_tlv = NDEF_TLV_L; + /* Default lock bytes shall be taken */ + NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag = + TRUE; + result = phFriNfc_MfUL_GetDefaultLockBytesInfo (NdefSmtCrdFmt); + break; + } + + default: + { + parse_tlv = LOCK_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + break; + } + + case LOCK_TLV_L: + { + if (LOCK_CTRL_LEN_IN_TLV == *(data_to_parse + parse_index)) + { + parse_tlv = LOCK_TLV_V; + } + else + { + skip_lock_mem_size = 0; + parse_tlv = LOCK_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + } + break; + } + + case LOCK_TLV_V: + { + switch (lock_mem_ndef_index) + { + case 0: + case 1: + { + NdefSmtCrdFmt->AddInfo.Type2Info.DefaultLockBytesFlag = + FALSE; + NdefSmtCrdFmt->AddInfo.Type2Info.DynLockBytes[lock_mem_ndef_index] = + *(data_to_parse + parse_index); + lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1); + break; + } + + case 2: + { + NdefSmtCrdFmt->AddInfo.Type2Info.DynLockBytes[lock_mem_ndef_index] = + *(data_to_parse + parse_index); + parse_tlv = NDEF_TLV_T; + lock_mem_ndef_index = 0; + result = phFriNfc_MfUL_GetLockBytesInfo (NdefSmtCrdFmt); + break; + } + + default: + { + skip_lock_mem_size = 0; + parse_tlv = LOCK_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + break; + } /* switch (lock_mem_ndef_index) in case LOCK_TLV_V */ + + case NDEF_TLV_T: + { + switch (*(data_to_parse + parse_index)) + { + case MFUL_NULL_TLV: + { + /* Do nothing, parse further */ + break; + } + + case NDEF_TYPE_IN_TLV: + { + parse_tlv = NDEF_TLV_L; + break; + } + + default: + { + skip_lock_mem_size = 0; + parse_tlv = LOCK_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + break; + } /* switch (*(data_to_parse + parse_index)) in case NDEF_TLV_T */ + + case NDEF_TLV_L: + { + switch (lock_mem_ndef_index) + { + case 0: + { + if (THREE_BYTE_LENGTH_FIELD == *(data_to_parse + parse_index)) + { + lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1); + } + else + { + ndef_data_size = *(data_to_parse + parse_index); + parse_tlv = NDEF_TLV_V; + lock_mem_ndef_index = 0; + } + break; + } + + case 1: + { + ndef_data_size = (uint16_t)(*(data_to_parse + parse_index) << 8); + break; + } + + case 2: + { + ndef_data_size = (uint16_t)(ndef_data_size | + *(data_to_parse + parse_index)); + parse_tlv = NDEF_TLV_V; + lock_mem_ndef_index = 0; + break; + } + } /* switch (lock_mem_ndef_index) in case NDEF_TLV_L */ + break; + } + + case NDEF_TLV_V: + { + break; + } + + default: + { + skip_lock_mem_size = 0; + parse_tlv = LOCK_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } /* switch (parse_tlv) */ + + } /* else part of if (0 != skip_lock_mem_size) */ + + if (0 == card_size_remaining) + { + skip_lock_mem_size = 0; + parse_tlv = LOCK_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else if (NDEF_TLV_V != parse_tlv) + { + /* Increment the index */ + parse_index = (uint8_t)(parse_index + 1); + /* card size is decremented as the memory area is parsed */ + card_size_remaining = (uint16_t)(card_size_remaining - 1); + } + else + { + /* L field of the NDEF TLV + L field can have 1 byte or also 3 bytes + */ + uint8_t length_to_deduct = 1; + + if ((NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes[TYPE_2_MEM_SIZE_POSITION] + * 8) >= THREE_BYTE_LENGTH_FIELD) + { + length_to_deduct = 3; + } + /* parse_tlv has reached the VALUE field of the NDEF TLV */ + if ((card_size_remaining - length_to_deduct) < ndef_data_size) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_NO_NDEF_SUPPORT); + } + + lock_mem_ndef_index = 0; + skip_lock_mem_size = 0; + card_size_remaining = 0; + } + } /* while ((parse_index < size_to_parse) + && (NFCSTATUS_SUCCESS != result) + && (NDEF_TLV_V != parse_tlv) + && (0 != card_size_remaining)) */ + + if ((NDEF_TLV_V == parse_tlv) || (NFCSTATUS_SUCCESS != result)) + { + parse_tlv = LOCK_TLV_T; + } + else + { + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES; + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = + (NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock + 4); + + result = phFriNfc_MfUL_H_WrRd (NdefSmtCrdFmt); + } + + if (NFCSTATUS_PENDING != result) + { + lock_mem_ndef_index = 0; + skip_lock_mem_size = 0; + card_size_remaining = 0; + } + return result; +} + +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +static NFCSTATUS phFriNfc_MfUL_H_WrRd( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt ) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Fill the send buffer */ + phFriNfc_MfUL_H_fillSendBuf(NdefSmtCrdFmt, + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock); + + /* Call transceive */ + Result = phFriNfc_MfUL_H_Transceive (NdefSmtCrdFmt); + + return Result; +} + +static NFCSTATUS phFriNfc_MfUL_H_Transceive(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* set the data for additional data exchange*/ + NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefSmtCrdFmt->psDepAdditionalInfo.DepFlags.NADPresent = 0; + NdefSmtCrdFmt->psDepAdditionalInfo.NAD = 0; + + /*set the completion routines for the card operations*/ + NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = phFriNfc_NdefSmtCrd_Process; + NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = NdefSmtCrdFmt; + + *NdefSmtCrdFmt->SendRecvLength = PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE; + + /* Call the Overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefSmtCrdFmt->LowerDevice, + &NdefSmtCrdFmt->SmtCrdFmtCompletionInfo, + NdefSmtCrdFmt->psRemoteDevInfo, + NdefSmtCrdFmt->Cmd, + &NdefSmtCrdFmt->psDepAdditionalInfo, + NdefSmtCrdFmt->SendRecvBuf, + NdefSmtCrdFmt->SendLength, + NdefSmtCrdFmt->SendRecvBuf, + NdefSmtCrdFmt->SendRecvLength); + return Result; +} + +static void phFriNfc_MfUL_H_fillSendBuf( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint8_t BlockNo) +{ +#ifdef PH_NDEF_MIFARE_ULC + uint8_t NDEFTLV1[4] = {0x01, 0x03, 0xA0, 0x10}; + uint8_t NDEFTLV2[4] = {0x44, 0x03, 0x00, 0xFE}; +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + uint8_t NDEFTLV[4] = {0x03, 0x00, 0xFE, 0x00}; + + + + + /* First byte for send buffer is always the block number */ + NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_0] = (uint8_t)BlockNo; + switch(NdefSmtCrdFmt->State) + { +#ifdef FRINFC_READONLY_NDEF + + case PH_FRINFC_MFUL_FMT_RO_RD_16BYTES: + { +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead; +#else + /* Read command */ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead; +#endif /* #ifdef PH_HAL4_ENABLE */ + *NdefSmtCrdFmt->SendRecvBuf = RD_LOCK_OTP_BLOCK_NUMBER; + /* Send length for read command is always one */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1; + break; + } + +#ifdef PH_NDEF_MIFARE_ULC + + case PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES: + { +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead; +#else + /* Read command */ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead; +#endif /* #ifdef PH_HAL4_ENABLE */ + *NdefSmtCrdFmt->SendRecvBuf = + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock; + /* Send length for read command is always one */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1; + break; + } + + case PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES: + { +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead; +#else + /* Read command */ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead; +#endif /* #ifdef PH_HAL4_ENABLE */ + *NdefSmtCrdFmt->SendRecvBuf = NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock; + /* Send length for read command is always one */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1; + break; + } + + case PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES: + { +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4; +#else + /* Write command */ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4; +#endif /* #ifdef PH_HAL4_ENABLE */ + + /* Send length for read command is always one */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5; + *NdefSmtCrdFmt->SendRecvBuf = NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock; + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], + NdefSmtCrdFmt->AddInfo.Type2Info.DynLockBytes, + PH_FRINFC_MFUL_FMT_VAL_4); + break; + } + +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + + case PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES: + { +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4; +#else + /* Read command */ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4; +#endif /* #ifdef PH_HAL4_ENABLE */ + + /* Send length for read command is always one */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5; + *NdefSmtCrdFmt->SendRecvBuf = RD_LOCK_OTP_BLOCK_NUMBER; + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], + NdefSmtCrdFmt->AddInfo.Type2Info.LockBytes, + PH_FRINFC_MFUL_FMT_VAL_4); + break; + } + + case PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES: + { +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4; +#else + /* Read command */ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4; +#endif /* #ifdef PH_HAL4_ENABLE */ + + /* Send length for read command is always one */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5; + *NdefSmtCrdFmt->SendRecvBuf = OTP_BLOCK_NUMBER; + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], + NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes, + PH_FRINFC_MFUL_FMT_VAL_4); + break; + } + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + + case PH_FRINFC_MFUL_FMT_RD_16BYTES: +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareRead; +#else + /* Read command */ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareRead; +#endif /* #ifdef PH_HAL4_ENABLE */ + /* Send length for read command is always one */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_1; + break; + + case PH_FRINFC_MFUL_FMT_WR_OTPBYTES: + /* Send length for read command is always Five */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5; + /* Write command */ +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4; +#else + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4; +#endif /* #ifdef PH_HAL4_ENABLE */ + /* Copy the OTP bytes */ + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], + NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes, + PH_FRINFC_MFUL_FMT_VAL_4); + break; + + case PH_FRINFC_MFUL_FMT_WR_TLV: +#ifndef PH_NDEF_MIFARE_ULC + default: +#endif /* #ifndef PH_NDEF_MIFARE_ULC */ + /* Send length for read command is always Five */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5; + /* Write command */ +#ifdef PH_HAL4_ENABLE + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4; +#else + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite4; +#endif /* #ifdef PH_HAL4_ENABLE */ + /* Copy the NDEF TLV */ +#ifdef PH_NDEF_MIFARE_ULC + + if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD) + { + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], + NDEFTLV1, + PH_FRINFC_MFUL_FMT_VAL_4); + } + else if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_UL_CARD) + { + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], + NDEFTLV, + PH_FRINFC_MFUL_FMT_VAL_4); + } + else + { + } +#else + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], + NDEFTLV, + PH_FRINFC_MFUL_FMT_VAL_4); + +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + + break; + +#ifdef PH_NDEF_MIFARE_ULC + case PH_FRINFC_MFUL_FMT_WR_TLV1: + if (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD) + { + /* Send length for write command is always Five */ + NdefSmtCrdFmt->SendLength = PH_FRINFC_MFUL_FMT_VAL_5; + /* Write command */ + NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareWrite4; + (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_1], + NDEFTLV2, + PH_FRINFC_MFUL_FMT_VAL_4); + } + break; + default: + break; +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + + + } +} + +static NFCSTATUS phFriNfc_MfUL_H_ProRd16Bytes( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt ) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_FORMAT_ERROR); + uint32_t memcompare = PH_FRINFC_MFUL_FMT_VAL_0; + uint8_t ZeroBuf[] = {0x00, 0x00, 0x00, 0x00}; + +#ifdef PH_NDEF_MIFARE_ULC + uint8_t OTPByteUL[] = PH_FRINFC_MFUL_FMT_OTP_BYTES; + uint8_t OTPByteULC[] = PH_FRINFC_MFULC_FMT_OTP_BYTES; +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + + /* Check the lock bits (byte number 2 and 3 of block number 2) */ + if ((NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_2] == + PH_FRINFC_MFUL_FMT_LOCK_BITS_VAL) && + (NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_3] == + PH_FRINFC_MFUL_FMT_LOCK_BITS_VAL)) + { + +#ifdef PH_NDEF_MIFARE_ULC + + if (NdefSmtCrdFmt->SendRecvBuf[8] == 0x02 && + NdefSmtCrdFmt->SendRecvBuf[9] == 0x00) + { + NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD; + + (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes, + OTPByteULC, + sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes)); + } + else if (NdefSmtCrdFmt->SendRecvBuf[8] == 0xFF && + NdefSmtCrdFmt->SendRecvBuf[9] == 0xFF) + { + NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD; + + (void)memcpy(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes, + OTPByteUL, + sizeof(NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes)); + } + else + { + NdefSmtCrdFmt->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD; + } + +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + + memcompare = (uint32_t) + MemCompare1(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_4], + NdefSmtCrdFmt->AddInfo.Type2Info.OTPBytes, + PH_FRINFC_MFUL_FMT_VAL_4); + + if (memcompare == PH_FRINFC_MFUL_FMT_VAL_0) + { + /* Write NDEF TLV in block number 4 */ + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = + PH_FRINFC_MFUL_FMT_VAL_4; + /* Card already have the OTP bytes so write TLV */ + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV; + } + else + { + /* IS the card new, OTP bytes = {0x00, 0x00, 0x00, 0x00} */ + memcompare = (uint32_t)MemCompare1(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFUL_FMT_VAL_4], + ZeroBuf, + PH_FRINFC_MFUL_FMT_VAL_4); + /* If OTP bytes are Zero then the card is Zero */ + if (memcompare == PH_FRINFC_MFUL_FMT_VAL_0) + { + /* Write OTP bytes in block number 3 */ + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = + PH_FRINFC_MFUL_FMT_VAL_3; + /* Card already have the OTP bytes so write TLV */ + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_OTPBYTES; + } + } + } + + + +#ifdef PH_NDEF_MIFARE_ULC + if( + ((NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_TLV) || + (NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_OTPBYTES)) && + ((NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD) || + (NdefSmtCrdFmt->CardType == PH_FRINFC_NDEFMAP_MIFARE_UL_CARD)) + ) +#else + if((NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_TLV) || + (NdefSmtCrdFmt->State == PH_FRINFC_MFUL_FMT_WR_OTPBYTES)) +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + { + Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt); + } + return Result; +} + +static NFCSTATUS phFriNfc_MfUL_H_ProWrOTPBytes( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt ) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + /* Card already have the OTP bytes so write TLV */ + NdefSmtCrdFmt->State = PH_FRINFC_MFUL_FMT_WR_TLV; + + /* Write NDEF TLV in block number 4 */ + NdefSmtCrdFmt->AddInfo.Type2Info.CurrentBlock = + PH_FRINFC_MFUL_FMT_VAL_4; + + Result = phFriNfc_MfUL_H_WrRd(NdefSmtCrdFmt); + return Result; +} + diff --git a/libnfc-nxp/phFriNfc_MifULFormat.h b/libnfc-nxp/phFriNfc_MifULFormat.h new file mode 100644 index 0000000..5238014 --- /dev/null +++ b/libnfc-nxp/phFriNfc_MifULFormat.h @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* + * \file phFriNfc_MifULFormat.h + * \brief NFC Ndef Formatting For Mifare standard card. + * + * Project: NFC-FRI + * + * $Date: Mon Dec 13 14:14:12 2010 $ + * $Author: ing02260 $ + * $Revision: 1.5 $ + * $Aliases: $ + * + */ + +#ifndef PHFRINFC_MIFULFORMAT_H +#define PHFRINFC_MIFULFORMAT_H + +#include +#ifdef PH_HAL4_ENABLE + #include +#else + #include +#endif +#include +#include +#include + +#ifdef PH_NDEF_MIFARE_ULC +#include +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + +#define PH_FRINFC_MIFUL_FORMAT_FILEREVISION "$Revision: 1.5 $" +#define PH_FRINFC_MIFUL_FORMAT_FILEALIASES "$Aliases: $" + + +/*! + * \name Mifare UL - constants for the state + * + */ +/*@{*/ +#define PH_FRINFC_MFUL_FMT_RESET_INIT 0 /*!< Reset state */ +#define PH_FRINFC_MFUL_FMT_RD_16BYTES 1 /*!< Read 16 bytes */ +#define PH_FRINFC_MFUL_FMT_WR_OTPBYTES 2 /*!< Write OTP bytes */ +#define PH_FRINFC_MFUL_FMT_WR_TLV 3 /*!< Write TLV */ +#ifdef PH_NDEF_MIFARE_ULC +#define PH_FRINFC_MFUL_FMT_WR_TLV1 4 /*!< Write TLV (second part) */ +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ +#ifdef FRINFC_READONLY_NDEF +#define PH_FRINFC_MFUL_FMT_RO_RD_16BYTES 5 /*!< Read only the tag */ +#define PH_FRINFC_MFUL_FMT_RO_WR_LOCK_BYTES 6 /*!< Write lock bytes to make the tag Read only */ +#define PH_FRINFC_MFUL_FMT_RO_WR_OTP_BYTES 7 /*!< Write OTP bytes to make the tag Read only */ + +#ifdef PH_NDEF_MIFARE_ULC +#define PH_FRINFC_MFUL_FMT_RO_RD_DYN_LOCK_BYTES 8 /*!< Read default dynamic lock bytes address */ +#define PH_FRINFC_MFUL_FMT_RO_WR_DYN_LOCK_BYTES 9 /*!< Write default dynamic lock bytes address */ +#define PH_FRINFC_MFUL_FMT_RO_PARSE_NDEF 10 /*!< Write default dynamic lock bytes address */ +#define PH_FRINFC_MFUL_FMT_RO_NDEF_PARSE_RD_BYTES 12 /*!< Read bytes from the card for parsing NDEF */ +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/*@}*/ + + +/*! +* \name Mifare standard - Block numbers +* +*/ +/*@{*/ +#define PH_FRINFC_MFUL_FMT_LOCK_BITS_VAL 0x00 /*!< Lock bits block is 2 */ + +/*@}*/ + +/*! + * \name Mifare UL - OTP bytes + * + */ +/*@{*/ +#ifdef PH_NDEF_MIFARE_ULC +#define PH_FRINFC_MFULC_FMT_OTP_BYTES {0xE1, 0x10, 0x12, 0x00} /*!< OTP bytes macro */ +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ +#define PH_FRINFC_MFUL_FMT_OTP_BYTES {0xE1, 0x10, 0x06, 0x00} /*!< OTP bytes macro */ + +/*@}*/ + +/*! + * \name Mifare UL - enums the values + * + */ +/*@{*/ +enum{ +PH_FRINFC_MFUL_FMT_VAL_0, +PH_FRINFC_MFUL_FMT_VAL_1, +PH_FRINFC_MFUL_FMT_VAL_2, +PH_FRINFC_MFUL_FMT_VAL_3, +PH_FRINFC_MFUL_FMT_VAL_4, +PH_FRINFC_MFUL_FMT_VAL_5, +PH_FRINFC_MFUL_FMT_VAL_6, +PH_FRINFC_MFUL_FMT_VAL_7 +}; +/*@}*/ + +/*! + * \name Mifare UL - constants + * + */ +/*@{*/ +#define PH_FRINFC_MFUL_FMT_NON_NDEF_COMPL 0 /*!< Card is not ndef compliant */ +#define PH_FRINFC_MFUL_FMT_NDEF_COMPL 1 /*!< Card is ndef compliant */ +/*@}*/ + +/*! + * \name Mifare UL - constants + * + */ +/*@{*/ +#define PH_FRINFC_MFUL_FMT_MAX_RECV_LENGTH 252 /*!< Maximum receive length */ +#define PH_FRINFC_MFUL_FMT_WR_SEND_LENGTH 5 /*!< Send length for write */ +#define PH_FRINFC_MFUL_FMT_MAX_BLK 16 /*!< Maximum blocks */ + +/*@}*/ + +/*! + * \name Mifare UL - constants for filling send buffer, calculating the block number, + * checking the authenticate state + * + */ +/*@{*/ + +/*@}*/ + + +/** + * \ingroup grp_fri_smart_card_formatting + * \brief Smart Card Formatting \b Reset function + * + * \copydoc page_reg Resets the component instance to the initial state and initializes the + * internal variables. + */ +void phFriNfc_MfUL_Reset(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +/*! + * \ingroup grp_fri_smart_card_formatting + * + * \brief Initiates the card formatting procedure for Remote Smart Card Type. + * + * \copydoc page_ovr The function initiates and formats the Smart Card.After this formation, remote + * card would be properly initialized and Ndef Compliant. + * Depending upon the different card type, this function handles formatting procedure. + * This function also handles the different recovery procedures for different types of the cards. For both + * Format and Recovery Management same API is used. + * + * \param[in] phFriNfc_sNdefSmartCardFmt_t Pointer to a valid instance of the \ref phFriNfc_sNdefSmartCardFmt_t + * structure describing the component context. + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval Other values An error has occurred. + * + */ +NFCSTATUS phFriNfc_MfUL_Format(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +#ifdef FRINFC_READONLY_NDEF + +/*! + * \ingroup grp_fri_smart_card_formatting + * + * \brief Initiates the conversion of the already NDEF formatted tag to READ ONLY. + * + * \copydoc page_ovr The function initiates the conversion of the already NDEF formatted + * tag to READ ONLY.After this formation, remote card would be properly Ndef Compliant and READ ONLY. + * Depending upon the different card type, this function handles formatting procedure. + * + * \param[in] phFriNfc_sNdefSmartCardFmt_t Pointer to a valid instance of the \ref phFriNfc_sNdefSmartCardFmt_t + * structure describing the component context. + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval Other values An error has occurred. + * + */ +NFCSTATUS +phFriNfc_MfUL_ConvertToReadOnly ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/** + *\ingroup grp_fri_smart_card_formatting + * + * \brief Smart card Formatting \b Completion \b Routine or \b Process function + * + * \copydoc page_ovr Completion Routine: This function is called by the lower layer (OVR HAL) + * when an I/O operation has finished. The internal state machine decides + * whether to call into the lower device again or to complete the process + * by calling into the upper layer's completion routine, stored within this + * component's context (\ref phFriNfc_sNdefSmtCrdFmt_t). + * + * The function call scheme is according to \ref grp_interact. No State reset is performed during + * operation. + * + * \param[in] Context The context of the current (not the lower/upper) instance, as set by the lower, + * calling layer, upon its completion. + * \param[in] Status The completion status of the lower layer (to be handled by the implementation of + * the state machine of this function like a regular return value of an internally + * called function). + * + * \note For general information about the completion routine interface please see \ref pphFriNfc_Cr_t . * The Different Status Values are as follows + * + */ +void phFriNfc_MfUL_Process(void *Context, + NFCSTATUS Status); +#endif /* PHFRINFC_MIFULFORMAT_H */ + diff --git a/libnfc-nxp/phFriNfc_MifareStdMap.c b/libnfc-nxp/phFriNfc_MifareStdMap.c new file mode 100644 index 0000000..c9f2e4b --- /dev/null +++ b/libnfc-nxp/phFriNfc_MifareStdMap.c @@ -0,0 +1,6344 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc_MifareStdMap.c + * \brief NFC Ndef Mapping For Remote Devices. + * + * Project: NFC-FRI + * + * $Date: Thu May 6 10:01:55 2010 $ + * $Author: ing02260 $ + * $Revision: 1.22 $ + * $Aliases: NFC_FRI1.1_WK1017_R34_4,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED + +#include +#include + +#ifndef PH_HAL4_ENABLE +#include +#endif + +#include + +#include + +/*! \ingroup grp_file_attributes + * \name NDEF Mapping + * + * File: \ref phFriNfcNdefMap.c + * + */ +/*@{*/ +#define PHFRINFCMIFARESTDMAP_FILEREVISION "$Revision: 1.22 $" +#define PHFRINFCMIFARESTDMAP_FILEALIASES "$Aliases: NFC_FRI1.1_WK1017_R34_4,NFC_FRI1.1_WK1023_R35_1 $" +/*@}*/ +/*@}*/ + +/*! + * \name Mifare Standard Mapping - Helper Functions + * + */ +/*@{*/ + +/*! + * \brief \copydoc page_ovr Helper function for Mifare Std. This function Reads + * a block from the card. + */ +static NFCSTATUS phFriNfc_MifStd_H_RdABlock(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare Std. This function writes + * into a block of the card. + */ +static NFCSTATUS phFriNfc_MifStd_H_WrABlock(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare Std. This function authenticates + * one sector at a time. + */ +static NFCSTATUS phFriNfc_MifStd_H_AuthSector(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare 4k Check Ndef to + * get the next AID blocks + */ +static NFCSTATUS phFriNfc_MifStd4k_H_CheckNdef(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Check Ndef to store the AIDs + */ +static void phFriNfc_MifStd_H_fillAIDarray(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to get the Sector from the current block + */ +static uint8_t phFriNfc_MifStd_H_GetSect(uint8_t BlockNumber); + +/*! + * \brief \copydoc page_ovr Helper function to check the Ndef compliance of the + * current block, if the block is not Ndef Compliant, increment the block till + * the next Ndef compliant block using the Get Sector Helper function + */ +static NFCSTATUS phFriNfc_MifStd_H_BlkChk(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to read the access bits of each sector + */ +static NFCSTATUS phFriNfc_MifStd_H_RdAcsBit(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to check the access bits of each sector + */ +static NFCSTATUS phFriNfc_MifStd_H_ChkAcsBit(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for read access bits, depending + * on the read/write/check ndef function called + */ +static NFCSTATUS phFriNfc_MifStd_H_ChkRdWr(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for check ndef to check the + * ndef compliant sectors + */ +static void phFriNfc_MifStd_H_ChkNdefCmpltSects(phFriNfc_NdefMap_t *NdefMap); + +#if 0 +/*! + * \brief \copydoc page_ovr Helper function for read ndef to check the + * the length L of the ndef TLV + */ +static uint8_t phFriNfc_MifStd_H_ChkNdefLen(phFriNfc_NdefMap_t *NdefMap, + uint8_t NDEFlength, + uint8_t *CRFlag); + +/*! + * \brief \copydoc page_ovr Helper function for read ndef to copy the + * card data to the user buffer + */ +static NFCSTATUS phFriNfc_MifStd_H_RdNdefTLV(phFriNfc_NdefMap_t *NdefMap, + uint8_t *Temp16Bytes); + +#endif + +/*! + * \brief \copydoc page_ovr Helper function for read ndef to process the + * remaining bytes of length (L) in the TLV + */ +static NFCSTATUS phFriNfc_MifStd_H_RemainTLV(phFriNfc_NdefMap_t *NdefMap, + uint8_t *Flag, + uint8_t *Temp16Bytes); + +/*! + * \brief \copydoc page_ovr Helper function for read ndef to process the + * internal bytes + */ +static NFCSTATUS phFriNfc_MifStd_H_ChkIntLen(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for read ndef to check the + * internal bytes without ndef tlv flag + */ +static NFCSTATUS phFriNfc_MifStd_H_IntLenWioutNdef(phFriNfc_NdefMap_t *NdefMap, + uint8_t *Flag, + uint8_t *TempintBytes); +#if 0 +/*! + * \brief \copydoc page_ovr Helper function for read ndef to check the + * internal bytes without ndef tlv flag + */ +static NFCSTATUS phFriNfc_MifStd_H_IntLenWithNdef(phFriNfc_NdefMap_t *NdefMap, + uint8_t *TempintBytes); +#endif +/*! + * \brief \copydoc page_ovr Helper function for write ndef to add the TLV + * structure + */ +static uint8_t phFriNfc_MifStd_H_UpdateTLV(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for write ndef to write the Length TLV + * + */ +static NFCSTATUS phFriNfc_MifStd_H_WriteNdefLen(phFriNfc_NdefMap_t *NdefMap); +#if 0 +/*! + * \brief \copydoc page_ovr Helper function for check ndef to check the ndef + * compliant blocks is 0 + */ +static NFCSTATUS phFriNfc_MifStd_H_ChkNdefCmpltBlocks(phFriNfc_NdefMap_t *NdefMap); +#endif +/*! + * \brief \copydoc page_ovr Helper function to set the authentication flag + * for the ndef TLV block + */ +static void phFriNfc_MifStd_H_SetNdefBlkAuth(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to reset ndef TLV values. This is + * used when the offset is BEGIN + */ +static void phFriNfc_MifStd_H_RdWrReset(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to read the first ndef compliant block to + * change the length + */ +static NFCSTATUS phFriNfc_MifStd_H_RdtoWrNdefLen(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to get the actual length of card + * + */ +static NFCSTATUS phFriNfc_MifStd_H_GetActCardLen(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to check all the TLVs + * + */ +static NFCSTATUS phFriNfc_MifStd_H_ChkTLVs(phFriNfc_NdefMap_t *NdefMap, + uint8_t *CRFlag); + +/*! + * \brief \copydoc page_ovr Helper function to get the next TLV + * + */ +static NFCSTATUS phFriNfc_MifStd_H_GetNxtTLV(phFriNfc_NdefMap_t *NdefMap, + uint16_t *TempLength, + uint8_t *TL4bytesFlag); + +/*! + * \brief \copydoc page_ovr Helper function to know whether the read + * 16 bytes are parsed completely + */ +static NFCSTATUS phFriNfc_MifStd_H_Chk16Bytes(phFriNfc_NdefMap_t *NdefMap, + uint16_t TempLength); + +/*! + * \brief \copydoc page_ovr Helper function to know whether the read + * 16 bytes are parsed completely + */ +static NFCSTATUS phFriNfc_MifStd_H_ChkRemainTLVs(phFriNfc_NdefMap_t *NdefMap, + uint8_t *CRFlag, + uint8_t *NDEFFlag); + +/*! + * \brief \copydoc page_ovr Helper function to call the Completion Routine + * + */ +static void phFriNfc_MifStd_H_Complete(phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Result); + +/*! + * \brief \copydoc page_ovr Helper function to get the Mifare 1k Sector Trailer + * + */ +static void phFriNfc_MifStd_H_Get1kStTrail(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to get the Mifare 4k Sector Trailer + * + */ +static void phFriNfc_MifStd_H_Get4kStTrail(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to process the check ndef call + * + */ +static NFCSTATUS phFriNfc_MifStd_H_ProChkNdef(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to process the authentication of a sector + * + */ +static NFCSTATUS phFriNfc_MifStd_H_ProAuth(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to read 16 bytes from a specifed block no. + * + */ +static NFCSTATUS phFriNfc_MifStd_H_Rd16Bytes(phFriNfc_NdefMap_t *NdefMap, + uint8_t BlockNo); + +/*! + * \brief \copydoc page_ovr Helper function to process access bits of the + * sector trailer + */ +static NFCSTATUS phFriNfc_MifStd_H_ProAcsBits(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to check the GPB bytes + */ +static NFCSTATUS phFriNfc_MifStd_H_GPBChk(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to check for the different + * status value in the process because of proprietary forum sector + */ +static NFCSTATUS phFriNfc_MifStd_H_ProStatNotValid(phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS status); + +/*! + * \brief \copydoc page_ovr Helper function to read the NDEF TLV block + */ +static NFCSTATUS phFriNfc_MifStd_H_RdBeforeWr(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to process the NDEF TLV block + * read bytes to start write from the NDEF TLV + */ +static NFCSTATUS phFriNfc_MifStd_H_ProBytesToWr(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to fill the send buffer to write + */ +static NFCSTATUS phFriNfc_MifStd_H_fillSendBuf(phFriNfc_NdefMap_t *NdefMap, + uint8_t Length); + +/*! + * \brief \copydoc page_ovr Helper function to write 16 bytes in a block + */ +static NFCSTATUS phFriNfc_MifStd_H_WrTLV(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to process the write TLV bytes in a block + */ +static NFCSTATUS phFriNfc_MifStd_H_ProWrTLV(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to update the remaining TLV + */ +static uint8_t phFriNfc_MifStd_H_UpdRemTLV(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to update the length field if more than one + * NULL TLVs exists before of the NDEF TLV + */ +static void phFriNfc_MifStd_H_fillTLV1(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to update the length field if more than one + * NULL TLVs does not exists before the TLV + */ +static void phFriNfc_MifStd_H_fillTLV2(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to increment/decrement the ndef tlv block + * and read the block + */ +static NFCSTATUS phFriNfc_MifStd_H_CallWrNdefLen(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to check the current block is valid or not + * if not valid decrement the current block till the valid block + */ +static NFCSTATUS phFriNfc_MifStd_H_BlkChk_1(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function update the length of the TLV if NULL TLVs + * greater than or equal to 2 + */ +static void phFriNfc_MifStd_H_fillTLV1_1(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function update the length of the TLV if NULL TLVs + * less than 2 + */ +static void phFriNfc_MifStd_H_fillTLV2_1(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to read the TLV block + */ +static NFCSTATUS phFriNfc_MifStd_H_RdTLV(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to process the read TLV block + */ +static NFCSTATUS phFriNfc_MifStd_H_ProRdTLV(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to write the terminator TLV + */ +static NFCSTATUS phFriNfc_MifStd_H_WrTermTLV(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to process the write a block function + */ +static NFCSTATUS phFriNfc_MifStd_H_ProWrABlock(phFriNfc_NdefMap_t *NdefMap); + +#ifndef PH_HAL4_ENABLE +/*! + * \brief \copydoc page_ovr Helper function to call poll function after the + * authentication has failed + */ +static NFCSTATUS phFriNfc_MifStd_H_CallPoll(phFriNfc_NdefMap_t *NdefMap); +#endif + +/*! + * \brief \copydoc page_ovr Helper function to call connect function after the + * authentication has failed + */ +static NFCSTATUS phFriNfc_MifStd_H_CallConnect(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to call disconnect function after the + * authentication has failed + */ +static NFCSTATUS phFriNfc_MifStd_H_CallDisCon(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function to call know the ndef compliant block using + */ +static void phFriNfc_MifStd1k_H_BlkChk(phFriNfc_NdefMap_t *NdefMap, + uint8_t SectorID, + uint8_t *callbreak); + +static uint8_t phFriNfc_MifStd_H_GetSectorTrailerBlkNo(uint8_t SectorID ); +static NFCSTATUS phFriNfc_MifStd_H_ProSectorTrailorAcsBits(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_MifStd_H_WrSectorTrailorBlock(phFriNfc_NdefMap_t *NdefMap); +static NFCSTATUS phFriNfc_MifStd_H_ProWrSectorTrailor(phFriNfc_NdefMap_t *NdefMap); + +/*@}*/ +/** + * \name Mifare Standard Mapping - Constants. + * + */ +/*@{*/ +/* As per the spec, the value of this macro + PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT1 shall be 0xA0 */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT1 0xA0 /**< \internal Authenticate Command for MAD Sector */ + +/* As per the spec, the value of this macro + PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT2 shall be 0xA1 */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT2 0xA1 /**< \internal Authenticate Command for MAD Sector */ + +/* As per the spec, the value of this macro + PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT3 shall be 0xA2 */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT3 0xA2 /**< \internal Authenticate Command for MAD Sector */ + +/* As per the spec, the value of this macro + PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT4 shall be 0xA3 */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT4 0xA3 /**< \internal Authenticate Command for MAD Sector */ + +/* As per the spec, the value of this macro + PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT5 shall be 0xA4 */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT5 0xA4 /**< \internal Authenticate Command for MAD Sector */ + +/* As per the spec, the value of this macro + PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT6 shall be 0xA5 */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT6 0xA5 /**< \internal Authenticate Command for MAD Sector */ + +/* As per the spec, the value of this macro + PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT1 shall be 0xD3 */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT1 0xD3 /**< \internal Authenticate Command for NDEF Sectors 1 */ + +/* As per the spec, the value of this macro + PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT2 shall be 0xF7 */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT2 0xF7 /**< \internal Authenticate Command for NDEF Sectors 2 */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_NDEF_COMPVAL2 0x03 /**< \internal Ndef Compliant command 1 */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_NDEF_COMPVAL1 0xE1 /**< \internal Ndef Compliant command 2 */ + +/* Enable access bits check for the MAD sector +#define ENABLE_ACS_BIT_CHK_FOR_MAD */ +/*@}*/ + +NFCSTATUS phFriNfc_MifareStdMap_H_Reset(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t index = PH_FRINFC_MIFARESTD_VAL0; + if ( NdefMap == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Current Block stores the present block accessed in the card */ + NdefMap->StdMifareContainer.currentBlock = PH_FRINFC_MIFARESTD_VAL0; + + for(index = PH_FRINFC_MIFARESTD_VAL0; index < + PH_FRINFC_NDEFMAP_MIFARESTD_ST15_BYTES; index++) + { + /* internal buffer to store the odd bytes of length < 15 */ + NdefMap->StdMifareContainer.internalBuf[index] = PH_FRINFC_MIFARESTD_VAL0; + } + /* odd bytes length stored in the internal buffer */ + NdefMap->StdMifareContainer.internalLength = PH_FRINFC_MIFARESTD_VAL0; + + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED; + + /* Flag to get that last few bytes are taken from the user buffer */ + NdefMap->StdMifareContainer.RemainingBufFlag = PH_FRINFC_MIFARESTD_FLAG0; + + /* Flag to find that the read/write operation has reached the end of the card. + Further reading/writing is not possible */ + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = PH_FRINFC_MIFARESTD_FLAG0; + + /* Flag to get that last few bytes are taken from the internal buffer */ + NdefMap->StdMifareContainer.internalBufFlag = PH_FRINFC_MIFARESTD_FLAG0; + + /* Authentication Flag for every sector */ + NdefMap->StdMifareContainer.AuthDone = PH_FRINFC_MIFARESTD_FLAG0; + + /* Used in Check Ndef for storing the sector ID */ + NdefMap->StdMifareContainer.SectorIndex = PH_FRINFC_MIFARESTD_VAL0; + + NdefMap->StdMifareContainer.NdefBlocks = PH_FRINFC_MIFARESTD_VAL0; + + NdefMap->StdMifareContainer.NoOfNdefCompBlocks = PH_FRINFC_MIFARESTD_VAL0; + + NdefMap->StdMifareContainer.ReadAcsBitFlag = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->StdMifareContainer.remSizeUpdFlag = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->TLVStruct.NoLbytesinTLV = PH_FRINFC_MIFARESTD_VAL0; + + NdefMap->TLVStruct.prevLenByteValue = PH_FRINFC_MIFARESTD_VAL0; + + NdefMap->TLVStruct.BytesRemainLinTLV = PH_FRINFC_MIFARESTD_VAL0; + + NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_MIFARESTD_VAL0; + + NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_MIFARESTD_VAL0; + + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL0; + + NdefMap->StdMifareContainer.remainingSize = PH_FRINFC_MIFARESTD_VAL0; + + NdefMap->StdMifareContainer.ReadNdefFlag = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->StdMifareContainer.WrNdefFlag = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->StdMifareContainer.ChkNdefFlag = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->StdMifareContainer.aidCompleteFlag = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->StdMifareContainer.NFCforumSectFlag = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->StdMifareContainer.ProprforumSectFlag = PH_FRINFC_MIFARESTD_PROP_1ST_CONFIG; + + NdefMap->StdMifareContainer.ReadCompleteFlag = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->StdMifareContainer.FirstReadFlag = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->StdMifareContainer.WrLength = PH_FRINFC_MIFARESTD_VAL1; + + NdefMap->StdMifareContainer.ChkNdefCompleteFlag = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->StdMifareContainer.ReadOnlySectorIndex = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->StdMifareContainer.TotalNoSectors = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->StdMifareContainer.SectorTrailerBlockNo = PH_FRINFC_MIFARESTD_FLAG0; + } + + return status; +} + +/*! + * \brief Check whether a particular Remote Device is NDEF compliant. + * + * The function checks whether the peer device is NDEF compliant. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t + * structure describing the component context. + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval Others An error has occurred. + * + */ + +NFCSTATUS phFriNfc_MifareStdMap_ChkNdef( phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint8_t atq, + sak; + + if ( NdefMap == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* set the data for additional data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + NdefMap->psDepAdditionalInfo.NAD = 0; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE; + NdefMap->StdMifareContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_CHK_NDEF; + + /* Get the Select Response and Sense Response to get + the exact Card Type either Mifare 1k or 4k */ +#ifndef PH_HAL4_ENABLE + sak = NdefMap->psRemoteDevInfo->RemoteDevInfo.CardInfo106. + Startup106.SelRes; + atq = NdefMap->psRemoteDevInfo->RemoteDevInfo.CardInfo106. + Startup106.SensRes[0]; +#else + sak = NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak; + atq = NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA[0]; + PHNFC_UNUSED_VARIABLE(atq); +#endif + + if (0x08 == (sak & 0x18)) + { + /* Total Number of Blocks in Mifare 1k Card */ + NdefMap->StdMifareContainer.NoOfNdefCompBlocks = + PH_FRINFC_NDEFMAP_MIFARESTD_1KNDEF_COMPBLOCK; + NdefMap->StdMifareContainer.remainingSize = + ((NdefMap->CardType == PH_FRINFC_MIFARESTD_VAL0)? + (PH_FRINFC_NDEFMAP_MIFARESTD_1KNDEF_COMPBLOCK * + PH_FRINFC_MIFARESTD_BLOCK_BYTES): + NdefMap->StdMifareContainer.remainingSize); + NdefMap->CardType = PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD; + } + else + { + /* Total Number of Blocks in Mifare 4k Card */ + NdefMap->StdMifareContainer.NoOfNdefCompBlocks = + PH_FRINFC_NDEFMAP_MIFARESTD_4KNDEF_COMPBLOCK; + NdefMap->StdMifareContainer.remainingSize = + ((NdefMap->CardType == PH_FRINFC_MIFARESTD_VAL0)? + (PH_FRINFC_NDEFMAP_MIFARESTD_4KNDEF_COMPBLOCK * + PH_FRINFC_MIFARESTD_BLOCK_BYTES): + NdefMap->StdMifareContainer.remainingSize); + NdefMap->CardType = PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD; + } + + + /* phFriNfc_MifareStdMap_ChkNdef should be called only + when currentBlock is 0 OR 64,65 and 66 (for Mifare 4k). + Otherwise return error */ + /* and also Check the Authentication Flag */ + if((NdefMap->StdMifareContainer.currentBlock != 0) && + (NdefMap->StdMifareContainer.currentBlock != 1) && + (NdefMap->StdMifareContainer.currentBlock != 2) && + (NdefMap->StdMifareContainer.currentBlock != 64) && + (NdefMap->StdMifareContainer.currentBlock != 65) && + (NdefMap->StdMifareContainer.currentBlock != 66) ) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else if( NdefMap->StdMifareContainer.AuthDone == 0) + { + /* Block 0 contains Manufacturer information and + also other informaton. So go for block 1 which + contains AIDs. Authenticating any of the block + in a sector, Authenticates the whole sector */ + if(NdefMap->StdMifareContainer.currentBlock == 0) + { + NdefMap->StdMifareContainer.currentBlock = 1; + } + + status = phFriNfc_MifStd_H_AuthSector(NdefMap); + } + else + { + /* Mifare 1k, sak = 0x08 atq = 0x04 + Mifare 4k, sak = 0x38 atq = 0x02 */ + if ((NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD) || + (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD)) + { + /* Change the state to Check Ndef Compliant */ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_CHK_NDEF_COMP; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE; + NdefMap->StdMifareContainer.ChkNdefFlag = PH_FRINFC_MIFARESTD_FLAG1; + + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_MifareStdMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + +#ifndef PH_HAL4_ENABLE + NdefMap->Cmd.MfCmd = phHal_eMifareCmdListMifareRead; +#else + NdefMap->Cmd.MfCmd = phHal_eMifareRead; +#endif + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + NdefMap->SendRecvBuf[0] = NdefMap->StdMifareContainer.currentBlock; + NdefMap->SendLength = MIFARE_MAX_SEND_BUF_TO_READ; + + /* Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + } + else + { + /* Since we have decided temporarily not to go + for any new error codes we are using + NFCSTATUS_INVALID_PARAMETER even though it is not + the relevant error code here TBD */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + } + } + return status; +} + + +/*! + * \brief Initiates Reading of NDEF information from the Remote Device. + * + * The function initiates the reading of NDEF information from a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action + * has been triggered. + */ +NFCSTATUS phFriNfc_MifareStdMap_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + NdefMap->ApduBufferSize = *PacketDataLength; + NdefMap->NumOfBytesRead = PacketDataLength; + *NdefMap->NumOfBytesRead = 0; + NdefMap->ApduBuffIndex = 0; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + NdefMap->StdMifareContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_RD_NDEF; + + if((NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INVALID) + || (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INITIALIZED)) + { + /* Card state is not correct */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || ( NdefMap->PrevOperation == + PH_FRINFC_NDEFMAP_WRITE_OPE)) + { + phFriNfc_MifStd_H_RdWrReset(NdefMap); + NdefMap->StdMifareContainer.ReadNdefFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + /* Offset = Current, but the read has reached the End of Card */ + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (NdefMap->StdMifareContainer.ReadWriteCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG1)) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + NdefMap->Offset = (((Offset != PH_FRINFC_NDEFMAP_SEEK_BEGIN) && + ( NdefMap->PrevOperation == + PH_FRINFC_NDEFMAP_WRITE_OPE))? + PH_FRINFC_NDEFMAP_SEEK_BEGIN: + Offset); + status = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(status == NFCSTATUS_SUCCESS) + { + NdefMap->ApduBuffer = PacketData; + + /* Read Operation in Progress */ + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = PH_FRINFC_MIFARESTD_FLAG0; + + /* Check Authentication Flag */ + status = + ((NdefMap->StdMifareContainer.AuthDone == PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_RdABlock(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + } + } + return status; +} + +/*! + * \brief Initiates Writing of NDEF information to the Remote Device. + * + * The function initiates the writing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action + * has been triggered. + */ +NFCSTATUS phFriNfc_MifareStdMap_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + NdefMap->ApduBuffer = PacketData; + NdefMap->ApduBufferSize = *PacketDataLength; + NdefMap->ApduBuffIndex = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->WrNdefPacketLength = PacketDataLength; + *NdefMap->WrNdefPacketLength = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + NdefMap->StdMifareContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_WR_NDEF; + + if((NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INVALID) + || (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_ONLY)) + { + /* Card state is not correct */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || + (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE)) + { + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.RdBeforeWrFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->StdMifareContainer.WrNdefFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->StdMifareContainer.internalLength = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->StdMifareContainer.RdAfterWrFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.AuthDone = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.NdefTLVAuthFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.FirstReadFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.remainingSize = + (NdefMap->StdMifareContainer.NoOfNdefCompBlocks * + PH_FRINFC_MIFARESTD_BLOCK_BYTES); + NdefMap->StdMifareContainer.currentBlock = + PH_FRINFC_MIFARESTD_BLK4; + NdefMap->StdMifareContainer.NdefBlocks = PH_FRINFC_MIFARESTD_VAL1; + NdefMap->StdMifareContainer.NFCforumSectFlag = PH_FRINFC_MIFARESTD_FLAG0; + /* This macro is added, to be compliant with the previous HAL 2.0 + For HAL 2.0, polling is done before writing data to the mifare + std (if the offset is BEGIN), because if an error is reported + during read or write and again write is called, the PN531 state is + unchanged (so write will fail), to bring the PN531 to the correct + state, polling is done. + Changed on 13th Jan 2009 + */ +#ifdef PH_HAL4_ENABLE + NdefMap->StdMifareContainer.PollFlag = PH_FRINFC_MIFARESTD_FLAG0; +#else + NdefMap->StdMifareContainer.PollFlag = PH_FRINFC_MIFARESTD_FLAG1; +#endif /* #ifdef PH_HAL4_ENABLE */ + NdefMap->StdMifareContainer.WrLength = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->StdMifareContainer.FirstWriteFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + + if(((Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (NdefMap->StdMifareContainer.ReadWriteCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG1)) || ((NdefMap->StdMifareContainer.PollFlag == + PH_FRINFC_MIFARESTD_FLAG1) && (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR))) + { + /* Offset = Current, but the read has reached the End of Card */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + NdefMap->Offset = (((Offset != PH_FRINFC_NDEFMAP_SEEK_BEGIN) && + ( NdefMap->PrevOperation == + PH_FRINFC_NDEFMAP_READ_OPE))? + PH_FRINFC_NDEFMAP_SEEK_BEGIN: + Offset); + NdefMap->StdMifareContainer.AuthDone = PH_FRINFC_MIFARESTD_FLAG0; + status = phFriNfc_MifStd_H_BlkChk(NdefMap); + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = PH_FRINFC_MIFARESTD_FLAG0; + if(status == NFCSTATUS_SUCCESS) + { + if(NdefMap->StdMifareContainer.PollFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + /* if poll flag is set then call disconnect because the authentication + has failed so reactivation of card is required */ + status = phFriNfc_MifStd_H_CallDisCon(NdefMap); + } + /* Check Authentication Flag */ + else if(NdefMap->StdMifareContainer.AuthDone == PH_FRINFC_MIFARESTD_FLAG1) + { + status = ((NdefMap->Offset == + PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + phFriNfc_MifStd_H_RdBeforeWr(NdefMap): + phFriNfc_MifStd_H_WrABlock(NdefMap)); + } + else + { + status = phFriNfc_MifStd_H_AuthSector(NdefMap); + } + } + } + } + return status; +} + + +/*! + * \brief Completion Routine, Processing function, needed to avoid long blocking. + * \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion + * Routine in order to be able to notify the component that an I/O has finished and data are + * ready to be processed. + * + */ + +void phFriNfc_MifareStdMap_Process( void *Context, + NFCSTATUS Status) +{ + + phFriNfc_NdefMap_t *NdefMap; + + uint8_t NDEFFlag = 0, + CRFlag = 0, + Temp16Bytes = 0, + i = 0; + + + NdefMap = (phFriNfc_NdefMap_t *)Context; + + if((Status & PHNFCSTBLOWER) == (NFCSTATUS_SUCCESS & PHNFCSTBLOWER)) + { + switch(NdefMap->State) + { + case PH_FRINFC_NDEFMAP_STATE_CHK_NDEF_COMP: + Status = phFriNfc_MifStd_H_ProChkNdef(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_STATE_READ: + + /* Receive Length for read shall always be equal to 16 */ + if((*NdefMap->SendRecvLength == PH_FRINFC_MIFARESTD_BYTES_READ) && + (NdefMap->ApduBuffIndex < (uint16_t)NdefMap->ApduBufferSize)) + { + Temp16Bytes = PH_FRINFC_MIFARESTD_VAL0; + NDEFFlag = (uint8_t)PH_FRINFC_MIFARESTD_FLAG1; + if(NdefMap->TLVStruct.BytesRemainLinTLV != 0) + { + NDEFFlag = PH_FRINFC_MIFARESTD_FLAG0; + CRFlag = PH_FRINFC_MIFARESTD_FLAG0; + /* To read the remaining length (L) in TLV */ + Status = phFriNfc_MifStd_H_RemainTLV(NdefMap, &NDEFFlag, &Temp16Bytes); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + } + + /* check the NDEFFlag is set. if this is not set, then + in the above RemainTLV function all the 16 bytes has been + read */ +#if 0 + if((NDEFFlag == PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_MIFARESTD_FLAG1)) + { + /* if the block is NDEF TLV then get data from here */ + Status = phFriNfc_MifStd_H_RdNdefTLV(NdefMap, &Temp16Bytes); + } +#endif + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_RECEIVE_LENGTH); + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + break; + + case PH_FRINFC_NDEFMAP_STATE_WRITE: + Status = phFriNfc_MifStd_H_ProWrABlock(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + /* Call Completion Routine if CR Flag is Set to 1 */ + if(CRFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + *NdefMap->WrNdefPacketLength = NdefMap->ApduBuffIndex; + } + break; + + case PH_FRINFC_NDEFMAP_STATE_AUTH: + NdefMap->StdMifareContainer.FirstReadFlag = PH_FRINFC_MIFARESTD_FLAG0; + Status = phFriNfc_MifStd_H_ProAuth(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_STATE_RD_ACS_BIT: + Status = phFriNfc_MifStd_H_ProAcsBits(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_STATE_WR_NDEF_LEN: + if(NdefMap->StdMifareContainer.RdAfterWrFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + Status = phFriNfc_MifStd_H_CallWrNdefLen(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + } + else + { + /* Check this */ + if(NdefMap->StdMifareContainer.TempBlockNo == + NdefMap->StdMifareContainer.currentBlock) + { + (void)memcpy( NdefMap->StdMifareContainer.internalBuf, + NdefMap->StdMifareContainer.Buffer, + NdefMap->StdMifareContainer.internalLength); + } + *NdefMap->WrNdefPacketLength = NdefMap->ApduBuffIndex; + NdefMap->StdMifareContainer.currentBlock = + NdefMap->StdMifareContainer.TempBlockNo; + NdefMap->CardState = (uint8_t)((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INITIALIZED)? + PH_NDEFMAP_CARD_STATE_READ_WRITE: + NdefMap->CardState); + CRFlag = (uint8_t)PH_FRINFC_MIFARESTD_FLAG1; + } + /*NdefMap->StdMifareContainer.remainingSize -= + (((NdefMap->ApduBufferSize) > (PH_FRINFC_MIFARESTD_NDEFTLV_L - + PH_FRINFC_MIFARESTD_VAL1))? + ((uint16_t)(*NdefMap->WrNdefPacketLength + + PH_FRINFC_MIFARESTD_VAL4)): + ((uint16_t)(*NdefMap->WrNdefPacketLength + + PH_FRINFC_MIFARESTD_VAL2)));*/ + break; + + case PH_FRINFC_NDEFMAP_STATE_RD_TO_WR_NDEF_LEN: + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + if(*NdefMap->SendRecvLength == PH_FRINFC_MIFARESTD_BYTES_READ) + { + /* Size of NdefMap->SendRecvBuf is set by phLibNfc_Gen_NdefMapReset to PH_LIBNFC_GEN_MAX_BUFFER */ + /* We don't have to check memory here */ + for (i = PH_FRINFC_MIFARESTD_BYTES_READ; i > 0; i--) + { + NdefMap->SendRecvBuf[i] = NdefMap->SendRecvBuf[i-1]; + } + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + NdefMap->StdMifareContainer.currentBlock; + Status = phFriNfc_MifStd_H_WriteNdefLen(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + } + break; + + case PH_FRINFC_NDEFMAP_STATE_GET_ACT_CARDSIZE: + NDEFFlag = PH_FRINFC_MIFARESTD_FLAG1; + if(NdefMap->TLVStruct.NoLbytesinTLV > PH_FRINFC_MIFARESTD_VAL0) + { + NDEFFlag = PH_FRINFC_MIFARESTD_FLAG0; + Status = phFriNfc_MifStd_H_ChkRemainTLVs(NdefMap, &CRFlag, &NDEFFlag); + NdefMap->TLVStruct.NoLbytesinTLV = + PH_FRINFC_MIFARESTD_VAL0; + } + if((NDEFFlag == PH_FRINFC_MIFARESTD_FLAG1) && + (CRFlag != PH_FRINFC_MIFARESTD_FLAG1)) + { + Status = phFriNfc_MifStd_H_ChkTLVs(NdefMap, &CRFlag); + } + if(((NdefMap->StdMifareContainer.ReadNdefFlag == + PH_FRINFC_MIFARESTD_FLAG1) || + (NdefMap->StdMifareContainer.WrNdefFlag == + PH_FRINFC_MIFARESTD_FLAG1))&& + (Status != NFCSTATUS_PENDING)) + { + NdefMap->StdMifareContainer.NFCforumSectFlag = + PH_FRINFC_MIFARESTD_FLAG1; + CRFlag = PH_FRINFC_MIFARESTD_FLAG0; + /* if the card state has changed to initialised and + read ndef is called then error is returned */ + if(((NdefMap->StdMifareContainer.WrNdefFlag == + PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_ONLY)) || + ((NdefMap->StdMifareContainer.ReadNdefFlag == + PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INITIALIZED))) + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + if(NdefMap->StdMifareContainer.AuthDone == + PH_FRINFC_MIFARESTD_FLAG0) + { + Status = phFriNfc_MifStd_H_AuthSector(NdefMap); + } + else + { + Status = ((NdefMap->StdMifareContainer.ReadNdefFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_RdTLV(NdefMap): + phFriNfc_MifStd_H_RdBeforeWr(NdefMap)); + } + NdefMap->StdMifareContainer.ReadNdefFlag = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.WrNdefFlag = + PH_FRINFC_MIFARESTD_FLAG0; + + } + if(NdefMap->StdMifareContainer.ChkNdefFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + } + break; + + case PH_FRINFC_NDEFMAP_STATE_RD_BEF_WR: + /* Read flag says that already part of TLV has been written */ + Status = phFriNfc_MifStd_H_ProBytesToWr(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_STATE_WR_TLV: + Status = phFriNfc_MifStd_H_ProWrTLV(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_STATE_RD_TLV: + Status = phFriNfc_MifStd_H_ProRdTLV(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_STATE_TERM_TLV: + phFriNfc_MifStd_H_SetNdefBlkAuth(NdefMap); + NdefMap->StdMifareContainer.currentBlock = + NdefMap->TLVStruct.NdefTLVBlock; + Status = phFriNfc_MifStd_H_RdtoWrNdefLen(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_STATE_DISCONNECT: + NdefMap->StdMifareContainer.PollFlag = PH_FRINFC_MIFARESTD_FLAG0; + +#ifndef PH_HAL4_ENABLE + Status = phFriNfc_MifStd_H_CallPoll(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_STATE_POLL: +#endif + Status = phFriNfc_MifStd_H_CallConnect(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_STATE_CONNECT: + if(NdefMap->StdMifareContainer.FirstReadFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + NdefMap->StdMifareContainer.FirstReadFlag = PH_FRINFC_MIFARESTD_FLAG0; + Status = phFriNfc_MifStd_H_AuthSector(NdefMap); + } + else if((NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD || + NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD) && + (NdefMap->StdMifareContainer.ReadOnlySectorIndex && + NdefMap->StdMifareContainer.SectorTrailerBlockNo == NdefMap->StdMifareContainer.currentBlock)) + { + NdefMap->StdMifareContainer.ReadOnlySectorIndex = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.SectorTrailerBlockNo = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.currentBlock = PH_FRINFC_MIFARESTD_FLAG0; + Status = NFCSTATUS_FAILED; + } + else + { + Status = ((((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE)) || + (NdefMap->StdMifareContainer.WrLength > + PH_FRINFC_MIFARESTD_VAL0))? + phFriNfc_MifStd_H_ProStatNotValid(NdefMap, Status): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_STATE_RD_SEC_ACS_BIT: + Status = phFriNfc_MifStd_H_ProSectorTrailorAcsBits(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + if ((CRFlag == PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->StdMifareContainer.WriteAcsBitFlag == PH_FRINFC_MIFARESTD_FLAG0)) + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + } + break; + + case PH_FRINFC_NDEFMAP_STATE_WRITE_SEC: + /* Set flag for writing of Acs bit */ + NdefMap->StdMifareContainer.WriteAcsBitFlag = PH_FRINFC_MIFARESTD_FLAG1; + + /* The first NDEF sector is already made read only, + set card state to read only and proceed*/ + if(NdefMap->CardState != PH_NDEFMAP_CARD_STATE_READ_ONLY) + { + Status = phFriNfc_MapTool_SetCardState(NdefMap, NdefMap->TLVStruct.BytesRemainLinTLV); + if(Status != NFCSTATUS_SUCCESS) + { + CRFlag = (uint8_t) PH_FRINFC_MIFARESTD_FLAG1; + } + } + + if (CRFlag != PH_FRINFC_MIFARESTD_FLAG1) + { + Status = phFriNfc_MifStd_H_ProWrSectorTrailor(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + } + break; + + default: + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + } + else if(NdefMap->State == PH_FRINFC_NDEFMAP_STATE_AUTH) + { + NdefMap->StdMifareContainer.PollFlag = PH_FRINFC_MIFARESTD_FLAG1; + if(NdefMap->StdMifareContainer.FirstWriteFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + NdefMap->StdMifareContainer.FirstWriteFlag = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.WrLength = + ((NdefMap->StdMifareContainer.NFCforumSectFlag == + PH_FRINFC_MIFARESTD_FLAG0)? + PH_FRINFC_MIFARESTD_VAL1: + NdefMap->StdMifareContainer.WrLength); + } + /*if(NdefMap->StdMifareContainer.WrLength != PH_FRINFC_MIFARESTD_VAL0) + { + Status = NFCSTATUS_SUCCESS; + NdefMap->StdMifareContainer.ReadCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + *NdefMap->WrNdefPacketLength = NdefMap->ApduBuffIndex; + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + else*/ if(NdefMap->StdMifareContainer.WrLength == PH_FRINFC_MIFARESTD_VAL0) + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + else + { + /* Authentication has failed */ + Status = phFriNfc_MifStd_H_CallDisCon(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + } + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + /* Call Completion Routine if CR Flag is Set to 1 */ + if(CRFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + phFriNfc_MifStd_H_Complete(NdefMap, Status); + } +} + +static NFCSTATUS phFriNfc_MifStd_H_RdABlock(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + /* set the data for additional data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + NdefMap->psDepAdditionalInfo.NAD = 0; + + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_READ; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_MifareStdMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + if( NdefMap->ApduBuffIndex < + (uint16_t)NdefMap->ApduBufferSize) + { + + if(NdefMap->StdMifareContainer.internalLength > PH_FRINFC_MIFARESTD_VAL0) + { + status = phFriNfc_MifStd_H_ChkIntLen(NdefMap); + }/* internal Length Check */ + else + { + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + NdefMap->StdMifareContainer.currentBlock; + NdefMap->SendLength = MIFARE_MAX_SEND_BUF_TO_READ; + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + +#ifndef PH_HAL4_ENABLE + NdefMap->Cmd.MfCmd = phHal_eMifareCmdListMifareRead; +#else + NdefMap->Cmd.MfCmd = phHal_eMifareRead; +#endif + /* Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + } + } + else + { + /* Check for the Card Size */ + if((((NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + NdefMap->StdMifareContainer.NdefBlocks) * + PH_FRINFC_MIFARESTD_BYTES_READ) == 0) || + (NdefMap->ApduBufferSize == NdefMap->ApduBuffIndex)) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + (uint8_t)((((NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + NdefMap->StdMifareContainer.NdefBlocks) * + PH_FRINFC_MIFARESTD_BYTES_READ) == 0)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + *NdefMap->NumOfBytesRead = NdefMap->ApduBuffIndex; + status = PHNFCSTVAL(CID_NFC_NONE, + NFCSTATUS_SUCCESS); + } + else + { + /*Error: The control should not ideally come here. + Return Error.*/ +#ifndef PH_HAL4_ENABLE + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_CMD_ABORTED); +#else + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_FAILED); +#endif + } + } + return status; +} + + +static NFCSTATUS phFriNfc_MifStd_H_WrABlock(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + uint16_t RemainingBytes = 0, + BytesRemained = 0, + index = 0; + + uint8_t Temp16Bytes = 0; + + /* set the data for additional data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + NdefMap->psDepAdditionalInfo.NAD = 0; + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_MifareStdMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_WRITE; + + /* User Buffer Check */ + if( NdefMap->ApduBuffIndex < + (uint16_t)NdefMap->ApduBufferSize) + { + RemainingBytes = (((uint16_t)(NdefMap->ApduBufferSize - + NdefMap->ApduBuffIndex) < + NdefMap->StdMifareContainer.remainingSize )? + (uint16_t)(NdefMap->ApduBufferSize - + NdefMap->ApduBuffIndex): + NdefMap->StdMifareContainer.remainingSize); + + NdefMap->SendRecvBuf[0] = NdefMap->StdMifareContainer.currentBlock; + Temp16Bytes += PH_FRINFC_MIFARESTD_INC_1; + /* Check for internal bytes */ + + if(NdefMap->StdMifareContainer.internalLength > 0) + { + /* copy the bytes previously written in the internal Buffer */ + (void)memcpy(&( NdefMap->SendRecvBuf[Temp16Bytes]), + NdefMap->StdMifareContainer.internalBuf, + NdefMap->StdMifareContainer.internalLength); + + Temp16Bytes += (uint8_t)(NdefMap->StdMifareContainer.internalLength); + if(RemainingBytes >= ( MIFARE_MAX_SEND_BUF_TO_WRITE - + Temp16Bytes)) + { + /* Copy the Remaining bytes from the user buffer to make the send + data and length = 16 */ + (void)memcpy(&(NdefMap->SendRecvBuf[Temp16Bytes]), + NdefMap->ApduBuffer, + (MIFARE_MAX_SEND_BUF_TO_WRITE - Temp16Bytes)); + + NdefMap->NumOfBytesWritten = + (MIFARE_MAX_SEND_BUF_TO_WRITE - Temp16Bytes); + Temp16Bytes += (MIFARE_MAX_SEND_BUF_TO_WRITE - Temp16Bytes); + *NdefMap->DataCount = (Temp16Bytes - PH_FRINFC_MIFARESTD_VAL1); + } + else + { + (void)memcpy(&(NdefMap->SendRecvBuf[Temp16Bytes]), + NdefMap->ApduBuffer, + RemainingBytes); + + NdefMap->StdMifareContainer.internalBufFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->NumOfBytesWritten = RemainingBytes; + Temp16Bytes += (uint8_t)(RemainingBytes); + *NdefMap->DataCount = (Temp16Bytes - PH_FRINFC_MIFARESTD_VAL1); + + BytesRemained = (MIFARE_MAX_SEND_BUF_TO_WRITE - Temp16Bytes); + /* Pad empty bytes with Zeroes to complete 16 bytes*/ + for(index = 0; index < BytesRemained; index++) + { + NdefMap->SendRecvBuf[(Temp16Bytes + index)] = + (uint8_t)((index == PH_FRINFC_MIFARESTD_VAL0)? + PH_FRINFC_MIFARESTD_TERMTLV_T: + PH_FRINFC_MIFARESTD_NULLTLV_T); + NdefMap->TLVStruct.SetTermTLVFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + Temp16Bytes += (uint8_t)(BytesRemained); + } + } + else + { + if(RemainingBytes >= (MIFARE_MAX_SEND_BUF_TO_WRITE - Temp16Bytes)) + { + /* Bytes left to write < 16 + copy remaining bytes */ + (void)memcpy( &(NdefMap->SendRecvBuf[ + Temp16Bytes]), + &(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + (MIFARE_MAX_SEND_BUF_TO_WRITE - Temp16Bytes)); + + NdefMap->NumOfBytesWritten = (MIFARE_MAX_SEND_BUF_TO_WRITE - Temp16Bytes); + Temp16Bytes += (MIFARE_MAX_SEND_BUF_TO_WRITE - Temp16Bytes); + *NdefMap->DataCount = (Temp16Bytes - PH_FRINFC_MIFARESTD_VAL1); + } + else + { + /* Bytes left to write < 16 + copy remaining bytes */ + (void)memcpy(&(NdefMap->SendRecvBuf[ + Temp16Bytes]), + &(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + RemainingBytes); + + NdefMap->StdMifareContainer.RemainingBufFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->NumOfBytesWritten = RemainingBytes; + Temp16Bytes += (uint8_t)(RemainingBytes); + *NdefMap->DataCount = (Temp16Bytes - PH_FRINFC_MIFARESTD_VAL1); + + + /* Pad empty bytes with Zeroes to complete 16 bytes*/ + for(index = Temp16Bytes; index < MIFARE_MAX_SEND_BUF_TO_WRITE; index++) + { + NdefMap->SendRecvBuf[index] = (uint8_t)((index == + Temp16Bytes)? + PH_FRINFC_MIFARESTD_TERMTLV_T: + PH_FRINFC_MIFARESTD_NULLTLV_T); + + NdefMap->TLVStruct.SetTermTLVFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + } + } + /* Buffer to store 16 bytes which is writing to the present block */ + (void)memcpy( NdefMap->StdMifareContainer.Buffer, + &(NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_INC_1]), + PH_FRINFC_MIFARESTD_BLOCK_BYTES); + + /* Write from here */ + NdefMap->SendLength = MIFARE_MAX_SEND_BUF_TO_WRITE; +#ifndef PH_HAL4_ENABLE + NdefMap->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite16; +#else + NdefMap->Cmd.MfCmd = phHal_eMifareWrite16; +#endif + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + /* Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + } + else/* Check User Buffer */ + { + if(NdefMap->StdMifareContainer.NdefBlocks > + NdefMap->StdMifareContainer.NoOfNdefCompBlocks) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + status = PHNFCSTVAL(CID_NFC_NONE, + NFCSTATUS_SUCCESS); + } + else if( NdefMap->ApduBuffIndex == + (uint16_t)NdefMap->ApduBufferSize) + { + status = PHNFCSTVAL(CID_NFC_NONE, + NFCSTATUS_SUCCESS); + } + else + { + /*Error: The control should not ideally come here. + Return Error.*/ +#ifndef PH_HAL4_ENABLE + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_CMD_ABORTED); +#else + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_FAILED); +#endif + } + } + return status; +} + +static NFCSTATUS phFriNfc_MifStd_H_AuthSector(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + /* set the data for additional data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + NdefMap->psDepAdditionalInfo.NAD = 0; + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_MifareStdMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_AUTH; + + /* Authenticate */ +#ifndef PH_HAL4_ENABLE + NdefMap->Cmd.MfCmd = phHal_eMifareCmdListMifareAuthentA; +#else + NdefMap->Cmd.MfCmd = phHal_eMifareAuthentA; +#endif + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + ((NdefMap->TLVStruct.NdefTLVAuthFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + NdefMap->TLVStruct.NdefTLVBlock: + NdefMap->StdMifareContainer.currentBlock); + + /* if MAD blocks then authentication key is + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 else + 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 */ + if(( (NdefMap->StdMifareContainer.currentBlock != PH_FRINFC_MIFARESTD_MAD_BLK0) && + (NdefMap->StdMifareContainer.currentBlock != PH_FRINFC_MIFARESTD_MAD_BLK1) && + (NdefMap->StdMifareContainer.currentBlock != PH_FRINFC_MIFARESTD_MAD_BLK2) && + (NdefMap->StdMifareContainer.currentBlock != PH_FRINFC_MIFARESTD_MAD_BLK64) && + (NdefMap->StdMifareContainer.currentBlock != PH_FRINFC_MIFARESTD_MAD_BLK65) && + (NdefMap->StdMifareContainer.currentBlock != PH_FRINFC_MIFARESTD_MAD_BLK66)) || + (NdefMap->TLVStruct.NdefTLVAuthFlag == + (uint8_t)PH_FRINFC_MIFARESTD_FLAG1)) + { + NdefMap->SendRecvBuf[1] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT1; /* 0xD3 */ + NdefMap->SendRecvBuf[2] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT2; /* 0xF7 */ + NdefMap->SendRecvBuf[3] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT1; /* 0xD3 */ + NdefMap->SendRecvBuf[4] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT2; /* 0xF7 */ + NdefMap->SendRecvBuf[5] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT1; /* 0xD3 */ + NdefMap->SendRecvBuf[6] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT2; /* 0xF7 */ + } + else + { + NdefMap->SendRecvBuf[1] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT1; /* 0xA0 */ + NdefMap->SendRecvBuf[2] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT2; /* 0xA1 */ + NdefMap->SendRecvBuf[3] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT3; /* 0xA2 */ + NdefMap->SendRecvBuf[4] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT4; /* 0xA3 */ + NdefMap->SendRecvBuf[5] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT5; /* 0xA4 */ + NdefMap->SendRecvBuf[6] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_MADSECT6; /* 0xA5 */ + } + + if (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD || + NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD) + { + if (NdefMap->StdMifareContainer.ReadOnlySectorIndex && + NdefMap->StdMifareContainer.SectorTrailerBlockNo == NdefMap->StdMifareContainer.currentBlock) + { + memcpy (&NdefMap->SendRecvBuf[1], &NdefMap->StdMifareContainer.UserScrtKeyB[0], PH_FRINFC_MIFARESTD_KEY_LEN); + + /* Authenticate with KeyB*/ +#ifndef PH_HAL4_ENABLE + NdefMap->Cmd.MfCmd = phHal_eMifareCmdListMifareAuthentB; +#else + NdefMap->Cmd.MfCmd = phHal_eMifareAuthentB; +#endif + } + } + + NdefMap->SendLength = MIFARE_AUTHENTICATE_CMD_LENGTH; + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + /* Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + + return status; +} + +static void phFriNfc_MifStd_H_Complete(phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Result) +{ + /* set the state back to the Reset_Init state*/ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; + + /* set the completion routine*/ + NdefMap->CompletionRoutine[NdefMap->StdMifareContainer.CRIndex]. + CompletionRoutine(NdefMap->CompletionRoutine->Context, Result); +} + +static NFCSTATUS phFriNfc_MifStd4k_H_CheckNdef(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Get the AID Block */ + if(NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK2) + { + NdefMap->StdMifareContainer.currentBlock = PH_FRINFC_MIFARESTD_MAD_BLK64; + NdefMap->StdMifareContainer.AuthDone = PH_FRINFC_MIFARESTD_FLAG0; + } + else if(NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK64) + { + NdefMap->StdMifareContainer.currentBlock = PH_FRINFC_MIFARESTD_MAD_BLK65; + } + else + { + NdefMap->StdMifareContainer.currentBlock = PH_FRINFC_MIFARESTD_MAD_BLK66; + } + + Result = phFriNfc_MifareStdMap_ChkNdef(NdefMap); + + return Result; + +} + +static void phFriNfc_MifStd_H_fillAIDarray(phFriNfc_NdefMap_t *NdefMap) +{ + uint8_t byteindex = 0; + + if( (NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK1) || + (NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK64)) + { + /* The First Two Bytes in Receive Buffer + are CRC bytes so it is not copied + instead, 0 is copied in AID[0] & AID[1] */ + NdefMap->StdMifareContainer.aid[NdefMap->StdMifareContainer.SectorIndex] = + PH_FRINFC_MIFARESTD_NDEF_COMP; + NdefMap->StdMifareContainer.SectorIndex++; + byteindex = 2; + } + + while(byteindex < PH_FRINFC_MIFARESTD_BYTES_READ) + { + if((NdefMap->SendRecvBuf[byteindex] == PH_FRINFC_NDEFMAP_MIFARESTD_NDEF_COMPVAL2) && + (NdefMap->SendRecvBuf[(byteindex + 1)] == PH_FRINFC_NDEFMAP_MIFARESTD_NDEF_COMPVAL1)) + { + /* This flag is set when a NFC forum sector is found in a + MAD block for the first time*/ + NdefMap->StdMifareContainer.NFCforumSectFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->StdMifareContainer.aid[NdefMap->StdMifareContainer.SectorIndex] = + PH_FRINFC_MIFARESTD_NDEF_COMP; + NdefMap->StdMifareContainer.SectorIndex++; + } + else + { + NdefMap->StdMifareContainer.aid[NdefMap->StdMifareContainer.SectorIndex] = + PH_FRINFC_MIFARESTD_NON_NDEF_COMP; + NdefMap->StdMifareContainer.SectorIndex++; + /* AID complete flag is set when a non NFC forum sector is found in a + MAD block after the NFC forum sector. After setting this, all other + values are ignored and are NOT NDEF compliant */ + NdefMap->StdMifareContainer.aidCompleteFlag = + ((NdefMap->StdMifareContainer.NFCforumSectFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + NdefMap->StdMifareContainer.NFCforumSectFlag = PH_FRINFC_MIFARESTD_FLAG0; + if(NdefMap->StdMifareContainer.aidCompleteFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + break; + } + } + byteindex += 2; + } + + /* If "aidCompleteFlag" is set then the remaining sectors are made NOT + NDEF compliant */ + if((NdefMap->StdMifareContainer.aidCompleteFlag == PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD)) + { + /* for Mifare 1k there are 16 sectors, till this number all sectors + are made NOT NDEF compliant */ + for(byteindex = NdefMap->StdMifareContainer.SectorIndex; + byteindex < PH_FRINFC_MIFARESTD1K_TOTAL_SECTOR; + byteindex++) + { + NdefMap->StdMifareContainer.aid[byteindex] = + PH_FRINFC_MIFARESTD_NON_NDEF_COMP; + } + } + /* for Mifare 4k there are 40 sectors, till this number all sectors + are made NOT NDEF compliant */ + else if((NdefMap->StdMifareContainer.aidCompleteFlag == PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD)) + { + for(byteindex = NdefMap->StdMifareContainer.SectorIndex; + byteindex < PH_FRINFC_MIFARESTD4K_TOTAL_SECTOR; + byteindex++) + { + NdefMap->StdMifareContainer.aid[byteindex] = + PH_FRINFC_MIFARESTD_NON_NDEF_COMP; + } + } +} + +static NFCSTATUS phFriNfc_MifStd_H_BlkChk(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t SectorID = 0, callbreak = 0; + + for(;;) + { + /* Get a Sector ID for the Current Block */ + SectorID = phFriNfc_MifStd_H_GetSect(NdefMap->StdMifareContainer.currentBlock); + /* Check the card Type 1k or 4k */ + /* enter if Mifare 1k card. For Mifare 4k go to else */ + if(NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD) + { + /* if Sector Id > 15 No Sectors to write */ + if(SectorID > 15) + { + SectorID = phFriNfc_MifStd_H_GetSect(NdefMap->StdMifareContainer.currentBlock); + /*Error: No Ndef Compliant Sectors present.*/ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + callbreak = 1; + } + else + { + phFriNfc_MifStd1k_H_BlkChk(NdefMap, SectorID, &callbreak); + } + } /* End of if */ /* End of Mifare 1k check */ + else /* Mifare 4k check starts here */ + { + /* Sector > 39 no ndef compliant sectors found*/ + if(SectorID > PH_FRINFC_MIFARESTD_SECTOR_NO39) + { + /*Error: No Ndef Compliant Sectors present.*/ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + callbreak = 1; + } + else if(NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK64) + { + NdefMap->StdMifareContainer.currentBlock += PH_FRINFC_MIFARESTD_BLK4; + } + else if(SectorID < PH_FRINFC_MIFARESTD_SECTOR_NO32) /* sector < 32 contains 4 blocks in each sector */ + { + /* If the block checked is 63, the 3 blocks after this + are AID(MAD) blocks so its need to be skipped */ + if(NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK63) + { + NdefMap->StdMifareContainer.currentBlock += PH_FRINFC_MIFARESTD_BLK4; + } + else + { + phFriNfc_MifStd1k_H_BlkChk(NdefMap, SectorID, &callbreak); + } + } + else + { + /* every last block of a sector needs to be skipped */ + if(((NdefMap->StdMifareContainer.currentBlock + 1) % + PH_FRINFC_MIFARESTD_BLOCK_BYTES) == 0) + { + NdefMap->StdMifareContainer.currentBlock++; + } + else + { + if(NdefMap->StdMifareContainer.aid[SectorID] == + PH_FRINFC_MIFARESTD_NDEF_COMP) + { + /* Check whether the block is first block of a (next)new sector and + also check if it is first block then internal length is zero + or not. Because once Authentication is done for the sector again + we should not authenticate it again */ + /* In this case 32 sectors contains 4 blocks and next remaining 8 sectors + contains 16 blocks that is why (32 * 4) + (sectorID - 32) *16*/ + if((NdefMap->StdMifareContainer.currentBlock == + ((PH_FRINFC_MIFARESTD_SECTOR_NO32 * PH_FRINFC_MIFARESTD_BLK4) + + ((SectorID - PH_FRINFC_MIFARESTD_SECTOR_NO32) * PH_FRINFC_MIFARESTD_BLOCK_BYTES))) && + (NdefMap->StdMifareContainer.internalLength == 0)) + { + NdefMap->StdMifareContainer.AuthDone = 0; + } + callbreak = 1; + } + else + { + NdefMap->StdMifareContainer.currentBlock += 16; + } + } + } + } + if(callbreak == 1) + { + break; + } + } + + return Result; +} + +static uint8_t phFriNfc_MifStd_H_GetSect(uint8_t BlockNumber) +{ + uint8_t SectorID = 0; + + if(BlockNumber >= PH_FRINFC_MIFARESTD4K_BLK128) + { + SectorID = (uint8_t)(PH_FRINFC_MIFARESTD_SECTOR_NO32 + + ((BlockNumber - PH_FRINFC_MIFARESTD4K_BLK128)/ + PH_FRINFC_MIFARESTD_BLOCK_BYTES)); + } + else + { + SectorID = (BlockNumber/PH_FRINFC_MIFARESTD_BLK4); + } + return SectorID; +} + +static NFCSTATUS phFriNfc_MifStd_H_RdAcsBit(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RD_ACS_BIT; + + if( NdefMap->StdMifareContainer.ReadOnlySectorIndex && + NdefMap->StdMifareContainer.currentBlock == NdefMap->StdMifareContainer.SectorTrailerBlockNo) + { + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RD_SEC_ACS_BIT; + } + + if(NdefMap->StdMifareContainer.ReadAcsBitFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + /* Get the sector trailer */ + ((NdefMap->StdMifareContainer.currentBlock > 127)? + phFriNfc_MifStd_H_Get4kStTrail(NdefMap): + phFriNfc_MifStd_H_Get1kStTrail(NdefMap)); + } + else + { + /* Give the current block to read */ + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + NdefMap->StdMifareContainer.currentBlock; + } + + Result = phFriNfc_MifStd_H_Rd16Bytes(NdefMap, + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0]); + + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_ChkAcsBit(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Blocks from 0 to 3 and from 64 to 67(MAD blocks) */ + if((NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK0) || + (NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK1) || + (NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK2) || + (NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK3) || + (NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK64) || + (NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK65) || + (NdefMap->StdMifareContainer.currentBlock == PH_FRINFC_MIFARESTD_MAD_BLK66) ) + { + /* Access bits check removed for the MAD blocks */ +#ifdef ENABLE_ACS_BIT_CHK_FOR_MAD + + if(((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL6] & + PH_FRINFC_MIFARESTD_MASK_FF) == + PH_FRINFC_MIFARESTD_MADSECT_ACS_BYTE6) && + ((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL7] & + PH_FRINFC_MIFARESTD_MASK_FF) == + PH_FRINFC_MIFARESTD_MADSECT_ACS_BYTE7) && + ((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL8] & + PH_FRINFC_MIFARESTD_MASK_FF) == + PH_FRINFC_MIFARESTD_ACS_BYTE8)) + { + NdefMap->StdMifareContainer.WriteFlag = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.ReadFlag = + PH_FRINFC_MIFARESTD_FLAG1; + } + else + { + NdefMap->StdMifareContainer.WriteFlag = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.ReadFlag = + PH_FRINFC_MIFARESTD_FLAG0; + } + +#else /* #ifdef ENABLE_ACS_BIT_CHK_FOR_MAD */ + + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED; + +#endif /* #ifdef ENABLE_ACS_BIT_CHK_FOR_MAD */ + } + else + { + /* Check for Access bytes 6, 7 and 8 value = + 0x7F, 0x07, 0x88 NFC forum sectors*/ + if(((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL6] & + PH_FRINFC_MIFARESTD_MASK_FF) == + PH_FRINFC_MIFARESTD_NFCSECT_ACS_BYTE6) && + ((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL7] & + PH_FRINFC_MIFARESTD_MASK_FF) == + PH_FRINFC_MIFARESTD_NFCSECT_ACS_BYTE7) && + ((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL8] & + PH_FRINFC_MIFARESTD_MASK_FF) == + PH_FRINFC_MIFARESTD_ACS_BYTE8)) + { + NdefMap->StdMifareContainer.WriteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->StdMifareContainer.ReadFlag = + PH_FRINFC_MIFARESTD_FLAG1; + } + else if(((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL6] & + PH_FRINFC_MIFARESTD_MASK_FF) == + PH_FRINFC_MIFARESTD_NFCSECT_RDACS_BYTE6) && + ((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL7] & + PH_FRINFC_MIFARESTD_MASK_FF) == + PH_FRINFC_MIFARESTD_NFCSECT_RDACS_BYTE7) && + ((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL8] & + PH_FRINFC_MIFARESTD_MASK_FF) == + PH_FRINFC_MIFARESTD_NFCSECT_RDACS_BYTE8)) + { + /* Read Only state */ + /* Check for Access bytes 6, 7 and 8 value = + 0x55, 0xAD, 0x2A NFC forum Sectors*/ + NdefMap->StdMifareContainer.WriteFlag = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.ReadFlag = + PH_FRINFC_MIFARESTD_FLAG1; + } + else + { + NdefMap->StdMifareContainer.WriteFlag = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.ReadFlag = + PH_FRINFC_MIFARESTD_FLAG0; + } + +#ifdef ENABLE_ACS_BIT_CHK_FOR_MAD + + /* Do nothing */ + +#else /* #ifdef ENABLE_ACS_BIT_CHK_FOR_MAD */ + + Result = phFriNfc_MifStd_H_GPBChk(NdefMap); + +#endif /* #ifdef ENABLE_ACS_BIT_CHK_FOR_MAD */ + + } + +#ifdef ENABLE_ACS_BIT_CHK_FOR_MAD + + Result = phFriNfc_MifStd_H_GPBChk(NdefMap); + +#endif /* #ifdef ENABLE_ACS_BIT_CHK_FOR_MAD */ + + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_ChkRdWr(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + switch(NdefMap->PrevOperation) + { + case PH_FRINFC_NDEFMAP_CHECK_OPE: + if(NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID) + { + /* No permission to read */ + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_READ_FAILED); + } + else if((NdefMap->StdMifareContainer.currentBlock > 3) && + (NdefMap->StdMifareContainer.ChkNdefCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->StdMifareContainer.currentBlock != + PH_FRINFC_MIFARESTD_MAD_BLK65) && + (NdefMap->StdMifareContainer.currentBlock != + PH_FRINFC_MIFARESTD_MAD_BLK66)) + { + /* NdefMap->StdMifareContainer.currentBlock = + ((NdefMap->StdMifareContainer.ReadCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + NdefMap->StdMifareContainer.currentBlock: + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_VAL4)); + NdefMap->StdMifareContainer.currentBlock = + ((NdefMap->StdMifareContainer.currentBlock == + PH_FRINFC_MIFARESTD_MAD_BLK64)? + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_VAL4): + NdefMap->StdMifareContainer.currentBlock);*/ + + Result = ((NdefMap->StdMifareContainer.ReadAcsBitFlag == + PH_FRINFC_MIFARESTD_FLAG0)? + phFriNfc_MifStd_H_RdAcsBit(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + else + { + Result = phFriNfc_MifareStdMap_ChkNdef(NdefMap); + } + break; + + case PH_FRINFC_NDEFMAP_READ_OPE: + if(NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID) + { + /* No permission to Read */ + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_READ_FAILED); + } + else if(NdefMap->StdMifareContainer.ReadNdefFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + Result = phFriNfc_MifStd_H_GetActCardLen(NdefMap); + } + else + { + Result = phFriNfc_MifStd_H_RdABlock(NdefMap); + } + break; + + case PH_FRINFC_NDEFMAP_WRITE_OPE: + if((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID) || + (NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_READ_ONLY)) + { + /* No permission to Read */ + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_WRITE_FAILED); + } + else if(NdefMap->StdMifareContainer.WrNdefFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + Result = phFriNfc_MifStd_H_GetActCardLen(NdefMap); + } + else if(NdefMap->StdMifareContainer.RdBeforeWrFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + /*NdefMap->StdMifareContainer.ReadFlag = + PH_FRINFC_MIFARESTD_FLAG0;*/ + Result = phFriNfc_MifStd_H_RdBeforeWr(NdefMap); + } + else if(NdefMap->StdMifareContainer.RdAfterWrFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + Result = phFriNfc_MifStd_H_RdtoWrNdefLen(NdefMap); + } + else + { + Result = (((NdefMap->TLVStruct.NdefTLVBlock == + NdefMap->StdMifareContainer.currentBlock) && + (NdefMap->Offset == + PH_FRINFC_NDEFMAP_SEEK_BEGIN))? + phFriNfc_MifStd_H_RdBeforeWr(NdefMap): + phFriNfc_MifStd_H_WrABlock(NdefMap)); + } + break; + + case PH_FRINFC_NDEFMAP_GET_ACTSIZE_OPE: + Result = ((NdefMap->StdMifareContainer.ReadFlag == + PH_FRINFC_MIFARESTD_FLAG0)? + (PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_READ_FAILED)): + phFriNfc_MifStd_H_GetActCardLen(NdefMap)); + break; + + default: + /* Operation is not correct */ + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + + break; + } + return Result; +} + +static void phFriNfc_MifStd_H_ChkNdefCmpltSects(phFriNfc_NdefMap_t *NdefMap) +{ + uint8_t index = 0; + if(NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD) + { + for(index = 0; index < PH_FRINFC_MIFARESTD4K_TOTAL_SECTOR; index++) + { + /* For Mifare 4k, Block 0 to 31 contains 4 blocks */ + /* sector 0 and 15 are aid blocks */ + if(index != PH_FRINFC_MIFARESTD_SECTOR_NO16) + { + if(( (index < 32) && (index != PH_FRINFC_MIFARESTD_SECTOR_NO0)) + && (NdefMap->StdMifareContainer.aid[index] == + PH_FRINFC_MIFARESTD_NON_NDEF_COMP)) + { + /* Only 3 blocks can be read/written till sector 31 */ + NdefMap->StdMifareContainer.NoOfNdefCompBlocks -= + PH_FRINFC_MIFARESTD_MAD_BLK3; + + } + else + { + /* For Mifare 4k, Block 32 to 39 contains 16 blocks */ + if(NdefMap->StdMifareContainer.aid[index] == + PH_FRINFC_MIFARESTD_NON_NDEF_COMP) + { + /* Only 15 blocks can be read/written from sector 31 */ + NdefMap->StdMifareContainer.NoOfNdefCompBlocks -= + PH_FRINFC_MIFARESTD_BLK15; + } + } + } + } /* For index > 40 */ + } + else + { + for(index = PH_FRINFC_MIFARESTD_SECTOR_NO1; + index < PH_FRINFC_MIFARESTD_SECTOR_NO16; index++) + { + if(NdefMap->StdMifareContainer.aid[index] == + PH_FRINFC_MIFARESTD_NON_NDEF_COMP) + { + /* Only three blocks can be read/written in + a sector. So if a sector is non-ndef + compliant, decrement 3 */ + NdefMap->StdMifareContainer.NoOfNdefCompBlocks -= + PH_FRINFC_MIFARESTD_MAD_BLK3; + } + } + } +} + +#if 0 +static uint8_t phFriNfc_MifStd_H_ChkNdefLen(phFriNfc_NdefMap_t *NdefMap, + uint8_t NDEFlength, + uint8_t *CRFlag) +{ + uint8_t NoLengthBytesinTLV = 0, + TempBuffer[16] = {0}; + uint16_t TempLength = 0; + + TempLength = ((NdefMap->StdMifareContainer.internalLength > 0)? + NdefMap->StdMifareContainer.internalLength : + PH_FRINFC_MIFARESTD_BYTES_READ); + + if(NdefMap->StdMifareContainer.internalLength > 0) + { + (void)memcpy( TempBuffer, + NdefMap->StdMifareContainer.internalBuf, + TempLength); + } + else + { + (void)memcpy( TempBuffer, + NdefMap->SendRecvBuf, + TempLength); + } + + /* if number of bytes for length (L) in TLV is greater than 0*/ + if(NdefMap->TLVStruct.NoLbytesinTLV != PH_FRINFC_MIFARESTD_VAL0) + { + switch(NdefMap->TLVStruct.NoLbytesinTLV) + { + /* there are two bytes remaining in the length (L) of TLV */ + case PH_FRINFC_MIFARESTD_VAL2: + NoLengthBytesinTLV = PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES2; + /* Get the value of the length (L) of the TLV */ + NdefMap->TLVStruct.BytesRemainLinTLV = *TempBuffer; + NdefMap->TLVStruct.BytesRemainLinTLV = + ((NdefMap->TLVStruct.BytesRemainLinTLV + << PH_FRINFC_MIFARESTD_LEFTSHIFT8) + (TempBuffer[ + PH_FRINFC_MIFARESTD_INC_1])); + + *CRFlag = (uint8_t)((NdefMap->TLVStruct.BytesRemainLinTLV < + PH_FRINFC_MIFARESTD_NDEFTLV_L)? + PH_FRINFC_MIFARESTD_FLAG1 : + PH_FRINFC_MIFARESTD_FLAG0); + NdefMap->TLVStruct.BytesRemainLinTLV = ((*CRFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + PH_FRINFC_MIFARESTD_VAL0: + NdefMap->TLVStruct.BytesRemainLinTLV); + break; + + /* there is only one byte remaining in the length (L) of TLV */ + case PH_FRINFC_MIFARESTD_VAL1: + NoLengthBytesinTLV = PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES1; + /* Get the value of the length (L) of the TLV */ + NdefMap->TLVStruct.BytesRemainLinTLV = + NdefMap->TLVStruct.prevLenByteValue; + + NdefMap->TLVStruct.BytesRemainLinTLV = + ((NdefMap->TLVStruct.BytesRemainLinTLV + << PH_FRINFC_MIFARESTD_LEFTSHIFT8) + (*TempBuffer)); + *CRFlag = (uint8_t)((NdefMap->TLVStruct.BytesRemainLinTLV < + PH_FRINFC_MIFARESTD_NDEFTLV_L)? + PH_FRINFC_MIFARESTD_FLAG1 : + PH_FRINFC_MIFARESTD_FLAG0); + + NdefMap->TLVStruct.BytesRemainLinTLV = ((*CRFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + PH_FRINFC_MIFARESTD_VAL0: + NdefMap->TLVStruct.BytesRemainLinTLV); + break; + + default: + break; + } + NdefMap->TLVStruct.NoLbytesinTLV = PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES0; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.LcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + else if(TempBuffer[NDEFlength] < + PH_FRINFC_MIFARESTD_NDEFTLV_L) + { + NoLengthBytesinTLV = PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES1; + /* Get the value of the length (L) of the TLV */ + NdefMap->TLVStruct.BytesRemainLinTLV = + TempBuffer[NDEFlength]; + + /* if NDEFLength has reached 16 bytes, then the next coming byte is not of type in TLV */ + NdefMap->TLVStruct.TcheckedinTLVFlag = (((NDEFlength + PH_FRINFC_MIFARESTD_INC_1) + == PH_FRINFC_MIFARESTD_BYTES_READ)? + PH_FRINFC_MIFARESTD_FLAG1 : + PH_FRINFC_MIFARESTD_FLAG0); + /* if NDEFLength has reached 16 bytes, then the next coming byte is not of length in TLV */ + NdefMap->TLVStruct.LcheckedinTLVFlag = (((NDEFlength + PH_FRINFC_MIFARESTD_INC_1) + == PH_FRINFC_MIFARESTD_BYTES_READ)? + PH_FRINFC_MIFARESTD_FLAG1 : + PH_FRINFC_MIFARESTD_FLAG0); + } + else + { + if((NDEFlength + PH_FRINFC_MIFARESTD_INC_1) + == PH_FRINFC_MIFARESTD_BYTES_READ) + { + NoLengthBytesinTLV = PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES1; + /* Number of bytes left for length (L) field in TLV */ + NdefMap->TLVStruct.NoLbytesinTLV = PH_FRINFC_MIFARESTD_VAL2; + /* if NDEFLength has reached 16 bytes, then the next coming byte is not of type in TLV */ + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.LcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + else if((NDEFlength + PH_FRINFC_MIFARESTD_INC_2) + == PH_FRINFC_MIFARESTD_BYTES_READ) + { + NoLengthBytesinTLV = PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES2; + /* Number of bytes left for length (L) field in TLV */ + NdefMap->TLVStruct.NoLbytesinTLV = PH_FRINFC_MIFARESTD_VAL1; + /* if NDEFLength has reached 16 bytes, then the next byte is not of type in TLV */ + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.LcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + /* copy the value of the length field */ + NdefMap->TLVStruct.prevLenByteValue = + NdefMap->SendRecvBuf[(NDEFlength + PH_FRINFC_MIFARESTD_INC_1)]; + } + else + { + /* if NDEFLength has reached 16 bytes, then the next byte is not of type in TLV */ + NdefMap->TLVStruct.TcheckedinTLVFlag = (((NDEFlength + PH_FRINFC_MIFARESTD_INC_3) + == PH_FRINFC_MIFARESTD_BYTES_READ)? + PH_FRINFC_MIFARESTD_FLAG1 : + PH_FRINFC_MIFARESTD_FLAG0); + + /* if NDEFLength has reached 16 bytes, then the next byte is not of length in TLV */ + NdefMap->TLVStruct.LcheckedinTLVFlag = (((NDEFlength + PH_FRINFC_MIFARESTD_INC_1) + == PH_FRINFC_MIFARESTD_BYTES_READ)? + PH_FRINFC_MIFARESTD_FLAG1 : + PH_FRINFC_MIFARESTD_FLAG0); + + /* Number of bytes left for length (L) field in TLV */ + NdefMap->TLVStruct.NoLbytesinTLV = PH_FRINFC_MIFARESTD_VAL0; + + NoLengthBytesinTLV = PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES3; + /* Get the value of the length (L) of the TLV */ + NdefMap->TLVStruct.BytesRemainLinTLV = + TempBuffer[(NDEFlength + + PH_FRINFC_MIFARESTD_INC_1)]; + + NdefMap->TLVStruct.BytesRemainLinTLV = + ((NdefMap->TLVStruct.BytesRemainLinTLV + << PH_FRINFC_MIFARESTD_LEFTSHIFT8) + TempBuffer[ + (NDEFlength +PH_FRINFC_MIFARESTD_INC_2)]); + + *CRFlag = (uint8_t)((NdefMap->TLVStruct.BytesRemainLinTLV < + PH_FRINFC_MIFARESTD_NDEFTLV_L)? + PH_FRINFC_MIFARESTD_FLAG1 : + PH_FRINFC_MIFARESTD_FLAG0); + } + } + return NoLengthBytesinTLV; +} +#endif +#if 0 +static NFCSTATUS phFriNfc_MifStd_H_RdNdefTLV(phFriNfc_NdefMap_t *NdefMap, + uint8_t *Temp16Bytes) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t NDEFlength = 0, + RdFlag = 0, + CRFlag = 0; + uint16_t RemainingBytes = 0; + + while(PH_FRINFC_MIFARESTD_FLAG1 == NdefMap->TLVStruct.NdefTLVFoundFlag) + { + RemainingBytes = ((uint16_t)NdefMap->ApduBufferSize - + NdefMap->ApduBuffIndex); + if(((( NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + NdefMap->StdMifareContainer.NdefBlocks) * + PH_FRINFC_MIFARESTD_BLOCK_BYTES) + + PH_FRINFC_MIFARESTD_BLOCK_BYTES) < + RemainingBytes) + { + /* If the user Buffer is greater than the Card Size + set LastBlockFlag = 1. This Flag is used to read bytes + till the end of the card only */ + RemainingBytes = ((( NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + NdefMap->StdMifareContainer.NdefBlocks) * 16) + + NdefMap->StdMifareContainer.internalLength); + + } + /* Ndef TLV flag to 0 */ + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG0; + + if((NdefMap->TLVStruct.TcheckedinTLVFlag != PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->TLVStruct.LcheckedinTLVFlag != PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->TLVStruct.NoLbytesinTLV != PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES0)) + { + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + + /* if type (T) of TLV flag is not set then only the below check is valid + because, for eg. assume, type (T) of TLV flag is set then this means + that it is already checked from the previous 16 bytes data (T is the + last byte of 16 bytes */ + if(NdefMap->TLVStruct.TcheckedinTLVFlag != PH_FRINFC_MIFARESTD_FLAG1) + { + CRFlag = ((NdefMap->SendRecvBuf[(*Temp16Bytes)]!= + PH_FRINFC_MIFARESTD_NDEFTLV_T)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + if(CRFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + RdFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + /* skip Type T of the TLV */ + *Temp16Bytes += PH_FRINFC_MIFARESTD_INC_1; + } + else + { + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + + if((*Temp16Bytes + PH_FRINFC_MIFARESTD_VAL1) == PH_FRINFC_MIFARESTD_BYTES_READ) + { + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG1; + /* 16 bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + if(NdefMap->StdMifareContainer.AuthDone == PH_FRINFC_MIFARESTD_FLAG1) + { + Result = phFriNfc_MifStd_H_RdABlock(NdefMap); + } + else + { + Result = phFriNfc_MifStd_H_AuthSector(NdefMap); + } + } + break; + } + /* skip number of bytes taken by L in TLV, if L is already read */ + if(NdefMap->TLVStruct.LcheckedinTLVFlag != PH_FRINFC_MIFARESTD_FLAG1) + { + /*CRFlag = (((*(NdefMap->SendRecvBuf + *Temp16Bytes) == + PH_FRINFC_MIFARESTD_NDEFTLV_L0) && + (NdefMap->TLVStruct.NoLbytesinTLV == + PH_FRINFC_MIFARESTD_VAL0))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0);*/ + + NDEFlength = *Temp16Bytes; + *Temp16Bytes += phFriNfc_MifStd_H_ChkNdefLen(NdefMap, + NDEFlength, + &CRFlag); + if(CRFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + break; + } + + } + else + { + NdefMap->TLVStruct.LcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + + if(*Temp16Bytes == PH_FRINFC_MIFARESTD_BYTES_READ) + { + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG1; + /* 16 bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + if(NdefMap->StdMifareContainer.AuthDone == PH_FRINFC_MIFARESTD_FLAG1) + { + Result = phFriNfc_MifStd_H_RdABlock(NdefMap); + } + else + { + Result = phFriNfc_MifStd_H_AuthSector(NdefMap); + } + } + break; + } + + if((NdefMap->TLVStruct.BytesRemainLinTLV <= + (PH_FRINFC_MIFARESTD_BYTES_READ - *Temp16Bytes)) && + (RemainingBytes <= + NdefMap->TLVStruct.BytesRemainLinTLV)) + { + /* Copy data to user buffer */ + (void)memcpy(&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + &(NdefMap->SendRecvBuf[ + (*Temp16Bytes)]), + RemainingBytes); + NdefMap->ApduBuffIndex += RemainingBytes; + *Temp16Bytes += ((uint8_t)RemainingBytes); + NdefMap->TLVStruct.BytesRemainLinTLV -= RemainingBytes; + + if(NdefMap->TLVStruct.BytesRemainLinTLV == 0) + { + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.LcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + else + { + /* copy the bytes to internal buffer that are read, + but not used for the user buffer */ + (void)memcpy(NdefMap->StdMifareContainer.internalBuf, + &(NdefMap->SendRecvBuf[(*Temp16Bytes)]), + (PH_FRINFC_MIFARESTD_BYTES_READ - *Temp16Bytes)); + + /* TempLength of the internal buffer */ + NdefMap->StdMifareContainer.internalLength = + (PH_FRINFC_MIFARESTD_BYTES_READ - *Temp16Bytes); + } + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + else if((NdefMap->TLVStruct.BytesRemainLinTLV <= + (PH_FRINFC_MIFARESTD_BYTES_READ - *Temp16Bytes)) && + (RemainingBytes > + NdefMap->TLVStruct.BytesRemainLinTLV)) + { + /* Copy data to user buffer */ + (void)memcpy(&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + &(NdefMap->SendRecvBuf[ + (*Temp16Bytes)]), + NdefMap->TLVStruct.BytesRemainLinTLV); + /* increment the user buffer index */ + NdefMap->ApduBuffIndex += NdefMap->TLVStruct.BytesRemainLinTLV; + *Temp16Bytes += ((uint8_t)NdefMap->TLVStruct.BytesRemainLinTLV); + NdefMap->TLVStruct.BytesRemainLinTLV = 0; + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.LcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + + /* check for 16 bytes of data been used */ + if(*Temp16Bytes == PH_FRINFC_MIFARESTD_BYTES_READ) + { + /* 16 bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + if(NdefMap->StdMifareContainer.AuthDone == PH_FRINFC_MIFARESTD_FLAG1) + { + Result = phFriNfc_MifStd_H_RdABlock(NdefMap); + } + else + { + Result = phFriNfc_MifStd_H_AuthSector(NdefMap); + } + } + break; + } + } + else if((NdefMap->TLVStruct.BytesRemainLinTLV > + (PH_FRINFC_MIFARESTD_BYTES_READ - *Temp16Bytes)) && + (RemainingBytes <= + (PH_FRINFC_MIFARESTD_BYTES_READ - *Temp16Bytes))) + { + /* Copy data to user buffer */ + (void)memcpy(&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + &(NdefMap->SendRecvBuf[ + (*Temp16Bytes)]), + RemainingBytes); + NdefMap->ApduBuffIndex += RemainingBytes; + NdefMap->TLVStruct.BytesRemainLinTLV -= RemainingBytes; + if(RemainingBytes == (PH_FRINFC_MIFARESTD_BYTES_READ - *Temp16Bytes)) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = (uint8_t) + (((NdefMap->StdMifareContainer.remainingSize == PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.BytesRemainLinTLV == PH_FRINFC_MIFARESTD_VAL0))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + /* 16 bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + } + else + { + /* copy the bytes to internal buffer, that are read, + but not used for the user buffer */ + (void)memcpy(NdefMap->StdMifareContainer.internalBuf, + &(NdefMap->SendRecvBuf[((*Temp16Bytes) + RemainingBytes)]), + (PH_FRINFC_MIFARESTD_BYTES_READ - + (*Temp16Bytes + RemainingBytes))); + + /* Length of the internal buffer */ + NdefMap->StdMifareContainer.internalLength = + (PH_FRINFC_MIFARESTD_BYTES_READ - + (*Temp16Bytes + RemainingBytes)); + } + *Temp16Bytes += ((uint8_t)RemainingBytes); + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + else + { + if((NdefMap->TLVStruct.BytesRemainLinTLV > + (PH_FRINFC_MIFARESTD_BYTES_READ - *Temp16Bytes)) && + (RemainingBytes > + (PH_FRINFC_MIFARESTD_BYTES_READ - *Temp16Bytes))) + { + /* Copy data to user buffer */ + (void)memcpy(&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + &(NdefMap->SendRecvBuf[ + (*Temp16Bytes)]), + (PH_FRINFC_MIFARESTD_BYTES_READ - *Temp16Bytes)); + NdefMap->ApduBuffIndex += (PH_FRINFC_MIFARESTD_BYTES_READ - *Temp16Bytes); + NdefMap->TLVStruct.BytesRemainLinTLV -= + (PH_FRINFC_MIFARESTD_BYTES_READ - *Temp16Bytes); + *Temp16Bytes = PH_FRINFC_MIFARESTD_BYTES_READ; + + + /* 16 bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + Result = ((NdefMap->StdMifareContainer.AuthDone == + PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_RdABlock(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + break; + } + } + } + + if(CRFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + Result = (((RdFlag == PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->ApduBuffIndex == PH_FRINFC_MIFARESTD_VAL0))? + (PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_CARD_REACHED)): + Result); + *NdefMap->NumOfBytesRead = NdefMap->ApduBuffIndex; + phFriNfc_MifStd_H_Complete(NdefMap, Result); + } + return Result; +} +#endif + +static NFCSTATUS phFriNfc_MifStd_H_RemainTLV(phFriNfc_NdefMap_t *NdefMap, + uint8_t *Flag, + uint8_t *Temp16Bytes) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t CRFlag = 0; + uint16_t RemainingBytes = 0; + + RemainingBytes = ((uint16_t)NdefMap->ApduBufferSize - + NdefMap->ApduBuffIndex); + + if(NdefMap->StdMifareContainer.remainingSize < + RemainingBytes) + { + /* If the user Buffer is greater than the Card Size + set LastBlockFlag = 1. This Flag is used to read bytes + till the end of the card only */ + RemainingBytes = NdefMap->StdMifareContainer.remainingSize; + } + + /* Remaining Bytes of length (L) in TLV <= 16 */ + if((NdefMap->TLVStruct.BytesRemainLinTLV <= + (PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes))) && + (RemainingBytes <= NdefMap->TLVStruct.BytesRemainLinTLV)) + { + /* Copy data to user buffer */ + (void)memcpy(&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + &(NdefMap->SendRecvBuf[ + (*Temp16Bytes)]), + RemainingBytes); + NdefMap->ApduBuffIndex += RemainingBytes; + NdefMap->StdMifareContainer.remainingSize -= RemainingBytes; + + /* copy the bytes to internal buffer, that are read, + but not used for the user buffer */ + if(RemainingBytes != NdefMap->TLVStruct.BytesRemainLinTLV) + { + (void)memcpy( NdefMap->StdMifareContainer.internalBuf, +#ifdef PH_HAL4_ENABLE + &(NdefMap->SendRecvBuf[((*Temp16Bytes) + RemainingBytes)]), +#else + &(NdefMap->SendRecvBuf[RemainingBytes]), +#endif /* #ifdef PH_HAL4_ENABLE */ + ((PH_FRINFC_MIFARESTD_BYTES_READ - + (*Temp16Bytes)) - RemainingBytes)); + + /* internal buffer length */ + NdefMap->StdMifareContainer.internalLength = + ((PH_FRINFC_MIFARESTD_BYTES_READ - + (*Temp16Bytes)) - RemainingBytes); + } + *Temp16Bytes += ((uint8_t)RemainingBytes); + /* Remaining Bytes of length value in TLV */ + NdefMap->TLVStruct.BytesRemainLinTLV -= RemainingBytes; + + if(NdefMap->StdMifareContainer.internalLength == PH_FRINFC_MIFARESTD_VAL0) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = (uint8_t) + (((NdefMap->StdMifareContainer.remainingSize == PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.BytesRemainLinTLV == PH_FRINFC_MIFARESTD_VAL0))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + /* internal length bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + } + + if(NdefMap->TLVStruct.BytesRemainLinTLV == PH_FRINFC_MIFARESTD_VAL0) + { + /* Remaining Bytes of length (L) in TLV is Zero means that the next + coming bytes are containing type (T), length (L) in TLV */ + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.LcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + /* call completion routine */ + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + *Flag = PH_FRINFC_MIFARESTD_FLAG0; + } + else if((NdefMap->TLVStruct.BytesRemainLinTLV <= + (PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes))) && + (RemainingBytes > NdefMap->TLVStruct.BytesRemainLinTLV)) + { + /* Copy data to user buffer */ + (void)memcpy(&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + &(NdefMap->SendRecvBuf[ + (*Temp16Bytes)]), + NdefMap->TLVStruct.BytesRemainLinTLV); + NdefMap->ApduBuffIndex += NdefMap->TLVStruct.BytesRemainLinTLV; + NdefMap->StdMifareContainer.remainingSize -= + NdefMap->TLVStruct.BytesRemainLinTLV; + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG1; + *Temp16Bytes += ((uint8_t)NdefMap->TLVStruct.BytesRemainLinTLV); + NdefMap->TLVStruct.BytesRemainLinTLV = PH_FRINFC_MIFARESTD_VAL0; + + *Flag = PH_FRINFC_MIFARESTD_FLAG1; + + NdefMap->TLVStruct.LcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + /* 16 bytes completed */ + if(NdefMap->TLVStruct.BytesRemainLinTLV == + PH_FRINFC_MIFARESTD_BYTES_READ) + { + *Flag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.BytesRemainLinTLV = + PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES0; + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + if(NdefMap->StdMifareContainer.AuthDone == PH_FRINFC_MIFARESTD_FLAG1) + { + Result = phFriNfc_MifStd_H_RdABlock(NdefMap); + } + else + { + Result = phFriNfc_MifStd_H_AuthSector(NdefMap); + } + } + } + else + { + NdefMap->TLVStruct.BytesRemainLinTLV = + PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES0; + /* The read operation has finished. so, completion routine + can be called. set the Completion routine(CR) flag */ + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + } + else if((NdefMap->TLVStruct.BytesRemainLinTLV > + (PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes))) && + (RemainingBytes <= (PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes)))) + { + /* Copy data to user buffer */ + (void)memcpy(&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + &(NdefMap->SendRecvBuf[ + (*Temp16Bytes)]), + RemainingBytes); + NdefMap->ApduBuffIndex += RemainingBytes; + NdefMap->StdMifareContainer.remainingSize -= RemainingBytes; + + /* Remaining Bytes of length (L) in TLV */ + NdefMap->TLVStruct.BytesRemainLinTLV -= RemainingBytes; + /* + The below macro PH_HAL4_ENABLE is added because, + there is an error with the following sequence + Read begin (for ex : with 10 bytes) + Read current (for ex : with 10 bytes). Here error buffer + is returned + Reason : During first read, internal buffer is updated + with the wrong buffer values + Actually, if we read the first block (means TLV block), it + contains even the TLV structure. so to copy the actual buffer, + the TLV shall be excluded + */ +#ifdef PH_HAL4_ENABLE + /* copy the bytes to internal buffer, that are read, + but not used for the user buffer */ + (void)memcpy( NdefMap->StdMifareContainer.internalBuf, + &(NdefMap->SendRecvBuf[(RemainingBytes + (*Temp16Bytes))]), + ((PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes)) + - RemainingBytes)); + + /* internal buffer length */ + NdefMap->StdMifareContainer.internalLength = + ((PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes)) - RemainingBytes); +#else + /* copy the bytes to internal buffer, that are read, + but not used for the user buffer */ + (void)memcpy( NdefMap->StdMifareContainer.internalBuf, + &(NdefMap->SendRecvBuf[RemainingBytes]), + ((PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes)) + - RemainingBytes)); + + /* internal buffer length */ + NdefMap->StdMifareContainer.internalLength = + ((PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes)) - RemainingBytes); +#endif /* #ifdef PH_HAL4_ENABLE */ + + if(RemainingBytes == (PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes))) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = (uint8_t) + (((NdefMap->StdMifareContainer.remainingSize == PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.BytesRemainLinTLV == PH_FRINFC_MIFARESTD_VAL0))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + /* internal length bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + } + *Temp16Bytes += ((uint8_t)RemainingBytes); + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG0; + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + *Flag = PH_FRINFC_MIFARESTD_FLAG0; + } + else + { + if((NdefMap->TLVStruct.BytesRemainLinTLV > + (PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes))) && + (RemainingBytes > (PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes)))) + { + *Flag = PH_FRINFC_MIFARESTD_FLAG0; + /* Copy data to user buffer */ + (void)memcpy(&(NdefMap->ApduBuffer + [NdefMap->ApduBuffIndex]), + &(NdefMap->SendRecvBuf[ + (*Temp16Bytes)]), + (PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes))); + NdefMap->ApduBuffIndex += (PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes)); + NdefMap->StdMifareContainer.remainingSize -= + (PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes)); + NdefMap->TLVStruct.BytesRemainLinTLV -= (PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes)); + *Temp16Bytes += (PH_FRINFC_MIFARESTD_BYTES_READ - (*Temp16Bytes)); + if(NdefMap->TLVStruct.BytesRemainLinTLV != PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES0) + { + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + /* 16 bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + Result = ((NdefMap->StdMifareContainer.AuthDone == + PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_RdABlock(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + } + } + + if(CRFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + *NdefMap->NumOfBytesRead = NdefMap->ApduBuffIndex; + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = (uint8_t) + (((NdefMap->StdMifareContainer.remainingSize == PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.BytesRemainLinTLV == PH_FRINFC_MIFARESTD_VAL0))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + } + + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_ChkIntLen(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t NDEFFlag = PH_FRINFC_MIFARESTD_FLAG1; + uint8_t TempintBytes = 0; + + if(NdefMap->TLVStruct.BytesRemainLinTLV != 0) + { + NDEFFlag = PH_FRINFC_MIFARESTD_FLAG0; + /* To read the remaining length (L) in TLV */ + Result = phFriNfc_MifStd_H_IntLenWioutNdef(NdefMap, &NDEFFlag, &TempintBytes); + } + NDEFFlag = PH_FRINFC_MIFARESTD_FLAG0; + /* check the NDEFFlag is set. if this is not set, then + in the above RemainTLV function all the 16 bytes has been + read */ +#if 0 + if((NDEFFlag == PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_MIFARESTD_FLAG1)) + { + /* if the block is NDEF TLV then get data from here */ + Result = phFriNfc_MifStd_H_IntLenWithNdef(NdefMap, &TempintBytes); + } +#endif + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_IntLenWioutNdef(phFriNfc_NdefMap_t *NdefMap, + uint8_t *Flag, + uint8_t *TempintBytes) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t CRFlag = 0; + uint16_t RemainingBytes = 0; + + RemainingBytes = ((uint16_t)NdefMap->ApduBufferSize - + NdefMap->ApduBuffIndex); + + if(NdefMap->StdMifareContainer.remainingSize < + RemainingBytes) + { + /* If the user Buffer is greater than the Card Size + set LastBlockFlag = 1. This Flag is used to read bytes + till the end of the card only */ + RemainingBytes = NdefMap->StdMifareContainer.remainingSize; + } + + /* Remaining Bytes of length (L) in TLV <= internal length */ + if((NdefMap->TLVStruct.BytesRemainLinTLV <= + NdefMap->StdMifareContainer.internalLength) && + (RemainingBytes <= NdefMap->TLVStruct.BytesRemainLinTLV)) + { + (void)memcpy(&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + &(NdefMap->StdMifareContainer.internalBuf[ + (*TempintBytes)]), + RemainingBytes); + NdefMap->ApduBuffIndex += RemainingBytes; + NdefMap->StdMifareContainer.remainingSize -= RemainingBytes; + *TempintBytes += ((uint8_t)RemainingBytes); + + /* copy the bytes to internal buffer, that are read, + but not used for the user buffer */ + (void)memcpy( NdefMap->StdMifareContainer.internalBuf, + &(NdefMap->StdMifareContainer.internalBuf[RemainingBytes]), + (NdefMap->StdMifareContainer.internalLength - RemainingBytes)); + + /* internal buffer length */ + NdefMap->StdMifareContainer.internalLength -= RemainingBytes; + + NdefMap->TLVStruct.BytesRemainLinTLV -= RemainingBytes; + if(NdefMap->StdMifareContainer.internalLength == PH_FRINFC_MIFARESTD_VAL0) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = (uint8_t) + (((NdefMap->StdMifareContainer.remainingSize == PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.BytesRemainLinTLV == PH_FRINFC_MIFARESTD_VAL0))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + /* internal length bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + } + + /* Remaining Bytes of length value in TLV */ + if(NdefMap->TLVStruct.BytesRemainLinTLV == 0) + { + /* Remaining Bytes of length (L) in TLV is Zero means that the next + coming bytes are containing type (T), length (L) in TLV */ + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.LcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + /* call completion routine */ + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + *Flag = PH_FRINFC_MIFARESTD_FLAG0; + } + else if((NdefMap->TLVStruct.BytesRemainLinTLV <= + NdefMap->StdMifareContainer.internalLength) && + (RemainingBytes > NdefMap->TLVStruct.BytesRemainLinTLV)) + { + (void)memcpy(&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]), + &(NdefMap->StdMifareContainer.internalBuf[(*TempintBytes)]), + NdefMap->TLVStruct.BytesRemainLinTLV); + + NdefMap->ApduBuffIndex += NdefMap->TLVStruct.BytesRemainLinTLV; + NdefMap->StdMifareContainer.remainingSize -= + NdefMap->TLVStruct.BytesRemainLinTLV; + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG1; + + *TempintBytes += ((uint8_t)NdefMap->TLVStruct.BytesRemainLinTLV); + *Flag = PH_FRINFC_MIFARESTD_FLAG1; + + NdefMap->TLVStruct.LcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + + NdefMap->TLVStruct.BytesRemainLinTLV = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = (uint8_t) + (((NdefMap->StdMifareContainer.remainingSize == PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.BytesRemainLinTLV == PH_FRINFC_MIFARESTD_VAL0))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); +#ifdef PH_HAL4_ENABLE + + if (PH_FRINFC_MIFARESTD_FLAG1 == + NdefMap->StdMifareContainer.ReadWriteCompleteFlag) + { + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + +#endif /* #ifdef PH_HAL4_ENABLE */ + + if( NdefMap->TLVStruct.BytesRemainLinTLV == + NdefMap->StdMifareContainer.internalLength) + { + /* Remaining Bytes in Length (L) field of TLV is 0 */ + NdefMap->TLVStruct.BytesRemainLinTLV = + PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES0; + NdefMap->StdMifareContainer.internalLength = PH_FRINFC_MIFARESTD_VAL0; + *Flag = PH_FRINFC_MIFARESTD_FLAG0; + /* internal length bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + Result = + ((NdefMap->StdMifareContainer.AuthDone == PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_RdABlock(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + } + else + { + /* Remaining Bytes in Length (L) field of TLV is 0 */ + NdefMap->TLVStruct.BytesRemainLinTLV = + PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES0; + *Flag = PH_FRINFC_MIFARESTD_FLAG1; + } + } + else if((NdefMap->TLVStruct.BytesRemainLinTLV > + NdefMap->StdMifareContainer.internalLength) && + (RemainingBytes <= NdefMap->StdMifareContainer.internalLength)) + { + (void)memcpy(&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]), + &(NdefMap->StdMifareContainer.internalBuf[(*TempintBytes)]), + RemainingBytes); + + NdefMap->ApduBuffIndex += RemainingBytes; + NdefMap->StdMifareContainer.remainingSize -= + RemainingBytes; + *TempintBytes += ((uint8_t)RemainingBytes); + /* Remaining Bytes of length (L) in TLV */ + NdefMap->TLVStruct.BytesRemainLinTLV -= RemainingBytes; + + /* copy the bytes to internal buffer, that are read, + but not used for the user buffer */ + (void)memcpy( NdefMap->StdMifareContainer.internalBuf, + &(NdefMap->StdMifareContainer.internalBuf[RemainingBytes]), + (NdefMap->StdMifareContainer.internalLength - RemainingBytes)); + + /* internal buffer length */ + NdefMap->StdMifareContainer.internalLength -= RemainingBytes; + if(NdefMap->StdMifareContainer.internalLength == PH_FRINFC_MIFARESTD_VAL0) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = (uint8_t) + (((NdefMap->StdMifareContainer.remainingSize == PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.BytesRemainLinTLV == PH_FRINFC_MIFARESTD_VAL0))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + /* internal length bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + } + + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG0; + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + *Flag = PH_FRINFC_MIFARESTD_FLAG0; + } + else + { + if((NdefMap->TLVStruct.BytesRemainLinTLV > + NdefMap->StdMifareContainer.internalLength) && + (RemainingBytes > NdefMap->StdMifareContainer.internalLength)) + { + (void)memcpy(&(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]), + &(NdefMap->StdMifareContainer.internalBuf[(*TempintBytes)]), + NdefMap->StdMifareContainer.internalLength); + *Flag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->ApduBuffIndex += NdefMap->StdMifareContainer.internalLength; + NdefMap->StdMifareContainer.remainingSize -= + NdefMap->StdMifareContainer.internalLength; + NdefMap->TLVStruct.BytesRemainLinTLV -= NdefMap->StdMifareContainer.internalLength; + + if(NdefMap->TLVStruct.BytesRemainLinTLV != PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES0) + { + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + + NdefMap->StdMifareContainer.internalLength = PH_FRINFC_MIFARESTD_VAL0; + /* internal length bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + Result = ((NdefMap->StdMifareContainer.AuthDone == + PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_RdABlock(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + } + } + + if(CRFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = (uint8_t) + (((NdefMap->StdMifareContainer.remainingSize == PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.BytesRemainLinTLV == PH_FRINFC_MIFARESTD_VAL0))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + *NdefMap->NumOfBytesRead = NdefMap->ApduBuffIndex; + } + return Result; +} +#if 0 +static NFCSTATUS phFriNfc_MifStd_H_IntLenWithNdef(phFriNfc_NdefMap_t *NdefMap, + uint8_t *TempintBytes) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint16_t RemainingBytes = 0; + uint8_t CRFlag = PH_FRINFC_MIFARESTD_FLAG0, + RdFlag = PH_FRINFC_MIFARESTD_FLAG0, + NDEFlength = 0; + + RemainingBytes = (uint16_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + while(PH_FRINFC_MIFARESTD_FLAG1 == NdefMap->TLVStruct.NdefTLVFoundFlag) + { + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG0; + RemainingBytes = ((uint16_t)NdefMap->ApduBufferSize - + NdefMap->ApduBuffIndex); + if(((( NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + NdefMap->StdMifareContainer.NdefBlocks) * + PH_FRINFC_MIFARESTD_BLOCK_BYTES) + + (NdefMap->StdMifareContainer.internalLength - + *TempintBytes)) < + RemainingBytes) + { + /* If the user Buffer is greater than the Card Size + set LastBlockFlag = 1. This Flag is used to read bytes + till the end of the card only */ + RemainingBytes = ((( NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + NdefMap->StdMifareContainer.NdefBlocks) * 16) + + (NdefMap->StdMifareContainer.internalLength - + *TempintBytes)); + + } + + if((NdefMap->TLVStruct.TcheckedinTLVFlag != PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->TLVStruct.LcheckedinTLVFlag != PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->TLVStruct.NoLbytesinTLV != PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES0)) + { + CRFlag = 1; + break; + } + + /* if type (T) of TLV flag is not set then only the below check is valid + because, for eg. assume, type (T) of TLV flag is set then this means + that it is already checked from the previous internal bytes data (T is the + last byte of internal bytes */ + if(NdefMap->TLVStruct.TcheckedinTLVFlag != PH_FRINFC_MIFARESTD_FLAG1) + { + CRFlag =(uint8_t) ((NdefMap->StdMifareContainer.internalBuf[(*TempintBytes)]!= + PH_FRINFC_MIFARESTD_NDEFTLV_T)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + if(CRFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + RdFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + /* skip Type T of the TLV */ + *TempintBytes += PH_FRINFC_MIFARESTD_INC_1; + } + else + { + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + + if(*TempintBytes == NdefMap->StdMifareContainer.internalLength) + { + NdefMap->StdMifareContainer.internalLength = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG1; + /* 16 bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + Result = + ((NdefMap->StdMifareContainer.AuthDone == PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_RdABlock(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + break; + } + + /* skip number of bytes taken by L in TLV, if L is already read */ + if(NdefMap->TLVStruct.LcheckedinTLVFlag != PH_FRINFC_MIFARESTD_FLAG1) + { + CRFlag = (uint8_t)((NdefMap->StdMifareContainer.internalBuf[(*TempintBytes)]== + PH_FRINFC_MIFARESTD_NDEFTLV_L0)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + if(CRFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + RdFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + NDEFlength = *TempintBytes; + *TempintBytes += phFriNfc_MifStd_H_ChkNdefLen(NdefMap, + NDEFlength, + &CRFlag); + if(CRFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + RdFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + } + else + { + NdefMap->TLVStruct.LcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + + if(*TempintBytes == NdefMap->StdMifareContainer.internalLength) + { + NdefMap->StdMifareContainer.internalLength = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG1; + /* 16 bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + Result = ((NdefMap->StdMifareContainer.AuthDone == + PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_RdABlock(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + break; + } + + if( (NdefMap->TLVStruct.BytesRemainLinTLV <= + (NdefMap->StdMifareContainer.internalLength - *TempintBytes)) && + (RemainingBytes <= NdefMap->TLVStruct.BytesRemainLinTLV)) + { + /* Copy the internal bytes to the user buffer */ + (void)memcpy(&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + &(NdefMap->StdMifareContainer.internalBuf[ + (*TempintBytes)]), + RemainingBytes); + + NdefMap->ApduBuffIndex += RemainingBytes; + *TempintBytes += ((uint8_t)RemainingBytes); + NdefMap->TLVStruct.BytesRemainLinTLV -= RemainingBytes; + if(NdefMap->TLVStruct.BytesRemainLinTLV == 0) + { + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + /* Update the internal length */ + (void)memcpy( NdefMap->StdMifareContainer.internalBuf, + &(NdefMap->StdMifareContainer.internalBuf[ + (*TempintBytes)]), + RemainingBytes); + NdefMap->StdMifareContainer.internalLength -= (*TempintBytes + + RemainingBytes); + + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + else if((NdefMap->TLVStruct.BytesRemainLinTLV <= + (NdefMap->StdMifareContainer.internalLength - *TempintBytes)) && + (RemainingBytes > NdefMap->TLVStruct.BytesRemainLinTLV)) + { + /* Copy data to user buffer */ + (void)memcpy(&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + &(NdefMap->StdMifareContainer.internalBuf[ + (*TempintBytes)]), + NdefMap->TLVStruct.BytesRemainLinTLV); + + /* increment the user buffer index */ + NdefMap->ApduBuffIndex += NdefMap->TLVStruct.BytesRemainLinTLV; + *TempintBytes += ((uint8_t)NdefMap->TLVStruct.BytesRemainLinTLV); + NdefMap->TLVStruct.BytesRemainLinTLV = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG1; + + /* check for internal length bytes of data been used */ + if(*TempintBytes == NdefMap->StdMifareContainer.internalLength) + { + /* 16 bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + Result = ((NdefMap->StdMifareContainer.AuthDone == + PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_RdABlock(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + break; + } + } + else if((NdefMap->TLVStruct.BytesRemainLinTLV > + (NdefMap->StdMifareContainer.internalLength - *TempintBytes)) && + (RemainingBytes <= (NdefMap->StdMifareContainer.internalLength - + *TempintBytes))) + { + /* Copy data to user buffer */ + (void)memcpy(&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + &(NdefMap->StdMifareContainer.internalBuf[ + (*TempintBytes)]), + RemainingBytes); + NdefMap->ApduBuffIndex += RemainingBytes; + *TempintBytes += ((uint8_t)RemainingBytes); + NdefMap->TLVStruct.BytesRemainLinTLV -= RemainingBytes; + + /* copy the bytes to internal buffer, that are read, + but not used for the user buffer */ + (void)memcpy(NdefMap->StdMifareContainer.internalBuf, + &(NdefMap->StdMifareContainer.internalBuf[(*TempintBytes)]), + (NdefMap->StdMifareContainer.internalLength - *TempintBytes)); + + /* Length of the internal buffer */ + NdefMap->StdMifareContainer.internalLength -= *TempintBytes; + CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + else + { + if((NdefMap->TLVStruct.BytesRemainLinTLV > + (NdefMap->StdMifareContainer.internalLength - *TempintBytes)) && + (RemainingBytes > (NdefMap->StdMifareContainer.internalLength - + *TempintBytes))) + { + /* Copy data to user buffer */ + (void)memcpy(&(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + &(NdefMap->StdMifareContainer.internalBuf[ + (*TempintBytes)]), + (NdefMap->StdMifareContainer.internalLength - + *TempintBytes)); + NdefMap->ApduBuffIndex += (NdefMap->StdMifareContainer.internalLength - + *TempintBytes); + NdefMap->TLVStruct.BytesRemainLinTLV -= + (NdefMap->StdMifareContainer.internalLength - *TempintBytes); + *TempintBytes += (uint8_t)(NdefMap->StdMifareContainer.internalLength - + *TempintBytes); + + NdefMap->StdMifareContainer.internalLength -= *TempintBytes; + + /* 16 bytes completed */ + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + Result = ((NdefMap->StdMifareContainer.AuthDone == + PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_RdABlock(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + break; + } + } + } + + if(((( NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + NdefMap->StdMifareContainer.NdefBlocks) * + PH_FRINFC_MIFARESTD_BLOCK_BYTES) + + NdefMap->StdMifareContainer.internalLength) == + PH_FRINFC_MIFARESTD_VAL0) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + } + + if(CRFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + Result = (((RdFlag == PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->ApduBuffIndex == PH_FRINFC_MIFARESTD_VAL0))? + (PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED)): + Result); + + *NdefMap->NumOfBytesRead = NdefMap->ApduBuffIndex; + } + + return Result; +} +#endif + +static NFCSTATUS phFriNfc_MifStd_H_WriteNdefLen(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_WR_NDEF_LEN; + + /* If Current block = Ndef TLV block then the starting point + is writing from type of TLV + Else */ + + if(NdefMap->StdMifareContainer.currentBlock == + NdefMap->TLVStruct.NdefTLVBlock) + { + + if(NdefMap->TLVStruct.NULLTLVCount >= + PH_FRINFC_MIFARESTD_VAL2) + { + phFriNfc_MifStd_H_fillTLV1(NdefMap); + } + else + { + phFriNfc_MifStd_H_fillTLV2(NdefMap); + } + } + else + { + if(NdefMap->TLVStruct.NULLTLVCount >= + PH_FRINFC_MIFARESTD_VAL2) + { + phFriNfc_MifStd_H_fillTLV1_1(NdefMap); + } + else + { + phFriNfc_MifStd_H_fillTLV2_1(NdefMap); + } + } + + (void)memcpy( NdefMap->StdMifareContainer.Buffer, + &(NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL1]), + PH_FRINFC_MIFARESTD_BYTES_READ); + + + /* Write from here */ + NdefMap->SendLength = MIFARE_MAX_SEND_BUF_TO_WRITE; + +#ifndef PH_HAL4_ENABLE + NdefMap->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite16; +#else + NdefMap->Cmd.MfCmd = phHal_eMifareWrite16; +#endif + + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + /* Call the Overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + + return Result; +} +#if 0 +static NFCSTATUS phFriNfc_MifStd_H_ChkNdefCmpltBlocks(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + /* If NoOfNdefCompBlocks is found to be zero, + should we warn the user */ + if((NdefMap->StdMifareContainer.NoOfNdefCompBlocks != + PH_FRINFC_MIFARESTD_VAL0) && + (NdefMap->StdMifareContainer.NoOfNdefCompBlocks <= + PH_FRINFC_MIFARESTD4K_MAX_BLOCKS)) + { + /* Reading/writing to the card can start only + from the block 4 */ + NdefMap->StdMifareContainer.currentBlock = 4; + NdefMap->StdMifareContainer.AuthDone = PH_FRINFC_MIFARESTD_FLAG0; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if((Result == NFCSTATUS_SUCCESS) && + (NdefMap->StdMifareContainer.AuthDone == + PH_FRINFC_MIFARESTD_FLAG1)) + { + NdefMap->StdMifareContainer.ReadAcsBitFlag = 0; + Result = phFriNfc_MifStd_H_RdAcsBit(NdefMap); + } + else + { + Result = phFriNfc_MifStd_H_AuthSector(NdefMap); + } + } + return Result; +} +#endif + +static void phFriNfc_MifStd_H_RdWrReset(phFriNfc_NdefMap_t *NdefMap) +{ + NdefMap->StdMifareContainer.currentBlock = PH_FRINFC_MIFARESTD_BLK4; + NdefMap->StdMifareContainer.NdefBlocks = PH_FRINFC_MIFARESTD_VAL1; + NdefMap->TLVStruct.BytesRemainLinTLV = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.LcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.NdefTLVAuthFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_MIFARESTD_MAD_BLK0; + NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.NoLbytesinTLV = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->StdMifareContainer.internalLength = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->StdMifareContainer.AuthDone = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.NFCforumSectFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.FirstReadFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.remainingSize = (uint16_t) + (NdefMap->StdMifareContainer.NoOfNdefCompBlocks * + PH_FRINFC_MIFARESTD_BLOCK_BYTES); + NdefMap->StdMifareContainer.WrLength = PH_FRINFC_MIFARESTD_VAL1; + +} + +static NFCSTATUS phFriNfc_MifStd_H_RdtoWrNdefLen(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RD_TO_WR_NDEF_LEN; + + if(NdefMap->TLVStruct.NdefTLVAuthFlag == PH_FRINFC_MIFARESTD_FLAG1) + { + NdefMap->StdMifareContainer.AuthDone = PH_FRINFC_MIFARESTD_FLAG0; + Result = phFriNfc_MifStd_H_AuthSector(NdefMap); + } + else + { + NdefMap->SendRecvBuf[0] = NdefMap->StdMifareContainer.currentBlock; + NdefMap->SendLength = MIFARE_MAX_SEND_BUF_TO_READ; + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + +#ifndef PH_HAL4_ENABLE + NdefMap->Cmd.MfCmd = phHal_eMifareCmdListMifareRead; +#else + NdefMap->Cmd.MfCmd = phHal_eMifareRead; +#endif + /* Call the Overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + } + + return Result; +} + +static void phFriNfc_MifStd_H_SetNdefBlkAuth(phFriNfc_NdefMap_t *NdefMap) +{ + NdefMap->TLVStruct.NdefTLVAuthFlag = + ((phFriNfc_MifStd_H_GetSect(NdefMap->TLVStruct.NdefTLVBlock) + == phFriNfc_MifStd_H_GetSect(NdefMap->StdMifareContainer.currentBlock))? + PH_FRINFC_MIFARESTD_FLAG0: + PH_FRINFC_MIFARESTD_FLAG1); +} + +static NFCSTATUS phFriNfc_MifStd_H_GetActCardLen(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_GET_ACT_CARDSIZE; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_GET_ACTSIZE_OPE; + + Result = ((NdefMap->StdMifareContainer.AuthDone == + PH_FRINFC_MIFARESTD_FLAG0)? + phFriNfc_MifStd_H_AuthSector(NdefMap): + phFriNfc_MifStd_H_Rd16Bytes(NdefMap, + NdefMap->StdMifareContainer.currentBlock)); + + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_ChkTLVs(phFriNfc_NdefMap_t *NdefMap, + uint8_t *CRFlag) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint16_t TempLength = PH_FRINFC_MIFARESTD_VAL0, + ShiftLength = PH_FRINFC_MIFARESTD_VAL0; + uint8_t TL4bytesFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_GET_ACTSIZE_OPE; + TempLength = NdefMap->TLVStruct.NdefTLVByte; + for(;;) + { +#ifdef PH_HAL4_ENABLE + if((NdefMap->SendRecvBuf[TempLength] != PH_FRINFC_MIFARESTD_TERMTLV_T) && + (NdefMap->SendRecvBuf[TempLength] != PH_FRINFC_MIFARESTD_NULLTLV_T) && + (NdefMap->SendRecvBuf[TempLength] != PH_FRINFC_MIFARESTD_NDEFTLV_T) && + (FALSE == NdefMap->TLVStruct.NdefTLVFoundFlag)) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + NdefMap->TLVStruct.BytesRemainLinTLV = 0; + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + + } + else +#endif /* #ifdef PH_HAL4_ENABLE */ + if((NdefMap->SendRecvBuf[TempLength] != PH_FRINFC_MIFARESTD_TERMTLV_T) && + (NdefMap->SendRecvBuf[TempLength] != PH_FRINFC_MIFARESTD_NULLTLV_T)) + { + if(NdefMap->SendRecvBuf[TempLength] == PH_FRINFC_MIFARESTD_NDEFTLV_T) + { + NdefMap->TLVStruct.NdefTLVBlock = + NdefMap->StdMifareContainer.currentBlock; + NdefMap->TLVStruct.NdefTLVByte = (uint8_t)TempLength; + NdefMap->TLVStruct.NdefTLVFoundFlag = + ((NdefMap->SendRecvBuf[TempLength] == + PH_FRINFC_MIFARESTD_NDEFTLV_T)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + NdefMap->TLVStruct.NULLTLVCount = ((NdefMap->TLVStruct.NULLTLVCount + == PH_FRINFC_MIFARESTD_VAL1)? + PH_FRINFC_MIFARESTD_VAL0: + NdefMap->TLVStruct.NULLTLVCount); + } + else + { + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL0; + } + + TempLength++; + if(TempLength == PH_FRINFC_MIFARESTD_BYTES_READ) + { + NdefMap->TLVStruct.TcheckedinTLVFlag = + PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.NoLbytesinTLV = + PH_FRINFC_MIFARESTD_VAL3; + } + Result = phFriNfc_MifStd_H_Chk16Bytes( NdefMap, + TempLength); + if(Result != NFCSTATUS_SUCCESS) + { + *CRFlag = (uint8_t)((Result == NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG0: + PH_FRINFC_MIFARESTD_FLAG1); + break; + } + + if((((( NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + NdefMap->StdMifareContainer.NdefBlocks) * + PH_FRINFC_MIFARESTD_BLOCK_BYTES) + + (PH_FRINFC_MIFARESTD_BLOCK_BYTES - + TempLength)) < + NdefMap->SendRecvBuf[TempLength]) && + ((NdefMap->SendRecvBuf[TempLength] < + PH_FRINFC_MIFARESTD_NDEFTLV_L) && + (NdefMap->TLVStruct.NdefTLVFoundFlag != + PH_FRINFC_MIFARESTD_VAL1))) + { + /* Result = Error */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + + if((((( NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + NdefMap->StdMifareContainer.NdefBlocks) * + PH_FRINFC_MIFARESTD_BLOCK_BYTES) + + (PH_FRINFC_MIFARESTD_BLOCK_BYTES - + TempLength)) < + NdefMap->SendRecvBuf[TempLength]) && + ((NdefMap->SendRecvBuf[TempLength] == + PH_FRINFC_MIFARESTD_VAL0) && + (NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_MIFARESTD_VAL1))) + { + /* Result = Error */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + + if((NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->SendRecvBuf[TempLength] < + PH_FRINFC_MIFARESTD_NDEFTLV_L)) + { + Result = phFriNfc_MapTool_SetCardState(NdefMap, + NdefMap->SendRecvBuf[TempLength]); + NdefMap->TLVStruct.BytesRemainLinTLV = + NdefMap->SendRecvBuf[TempLength]; + NdefMap->StdMifareContainer.remainingSize -= + PH_FRINFC_MIFARESTD_VAL2; + /* This flag is set */ + NdefMap->StdMifareContainer.remSizeUpdFlag = + (uint8_t)((NdefMap->TLVStruct.NULLTLVCount >= + PH_FRINFC_MIFARESTD_VAL2)? + PH_FRINFC_MIFARESTD_FLAG0: + PH_FRINFC_MIFARESTD_FLAG1); + + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + + NdefMap->StdMifareContainer.remainingSize -= + (( NdefMap->SendRecvBuf[TempLength] < + PH_FRINFC_MIFARESTD_NDEFTLV_L)? + (NdefMap->SendRecvBuf[TempLength] + + PH_FRINFC_MIFARESTD_VAL2): + PH_FRINFC_MIFARESTD_VAL0); + + if (NdefMap->SendRecvBuf[TempLength] == + PH_FRINFC_MIFARESTD_VAL0) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + + TL4bytesFlag = PH_FRINFC_MIFARESTD_FLAG0; + /* get the next TLV after the proprietary TLV */ + Result = + ((NdefMap->SendRecvBuf[TempLength] < + PH_FRINFC_MIFARESTD_NDEFTLV_L)? + phFriNfc_MifStd_H_GetNxtTLV(NdefMap, &TempLength, &TL4bytesFlag): + NFCSTATUS_PENDING); + + if((TempLength >= PH_FRINFC_MIFARESTD_BYTES_READ) && + (Result == NFCSTATUS_SUCCESS)) + { + NdefMap->TLVStruct.TcheckedinTLVFlag = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.NoLbytesinTLV = + PH_FRINFC_MIFARESTD_VAL0; + + Result = phFriNfc_MifStd_H_GetActCardLen(NdefMap); + *CRFlag = (uint8_t)((Result != NFCSTATUS_PENDING)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + break; + } + else + { + if(Result == NFCSTATUS_PENDING) + { + TL4bytesFlag = PH_FRINFC_MIFARESTD_FLAG1; + Result = ((NdefMap->SendRecvBuf[TempLength] == + PH_FRINFC_MIFARESTD_NDEFTLV_L) ? + NFCSTATUS_SUCCESS: + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER))); + + if(Result != NFCSTATUS_SUCCESS) + { + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL0; + TempLength++; + /* Check 0xFF */ + if(TempLength == PH_FRINFC_MIFARESTD_BYTES_READ) + { + NdefMap->TLVStruct.TcheckedinTLVFlag = + PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.NoLbytesinTLV = + PH_FRINFC_MIFARESTD_VAL2; + } + Result = phFriNfc_MifStd_H_Chk16Bytes( NdefMap, + TempLength); + if(Result != NFCSTATUS_SUCCESS) + { + break; + } + + ShiftLength = NdefMap->SendRecvBuf[TempLength]; + TempLength++; + if(TempLength == PH_FRINFC_MIFARESTD_BYTES_READ) + { + NdefMap->TLVStruct.TcheckedinTLVFlag = + PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->TLVStruct.NoLbytesinTLV = + PH_FRINFC_MIFARESTD_VAL1; + NdefMap->TLVStruct.prevLenByteValue = + NdefMap->SendRecvBuf[(TempLength - + PH_FRINFC_MIFARESTD_VAL1)]; + } + Result = phFriNfc_MifStd_H_Chk16Bytes( NdefMap, + TempLength); + if(Result != NFCSTATUS_SUCCESS) + { + break; + } + + + if(((( NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + NdefMap->StdMifareContainer.NdefBlocks) * + PH_FRINFC_MIFARESTD_BLOCK_BYTES) + + (PH_FRINFC_MIFARESTD_BLOCK_BYTES - + TempLength)) < + (( ShiftLength + << 8) + NdefMap->SendRecvBuf[TempLength])) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + + break; + } + + if(NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + ShiftLength = (( ShiftLength<< 8) + + NdefMap->SendRecvBuf[TempLength]); + NdefMap->TLVStruct.BytesRemainLinTLV = ShiftLength; + Result = phFriNfc_MapTool_SetCardState(NdefMap, + ShiftLength); + NdefMap->StdMifareContainer.remainingSize -= + PH_FRINFC_MIFARESTD_VAL4; + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + break; + } + + NdefMap->StdMifareContainer.remainingSize -= + ((ShiftLength<< 8) + + NdefMap->SendRecvBuf[(TempLength + PH_FRINFC_MIFARESTD_VAL1)]); + TempLength++; + + /* get the next TLV after the proprietary TLV */ + Result = phFriNfc_MifStd_H_GetNxtTLV(NdefMap, &TempLength, &TL4bytesFlag); + + if((TempLength >= PH_FRINFC_MIFARESTD_BYTES_READ) && + (Result == NFCSTATUS_SUCCESS)) + { + NdefMap->TLVStruct.TcheckedinTLVFlag = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->TLVStruct.NoLbytesinTLV = + PH_FRINFC_MIFARESTD_VAL0; + Result = phFriNfc_MifStd_H_GetActCardLen(NdefMap); + + break; + } + break; + } + } + } + else if((NdefMap->SendRecvBuf[TempLength] == PH_FRINFC_MIFARESTD_TERMTLV_T) && + (NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_MIFARESTD_FLAG0)) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + break; + + } + else if(NdefMap->SendRecvBuf[TempLength] == PH_FRINFC_MIFARESTD_NULLTLV_T) + { + TempLength++; + NdefMap->TLVStruct.NULLTLVCount += PH_FRINFC_MIFARESTD_VAL1; + ShiftLength = NdefMap->SendRecvBuf[(TempLength - PH_FRINFC_MIFARESTD_VAL1)]; + NdefMap->StdMifareContainer.remainingSize -= PH_FRINFC_MIFARESTD_VAL1; + if(NdefMap->StdMifareContainer.remainingSize < + (( ShiftLength << 8) + NdefMap->SendRecvBuf[TempLength])) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + break; + } + Result = phFriNfc_MifStd_H_Chk16Bytes( NdefMap, + TempLength); + if(Result != NFCSTATUS_SUCCESS) + { + NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_MIFARESTD_VAL0; + break; + } + } + else + { + if((NdefMap->SendRecvBuf[TempLength] == PH_FRINFC_MIFARESTD_TERMTLV_T) && + (NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_MIFARESTD_FLAG1)) + { + TempLength++; + Result = NFCSTATUS_SUCCESS; + NdefMap->StdMifareContainer.remainingSize -= + PH_FRINFC_MIFARESTD_VAL1; + } + } + } + + if(NdefMap->TLVStruct.BytesRemainLinTLV > + NdefMap->StdMifareContainer.remainingSize) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT); + } + else + { + if(NdefMap->StdMifareContainer.remainingSize == + PH_FRINFC_MIFARESTD_VAL0) + { + Result = ((NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + NFCSTATUS_SUCCESS: + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER))); + } + } + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_GetNxtTLV(phFriNfc_NdefMap_t *NdefMap, + uint16_t *TempLength, + uint8_t *TL4bytesFlag) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint16_t LengthRemaining = PH_FRINFC_MIFARESTD_VAL0, + TempLen = PH_FRINFC_MIFARESTD_VAL0, + ShiftLength = PH_FRINFC_MIFARESTD_VAL0; + + TempLen = (*TempLength); + LengthRemaining = (PH_FRINFC_MIFARESTD_BYTES_READ - + (TempLen + PH_FRINFC_MIFARESTD_VAL1)); + + if(*TL4bytesFlag == PH_FRINFC_MIFARESTD_FLAG0) + { + (*TempLength) += (NdefMap->SendRecvBuf[TempLen] + + PH_FRINFC_MIFARESTD_VAL1); + + if(NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_MIFARESTD_FLAG0) + { + LengthRemaining = + (((*TempLength) < PH_FRINFC_MIFARESTD_BYTES_READ)? + PH_FRINFC_MIFARESTD_VAL0: + (NdefMap->SendRecvBuf[TempLen] - + LengthRemaining)); + } + else + { + LengthRemaining = + (((*TempLength) < PH_FRINFC_MIFARESTD_BYTES_READ)? + PH_FRINFC_MIFARESTD_VAL0: + (NdefMap->SendRecvBuf[TempLen] - + LengthRemaining)); + } + } + else + { + *TL4bytesFlag = PH_FRINFC_MIFARESTD_FLAG0; + if(NdefMap->TLVStruct.NoLbytesinTLV == + PH_FRINFC_MIFARESTD_VAL1) + { + ShiftLength = NdefMap->TLVStruct.prevLenByteValue; + (*TempLength) += ((ShiftLength + << 8) + NdefMap->SendRecvBuf[TempLen] + + PH_FRINFC_MIFARESTD_VAL1); + + LengthRemaining = + (((ShiftLength + << 8) + NdefMap->SendRecvBuf[TempLen]) - + LengthRemaining); + } + else + { + ShiftLength = NdefMap->SendRecvBuf[(TempLen - PH_FRINFC_MIFARESTD_VAL1)]; + (*TempLength) += ((ShiftLength + << 8) + NdefMap->SendRecvBuf[TempLen] + + PH_FRINFC_MIFARESTD_VAL1); + + LengthRemaining = + (((ShiftLength + << 8) + NdefMap->SendRecvBuf[TempLen]) - + LengthRemaining); + } + } + + NdefMap->TLVStruct.NdefTLVByte = + (uint8_t)(((*TempLength) < PH_FRINFC_MIFARESTD_BYTES_READ)? + (*TempLength): + (LengthRemaining % PH_FRINFC_MIFARESTD_BYTES_READ)); + + while(LengthRemaining != PH_FRINFC_MIFARESTD_VAL0) + { + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + LengthRemaining -= + ((LengthRemaining <= PH_FRINFC_MIFARESTD_BYTES_READ)? + LengthRemaining: + PH_FRINFC_MIFARESTD_BYTES_READ); + } + + if(NdefMap->TLVStruct.NdefTLVByte == PH_FRINFC_MIFARESTD_VAL0) + { + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + } + + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_Chk16Bytes(phFriNfc_NdefMap_t *NdefMap, + uint16_t TempLength) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + if(TempLength == PH_FRINFC_MIFARESTD_BYTES_READ) + { + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + + Result = + ((NdefMap->StdMifareContainer.AuthDone == PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_GetActCardLen(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_ChkRemainTLVs(phFriNfc_NdefMap_t *NdefMap, + uint8_t *CRFlag, + uint8_t *NDEFFlag) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint16_t TempLength = PH_FRINFC_MIFARESTD_VAL0, + ShiftLength = PH_FRINFC_MIFARESTD_VAL0; + uint8_t TL4bytesFlag = PH_FRINFC_MIFARESTD_FLAG0; + + switch(NdefMap->TLVStruct.NoLbytesinTLV) + { + case PH_FRINFC_MIFARESTD_VAL3: + /* if TLV is found then set card state */ + Result = ((NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MapTool_SetCardState(NdefMap, + NdefMap->SendRecvBuf[TempLength]): + Result); + + /* Check the length field is less than or + equal to 0xFF if yes enter below statement + else enter else if*/ + if((NdefMap->SendRecvBuf[TempLength] < + PH_FRINFC_MIFARESTD_NDEFTLV_L) && + (Result == NFCSTATUS_SUCCESS)) + { + NdefMap->StdMifareContainer.remainingSize -= + PH_FRINFC_MIFARESTD_VAL2; + + Result = ((NdefMap->SendRecvBuf[TempLength] > + NdefMap->StdMifareContainer.remainingSize)? + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT)): + Result); + TL4bytesFlag = PH_FRINFC_MIFARESTD_FLAG0; + if((NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_MIFARESTD_FLAG1) && + (Result == NFCSTATUS_SUCCESS)) + { + NdefMap->TLVStruct.BytesRemainLinTLV = + NdefMap->SendRecvBuf[TempLength]; + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + + } + else if(Result == NFCSTATUS_SUCCESS) + { + TempLength++; + Result = phFriNfc_MifStd_H_GetNxtTLV(NdefMap, + &TempLength, &TL4bytesFlag); + + NdefMap->StdMifareContainer.remainingSize -= + NdefMap->SendRecvBuf[TempLength]; + if((TempLength >= PH_FRINFC_MIFARESTD_BYTES_READ) && + (*CRFlag == PH_FRINFC_MIFARESTD_FLAG0)) + { + *NDEFFlag = PH_FRINFC_MIFARESTD_FLAG0; + Result = phFriNfc_MifStd_H_GetActCardLen(NdefMap); + } + } + + else + { + /* do nothing */ + } + } + else if((NdefMap->SendRecvBuf[TempLength] == + PH_FRINFC_MIFARESTD_NDEFTLV_L) && + (Result == NFCSTATUS_SUCCESS)) + { + TempLength++; + NdefMap->StdMifareContainer.remainingSize -= + PH_FRINFC_MIFARESTD_VAL4; + TL4bytesFlag = PH_FRINFC_MIFARESTD_FLAG0; + Result = (((((uint16_t)NdefMap->SendRecvBuf[TempLength] << 8) + + NdefMap->SendRecvBuf[(TempLength + + PH_FRINFC_MIFARESTD_VAL1)]) > + NdefMap->StdMifareContainer.remainingSize)? + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT)): + Result); + if((NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_MIFARESTD_FLAG1) && + (Result == NFCSTATUS_SUCCESS)) + { + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.BytesRemainLinTLV = + (((uint16_t)NdefMap->SendRecvBuf[TempLength] << 8) + + NdefMap->SendRecvBuf[(TempLength + + PH_FRINFC_MIFARESTD_VAL1)]); + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + else if(Result == NFCSTATUS_SUCCESS) + { + TempLength++; + + Result = phFriNfc_MifStd_H_GetNxtTLV(NdefMap, + &TempLength, &TL4bytesFlag); + NdefMap->StdMifareContainer.remainingSize -= + (((uint16_t)NdefMap->SendRecvBuf[TempLength] << 8) + + NdefMap->SendRecvBuf[(TempLength + + PH_FRINFC_MIFARESTD_VAL1)]); + + *NDEFFlag = PH_FRINFC_MIFARESTD_FLAG0; + Result = phFriNfc_MifStd_H_GetActCardLen(NdefMap); + } + else + { + /* do nothing */ + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + } + else + { + /* Result = Error */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT); + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + break; + + case PH_FRINFC_MIFARESTD_VAL2: + case PH_FRINFC_MIFARESTD_VAL1: + ShiftLength = ((NdefMap->TLVStruct.NoLbytesinTLV == + PH_FRINFC_MIFARESTD_VAL1)? + ((NdefMap->TLVStruct.prevLenByteValue << 8) + + NdefMap->SendRecvBuf[TempLength]): + (((uint16_t)NdefMap->SendRecvBuf[TempLength] << 8) + + NdefMap->SendRecvBuf[(TempLength + + PH_FRINFC_MIFARESTD_VAL1)])); + if(((( NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + NdefMap->StdMifareContainer.NdefBlocks) * + PH_FRINFC_MIFARESTD_BLOCK_BYTES) + + (PH_FRINFC_MIFARESTD_BLOCK_BYTES - + TempLength)) < + ShiftLength) + { + /* Result = Error */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + else + { + NdefMap->StdMifareContainer.remainingSize -= + PH_FRINFC_MIFARESTD_VAL2; + if(NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + NdefMap->TLVStruct.BytesRemainLinTLV = ShiftLength; + if(NdefMap->TLVStruct.BytesRemainLinTLV > + NdefMap->StdMifareContainer.remainingSize) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT); + } + *CRFlag = PH_FRINFC_MIFARESTD_FLAG1; + *NDEFFlag = PH_FRINFC_MIFARESTD_FLAG0; + } + else + { + NdefMap->StdMifareContainer.remainingSize -= + ShiftLength; + *CRFlag = PH_FRINFC_MIFARESTD_FLAG0; + TempLength += PH_FRINFC_MIFARESTD_VAL2; + TL4bytesFlag = PH_FRINFC_MIFARESTD_FLAG1; + Result = ((NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_MIFARESTD_FLAG1)? + NFCSTATUS_SUCCESS: + phFriNfc_MifStd_H_GetNxtTLV(NdefMap, &TempLength, &TL4bytesFlag)); + + *NDEFFlag = PH_FRINFC_MIFARESTD_FLAG0; + Result = phFriNfc_MifStd_H_GetActCardLen(NdefMap); + } + } + break; + + default: + break; + } + return Result; +} + +static void phFriNfc_MifStd_H_Get1kStTrail(phFriNfc_NdefMap_t *NdefMap) +{ + switch((NdefMap->StdMifareContainer.currentBlock % 4)) + { + case PH_FRINFC_MIFARESTD_VAL0: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_MAD_BLK3); + break; + + case PH_FRINFC_MIFARESTD_VAL1: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_MAD_BLK2); + break; + + case PH_FRINFC_MIFARESTD_VAL2: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_MAD_BLK1); + break; + + default: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + NdefMap->StdMifareContainer.currentBlock; + break; + } +} + +static void phFriNfc_MifStd_H_Get4kStTrail(phFriNfc_NdefMap_t *NdefMap) +{ + switch((NdefMap->StdMifareContainer.currentBlock % 16)) + { + case PH_FRINFC_MIFARESTD_MAD_BLK0: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK15); + break; + + case PH_FRINFC_MIFARESTD_MAD_BLK1: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK14); + break; + + case PH_FRINFC_MIFARESTD_MAD_BLK2: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK13); + break; + + case PH_FRINFC_MIFARESTD_MAD_BLK3: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK12); + break; + + case PH_FRINFC_MIFARESTD_BLK4: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK11); + break; + + case PH_FRINFC_MIFARESTD_BLK5: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK10); + break; + + case PH_FRINFC_MIFARESTD_BLK6: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK9); + break; + + case PH_FRINFC_MIFARESTD_BLK7: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK8); + break; + + case PH_FRINFC_MIFARESTD_BLK8: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK7); + break; + + case PH_FRINFC_MIFARESTD_BLK9: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK6); + break; + + case PH_FRINFC_MIFARESTD_BLK10: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK5); + break; + + case PH_FRINFC_MIFARESTD_BLK11: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK4); + break; + + case PH_FRINFC_MIFARESTD_BLK12: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_MAD_BLK3); + break; + + case PH_FRINFC_MIFARESTD_BLK13: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_MAD_BLK2); + break; + + case PH_FRINFC_MIFARESTD_BLK14: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + (NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_MAD_BLK1); + break; + + default: + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + NdefMap->StdMifareContainer.currentBlock; + break; + } +} + +static NFCSTATUS phFriNfc_MifStd_H_ProChkNdef(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + /* Copy remaining bytes into the AID array + from Receive Buffer till array number 7 in aid */ + if(NdefMap->StdMifareContainer.currentBlock == + PH_FRINFC_MIFARESTD_VAL1) + { + /* Helper Function to Store AID Information */ + phFriNfc_MifStd_H_fillAIDarray(NdefMap); + + NdefMap->StdMifareContainer.currentBlock = PH_FRINFC_MIFARESTD_VAL2; + /* read remaining AIDs from block number 2 */ + Result = ((NdefMap->StdMifareContainer.aidCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + Result: + phFriNfc_MifareStdMap_ChkNdef( NdefMap)); + } + else if(((NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD) && + (NdefMap->StdMifareContainer.currentBlock == + PH_FRINFC_MIFARESTD_MAD_BLK2)) || ( + (NdefMap->StdMifareContainer.currentBlock == + PH_FRINFC_MIFARESTD_MAD_BLK66) && + (NdefMap->CardType == + PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD))) + { + /* Helper Function to Store AID Information */ + phFriNfc_MifStd_H_fillAIDarray(NdefMap); + + NdefMap->StdMifareContainer.aidCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + }/* Mifare 1k and Mifare 4k end Check */ + else if((NdefMap->StdMifareContainer.currentBlock > + PH_FRINFC_MIFARESTD_VAL1) && + (NdefMap->CardType == + PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD)) + { + phFriNfc_MifStd_H_fillAIDarray(NdefMap); + /* read remaining AIDs from block number 2 */ + /* Mifare 4k Helper Function */ + Result = ((NdefMap->StdMifareContainer.aidCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + Result: + phFriNfc_MifStd4k_H_CheckNdef(NdefMap)); + } /* Card Type 4k Check */ + else + { + /* Since we have decided temporarily not to go + for any new error codes we are using + NFCSTATUS_INVALID_PARAMETER even though it is not + the relevant error code here TBD */ + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + } + + if(NdefMap->StdMifareContainer.aidCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + NdefMap->StdMifareContainer.ChkNdefCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + /* The check for NDEF compliant information is now over for + the Mifare 1K card. + Update(decrement) the NoOfNdefCompBlocks as much required, + depending on the NDEF compliant information found */ + /* Check the Sectors are Ndef Compliant */ + phFriNfc_MifStd_H_ChkNdefCmpltSects(NdefMap); + if((NdefMap->StdMifareContainer.NoOfNdefCompBlocks == 0) || + (NdefMap->StdMifareContainer.NoOfNdefCompBlocks > 255)) + { + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + NdefMap->StdMifareContainer.aidCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.NFCforumSectFlag = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.currentBlock = PH_FRINFC_MIFARESTD_BLK4; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + Result = ((Result != NFCSTATUS_SUCCESS)? + Result:phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + + } + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_ProAuth(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + if(NdefMap->TLVStruct.NdefTLVAuthFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + NdefMap->TLVStruct.NdefTLVAuthFlag = + PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.AuthDone = PH_FRINFC_MIFARESTD_FLAG1; + Result = phFriNfc_MifStd_H_RdtoWrNdefLen(NdefMap); + } + else + { + NdefMap->StdMifareContainer.AuthDone = 1; + NdefMap->StdMifareContainer.ReadAcsBitFlag = 1; + Result = phFriNfc_MifStd_H_RdAcsBit(NdefMap); + } + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_Rd16Bytes(phFriNfc_NdefMap_t *NdefMap, + uint8_t BlockNo) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = BlockNo; + NdefMap->SendLength = MIFARE_MAX_SEND_BUF_TO_READ; + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; +#ifndef PH_HAL4_ENABLE + NdefMap->Cmd.MfCmd = phHal_eMifareCmdListMifareRead; +#else + NdefMap->Cmd.MfCmd = phHal_eMifareRead; +#endif + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_MifareStdMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + /* Call the Overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_ProAcsBits(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t CRFlag = PH_FRINFC_MIFARESTD_FLAG0; + if(*NdefMap->SendRecvLength == PH_FRINFC_MIFARESTD_BYTES_READ) + { + if(NdefMap->StdMifareContainer.ReadAcsBitFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + /* check for the correct access bits */ + Result = phFriNfc_MifStd_H_ChkAcsBit(NdefMap); + + if((NdefMap->StdMifareContainer.ChkNdefFlag == + PH_FRINFC_MIFARESTD_FLAG1) && + (Result == NFCSTATUS_SUCCESS)) + { + if(NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INVALID) + { + NdefMap->StdMifareContainer.NoOfNdefCompBlocks = + ((NdefMap->StdMifareContainer.currentBlock >= + PH_FRINFC_MIFARESTD4K_BLK128)? + (NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + PH_FRINFC_MIFARESTD_BLK15): + (NdefMap->StdMifareContainer.NoOfNdefCompBlocks - + PH_FRINFC_MIFARESTD_MAD_BLK3)); + + NdefMap->StdMifareContainer.ProprforumSectFlag = + ((NdefMap->StdMifareContainer.NFCforumSectFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + PH_FRINFC_MIFARESTD_PROP_2ND_CONFIG: + PH_FRINFC_MIFARESTD_PROP_3RD_CONFIG); + + Result = phFriNfc_MifStd_H_ProStatNotValid(NdefMap, Result); + } + else + { + NdefMap->StdMifareContainer.NFCforumSectFlag = + (((NdefMap->StdMifareContainer.currentBlock == 64) && + (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD))? + NdefMap->StdMifareContainer.NFCforumSectFlag: + PH_FRINFC_MIFARESTD_FLAG1); + } + + if(NdefMap->StdMifareContainer.ProprforumSectFlag != + PH_FRINFC_MIFARESTD_PROP_2ND_CONFIG) + { + NdefMap->StdMifareContainer.ReadAcsBitFlag = PH_FRINFC_MIFARESTD_FLAG0; + /* ((NdefMap->StdMifareContainer.ReadCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + PH_FRINFC_MIFARESTD_FLAG0: + PH_FRINFC_MIFARESTD_FLAG1);*/ + + NdefMap->StdMifareContainer.ReadCompleteFlag = + (uint8_t)((((((NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_VAL4) >= + PH_FRINFC_MIFARESTD1K_MAX_BLK) && + (NdefMap->CardType == + PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD)) && + (NdefMap->StdMifareContainer.ReadCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG0)) || + (NdefMap->StdMifareContainer.ReadCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG1))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + NdefMap->StdMifareContainer.ReadCompleteFlag = + (uint8_t)((((((uint16_t)(NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_VAL4) >= + PH_FRINFC_MIFARESTD4K_MAX_BLK) && + (NdefMap->CardType == + PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD)) && + (NdefMap->StdMifareContainer.ReadCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG0)) || + (NdefMap->StdMifareContainer.ReadCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG1))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + NdefMap->StdMifareContainer.currentBlock = + ((NdefMap->StdMifareContainer.ReadCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + PH_FRINFC_MIFARESTD_BLK4: + NdefMap->StdMifareContainer.currentBlock); + + Result = + ((NdefMap->StdMifareContainer.ReadCompleteFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_BlkChk(NdefMap): + Result); + } + } + + Result = ((Result != NFCSTATUS_SUCCESS)? + Result: + phFriNfc_MifStd_H_ChkRdWr(NdefMap)); + } + else + { + NdefMap->StdMifareContainer.ChkNdefFlag = + PH_FRINFC_MIFARESTD_FLAG0; + /* Here its required to read the entire card to know the */ + /* Get exact ndef size of the card */ + Result = phFriNfc_MifStd_H_ChkTLVs(NdefMap, &CRFlag); + } + } + else + { + /* Since we have decided temporarily not to go + for any new error codes we are using + NFCSTATUS_INVALID_PARAMETER even though it is not + the relevant error code here TBD */ + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + } + + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_GPBChk(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Spec version needs to be checked every time */ + Result = phFriNfc_MapTool_ChkSpcVer(NdefMap, PH_FRINFC_MIFARESTD_VAL9); + + /* Check rhe read and write access field + in GPB is 00b + bit 0 and 1 for write access check + bit 2 and 3 for read access check */ + if(Result == NFCSTATUS_SUCCESS) + { + if(((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL9] & + PH_FRINFC_MIFARESTD_MASK_GPB_WR) == + PH_FRINFC_MIFARESTD_GPB_RD_WR_VAL) && + ((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL9] & + PH_FRINFC_MIFARESTD_MASK_GPB_RD) == + PH_FRINFC_MIFARESTD_GPB_RD_WR_VAL)) + { + NdefMap->CardState = (((NdefMap->StdMifareContainer.ChkNdefFlag == + PH_FRINFC_MIFARESTD_FLAG1) || + (NdefMap->StdMifareContainer.ReadNdefFlag == + PH_FRINFC_MIFARESTD_FLAG1) || + (NdefMap->StdMifareContainer.WrNdefFlag == + PH_FRINFC_MIFARESTD_FLAG1))? + PH_NDEFMAP_CARD_STATE_INITIALIZED: + PH_NDEFMAP_CARD_STATE_READ_WRITE); + } + else if(((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL9] & + PH_FRINFC_MIFARESTD_MASK_GPB_WR) != + PH_FRINFC_MIFARESTD_GPB_RD_WR_VAL) && + ((NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL9] & + PH_FRINFC_MIFARESTD_MASK_GPB_RD) == + PH_FRINFC_MIFARESTD_GPB_RD_WR_VAL)) + { + /* write access not given + only read access check */ + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY; + } + else + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } + } + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_ProStatNotValid(phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS status) +{ + NFCSTATUS Result = status; + /* if NFC forum sector is not found before the proprietary one then + authenticate the next sector + Else it is a error*/ + if(NdefMap->StdMifareContainer.NFCforumSectFlag == + PH_FRINFC_MIFARESTD_FLAG0) + { + NdefMap->StdMifareContainer.ProprforumSectFlag = + PH_FRINFC_MIFARESTD_PROP_3RD_CONFIG; + if(NdefMap->StdMifareContainer.currentBlock < + PH_FRINFC_MIFARESTD4K_BLK128) + { +#ifdef PH_HAL4_ENABLE + /* Fix for the disovery problem, + if 1st sector is invalid then ignore the remaining sectors and + send an error if the card is mifare 1k, + if the card is mifare 4k, then update the block number to 67 and + continue. + Even if the authentication of that block fails then send error */ + if(((NdefMap->StdMifareContainer.currentBlock < + PH_FRINFC_MIFARESTD_BLK4) && + (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD)) || + ((NdefMap->StdMifareContainer.currentBlock <= + PH_FRINFC_MIFARESTD_MAD_BLK67) && + (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD))) + { + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else if((NdefMap->StdMifareContainer.currentBlock < + PH_FRINFC_MIFARESTD_BLK4) && + (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD)) + { + Result = NFCSTATUS_SUCCESS; + NdefMap->StdMifareContainer.currentBlock = + PH_FRINFC_MIFARESTD_MAD_BLK67; + } + else +#endif /* #ifdef PH_HAL4_ENABLE */ + if(((NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK4) > + PH_FRINFC_MIFARESTD1K_MAX_BLK) && + (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD)) + { + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + NdefMap->StdMifareContainer.remainingSize -= + (PH_FRINFC_MIFARESTD_MAD_BLK3 * PH_FRINFC_MIFARESTD_BLOCK_BYTES); + NdefMap->StdMifareContainer.currentBlock += + PH_FRINFC_MIFARESTD_BLK4; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + } + } + else if((NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_BLK15) > + PH_FRINFC_MIFARESTD4K_MAX_BLK) + { + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + NdefMap->StdMifareContainer.remainingSize -= + (PH_FRINFC_MIFARESTD_BLK15 * PH_FRINFC_MIFARESTD_BLOCK_BYTES); + NdefMap->StdMifareContainer.currentBlock += + PH_FRINFC_MIFARESTD_BLOCK_BYTES; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + } + Result = ((Result != NFCSTATUS_SUCCESS)? + (PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT)): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + else if((NdefMap->StdMifareContainer.ProprforumSectFlag == + PH_FRINFC_MIFARESTD_PROP_3RD_CONFIG) && + (NdefMap->StdMifareContainer.NFCforumSectFlag == + PH_FRINFC_MIFARESTD_FLAG1)) + { + /* if the proprietary forum sector are found before + NFC forum sector then again a proprietary + forum sector are found after the NFC forum + sector */ + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + NdefMap->StdMifareContainer.ProprforumSectFlag = + PH_FRINFC_MIFARESTD_PROP_2ND_CONFIG; + switch(NdefMap->PrevOperation) + { + case PH_FRINFC_NDEFMAP_CHECK_OPE: + case PH_FRINFC_NDEFMAP_GET_ACTSIZE_OPE: + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + + case PH_FRINFC_NDEFMAP_READ_OPE: + if((NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->TLVStruct.NoLbytesinTLV == + PH_FRINFC_MIFARESTD_VAL0)) + { + *NdefMap->NumOfBytesRead = NdefMap->ApduBuffIndex; + Result = NFCSTATUS_SUCCESS; + } + else + { + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + break; + + case PH_FRINFC_NDEFMAP_WRITE_OPE: + default: + /* This means the further write is not possible, + EOF_NDEF_CONTAINER_REACHED */ + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + PH_FRINFC_MIFARESTD_FLAG1; + /* Write the length to the L field in the TLV */ + NdefMap->StdMifareContainer.TempBlockNo = + NdefMap->StdMifareContainer.currentBlock; + phFriNfc_MifStd_H_SetNdefBlkAuth(NdefMap); + NdefMap->StdMifareContainer.currentBlock = + NdefMap->TLVStruct.NdefTLVBlock; + Result = phFriNfc_MifStd_H_RdtoWrNdefLen(NdefMap); + break; + } + } + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_RdBeforeWr(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RD_BEF_WR; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + + Result = phFriNfc_MifStd_H_Rd16Bytes(NdefMap, + NdefMap->StdMifareContainer.currentBlock); + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_ProBytesToWr(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t TempLength = PH_FRINFC_MIFARESTD_VAL0; + + if(*NdefMap->SendRecvLength == PH_FRINFC_MIFARESTD_BYTES_READ) + { + (void)memcpy(&NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL1], + NdefMap->SendRecvBuf, + PH_FRINFC_MIFARESTD_BLOCK_BYTES); + + /* Write to Ndef TLV Block */ + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + NdefMap->StdMifareContainer.currentBlock; + + TempLength = ((NdefMap->StdMifareContainer.currentBlock == + NdefMap->TLVStruct.NdefTLVBlock)? + phFriNfc_MifStd_H_UpdateTLV(NdefMap): + phFriNfc_MifStd_H_UpdRemTLV(NdefMap)); + + NdefMap->StdMifareContainer.remainingSize -= + ((NdefMap->StdMifareContainer.remSizeUpdFlag == + PH_FRINFC_MIFARESTD_FLAG1)? + PH_FRINFC_MIFARESTD_VAL2: + PH_FRINFC_MIFARESTD_VAL0); + + NdefMap->StdMifareContainer.remSizeUpdFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_WR_TLV; + Result = ((TempLength == PH_FRINFC_MIFARESTD_BLOCK_BYTES)? + phFriNfc_MifStd_H_WrTLV(NdefMap): + phFriNfc_MifStd_H_fillSendBuf(NdefMap, TempLength)); + } + else + { + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_READ_FAILED); + } + + return Result; +} + +static uint8_t phFriNfc_MifStd_H_UpdateTLV(phFriNfc_NdefMap_t *NdefMap) +{ + uint8_t TempLength = PH_FRINFC_MIFARESTD_VAL0; + TempLength = (uint8_t)(NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_MIFARESTD_VAL1); + /* Creating TLV */ + if(NdefMap->TLVStruct.NULLTLVCount >= 2) + { + if((PH_FRINFC_MIFARESTD_BYTES_READ - TempLength) == + PH_FRINFC_MIFARESTD_VAL0) + { + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + } + else + { + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_L0; + } + } + else + { + switch((PH_FRINFC_MIFARESTD_BYTES_READ - + TempLength)) + { + case PH_FRINFC_MIFARESTD_VAL0: + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + break; + + case PH_FRINFC_MIFARESTD_VAL1: + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + TempLength++; + NdefMap->TLVStruct.prevLenByteValue = + (uint16_t)((NdefMap->SendRecvBuf[TempLength] >= + PH_FRINFC_MIFARESTD_NDEFTLV_L)? + PH_FRINFC_MIFARESTD_VAL0: + NdefMap->SendRecvBuf[TempLength]); + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + break; + + case PH_FRINFC_MIFARESTD_VAL2: + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + TempLength++; + NdefMap->TLVStruct.prevLenByteValue = + (uint16_t)((NdefMap->SendRecvBuf[TempLength] >= + PH_FRINFC_MIFARESTD_NDEFTLV_L)? + NdefMap->SendRecvBuf[(TempLength + + PH_FRINFC_MIFARESTD_VAL1)]: + NdefMap->SendRecvBuf[TempLength]); + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + break; + + default: + NdefMap->TLVStruct.prevLenByteValue = + NdefMap->SendRecvBuf[TempLength]; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_L0; + break; + } + } + + return TempLength; +} + +static NFCSTATUS phFriNfc_MifStd_H_fillSendBuf(phFriNfc_NdefMap_t *NdefMap, + uint8_t Length) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint16_t RemainingBytes = PH_FRINFC_MIFARESTD_VAL0, + BytesToWrite = PH_FRINFC_MIFARESTD_VAL0; + uint8_t index = PH_FRINFC_MIFARESTD_VAL0; + + Length = (Length + PH_FRINFC_MIFARESTD_VAL1); + + RemainingBytes = (uint16_t)((NdefMap->StdMifareContainer.remainingSize + < (uint16_t)(NdefMap->ApduBufferSize - + NdefMap->ApduBuffIndex))? + NdefMap->StdMifareContainer.remainingSize: + (NdefMap->ApduBufferSize - + NdefMap->ApduBuffIndex)); + + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = + NdefMap->StdMifareContainer.currentBlock; + /* Get the number of bytes that can be written after copying + the internal buffer */ + BytesToWrite = ((RemainingBytes < + ((PH_FRINFC_MIFARESTD_WR_A_BLK - Length) - + NdefMap->StdMifareContainer.internalLength))? + RemainingBytes: + ((PH_FRINFC_MIFARESTD_WR_A_BLK - Length) - + NdefMap->StdMifareContainer.internalLength)); + + if(NdefMap->StdMifareContainer.internalLength > + PH_FRINFC_MIFARESTD_VAL0) + { + /* copy the internal buffer to the send buffer */ + (void)memcpy(&(NdefMap->SendRecvBuf[ + Length]), + NdefMap->StdMifareContainer.internalBuf, + NdefMap->StdMifareContainer.internalLength); + } + + /* Copy Bytes to write in the send buffer */ + (void)memcpy(&(NdefMap->SendRecvBuf[ + (Length + + NdefMap->StdMifareContainer.internalLength)]), + &(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]), + BytesToWrite); + + /* update number of bytes written from the user buffer */ + NdefMap->NumOfBytesWritten = BytesToWrite; + + /* check the exact number of bytes written to a block including the + internal length */ + *NdefMap->DataCount = + ((BytesToWrite + NdefMap->StdMifareContainer.internalLength + + Length) - PH_FRINFC_MIFARESTD_VAL1); + + /* if total bytes to write in the card is less than 4 bytes then + pad zeroes till 4 bytes */ + if((BytesToWrite + NdefMap->StdMifareContainer.internalLength + + Length) < PH_FRINFC_MIFARESTD_WR_A_BLK) + { + for(index = (uint8_t)(BytesToWrite + + NdefMap->StdMifareContainer.internalLength + + Length); + index < PH_FRINFC_MIFARESTD_WR_A_BLK; + index++) + { + NdefMap->SendRecvBuf[index] = (uint8_t)((index == + (BytesToWrite + Length + + NdefMap->StdMifareContainer.internalLength))? + PH_FRINFC_MIFARESTD_TERMTLV_T: + PH_FRINFC_MIFARESTD_NULLTLV_T); + + NdefMap->TLVStruct.SetTermTLVFlag = PH_FRINFC_MIFARESTD_FLAG1; + } + } +#ifdef PH_HAL4_ENABLE + + NdefMap->TLVStruct.SetTermTLVFlag = PH_FRINFC_MIFARESTD_FLAG1; + +#endif /* #ifdef PH_HAL4_ENABLE */ + + /* A temporary buffer to hold four bytes of data that is + written to the card */ + (void)memcpy(NdefMap->StdMifareContainer.Buffer, + &(NdefMap->SendRecvBuf[ + PH_FRINFC_MIFARESTD_VAL1]), + PH_FRINFC_MIFARESTD_BLOCK_BYTES); + + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_WR_TLV; + Result = phFriNfc_MifStd_H_WrTLV(NdefMap); + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_WrTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* set the data for additional data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + NdefMap->psDepAdditionalInfo.NAD = 0; + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_MifareStdMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + /* Write from here */ + NdefMap->SendLength = MIFARE_MAX_SEND_BUF_TO_WRITE; + +#ifndef PH_HAL4_ENABLE + NdefMap->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite16; +#else + NdefMap->Cmd.MfCmd = phHal_eMifareWrite16; +#endif + + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + /* Call the Overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + + + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_ProWrTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + /* Check that if complete TLV has been written in the + card if yes enter the below check or go to else*/ + if(((((PH_FRINFC_MIFARESTD_BLOCK_BYTES - + NdefMap->TLVStruct.NdefTLVByte) == + PH_FRINFC_MIFARESTD_VAL1) && + (NdefMap->TLVStruct.NULLTLVCount >= + PH_FRINFC_MIFARESTD_VAL2)) || + (((PH_FRINFC_MIFARESTD_BLOCK_BYTES - + NdefMap->TLVStruct.NdefTLVByte) <= + PH_FRINFC_MIFARESTD_VAL3) && + (NdefMap->TLVStruct.NULLTLVCount == + PH_FRINFC_MIFARESTD_VAL0))) && + (NdefMap->StdMifareContainer.currentBlock == + NdefMap->TLVStruct.NdefTLVBlock)) + { + /* increment the block and chekc the block is in the same sector + using the block check function */ + NdefMap->StdMifareContainer.RdBeforeWrFlag = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.NdefBlocks++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + Result = ((NdefMap->StdMifareContainer.AuthDone == + PH_FRINFC_MIFARESTD_FLAG0)? + phFriNfc_MifStd_H_AuthSector(NdefMap): + phFriNfc_MifStd_H_RdBeforeWr(NdefMap)); + } + } + else + { + NdefMap->StdMifareContainer.RdBeforeWrFlag = PH_FRINFC_MIFARESTD_FLAG0; + if(NdefMap->ApduBuffIndex < + (uint16_t)NdefMap->ApduBufferSize) + { + if(*NdefMap->DataCount < PH_FRINFC_MIFARESTD_BLOCK_BYTES) + { + /* Write complete, so next byte shall be */ + NdefMap->StdMifareContainer.internalLength = + *NdefMap->DataCount; + + /* Copy bytes less than 16 to internal buffer + for the next write this can be used */ + (void)memcpy( NdefMap->StdMifareContainer.internalBuf, + NdefMap->StdMifareContainer.Buffer, + NdefMap->StdMifareContainer.internalLength); + } + + /* Increment the Send Buffer index */ + NdefMap->ApduBuffIndex += NdefMap->NumOfBytesWritten; + + NdefMap->StdMifareContainer.remainingSize -= + NdefMap->NumOfBytesWritten; + + /* Check for the End of Card */ + if((NdefMap->StdMifareContainer.remainingSize == + PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->ApduBuffIndex == NdefMap->ApduBufferSize)) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + (uint8_t)((NdefMap->StdMifareContainer.remainingSize == 0)? + PH_FRINFC_MIFARESTD_FLAG1:PH_FRINFC_MIFARESTD_FLAG0); + + if(NdefMap->StdMifareContainer.internalLength == + PH_FRINFC_MIFARESTD_VAL0) + { + NdefMap->StdMifareContainer.currentBlock++; + /* Mifare 4k Card, After 128th Block + each sector = 16 blocks in Mifare 4k */ + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + NdefMap->StdMifareContainer.NdefBlocks++; + } + + NdefMap->TLVStruct.SetTermTLVFlag = + (uint8_t)(((NdefMap->StdMifareContainer.remainingSize == + PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.SetTermTLVFlag == + PH_FRINFC_MIFARESTD_FLAG1))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + } + else + { + NdefMap->StdMifareContainer.currentBlock++; + /* Mifare 4k Card, After 128th Block + each sector = 16 blocks in Mifare 4k */ + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + NdefMap->StdMifareContainer.NdefBlocks++; + Result = ((NdefMap->StdMifareContainer.AuthDone == + PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_WrABlock(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + } + } + } + + if((Result == NFCSTATUS_SUCCESS) && + (NdefMap->TLVStruct.SetTermTLVFlag != + PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->StdMifareContainer.remainingSize > + PH_FRINFC_MIFARESTD_VAL0)) + { + Result = phFriNfc_MifStd_H_WrTermTLV(NdefMap); + } + else + { + if((Result == NFCSTATUS_SUCCESS) && + (NdefMap->TLVStruct.SetTermTLVFlag == + PH_FRINFC_MIFARESTD_FLAG1)) + { + /* Write the length to the L field in the TLV */ + NdefMap->StdMifareContainer.TempBlockNo = + NdefMap->StdMifareContainer.currentBlock; + phFriNfc_MifStd_H_SetNdefBlkAuth(NdefMap); + NdefMap->StdMifareContainer.currentBlock = + NdefMap->TLVStruct.NdefTLVBlock; + Result = phFriNfc_MifStd_H_RdtoWrNdefLen(NdefMap); + } + } + return Result; +} + +static uint8_t phFriNfc_MifStd_H_UpdRemTLV(phFriNfc_NdefMap_t *NdefMap) +{ + uint8_t TempLength = PH_FRINFC_MIFARESTD_VAL1; + if(NdefMap->TLVStruct.NULLTLVCount >= + PH_FRINFC_MIFARESTD_VAL2) + { + NdefMap->TLVStruct.prevLenByteValue = NdefMap->SendRecvBuf[TempLength]; + NdefMap->SendRecvBuf[TempLength] = + PH_FRINFC_MIFARESTD_NDEFTLV_L0; + } + else + { + switch((PH_FRINFC_MIFARESTD_BLOCK_BYTES - + NdefMap->TLVStruct.NdefTLVByte)) + { + case PH_FRINFC_MIFARESTD_VAL1: + NdefMap->TLVStruct.prevLenByteValue = + (((NdefMap->SendRecvBuf[TempLength] == + PH_FRINFC_MIFARESTD_NDEFTLV_L))? + (((uint16_t)NdefMap->SendRecvBuf[(TempLength + PH_FRINFC_MIFARESTD_VAL1)] + << PH_FRINFC_MIFARESTD_LEFTSHIFT8) + + NdefMap->SendRecvBuf[(TempLength + PH_FRINFC_MIFARESTD_VAL2)]): + NdefMap->SendRecvBuf[TempLength]); + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_L0; + break; + + case PH_FRINFC_MIFARESTD_VAL2: + NdefMap->TLVStruct.prevLenByteValue = + (((NdefMap->SendRecvBuf[TempLength] == + PH_FRINFC_MIFARESTD_NDEFTLV_L))? + (((uint16_t)NdefMap->SendRecvBuf[TempLength] << + PH_FRINFC_MIFARESTD_LEFTSHIFT8) + + NdefMap->SendRecvBuf[(TempLength + PH_FRINFC_MIFARESTD_VAL1)]): + NdefMap->SendRecvBuf[TempLength]); + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_L0; + break; + + case PH_FRINFC_MIFARESTD_VAL3: + default: + NdefMap->TLVStruct.prevLenByteValue = + ((NdefMap->TLVStruct.prevLenByteValue << + PH_FRINFC_MIFARESTD_LEFTSHIFT8) + + NdefMap->SendRecvBuf[TempLength]); + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_L0; + break; + } + } + return TempLength; +} + +static void phFriNfc_MifStd_H_fillTLV1(phFriNfc_NdefMap_t *NdefMap) +{ + uint8_t TempLength = (uint8_t)(NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_MIFARESTD_VAL1); + + NdefMap->TLVStruct.prevLenByteValue = + ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_CUR)? + (NdefMap->TLVStruct.prevLenByteValue + + NdefMap->ApduBuffIndex): + NdefMap->ApduBuffIndex); + + NdefMap->StdMifareContainer.RdAfterWrFlag = PH_FRINFC_MIFARESTD_FLAG1; + switch(NdefMap->TLVStruct.NdefTLVByte) + { + case PH_FRINFC_MIFARESTD_VAL0: + if(NdefMap->TLVStruct.prevLenByteValue >= + PH_FRINFC_MIFARESTD_NDEFTLV_L) + { + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)(NdefMap->TLVStruct.prevLenByteValue >> + PH_FRINFC_MIFARESTD_RIGHTSHIFT8); + NdefMap->SendRecvBuf[(TempLength + + PH_FRINFC_MIFARESTD_VAL1)] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + } + else + { + NdefMap->SendRecvBuf[TempLength] = + PH_FRINFC_MIFARESTD_NDEFTLV_T; + NdefMap->SendRecvBuf[(TempLength + + PH_FRINFC_MIFARESTD_VAL1)] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + + NdefMap->StdMifareContainer.RdAfterWrFlag = + PH_FRINFC_MIFARESTD_FLAG0; + } + break; + + case PH_FRINFC_MIFARESTD_VAL1: + if(NdefMap->TLVStruct.prevLenByteValue >= + PH_FRINFC_MIFARESTD_NDEFTLV_L) + { + NdefMap->SendRecvBuf[TempLength - PH_FRINFC_MIFARESTD_VAL1] = + PH_FRINFC_MIFARESTD_NDEFTLV_L; + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)(NdefMap->TLVStruct.prevLenByteValue >> + PH_FRINFC_MIFARESTD_RIGHTSHIFT8); + NdefMap->SendRecvBuf[(TempLength + + PH_FRINFC_MIFARESTD_VAL1)] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + } + else + { + NdefMap->SendRecvBuf[TempLength] = + PH_FRINFC_MIFARESTD_NDEFTLV_T; + NdefMap->SendRecvBuf[(TempLength + + PH_FRINFC_MIFARESTD_VAL1)] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + NdefMap->StdMifareContainer.RdAfterWrFlag = + PH_FRINFC_MIFARESTD_FLAG0; + } + break; + + case PH_FRINFC_MIFARESTD_VAL15: + /* if "Type" of TLV present at byte 15 */ + if(NdefMap->TLVStruct.prevLenByteValue >= + PH_FRINFC_MIFARESTD_NDEFTLV_L) + { + /* Update the null TLV, ndef TLV block and ndef TLV byte */ + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.NdefTLVBlock = + NdefMap->StdMifareContainer.currentBlock; + NdefMap->TLVStruct.NdefTLVByte = + (TempLength - PH_FRINFC_MIFARESTD_VAL3); + + NdefMap->SendRecvBuf[(TempLength - PH_FRINFC_MIFARESTD_VAL2)] = + PH_FRINFC_MIFARESTD_NDEFTLV_T; + NdefMap->SendRecvBuf[(TempLength - PH_FRINFC_MIFARESTD_VAL1)] = + PH_FRINFC_MIFARESTD_NDEFTLV_L; + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)(NdefMap->TLVStruct.prevLenByteValue >> + PH_FRINFC_MIFARESTD_RIGHTSHIFT8); + } + else + { + NdefMap->SendRecvBuf[TempLength] = + PH_FRINFC_MIFARESTD_NDEFTLV_T; + } + break; + + default: + /* Already the TLV is present so just append the length field */ + if(NdefMap->TLVStruct.prevLenByteValue >= + PH_FRINFC_MIFARESTD_NDEFTLV_L) + { + /* Update the null TLV, ndef TLV block and ndef TLV byte */ + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.NdefTLVBlock = + NdefMap->StdMifareContainer.currentBlock; + NdefMap->TLVStruct.NdefTLVByte = + (TempLength - PH_FRINFC_MIFARESTD_VAL3); + + NdefMap->SendRecvBuf[(TempLength - PH_FRINFC_MIFARESTD_VAL2)] = + (uint8_t)PH_FRINFC_MIFARESTD_NDEFTLV_T; + NdefMap->SendRecvBuf[(TempLength - PH_FRINFC_MIFARESTD_VAL1)] = + (uint8_t)PH_FRINFC_MIFARESTD_NDEFTLV_L; + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)(NdefMap->TLVStruct.prevLenByteValue >> + PH_FRINFC_MIFARESTD_RIGHTSHIFT8); + NdefMap->SendRecvBuf[(TempLength + PH_FRINFC_MIFARESTD_VAL1)] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + } + else + { + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + NdefMap->SendRecvBuf[(TempLength + PH_FRINFC_MIFARESTD_VAL1)] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + } + NdefMap->StdMifareContainer.RdAfterWrFlag = + PH_FRINFC_MIFARESTD_FLAG0; + break; + } +} + +static void phFriNfc_MifStd_H_fillTLV2(phFriNfc_NdefMap_t *NdefMap) +{ + uint8_t TempLength = (uint8_t)(NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_MIFARESTD_VAL1); + + NdefMap->TLVStruct.prevLenByteValue = ((NdefMap->Offset == + PH_FRINFC_NDEFMAP_SEEK_CUR)? + (NdefMap->TLVStruct.prevLenByteValue + + NdefMap->ApduBuffIndex): + NdefMap->ApduBuffIndex); + NdefMap->StdMifareContainer.RdAfterWrFlag = PH_FRINFC_MIFARESTD_FLAG1; + switch(NdefMap->TLVStruct.NdefTLVByte) + { + case PH_FRINFC_MIFARESTD_VAL13: + if(NdefMap->TLVStruct.prevLenByteValue >= + PH_FRINFC_MIFARESTD_NDEFTLV_L) + { + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_L; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = (uint8_t)(NdefMap->TLVStruct.prevLenByteValue >> + PH_FRINFC_MIFARESTD_RIGHTSHIFT8); + } + else + { + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + TempLength++; + + /* Update the null TLV, ndef TLV block and ndef TLV byte */ + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL2; + NdefMap->TLVStruct.NdefTLVBlock = + NdefMap->StdMifareContainer.currentBlock; + NdefMap->TLVStruct.NdefTLVByte = + (TempLength - PH_FRINFC_MIFARESTD_VAL1); + + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + } + break; + + case PH_FRINFC_MIFARESTD_VAL14: + if(NdefMap->TLVStruct.prevLenByteValue >= + PH_FRINFC_MIFARESTD_NDEFTLV_L) + { + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_L; + } + else + { + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + } + break; + + case PH_FRINFC_MIFARESTD_VAL15: + if(NdefMap->TLVStruct.prevLenByteValue >= + PH_FRINFC_MIFARESTD_NDEFTLV_L) + { + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + } + else + { + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + } + break; + + default: + if(NdefMap->TLVStruct.prevLenByteValue >= + PH_FRINFC_MIFARESTD_NDEFTLV_L) + { + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_L; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = (uint8_t)(NdefMap->TLVStruct.prevLenByteValue >> + PH_FRINFC_MIFARESTD_RIGHTSHIFT8); + TempLength++; + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + } + else + { + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NULLTLV_T; + TempLength++; + + /* Update the null TLV, ndef TLV block and ndef TLV byte */ + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL2; + NdefMap->TLVStruct.NdefTLVBlock = + NdefMap->StdMifareContainer.currentBlock; + NdefMap->TLVStruct.NdefTLVByte = + (TempLength - PH_FRINFC_MIFARESTD_VAL1); + + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + } + NdefMap->StdMifareContainer.RdAfterWrFlag = PH_FRINFC_MIFARESTD_FLAG0; + break; + } +} + +static NFCSTATUS phFriNfc_MifStd_H_CallWrNdefLen(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + if(NdefMap->TLVStruct.NULLTLVCount >= PH_FRINFC_MIFARESTD_VAL2) + { + if((NdefMap->TLVStruct.NdefTLVByte == PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.NdefTLVByte == PH_FRINFC_MIFARESTD_VAL1) ) + { + /* In this case, current block is decremented because the + NULL TLVs are in the previous block */ + NdefMap->StdMifareContainer.currentBlock--; + Result = phFriNfc_MifStd_H_BlkChk_1(NdefMap); + } + else + { + /* case NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_MIFARESTD_VAL15: + Current block is incremented to update the remaining TLV + structure */ + NdefMap->StdMifareContainer.currentBlock++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + } + } + else + { + if((NdefMap->TLVStruct.NdefTLVByte == PH_FRINFC_MIFARESTD_VAL13) || + (NdefMap->TLVStruct.NdefTLVByte == PH_FRINFC_MIFARESTD_VAL14) || + (NdefMap->TLVStruct.NdefTLVByte == PH_FRINFC_MIFARESTD_VAL15)) + { + /* Current block is incremented to update the remaining TLV + structure */ + NdefMap->StdMifareContainer.currentBlock++; + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + } + } + + Result = ((Result == NFCSTATUS_SUCCESS)? + phFriNfc_MifStd_H_RdtoWrNdefLen(NdefMap): + Result); + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_BlkChk_1(phFriNfc_NdefMap_t *NdefMap) +{ + /* This function is to check the current block is in the authenticated sector and + also check the block does not match with the sector trailer block. If there is a + match then decrement the block and say the caller that the authentication + is required */ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t SectorID = PH_FRINFC_MIFARESTD_VAL0; + + /* Get a Sector ID for the Current Block */ + SectorID = phFriNfc_MifStd_H_GetSect(NdefMap->StdMifareContainer.currentBlock); + + /* Check the sector id is valid or not and if valid then check the + current block is greater than 128 */ + if((NdefMap->StdMifareContainer.aid[SectorID] == + PH_FRINFC_MIFARESTD_NDEF_COMP) && + (((SectorID <= PH_FRINFC_MIFARESTD_VAL15) && + (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD)) || + ((SectorID <= PH_FRINFC_MIFARESTD_SECTOR_NO39) && + (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD)))) + { + if(NdefMap->StdMifareContainer.currentBlock > 128) + { + NdefMap->TLVStruct.NdefTLVAuthFlag = + ((((NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_VAL1) % + PH_FRINFC_MIFARESTD_MAD_BLK16) == + PH_FRINFC_MIFARESTD_VAL0)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + NdefMap->StdMifareContainer.currentBlock -= + ((((NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_VAL1) % + PH_FRINFC_MIFARESTD_MAD_BLK16) == + PH_FRINFC_MIFARESTD_VAL0)? + PH_FRINFC_MIFARESTD_VAL1: + PH_FRINFC_MIFARESTD_VAL0); + + } + else + { + NdefMap->TLVStruct.NdefTLVAuthFlag = + ((((NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_VAL1) % + PH_FRINFC_MIFARESTD_BLK4) == + PH_FRINFC_MIFARESTD_VAL0)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + NdefMap->StdMifareContainer.currentBlock -= + ((((NdefMap->StdMifareContainer.currentBlock + + PH_FRINFC_MIFARESTD_VAL1) % + PH_FRINFC_MIFARESTD_BLK4) == + PH_FRINFC_MIFARESTD_VAL1)? + PH_FRINFC_MIFARESTD_VAL1: + PH_FRINFC_MIFARESTD_VAL0); + + } + } + else + { + /*Error: No Ndef Compliant Sectors present.*/ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + } + + return Result; +} + +static void phFriNfc_MifStd_H_fillTLV1_1(phFriNfc_NdefMap_t *NdefMap) +{ + switch(NdefMap->TLVStruct.NdefTLVByte) + { + case PH_FRINFC_MIFARESTD_VAL0: + /* In the first write ndef length procedure, the + length is updated, in this case T and L = 0xFF of TLV are + updated */ + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.NdefTLVBlock = + NdefMap->StdMifareContainer.currentBlock; + NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_MIFARESTD_VAL14; + + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL15] = + PH_FRINFC_MIFARESTD_NDEFTLV_T; + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL16] = + PH_FRINFC_MIFARESTD_NDEFTLV_L; + break; + + case PH_FRINFC_MIFARESTD_VAL1: + /* In the first write ndef length procedure, the + length is updated, in this case T of TLV is + updated */ + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->TLVStruct.NdefTLVBlock = + NdefMap->StdMifareContainer.currentBlock; + NdefMap->TLVStruct.NdefTLVByte = + PH_FRINFC_MIFARESTD_VAL15; + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL16] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + break; + + case PH_FRINFC_MIFARESTD_VAL15: + default: + /* In the first ndef write length, part of the L field or only T + (if update length is less than 255) is updated */ + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL1] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + break; + } + NdefMap->StdMifareContainer.RdAfterWrFlag = PH_FRINFC_MIFARESTD_FLAG0; +} + +static void phFriNfc_MifStd_H_fillTLV2_1(phFriNfc_NdefMap_t *NdefMap) +{ + uint8_t TempLength = PH_FRINFC_MIFARESTD_VAL1; + switch(NdefMap->TLVStruct.NdefTLVByte) + { + case PH_FRINFC_MIFARESTD_VAL13: + /* In last write ndef length, part of length (L) field of TLV + is updated now */ + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + break; + + case PH_FRINFC_MIFARESTD_VAL14: + /* In last write ndef length, part of length (L) field of TLV + is updated now */ + if(NdefMap->TLVStruct.prevLenByteValue >= + PH_FRINFC_MIFARESTD_NDEFTLV_L) + { + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)(NdefMap->TLVStruct.prevLenByteValue >> + PH_FRINFC_MIFARESTD_RIGHTSHIFT8); + TempLength++; + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + } + else + { + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL2; + NdefMap->TLVStruct.NdefTLVBlock = + NdefMap->StdMifareContainer.currentBlock; + NdefMap->TLVStruct.NdefTLVByte = + (TempLength - PH_FRINFC_MIFARESTD_VAL1); + NdefMap->SendRecvBuf[TempLength] = PH_FRINFC_MIFARESTD_NDEFTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + } + break; + + case PH_FRINFC_MIFARESTD_VAL15: + default: + if(NdefMap->TLVStruct.prevLenByteValue >= + PH_FRINFC_MIFARESTD_NDEFTLV_L) + { + /* In last write ndef length, only T of TLV is updated and + length (L) field of TLV is updated now */ + NdefMap->SendRecvBuf[TempLength] = + PH_FRINFC_MIFARESTD_NDEFTLV_L; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)(NdefMap->TLVStruct.prevLenByteValue >> + PH_FRINFC_MIFARESTD_RIGHTSHIFT8); + TempLength++; + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + } + else + { + NdefMap->SendRecvBuf[TempLength] = + PH_FRINFC_MIFARESTD_NULLTLV_T; + TempLength++; + NdefMap->TLVStruct.NULLTLVCount = PH_FRINFC_MIFARESTD_VAL2; + NdefMap->TLVStruct.NdefTLVBlock = + NdefMap->StdMifareContainer.currentBlock; + NdefMap->TLVStruct.NdefTLVByte = + (TempLength - PH_FRINFC_MIFARESTD_VAL1); + NdefMap->SendRecvBuf[TempLength] = + PH_FRINFC_MIFARESTD_NDEFTLV_T; + TempLength++; + NdefMap->SendRecvBuf[TempLength] = + (uint8_t)NdefMap->TLVStruct.prevLenByteValue; + } + break; + } + NdefMap->StdMifareContainer.RdAfterWrFlag = PH_FRINFC_MIFARESTD_FLAG0; +} + +static NFCSTATUS phFriNfc_MifStd_H_RdTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RD_TLV; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + + Result = phFriNfc_MifStd_H_Rd16Bytes(NdefMap, + NdefMap->StdMifareContainer.currentBlock); + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_ProRdTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + uint8_t TempLength = PH_FRINFC_MIFARESTD_VAL0, + NDEFFlag = PH_FRINFC_MIFARESTD_FLAG1; + + /*TempLength = (uint8_t)(((NdefMap->TLVStruct.NULLTLVCount >= + PH_FRINFC_MIFARESTD_VAL2) && + (NdefMap->TLVStruct.BytesRemainLinTLV > 0xFE))? + ((NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_MIFARESTD_VAL2)% + PH_FRINFC_MIFARESTD_VAL16): + ((NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_MIFARESTD_VAL4)% + PH_FRINFC_MIFARESTD_VAL16));*/ + + TempLength = (uint8_t)((NdefMap->TLVStruct.BytesRemainLinTLV <= 0xFE)? + ((NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_MIFARESTD_VAL2)% + PH_FRINFC_MIFARESTD_VAL16): + ((NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_MIFARESTD_VAL4)% + PH_FRINFC_MIFARESTD_VAL16)); + + if((*NdefMap->SendRecvLength == PH_FRINFC_MIFARESTD_BYTES_READ) && + (NdefMap->ApduBuffIndex < NdefMap->ApduBufferSize)) + { + if(NdefMap->TLVStruct.BytesRemainLinTLV != 0) + { + NDEFFlag = PH_FRINFC_MIFARESTD_FLAG0; + /* To read the remaining length (L) in TLV */ + Result = phFriNfc_MifStd_H_RemainTLV(NdefMap, &NDEFFlag, &TempLength); + } + } + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_WrTermTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t index = PH_FRINFC_MIFARESTD_VAL0; + + /* Change the state to check ndef compliancy */ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_TERM_TLV; + + NdefMap->SendRecvBuf[index] = + NdefMap->StdMifareContainer.currentBlock; + index++; + NdefMap->SendRecvBuf[index] = PH_FRINFC_MIFARESTD_TERMTLV_T; + index++; + + while(index < PH_FRINFC_MIFARESTD_WR_A_BLK) + { + NdefMap->SendRecvBuf[index] = PH_FRINFC_MIFARESTD_NULLTLV_T; + index++; + } + + NdefMap->TLVStruct.SetTermTLVFlag = PH_FRINFC_MIFARESTD_FLAG0; + + Result = phFriNfc_MifStd_H_WrTLV(NdefMap); + + return Result; +} + + +static NFCSTATUS phFriNfc_MifStd_H_ProWrABlock(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + NdefMap->StdMifareContainer.WrLength = PH_FRINFC_MIFARESTD_VAL0; + if(NdefMap->ApduBuffIndex < + (uint16_t)NdefMap->ApduBufferSize) + { + /* Remaining bytes to write < 16 */ + if(NdefMap->StdMifareContainer.RemainingBufFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + /* Write complete, so next byte shall be */ + NdefMap->StdMifareContainer.internalLength = + *NdefMap->DataCount; + + /* Copy bytes less than 16 to internal buffer + for the next write this can be used */ + (void)memcpy( NdefMap->StdMifareContainer.internalBuf, + NdefMap->StdMifareContainer.Buffer, + NdefMap->StdMifareContainer.internalLength); + + /* Increment the Send Buffer index */ + NdefMap->ApduBuffIndex += NdefMap->NumOfBytesWritten; + + NdefMap->StdMifareContainer.remainingSize -= + NdefMap->NumOfBytesWritten; + + NdefMap->StdMifareContainer.RemainingBufFlag = PH_FRINFC_MIFARESTD_VAL0; + /* Check for the End of Card */ + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + (uint8_t)((NdefMap->StdMifareContainer.remainingSize == + PH_FRINFC_MIFARESTD_VAL0)? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + NdefMap->TLVStruct.SetTermTLVFlag = + (uint8_t)(((NdefMap->StdMifareContainer.remainingSize == + PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.SetTermTLVFlag == + PH_FRINFC_MIFARESTD_FLAG1))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + } /* internal Buffer > Send Buffer */ + else if(NdefMap->StdMifareContainer.internalBufFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + (void)memcpy(NdefMap->StdMifareContainer.internalBuf, + NdefMap->StdMifareContainer.Buffer, + *NdefMap->DataCount); + + NdefMap->StdMifareContainer.internalLength = + *NdefMap->DataCount; + + /* Increment the Send Buffer index */ + NdefMap->ApduBuffIndex += + NdefMap->NumOfBytesWritten; + + NdefMap->StdMifareContainer.remainingSize -= + NdefMap->NumOfBytesWritten; + + NdefMap->StdMifareContainer.internalBufFlag = + PH_FRINFC_MIFARESTD_FLAG0; + /* Check for the End of Card */ + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + (uint8_t)(((NdefMap->StdMifareContainer.remainingSize == + PH_FRINFC_MIFARESTD_VAL0) && + (NdefMap->StdMifareContainer.internalLength == + PH_FRINFC_MIFARESTD_VAL0))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + + NdefMap->TLVStruct.SetTermTLVFlag = + (uint8_t)(((NdefMap->StdMifareContainer.remainingSize == + PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.SetTermTLVFlag == + PH_FRINFC_MIFARESTD_FLAG1))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + } + else + { + NdefMap->StdMifareContainer.internalLength = 0; + /* Increment the Send Buffer index */ + NdefMap->ApduBuffIndex += + NdefMap->NumOfBytesWritten; + NdefMap->StdMifareContainer.remainingSize -= + NdefMap->NumOfBytesWritten; + + /* Check for the End of Card */ + if((NdefMap->StdMifareContainer.remainingSize == + PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->ApduBuffIndex == NdefMap->ApduBufferSize)) + { + NdefMap->StdMifareContainer.ReadWriteCompleteFlag = + (uint8_t)((NdefMap->StdMifareContainer.remainingSize == 0)? + PH_FRINFC_MIFARESTD_FLAG1:PH_FRINFC_MIFARESTD_FLAG0); + + if(NdefMap->StdMifareContainer.internalLength == + PH_FRINFC_MIFARESTD_VAL0) + { + NdefMap->StdMifareContainer.currentBlock++; + /* Mifare 4k Card, After 128th Block + each sector = 16 blocks in Mifare 4k */ + Result = ((NdefMap->StdMifareContainer.remainingSize == 0)? + Result: + phFriNfc_MifStd_H_BlkChk(NdefMap)); + NdefMap->StdMifareContainer.NdefBlocks++; + } + NdefMap->TLVStruct.SetTermTLVFlag = + (uint8_t)(((NdefMap->StdMifareContainer.remainingSize == + PH_FRINFC_MIFARESTD_VAL0) || + (NdefMap->TLVStruct.SetTermTLVFlag == + PH_FRINFC_MIFARESTD_FLAG1))? + PH_FRINFC_MIFARESTD_FLAG1: + PH_FRINFC_MIFARESTD_FLAG0); + } + else + { + NdefMap->StdMifareContainer.currentBlock++; + NdefMap->StdMifareContainer.WrLength = + (uint16_t)(NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex); + /* Mifare 4k Card, After 128th Block + each sector = 16 blocks in Mifare 4k */ + Result = phFriNfc_MifStd_H_BlkChk(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + NdefMap->StdMifareContainer.NdefBlocks++; + Result = ((NdefMap->StdMifareContainer.AuthDone == + PH_FRINFC_MIFARESTD_FLAG1)? + phFriNfc_MifStd_H_WrABlock(NdefMap): + phFriNfc_MifStd_H_AuthSector(NdefMap)); + } + } + } + } + else + { + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + } + + if((Result == NFCSTATUS_SUCCESS) && + (NdefMap->TLVStruct.SetTermTLVFlag != + PH_FRINFC_MIFARESTD_FLAG1) && + (NdefMap->StdMifareContainer.remainingSize > + PH_FRINFC_MIFARESTD_VAL0)) + { + Result = phFriNfc_MifStd_H_WrTermTLV(NdefMap); + } + else + { + if((Result == NFCSTATUS_SUCCESS) && + (NdefMap->TLVStruct.SetTermTLVFlag == + PH_FRINFC_MIFARESTD_FLAG1)) + { + /* Write the length to the L field in the TLV */ + NdefMap->StdMifareContainer.TempBlockNo = + NdefMap->StdMifareContainer.currentBlock; + phFriNfc_MifStd_H_SetNdefBlkAuth(NdefMap); + NdefMap->StdMifareContainer.currentBlock = + NdefMap->TLVStruct.NdefTLVBlock; + Result = phFriNfc_MifStd_H_RdtoWrNdefLen(NdefMap); + } + } + return Result; +} + +static NFCSTATUS phFriNfc_MifStd_H_CallDisCon(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + /*Set Ndef State*/ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_DISCONNECT; + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_MifareStdMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + +#ifndef PH_HAL4_ENABLE + /*Call the Overlapped HAL POLL function */ + Result = phFriNfc_OvrHal_Disconnect( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo); +#else + /*Call the Overlapped HAL Reconnect function */ + Result = phFriNfc_OvrHal_Reconnect( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo); +#endif + + return Result; +} + +#ifndef PH_HAL4_ENABLE +static NFCSTATUS phFriNfc_MifStd_H_CallPoll(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + /*Set Ndef State*/ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_POLL; + /* Opmodes */ + NdefMap->OpModeType[PH_FRINFC_MIFARESTD_VAL0] = phHal_eOpModesMifare; + NdefMap->OpModeType[PH_FRINFC_MIFARESTD_VAL1] = phHal_eOpModesArrayTerminator; + + /* Number of devices to poll */ + NdefMap->NoOfDevices = PH_FRINFC_MIFARESTD_VAL1; + + /*Call the Overlapped HAL POLL function */ + Result = phFriNfc_OvrHal_Poll( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->OpModeType, + NdefMap->psRemoteDevInfo, + &NdefMap->NoOfDevices, + NdefMap->StdMifareContainer.DevInputParam); + return Result; +} +#endif + +static NFCSTATUS phFriNfc_MifStd_H_CallConnect(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + /*Set Ndef State*/ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_CONNECT; + + /*Call the Overlapped HAL POLL function */ + Result = phFriNfc_OvrHal_Connect( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->StdMifareContainer.DevInputParam); + return Result; +} + +static void phFriNfc_MifStd1k_H_BlkChk(phFriNfc_NdefMap_t *NdefMap, + uint8_t SectorID, + uint8_t *callbreak) +{ + /* every last block of a sector needs to be skipped */ + if(((NdefMap->StdMifareContainer.currentBlock + PH_FRINFC_MIFARESTD_INC_1) % + PH_FRINFC_MIFARESTD_BLK4) == 0) + { + NdefMap->StdMifareContainer.currentBlock++; + } + else + { + if(NdefMap->StdMifareContainer.aid[SectorID] == + PH_FRINFC_MIFARESTD_NDEF_COMP) + { + /* Check whether the block is first block of a (next)new sector and + also check if it is first block then internal length is zero + or not. Because once Authentication is done for the sector again + we should not authenticate it again */ + if((NdefMap->StdMifareContainer.currentBlock == + (SectorID * PH_FRINFC_MIFARESTD_BLK4)) && + (NdefMap->StdMifareContainer.internalLength == 0)) + { + NdefMap->StdMifareContainer.AuthDone = 0; + } + *callbreak = 1; + } + else + { + NdefMap->StdMifareContainer.currentBlock += PH_FRINFC_MIFARESTD_BLK4; + } + } +} + +#ifdef UNIT_TEST +#include +#endif + +/* Convert the Mifare card to ReadOnly. + check preconditions before converting to read only + 1.shud b rd/write state + 2.check NDEF for the card shud b completed + 3.if alrady read only return */ +NFCSTATUS +phFriNfc_MifareStdMap_ConvertToReadOnly ( + phFriNfc_NdefMap_t *NdefMap, + const uint8_t *ScrtKeyB) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t totalNoSectors = 0 , sectorTrailerBlockNo = 0; + + if ( NdefMap == NULL) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else if ( PH_NDEFMAP_CARD_STATE_INVALID == NdefMap->CardState ) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_STATE); + } + else + { + /* card state is PH_NDEFMAP_CARD_STATE_READ_WRITE now */ + /* get AID array and parse */ + if( PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD == NdefMap->CardType ) + { + totalNoSectors = PH_FRINFC_MIFARESTD1K_TOTAL_SECTOR; + } + else if ( PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD == NdefMap->CardType ) + { + totalNoSectors = PH_FRINFC_MIFARESTD4K_TOTAL_SECTOR; + } + + /* Store Key B in the context */ + if(ScrtKeyB == NULL) + { + memset (NdefMap->StdMifareContainer.UserScrtKeyB, PH_FRINFC_MFSTD_FMT_DEFAULT_KEY, + PH_FRINFC_MIFARESTD_KEY_LEN); + } + else + { + memcpy (NdefMap->StdMifareContainer.UserScrtKeyB, ScrtKeyB, PH_FRINFC_MIFARESTD_KEY_LEN); + } + + NdefMap->StdMifareContainer.TotalNoSectors = totalNoSectors; + if(totalNoSectors == 0) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else + { + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.RdBeforeWrFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.WrNdefFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.internalLength = PH_FRINFC_MIFARESTD_VAL0; + NdefMap->StdMifareContainer.RdAfterWrFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.AuthDone = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.NFCforumSectFlag = PH_FRINFC_MIFARESTD_FLAG0; + NdefMap->StdMifareContainer.WriteAcsBitFlag = PH_FRINFC_MIFARESTD_FLAG0; + + /* Sector 0 is MAD sector .Start from Sector 1 */ + for(NdefMap->StdMifareContainer.ReadOnlySectorIndex = PH_FRINFC_MIFARESTD_FLAG1; + NdefMap->StdMifareContainer.ReadOnlySectorIndex < totalNoSectors; + NdefMap->StdMifareContainer.ReadOnlySectorIndex++) + { + /* skip MAD sectors */ + if( PH_FRINFC_MIFARESTD_SECTOR_NO16 == NdefMap->StdMifareContainer.ReadOnlySectorIndex ) + { + continue; + } + + /* if not NDEF compliant skip */ + if( PH_FRINFC_MIFARESTD_NON_NDEF_COMP == + NdefMap->StdMifareContainer.aid[NdefMap->StdMifareContainer.ReadOnlySectorIndex]) + { + continue; + } + + if (PH_FRINFC_MIFARESTD_NDEF_COMP == + NdefMap->StdMifareContainer.aid[NdefMap->StdMifareContainer.ReadOnlySectorIndex]) + { + /*get the sector trailer block number */ + sectorTrailerBlockNo = + phFriNfc_MifStd_H_GetSectorTrailerBlkNo(NdefMap->StdMifareContainer.ReadOnlySectorIndex); + NdefMap->StdMifareContainer.currentBlock = sectorTrailerBlockNo; + NdefMap->StdMifareContainer.SectorTrailerBlockNo = sectorTrailerBlockNo; + + /* Proceed to authenticate the sector with Key B + and modify the sector trailor bits to make it read only*/ + result = phFriNfc_MifStd_H_AuthSector(NdefMap); + + if (result == NFCSTATUS_PENDING ) + { + break; + } + } + } /* end for */ + + /* There are no NDEF sectors in this card , return */ + if(NdefMap->StdMifareContainer.ReadOnlySectorIndex == totalNoSectors && + NFCSTATUS_PENDING!= result ) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_NO_NDEF_SUPPORT); + } + } /* end else */ + } + + return result; +} + +/* Get the block number of the sector trailor for the given sector trailer Id */ +static uint8_t phFriNfc_MifStd_H_GetSectorTrailerBlkNo(uint8_t SectorID) +{ + uint8_t sectorTrailerblockNumber = 0; + + /* every last block of a sector needs to be skipped */ + if( SectorID < PH_FRINFC_MIFARESTD_SECTOR_NO32 ) + { + sectorTrailerblockNumber = ( SectorID * PH_FRINFC_MIFARESTD_BLK4 ) + 3; + } + else + { + sectorTrailerblockNumber = ((PH_FRINFC_MIFARESTD_SECTOR_NO32 * PH_FRINFC_MIFARESTD_BLK4) + + ((SectorID - PH_FRINFC_MIFARESTD_SECTOR_NO32) * PH_FRINFC_MIFARESTD_SECTOR_BLOCKS)) + 15; + } + + return sectorTrailerblockNumber; +} + +/* Called during ConvertToReadonly process to Authenticate NDEF compliant Sector */ +static NFCSTATUS phFriNfc_MifStd_H_ProSectorTrailorAcsBits(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + if(*NdefMap->SendRecvLength == PH_FRINFC_MIFARESTD_BYTES_READ) + { + if(NdefMap->StdMifareContainer.ReadAcsBitFlag == + PH_FRINFC_MIFARESTD_FLAG1) + { + /* check for the correct access bits */ + Result = phFriNfc_MifStd_H_ChkAcsBit(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + + if(NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_ONLY) + { + /* Go to next sector */ + Result = phFriNfc_MifStd_H_ProWrSectorTrailor(NdefMap); + } + else + { + /* tranceive to write the data into SendRecvBuff */ + Result = phFriNfc_MifStd_H_WrSectorTrailorBlock(NdefMap); + } + } + } + } + else + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + } + + return Result; +} + +/* Make current NDEF compliant Sector ReadOnly + modify the sector trailor bits and write it to the card*/ +static NFCSTATUS phFriNfc_MifStd_H_WrSectorTrailorBlock(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + /* set the data for additional data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + NdefMap->psDepAdditionalInfo.NAD = 0; + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_MifareStdMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + + /* next state (update sector index) */ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_WRITE_SEC; + + /* Buffer Check */ + if(NdefMap->SendRecvBuf != NULL) + { + NdefMap->SendRecvBuf[10] = 0x00; + NdefMap->SendRecvBuf[10] = NdefMap->SendRecvBuf[9] | PH_FRINFC_MIFARESTD_MASK_GPB_WR; /* WR bits 11*/ + + /*The NdefMap->SendRecvBuf already has the sector trailor. + modify the bits to make Read Only */ + NdefMap->SendRecvBuf[1] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT1; /* 0xD3 */ + NdefMap->SendRecvBuf[2] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT2; /* 0xF7 */ + NdefMap->SendRecvBuf[3] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT1; /* 0xD3 */ + NdefMap->SendRecvBuf[4] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT2; /* 0xF7 */ + NdefMap->SendRecvBuf[5] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT1; /* 0xD3 */ + NdefMap->SendRecvBuf[6] = PH_FRINFC_NDEFMAP_MIFARESTD_AUTH_NDEFSECT2; /* 0xF7 */ + + NdefMap->SendRecvBuf[7] = PH_FRINFC_MIFARESTD_NFCSECT_RDACS_BYTE6;/* 0x07 */ + NdefMap->SendRecvBuf[8] = PH_FRINFC_MIFARESTD_NFCSECT_RDACS_BYTE7;/* 0x8F */ + NdefMap->SendRecvBuf[9] = PH_FRINFC_MIFARESTD_NFCSECT_RDACS_BYTE8;/* 0x0F */ + + NdefMap->SendRecvBuf[11] = NdefMap->StdMifareContainer.UserScrtKeyB[0]; + NdefMap->SendRecvBuf[12] = NdefMap->StdMifareContainer.UserScrtKeyB[1]; + NdefMap->SendRecvBuf[13] = NdefMap->StdMifareContainer.UserScrtKeyB[2]; + NdefMap->SendRecvBuf[14] = NdefMap->StdMifareContainer.UserScrtKeyB[3]; + NdefMap->SendRecvBuf[15] = NdefMap->StdMifareContainer.UserScrtKeyB[4]; + NdefMap->SendRecvBuf[16] = NdefMap->StdMifareContainer.UserScrtKeyB[5]; + + /* Write to Ndef Sector Block */ + NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL0] = NdefMap->StdMifareContainer.currentBlock; + + /* Copy Ndef Sector Block into buffer */ + (void)memcpy(NdefMap->StdMifareContainer.Buffer, + &(NdefMap->SendRecvBuf[PH_FRINFC_MIFARESTD_VAL1]), + PH_FRINFC_MIFARESTD_BLOCK_BYTES); + + /* Write from here */ + NdefMap->SendLength = MIFARE_MAX_SEND_BUF_TO_WRITE; +#ifndef PH_HAL4_ENABLE + NdefMap->Cmd.MfCmd = phHal_eMifareCmdListMifareWrite16; +#else + NdefMap->Cmd.MfCmd = phHal_eMifareWrite16; +#endif + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + + /* Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive(NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + } + else + { + /* Error: The control should not ideally come here. + Return Error.*/ +#ifndef PH_HAL4_ENABLE + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_CMD_ABORTED); +#else + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_FAILED); +#endif + } + + return status; +} + +/* Make next NDEF compliant Sector ReadOnly */ +static NFCSTATUS phFriNfc_MifStd_H_ProWrSectorTrailor(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_FAILED; + uint8_t sectorTrailerBlockNo = 0; + + /*Increment Sector Index */ + NdefMap->StdMifareContainer.ReadOnlySectorIndex++; + + /* skip if MAD2 */ + if(PH_FRINFC_MIFARESTD_SECTOR_NO16 == NdefMap->StdMifareContainer.ReadOnlySectorIndex ) + { + NdefMap->StdMifareContainer.ReadOnlySectorIndex++; + } + + /* if current sector index exceeds total sector index then + all ndef sectors are made readonly then return success + If a NON def sector is encountered return success*/ + if (NdefMap->StdMifareContainer.ReadOnlySectorIndex >= NdefMap->StdMifareContainer.TotalNoSectors || + PH_FRINFC_MIFARESTD_NON_NDEF_COMP == + NdefMap->StdMifareContainer.aid[NdefMap->StdMifareContainer.ReadOnlySectorIndex]) + { + status = NFCSTATUS_SUCCESS; + } + else if(PH_FRINFC_MIFARESTD_NDEF_COMP == NdefMap->StdMifareContainer.aid[NdefMap->StdMifareContainer.ReadOnlySectorIndex]) + { + /* Convert next NDEF sector to read only */ + sectorTrailerBlockNo = phFriNfc_MifStd_H_GetSectorTrailerBlkNo(NdefMap->StdMifareContainer.ReadOnlySectorIndex); + NdefMap->StdMifareContainer.currentBlock = sectorTrailerBlockNo; + NdefMap->StdMifareContainer.SectorTrailerBlockNo = sectorTrailerBlockNo; + + status = phFriNfc_MifStd_H_AuthSector(NdefMap); + } + + return status; +} + +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ diff --git a/libnfc-nxp/phFriNfc_MifareStdMap.h b/libnfc-nxp/phFriNfc_MifareStdMap.h new file mode 100644 index 0000000..aeea7e7 --- /dev/null +++ b/libnfc-nxp/phFriNfc_MifareStdMap.h @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc_MifareStdMap.h + * \brief NFC Ndef Mapping For Remote Devices. + * + * Project: NFC-FRI + * + * $Date: Tue May 19 10:30:01 2009 $ + * $Author: ing07336 $ + * $Revision: 1.7 $ + * $Aliases: NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PHFRINFC_MIFARESTDMAP_H +#define PHFRINFC_MIFARESTDMAP_H + +#include +#ifdef PH_HAL4_ENABLE +#include +#else +#include +#endif +/** Fix: [NFC-FRI * * * CCB * * * 0000429]: + phFriNfc_MifareMap : Error during compilation **/ +#include +#include + +#ifndef PH_HAL4_ENABLE +#include +#endif + +#include +#include + +/*! \ingroup grp_file_attributes + * \name NDEF Mapping + * + * File: \ref phFriNfc_NdefMap.h + * + */ +/*@{*/ +#define PH_FRINFC_MIFARESTDMAP_FILEREVISION "$Revision: 1.7 $" +#define PH_FRINFC_MIFARESTDMAP_FILEALIASES "$Aliases: NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" +/*@}*/ + + +/*! \defgroup grp_fri_nfc_ndef_map NDEF Mapping for Remote Devices + * + * This component encapsulates Ndef Registration and Listening data and functionality. + */ +/*@{*/ + +/*! + * \name NDEF Mapping - states of the Finite State machine + * + */ +/*@{*/ +#define PH_FRINFC_NDEFMAP_STATE_INIT 0 /*!< Init state. The start-up state */ +#define PH_FRINFC_NDEFMAP_STATE_READ 1 /*!< Read State */ +#define PH_FRINFC_NDEFMAP_STATE_WRITE 2 /*!< Write is going on*/ +#define PH_FRINFC_NDEFMAP_STATE_AUTH 3 /*!< Authenticate is going on*/ +#define PH_FRINFC_NDEFMAP_STATE_CHK_NDEF_COMP 4 /*!< Check Ndef is going on */ +#define PH_FRINFC_NDEFMAP_STATE_RD_ACS_BIT 5 /*!< Read access bit is in progress */ +#define PH_FRINFC_NDEFMAP_STATE_WR_NDEF_LEN 6 /*!< Write NDEF TLV LEngth*/ +#define PH_FRINFC_NDEFMAP_STATE_RD_TO_WR_NDEF_LEN 7 /*!< read to write the Ndef TLV*/ +#define PH_FRINFC_NDEFMAP_STATE_GET_ACT_CARDSIZE 8 /*!< Get the card size */ +#define PH_FRINFC_NDEFMAP_STATE_RD_BEF_WR 9 /*!< Read the NDEF TLV block before starting write */ +#define PH_FRINFC_NDEFMAP_STATE_WR_TLV 10 /*!< Read the NDEF TLV block before starting write */ +#define PH_FRINFC_NDEFMAP_STATE_RD_TLV 11 /*!< Read the NDEF TLV block */ +#define PH_FRINFC_NDEFMAP_STATE_TERM_TLV 12 /*!< Write terminator TLV block */ +#define PH_FRINFC_NDEFMAP_STATE_POLL 13 /*!< Poll in progress */ +#define PH_FRINFC_NDEFMAP_STATE_DISCONNECT 14 /*!< Disconnect in progress */ +#define PH_FRINFC_NDEFMAP_STATE_CONNECT 15 /*!< Connect in progress */ + +#define PH_FRINFC_NDEFMAP_STATE_RD_SEC_ACS_BIT 16 /*!< Convert to ReadOnly in progress */ +#define PH_FRINFC_NDEFMAP_STATE_WRITE_SEC 17 /*!< Convert to ReadOnly in progress */ + + +/*@}*/ + +/*! + * \name Mifare Standard - NDEF Compliant Flags + * + */ +/*@{*/ +#define PH_FRINFC_MIFARESTD_NDEF_COMP 0 /*!< Sector is NDEF Compliant */ +#define PH_FRINFC_MIFARESTD_NON_NDEF_COMP 1 /*!< Sector is not NDEF Compliant */ +/*@}*/ + +/*! + * \name Mifare Standard - NDEF Compliant Flags + * + */ +/*@{*/ +#define PH_FRINFC_MIFARESTD_PROP_1ST_CONFIG 0 /*!< No proprietary forum sector found */ +#define PH_FRINFC_MIFARESTD_PROP_2ND_CONFIG 1 /*!< Here the proprietary + forum sector exists after NFC forum + sector */ +#define PH_FRINFC_MIFARESTD_PROP_3RD_CONFIG 2 /*!< Here the proprietary + forum sector exists before NFC forum + sector */ +/*@}*/ + +/*! + * \name Mifare Standard - NDEF Compliant Flags + * + */ +/*@{*/ +#define PH_FRINFC_MIFARESTD_MADSECT_ACS_BYTE6 0x78 /*!< Access Bit for Byte 6 in + MAD sector trailer */ +#define PH_FRINFC_MIFARESTD_MADSECT_ACS_BYTE7 0x77 /*!< Access Bit for Byte 7 in + MAD sector trailer */ +#define PH_FRINFC_MIFARESTD_NFCSECT_ACS_BYTE6 0x7F /*!< Access Bit for Byte 6 in + NFC forum sector trailer */ +#define PH_FRINFC_MIFARESTD_NFCSECT_ACS_BYTE7 0x07 /*!< Access Bit for Byte 7 in + NFC forum sector trailer */ +#define PH_FRINFC_MIFARESTD_ACS_BYTE8 0x88 /*!< Access Bit for Byte 8 in + all sector trailer */ +#define PH_FRINFC_MIFARESTD_NFCSECT_RDACS_BYTE6 0x07 /*!< Access Bit for Byte 6 in + NFC forum sector trailer for + Read Only State */ +#define PH_FRINFC_MIFARESTD_NFCSECT_RDACS_BYTE7 0x8F /*!< Access Bit for Byte 7 in + NFC forum sector trailer + Read Only State */ +#define PH_FRINFC_MIFARESTD_NFCSECT_RDACS_BYTE8 0x0F /*!< Access Bit for Byte 8 in + NFC forum sector trailer + Read Only State */ +/*@}*/ + +/*! + * \name Mifare Standard - Mifare Standard constants + * + */ +/*@{*/ +#define MIFARE_MAX_SEND_BUF_TO_READ 1 /*!< Send Length for Reading a Block */ +#define MIFARE_MAX_SEND_BUF_TO_WRITE 17 /*!< Send Length for writing a Block */ +#define MIFARE_AUTHENTICATE_CMD_LENGTH 7 /*!< Send Length for authenticating a Block */ +/*@}*/ + +/*! + * \name Mifare standard - Constants + * + */ +/*@{*/ +#define PH_FRINFC_MIFARESTD_MAD_BLK0 0 /*!< Block number 0 */ +#define PH_FRINFC_MIFARESTD_MAD_BLK1 1 /*!< Block number 1 */ +#define PH_FRINFC_MIFARESTD_MAD_BLK2 2 /*!< Block number 2 */ +#define PH_FRINFC_MIFARESTD_MAD_BLK3 3 /*!< Block number 3 */ +#define PH_FRINFC_MIFARESTD_BLK4 4 /*!< Block number 4 */ +#define PH_FRINFC_MIFARESTD_BLK5 5 /*!< Block number 5 */ +#define PH_FRINFC_MIFARESTD_BLK6 6 /*!< Block number 6 */ +#define PH_FRINFC_MIFARESTD_BLK7 7 /*!< Block number 7 */ +#define PH_FRINFC_MIFARESTD_BLK8 8 /*!< Block number 8 */ +#define PH_FRINFC_MIFARESTD_BLK9 9 /*!< Block number 9 */ +#define PH_FRINFC_MIFARESTD_BLK10 10 /*!< Block number 10 */ +#define PH_FRINFC_MIFARESTD_BLK11 11 /*!< Block number 11 */ +#define PH_FRINFC_MIFARESTD_BLK12 12 /*!< Block number 12 */ +#define PH_FRINFC_MIFARESTD_BLK13 13 /*!< Block number 13 */ +#define PH_FRINFC_MIFARESTD_BLK14 14 /*!< Block number 14 */ +#define PH_FRINFC_MIFARESTD_BLK15 15 /*!< Block number 15 */ +#define PH_FRINFC_MIFARESTD_MAD_BLK16 16 /*!< Block number 16 */ +#define PH_FRINFC_MIFARESTD_MAD_BLK63 63 /*!< Block number 63 */ +#define PH_FRINFC_MIFARESTD_MAD_BLK64 64 /*!< Block number 64 */ +#define PH_FRINFC_MIFARESTD_MAD_BLK65 65 /*!< Block number 65 */ +#define PH_FRINFC_MIFARESTD_MAD_BLK66 66 /*!< Block number 66 */ +#define PH_FRINFC_MIFARESTD_MAD_BLK67 67 /*!< Block number 67 */ +#define PH_FRINFC_MIFARESTD4K_BLK128 128 /*!< Block number 128 for Mifare 4k */ +#define PH_FRINFC_MIFARESTD_SECTOR_NO0 0 /*!< Sector 0 */ +#define PH_FRINFC_MIFARESTD_SECTOR_NO1 1 /*!< Sector 1 */ +#define PH_FRINFC_MIFARESTD_SECTOR_NO16 16 /*!< Sector 16 */ +#define PH_FRINFC_MIFARESTD_SECTOR_NO39 39 /*!< Sector 39 */ +#define PH_FRINFC_MIFARESTD_SECTOR_NO32 32 /*!< Sector 32 */ +#define PH_FRINFC_MIFARESTD4K_TOTAL_SECTOR 40 /*!< Sector 40 */ +#define PH_FRINFC_MIFARESTD1K_TOTAL_SECTOR 16 /*!< Sector 40 */ +#define PH_FRINFC_MIFARESTD_BYTES_READ 16 /*!< Bytes read */ +#define PH_FRINFC_MIFARESTD_BLOCK_BYTES 16 /*!< Bytes per block */ +#define PH_FRINFC_MIFARESTD_SECTOR_BLOCKS 16 /*!< Blocks per sector */ +#define PH_FRINFC_MIFARESTD_WR_A_BLK 17 /*!< 17 bytes (including current block) + are given to transfer */ +#define PH_FRINFC_MIFARESTD4K_MAX_BLOCKS 210 /*!< Maximum number of Mifare 4k Blocks + excluding sector trailer */ +#define PH_FRINFC_MIFARESTD1K_MAX_BLK 63 /*!< Maximum number of Mifare 1k blocks + including the sector trailer*/ +#define PH_FRINFC_MIFARESTD4K_MAX_BLK 254 /*!< Maximum number of Mifare 4k blocks + including the sector trailer*/ +#define PH_FRINFC_MIFARESTD_FLAG1 1 /*!< Flag to set 1 */ +#define PH_FRINFC_MIFARESTD_FLAG0 0 /*!< Flag to set 0 */ +#define PH_FRINFC_MIFARESTD_INC_1 1 /*!< increment by 1 */ +#define PH_FRINFC_MIFARESTD_INC_2 2 /*!< increment by 2 */ +#define PH_FRINFC_MIFARESTD_INC_3 3 /*!< increment by 3 */ +#define PH_FRINFC_MIFARESTD_INC_4 4 /*!< increment by 4 */ +#define PH_FRINFC_MIFARESTD_VAL0 0 /*!< Value initialised to 0 */ +#define PH_FRINFC_MIFARESTD_VAL1 1 /*!< Value initialised to 1 */ +#define PH_FRINFC_MIFARESTD_VAL2 2 /*!< Value initialised to 2 */ +#define PH_FRINFC_MIFARESTD_VAL3 3 /*!< Value initialised to 3 */ +#define PH_FRINFC_MIFARESTD_VAL4 4 /*!< Value initialised to 4 */ +#define PH_FRINFC_MIFARESTD_VAL5 5 /*!< Value initialised to 5 */ +#define PH_FRINFC_MIFARESTD_VAL6 6 /*!< Value initialised to 6 */ +#define PH_FRINFC_MIFARESTD_VAL7 7 /*!< Value initialised to 7 */ +#define PH_FRINFC_MIFARESTD_VAL8 8 /*!< Value initialised to 8 */ +#define PH_FRINFC_MIFARESTD_VAL9 9 /*!< Value initialised to 9 */ +#define PH_FRINFC_MIFARESTD_VAL10 10 /*!< Value initialised to 10 */ +#define PH_FRINFC_MIFARESTD_VAL11 11 /*!< Value initialised to 11 */ +#define PH_FRINFC_MIFARESTD_VAL12 12 /*!< Value initialised to 12 */ +#define PH_FRINFC_MIFARESTD_VAL13 13 /*!< Value initialised to 13 */ +#define PH_FRINFC_MIFARESTD_VAL14 14 /*!< Value initialised to 14 */ +#define PH_FRINFC_MIFARESTD_VAL15 15 /*!< Value initialised to 15 */ +#define PH_FRINFC_MIFARESTD_VAL16 16 /*!< Value initialised to 16 */ +#define PH_FRINFC_MIFARESTD_NDEFTLV_L 0xFF /*!< Length of the TLV */ +#define PH_FRINFC_MIFARESTD_NDEFTLV_T 0x03 /*!< Length of the TLV */ +#define PH_FRINFC_MIFARESTD_NDEFTLV_L0 0x00 /*!< Length of the TLV */ +#define PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES0 0 /*!< Number of bytes taken by length (L) of the TLV */ +#define PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES1 1 /*!< Number of bytes taken by length (L) of the TLV */ +#define PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES2 2 /*!< Number of bytes taken by length (L) of the TLV */ +#define PH_FRINFC_MIFARESTD_NDEFTLV_LBYTES3 3 /*!< Number of bytes taken by length (L) of the TLV */ +#define PH_FRINFC_MIFARESTD_PROPTLV_T 0xFD /*!< Type of Proprietary TLV */ +#define PH_FRINFC_MIFARESTD_TERMTLV_T 0xFE /*!< Type of Terminator TLV */ +#define PH_FRINFC_MIFARESTD_NULLTLV_T 0x00 /*!< Type of NULL TLV */ +#define PH_FRINFC_MIFARESTD_LEFTSHIFT8 8 /*!< Left shift by 8 */ +#define PH_FRINFC_MIFARESTD_RIGHTSHIFT8 8 /*!< Right shift by 8 */ +#define PH_FRINFC_MIFARESTD_MASK_FF 0xFF /*!< Mask 0xFF */ +#define PH_FRINFC_MIFARESTD_MASK_GPB_WR 0x03 /*!< Mask 0x03 for GPB byte */ +#define PH_FRINFC_MIFARESTD_MASK_GPB_RD 0x0C /*!< Mask 0xOC for GPB byte */ +#define PH_FRINFC_MIFARESTD_GPB_RD_WR_VAL 0x00 /*!< GPB Read Write value */ +#define PH_FRINFC_MIFARESTD_KEY_LEN 0x06 /*!< MIFARE Std key length */ + +/*@}*/ + + +/*! + * \brief \copydoc page_reg Resets the component instance to the initial state and lets the component forget about + * the list of registered items. Moreover, the lower device is set. + * + * \param[in] NdefMap Pointer to a valid or uninitialised instance of \ref phFriNfc_NdefMap_t . + * + * \note This function has to be called at the beginning, after creating an instance of + * \ref phFriNfc_NdefMap_t . Use this function to reset the instance and/or switch + * to a different underlying device (different NFC device or device mode, or different + * Remote Device). + */ +NFCSTATUS phFriNfc_MifareStdMap_H_Reset( phFriNfc_NdefMap_t *NdefMap); + + + +/*! + * \brief \copydoc page_ovr Initiates Reading of NDEF information from the Remote Device. + * + * The function initiates the reading of NDEF information from a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that receives the NDEF Packet. + * + * \param[in,out] PacketDataLength Pointer to a variable receiving the length of the NDEF packet. + * + * \param[in] Offset Indicates whether the read operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start reading from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start reading + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED No Space in the File to read. + * \retval NFCSTATUS_MORE_INFORMATION There are more bytes to read in the card. + * \retval NFCSTATUS_SUCCESS Last Byte of the card read. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ +NFCSTATUS phFriNfc_MifareStdMap_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + + +/*! + * \brief \copydoc page_ovr Initiates Writing of NDEF information to the Remote Device. + * + * The function initiates the writing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that holds the prepared NDEF Packet. + * + * \param[in,out] PacketDataLength Variable specifying the length of the prepared NDEF packet. + * + * \param[in] Offset Indicates whether the write operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start writing from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start writing + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED Last byte is written to the card after this + * no further writing is possible. + * \retval NFCSTATUS_SUCCESS Buffer provided by the user is completely written + * into the card. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_MifareStdMap_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + + +/*! + * \brief \copydoc page_ovr Check whether a particulat Remote Device is NDEF compliant. + * + * The function checks whether the peer device is NDEF compliant. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ +NFCSTATUS phFriNfc_MifareStdMap_ChkNdef(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_cb Completion Routine, Processing function, needed to avoid long blocking. + * + * The function call scheme is according to \ref grp_interact. No State reset is performed during operation. + * + * \copydoc pphFriNfc_Cr_t + * + * \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion + * Routine in order to be able to notify the component that an I/O has finished and data are + * ready to be processed. + * + */ +void phFriNfc_MifareStdMap_Process( void *Context, + NFCSTATUS Status); + +/*! + * + * The function Convert the Mifare card to ReadOnly. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_STATE The mifare card should be in read_write state to convert card to + * readonly.If any other state the function return NFCSTATUS_INVALID_STATE + *\retval NFCSTATUS_NOT_ALLOWED If card is already in read_only state or initialized state + * + */ +NFCSTATUS phFriNfc_MifareStdMap_ConvertToReadOnly(phFriNfc_NdefMap_t *NdefMap, const uint8_t *ScrtKeyB); + +#endif /* PHFRINFC_MIFARESTDMAP_H */ diff --git a/libnfc-nxp/phFriNfc_MifareULMap.c b/libnfc-nxp/phFriNfc_MifareULMap.c new file mode 100644 index 0000000..15e882e --- /dev/null +++ b/libnfc-nxp/phFriNfc_MifareULMap.c @@ -0,0 +1,3346 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc_MifareUL.c + * \brief This component encapsulates read/write/check ndef/process functionalities, + * for the Mifare UL card. + * + * Project: NFC-FRI + * + * $Date: Wed Feb 17 15:18:08 2010 $ + * $Author: ing07385 $ + * $Revision: 1.36 $ + * $Aliases: NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED + +#include +#include +#include +#include +#include + + +/*! \ingroup grp_file_attributes + * \name NDEF Mapping + * + * File: \ref phFriNfc_MifareUL.c + * + */ +/*@{*/ +#define PHFRINFCNDEFMAP_FILEREVISION "$Revision: 1.35 $" +#define PHFRINFCNDEFMAP_FILEALIASES "$Aliases: NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" +/*@}*/ +/* Completion Helper */ +static void phFriNfc_MifareUL_H_Complete(phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Status); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL. This function reads + * a 16 bytes from the card. + */ +static NFCSTATUS phFriNfc_MfUL_H_Rd16Bytes( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL. This function is + * to find NDEF TLV + */ +static NFCSTATUS phFriNfc_MfUL_H_findNDEFTLV(phFriNfc_NdefMap_t *NdefMap, + uint8_t *CRFlag); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL. This function is + * to check the completing the reading 16 bytes + */ +static NFCSTATUS phFriNfc_MfUL_H_Chk16Bytes(phFriNfc_NdefMap_t *NdefMap, + uint16_t TempLength); + + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL. This function is + * to read 16 bytes for the finding the ndef TLV + */ +static NFCSTATUS phFriNfc_MfUL_H_RdCardfindNdefTLV( phFriNfc_NdefMap_t *NdefMap, + uint8_t BlockNo); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL. This function is + * to check the remaining size of the 3 byte of length field in TLV + */ +static NFCSTATUS phFriNfc_MfUL_H_ChkRemainTLV(phFriNfc_NdefMap_t *NdefMap, + uint8_t *CRFlag); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL. This function is + * to byte and block number of the next TLV in the card and updating the + * remaining free space in the card + */ +static void phFriNfc_MfUL_H_UpdateLen(phFriNfc_NdefMap_t *NdefMap, + uint16_t DataLen); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL. Depending on the + * operation (read/write/check ndef), the next function is called + */ +static NFCSTATUS phFriNfc_MfUL_H_NxtOp(phFriNfc_NdefMap_t *NdefMap, + uint8_t *CRFlag); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL function. This + * function is to copy the read bytes to the internal "ReadBuf" buffer + */ +static NFCSTATUS phFriNfc_MfUL_H_CopyRdBytes(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL function. This + * function is to copy the read bytes to the user buffer + */ +static NFCSTATUS phFriNfc_MfUL_H_CpDataToUserBuf(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL function. This + * function is to write 4 bytes to 1 block in the card + */ +static NFCSTATUS phFriNfc_MfUL_H_Wr4bytes(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL function. This + * function is to check the CC bytes in block 3 card + */ +static NFCSTATUS phFriNfc_MfUL_H_ChkCCBytes(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL function. This + * function is to read the TLVs and then start writing + */ +static NFCSTATUS phFriNfc_MfUL_H_RdBeforeWrite(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL function. This + * function is to call write operation after reading the NDEF TLV block + */ +static NFCSTATUS phFriNfc_MfUL_H_CallWrOp(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL function. This + * function is to process the written data + */ +static NFCSTATUS phFriNfc_MfUL_H_ProWrittenBytes(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL function. This + * function is to fill the send buffer before write + */ +static NFCSTATUS phFriNfc_MfUL_H_fillSendBufToWr(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL function. This + * function is to update the length L of the TLV + */ +static NFCSTATUS phFriNfc_MfUL_H_UpdateWrLen(phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Mifare UL function. This + * function is to write the terminator TLV after writing all the bytes + */ +static NFCSTATUS phFriNfc_MfUL_H_WrTermTLV(phFriNfc_NdefMap_t *NdefMap); + +#ifdef LOCK_BITS_CHECK_ENABLE + static + void + phFriNfc_MfUL_H_ChkLockBits ( + phFriNfc_NdefMap_t *NdefMap); +#endif /* #ifdef LOCK_BITS_CHECK_ENABLE */ + +/*! + * \brief \copydoc select sector function for Mifare UL function. This + * function is to write the terminator TLV after writing all the bytes + */ +static NFCSTATUS phFriNfc_MfUL_H_SelectSector(phFriNfc_NdefMap_t *NdefMap, + uint8_t SectorNo, + uint8_t CmdNo, + uint8_t NextState); + + + +static void phFriNfc_MfUL_H_UpdateCrc( uint8_t ch, + uint16_t *lpwCrc ); + +static void phFriNfc_MfUL_H_ComputeCrc( int CRCType, + uint8_t *Data, + int Length, + uint8_t *TransmitFirst, + uint8_t *TransmitSecond + ); + +static void +phFriNfc_MfUL_CalcByteNum(phFriNfc_NdefMap_t *NdefMap); + + +#define CRC_A 0 +#define CRC_B 1 + + +NFCSTATUS phFriNfc_MifareUL_H_Reset(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + if ( NdefMap == NULL) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* TLV structure initialisation */ + NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_NDEFMAP_MFUL_VAL4; + NdefMap->TLVStruct.BytesRemainLinTLV = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->TLVStruct.NoLbytesinTLV = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->TLVStruct.prevLenByteValue = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + NdefMap->TLVStruct.ActualSize = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->TLVStruct.SetTermTLVFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + NdefMap->TLVStruct.WrLenFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + + /* Mifare UL container initialisation */ + NdefMap->MifareULContainer.ByteNumber = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->MifareULContainer.CRindex = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->MifareULContainer.CurrentSector = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->MifareULContainer.CurrentBlock = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->MifareULContainer.InternalLength = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->MifareULContainer.ReadBufIndex = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->MifareULContainer.ReadWriteCompleteFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + NdefMap->MifareULContainer.RemainingSize = PH_FRINFC_NDEFMAP_MFUL_VAL0; + + /* Fill all the structure related buffer to ZERO */ + (void)memset(NdefMap->TLVStruct.NdefTLVBuffer, + PH_FRINFC_NDEFMAP_MFUL_VAL0, + PH_FRINFC_NDEFMAP_MFUL_VAL4); + (void)memset(NdefMap->MifareULContainer.Buffer, + PH_FRINFC_NDEFMAP_MFUL_VAL0, + PH_FRINFC_NDEFMAP_MFUL_VAL4); + (void)memset(NdefMap->MifareULContainer.InternalBuf, + PH_FRINFC_NDEFMAP_MFUL_VAL0, + PH_FRINFC_NDEFMAP_MFUL_VAL4); + (void)memset(NdefMap->MifareULContainer.ReadBuf, + PH_FRINFC_NDEFMAP_MFUL_VAL0, + PH_FRINFC_NDEFMAP_MFUL_VAL64); + } + return Result; +} + +/*! + * \brief Initiates Reading of NDEF information from the Mifare UL. + * + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action + * has been triggered. + */ + +NFCSTATUS phFriNfc_MifareUL_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + + if((NdefMap != NULL) && (PacketData != NULL) && (PacketDataLength != NULL) && + (*PacketDataLength != PH_FRINFC_NDEFMAP_MFUL_VAL0) && + (Offset <= PH_FRINFC_NDEFMAP_SEEK_BEGIN) && + (NdefMap->CompletionRoutine->CompletionRoutine != NULL) && + (NdefMap->CompletionRoutine->Context != NULL ) && + ((NdefMap->CardState != PH_NDEFMAP_CARD_STATE_INITIALIZED) && + (NdefMap->CardState != PH_NDEFMAP_CARD_STATE_INVALID))) + { + /*Register PacketData to Data Buffer of NdefMap */ + NdefMap->ApduBuffer = PacketData; + /*Register PacketDataLength to Data Length of NdefMap */ + NdefMap->ApduBufferSize = *PacketDataLength ; + /* To return actual number of bytes read to the caller */ + NdefMap->NumOfBytesRead = PacketDataLength ; + *NdefMap->NumOfBytesRead = 0; + + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || ( NdefMap->PrevOperation == + PH_FRINFC_NDEFMAP_WRITE_OPE)) + { + NdefMap->MifareULContainer.CurrentBlock = PH_FRINFC_NDEFMAP_MFUL_BLOCK4; + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_NDEFMAP_MFUL_BLOCK4; + NdefMap->MifareULContainer.RemainingSize = NdefMap->CardMemSize; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + NdefMap->TLVStruct.NoLbytesinTLV = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->MifareULContainer.ReadBufIndex = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->MifareULContainer.ReadWriteCompleteFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + } + + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + NdefMap->MifareULContainer.CRindex = PH_FRINFC_NDEFMAP_CR_RD_NDEF; + + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (NdefMap->MifareULContainer.ReadWriteCompleteFlag == + PH_FRINFC_NDEFMAP_MFUL_FLAG1)) + { + /* No space on card for reading : we have already + reached the end of file ! + Offset is set to Continue Operation */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + NdefMap->Offset = (((Offset != PH_FRINFC_NDEFMAP_SEEK_BEGIN) && + ( NdefMap->PrevOperation != PH_FRINFC_NDEFMAP_READ_OPE))? + PH_FRINFC_NDEFMAP_SEEK_BEGIN: + Offset); + + Result = ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + phFriNfc_MfUL_H_RdCardfindNdefTLV(NdefMap, NdefMap->MifareULContainer.CurrentBlock): + phFriNfc_MfUL_H_CpDataToUserBuf(NdefMap)); + } + } + return Result; +} + + +/*! + * \brief Initiates writing of NDEF information to the Mifare UL. + * + * The function initiates the writing of NDEF information to a Mifare UL. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action + * has been triggered. + */ + +NFCSTATUS phFriNfc_MifareUL_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + + + + if((NdefMap != NULL) && (PacketData != NULL) && (PacketDataLength != NULL) && + (*PacketDataLength != PH_FRINFC_NDEFMAP_MFUL_VAL0) && + (Offset <= PH_FRINFC_NDEFMAP_SEEK_BEGIN) && + (NdefMap->CompletionRoutine->CompletionRoutine != NULL) && + (NdefMap->CompletionRoutine->Context != NULL ) && + ((NdefMap->CardState != PH_NDEFMAP_CARD_STATE_READ_ONLY) && + (NdefMap->CardState != PH_NDEFMAP_CARD_STATE_INVALID))) + { + NdefMap->MifareULContainer.CRindex = PH_FRINFC_NDEFMAP_CR_WR_NDEF; + /*Register PacketData to Data Buffer of NdefMap */ + NdefMap->ApduBuffer = PacketData; + /*Register PacketDataLength to Data Length of NdefMap */ + NdefMap->ApduBufferSize = *PacketDataLength ; + /* To return actual number of bytes read to the caller */ + NdefMap->WrNdefPacketLength = PacketDataLength ; + *NdefMap->WrNdefPacketLength = 0; + + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || ( NdefMap->PrevOperation == + PH_FRINFC_NDEFMAP_READ_OPE)) + { + NdefMap->MifareULContainer.CurrentSector = NdefMap->TLVStruct.NdefTLVSector; + NdefMap->MifareULContainer.CurrentBlock = NdefMap->TLVStruct.NdefTLVBlock; + NdefMap->TLVStruct.TcheckedinTLVFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + NdefMap->TLVStruct.NoLbytesinTLV = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->MifareULContainer.ReadBufIndex = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->MifareULContainer.ReadWriteCompleteFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + NdefMap->TLVStruct.WrLenFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + NdefMap->MifareULContainer.InternalLength = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->MifareULContainer.RemainingSize = + (NdefMap->CardMemSize - + (((NdefMap->TLVStruct.NdefTLVBlock - + PH_FRINFC_NDEFMAP_MFUL_BYTE4) * + PH_FRINFC_NDEFMAP_MFUL_BYTE4) + + NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_NDEFMAP_MFUL_VAL1)); + } + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + NdefMap->MifareULContainer.CRindex = PH_FRINFC_NDEFMAP_CR_WR_NDEF; + + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (NdefMap->MifareULContainer.ReadWriteCompleteFlag == + PH_FRINFC_NDEFMAP_MFUL_FLAG1)) + { + /* No space on card for reading : we have already + reached the end of file ! + Offset is set to Continue Operation */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + NdefMap->Offset = (((Offset != PH_FRINFC_NDEFMAP_SEEK_BEGIN) && + ( NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE))? + PH_FRINFC_NDEFMAP_SEEK_BEGIN: + Offset); + + if (NdefMap->TLVStruct.NdefTLVSector == 1) + { + NdefMap->MifareULContainer.CurrentSector = 1; + + /* Change to sector 1 */ + Result = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 1, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_WRITE_INIT_1); + + } + else + { + Result = ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + phFriNfc_MfUL_H_RdBeforeWrite(NdefMap): + phFriNfc_MfUL_H_fillSendBufToWr(NdefMap)); + } + } + } + + + return Result; +} + + + +/*! + * \brief Check whether a particular Mifare UL is NDEF compliant. + * + * The function checks whether the peer device is NDEF compliant. + * + */ + +NFCSTATUS phFriNfc_MifareUL_ChkNdef( phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint8_t index=0, + pSensRes[2] = {0}; + + /* set the data for additional data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + NdefMap->psDepAdditionalInfo.NAD = 0; + + /* + * Changed + * Description: CardInfo106 replase + */ + + /* retrive remote card information */ + pSensRes[0] = NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA[0]; + + NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_NDEFMAP_MFUL_VAL4; +#ifdef LOCK_BITS_CHECK_ENABLE + NdefMap->MifareULContainer.CurrentBlock = PH_FRINFC_NDEFMAP_MFUL_BLOCK2; +#else + NdefMap->MifareULContainer.CurrentBlock = PH_FRINFC_NDEFMAP_MFUL_BLOCK3; +#endif /* #ifdef LOCK_BITS_CHECK_ENABLE */ + NdefMap->MifareULContainer.CRindex = PH_FRINFC_NDEFMAP_CR_CHK_NDEF; + + /* Check for Mifare Bit information */ + if (((pSensRes[0] & PH_FRINFC_NDEFMAP_MFUL_CHECK_RESP) == PH_FRINFC_NDEFMAP_MFUL_CHECK_RESP)) + { + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE; + /* set the offset*/ + NdefMap->SendRecvBuf[index] = NdefMap->MifareULContainer.CurrentBlock; + + /*set the send length*/ + NdefMap->SendLength = PH_FRINFC_NDEFMAP_MFUL_MAX_SEND_BUF_TO_READ; + + /* Change the state to check ndef compliancy */ + NdefMap->State = PH_FRINFC_NDEFMAP_MFUL_STATE_CHK_NDEF_COMP; + + /* Set the card type as Mifare UL */ + NdefMap->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD; + + /* set the cmd to mifare read*/ + /* + * Changed + * Description: phHal_eMifareCmdListMifareRead replace with phHal_eMifareRead + */ + NdefMap->Cmd.MfCmd = phHal_eMifareRead; + + /* Set the CR and context for Mifare operations*/ + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_MifareUL_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + /*Set the Length*/ + *NdefMap->SendRecvLength = PH_FRINFC_NDEFMAP_MF_READ_BLOCK_SIZE; + + + /*Call the Overlapped HAL Transceive function */ + status = phFriNfc_OvrHal_Transceive(NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + } + else + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_REMOTE_DEVICE); + } + return status; +} + +static void +phFriNfc_MfUL_CalcByteNum(phFriNfc_NdefMap_t *NdefMap) +{ + uint8_t i = PH_FRINFC_NDEFMAP_MFUL_VAL0; + uint16_t TemLength = PH_FRINFC_NDEFMAP_MFUL_VAL0; + + + for (i = 0; i < 16; i++) + { + if ((NdefMap->MifareULContainer.ReadBuf[i] == + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_T) && + ((NdefMap->MifareULContainer.ReadBuf[i + 1] == + NdefMap->TLVStruct.ActualSize) || + (NdefMap->MifareULContainer.ReadBuf[i + 1] == 0xFF))) + { + if (NdefMap->MifareULContainer.ReadBuf[i + 1] == 0xFF) + { + TemLength = NdefMap->MifareULContainer.ReadBuf[i + 2] | + ((uint16_t)NdefMap->MifareULContainer.ReadBuf[i + 3] << 8); + + if (TemLength == NdefMap->TLVStruct.ActualSize) + { + NdefMap->MifareULContainer.ByteNumber = i + 1; + break; + } + } + else + { + NdefMap->MifareULContainer.ByteNumber = i + 1; + break; + } + } + } + + return; +} + + +#ifdef LOCK_BITS_CHECK_ENABLE + +#define MIF_UL_LOCK_BIT_CHECK 0xFF +#define MIF_UL_LOCK_BIT_0_VALUE 0x0F +#define MIF_UL_LOCK_BIT_1_VALUE 0x00 + +static +void +phFriNfc_MfUL_H_ChkLockBits ( + phFriNfc_NdefMap_t *NdefMap) +{ + uint8_t index = 2; + + if (((NdefMap->SendRecvBuf[index] & + MIF_UL_LOCK_BIT_CHECK) > MIF_UL_LOCK_BIT_0_VALUE) || + (MIF_UL_LOCK_BIT_1_VALUE != + (NdefMap->SendRecvBuf[(index + 1)] & MIF_UL_LOCK_BIT_CHECK))) + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY; + } +} + +#endif /* #ifdef LOCK_BITS_CHECK_ENABLE */ + +/*! + * \brief Completion Routine, Processing function, needed to avoid long + * blocking. + * \note The lower (Overlapped HAL) layer must register a pointer to + * this function as a Completion + * Routine in order to be able to notify the component that an I/O + * has finished and data are ready to be processed. + * + */ + +void phFriNfc_MifareUL_Process( void *Context, + NFCSTATUS Status) + +{ + + uint8_t index = PH_FRINFC_NDEFMAP_MFUL_VAL0, + i = PH_FRINFC_NDEFMAP_MFUL_VAL0; + phFriNfc_NdefMap_t *NdefMap; + uint16_t TemLength = PH_FRINFC_NDEFMAP_MFUL_VAL0; + /*uint16_t TempByte = PH_FRINFC_NDEFMAP_MFUL_VAL0; */ + static uint8_t CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + + /* set the context to Map module */ + + NdefMap = (phFriNfc_NdefMap_t *)Context; + + if ( Status == NFCSTATUS_SUCCESS ) + { + switch (NdefMap->State) + { + case PH_FRINFC_NDEFMAP_MFUL_STATE_CHK_NDEF_COMP: + if (*NdefMap->SendRecvLength == + PH_FRINFC_NDEFMAP_MFUL_RDBYTES_16) + { + /* Checks for the Ndef Compliency and validy of the memory size*/ + Status = phFriNfc_MfUL_H_ChkCCBytes(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_SUCCESS)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + +#ifdef LOCK_BITS_CHECK_ENABLE + + /* Check for lock bits */ + if (NFCSTATUS_SUCCESS == Status) + { + phFriNfc_MfUL_H_ChkLockBits(NdefMap); + } + +#endif /* #ifdef LOCK_BITS_CHECK_ENABLE */ + + /* Find the NDEF TLV */ + NdefMap->MifareULContainer.CurrentBlock = PH_FRINFC_NDEFMAP_MFUL_BLOCK4; + Status = ((Status != NFCSTATUS_SUCCESS)? + Status: + phFriNfc_MfUL_H_RdCardfindNdefTLV(NdefMap, + NdefMap->MifareULContainer.CurrentBlock)); + CRFlag = (uint8_t)(((Status != NFCSTATUS_PENDING ) || + (CRFlag == PH_FRINFC_NDEFMAP_MFUL_FLAG1))? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + +#ifdef PH_HAL4_ENABLE + if ((Status != NFCSTATUS_PENDING ) && + (Status != NFCSTATUS_SUCCESS)) + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } +#endif /* #ifdef PH_HAL4_ENABLE */ + } + break; + + + case PH_FRINFC_NDEFMAP_MFUL_STATE_READ: + /* check the received bytes size equals 16 bytes*/ + if (*NdefMap->SendRecvLength == + PH_FRINFC_NDEFMAP_MFUL_RDBYTES_16) + { + if(NdefMap->MifareULContainer.ReadBufIndex < + (NdefMap->TLVStruct.ActualSize + (((NdefMap->TLVStruct.NdefTLVBlock - + PH_FRINFC_NDEFMAP_MFUL_BLOCK4) + * PH_FRINFC_NDEFMAP_MFUL_VAL4) + (NdefMap->TLVStruct.NdefTLVByte - 1) + 4))) + + { + Status = phFriNfc_MfUL_H_CopyRdBytes(NdefMap); + } + + if (Status == NFCSTATUS_SUCCESS) + { + if(NdefMap->MifareULContainer.ReadBufIndex >= + (NdefMap->TLVStruct.ActualSize + (((NdefMap->TLVStruct.NdefTLVBlock - + PH_FRINFC_NDEFMAP_MFUL_BLOCK4) + * PH_FRINFC_NDEFMAP_MFUL_VAL4) + (NdefMap->TLVStruct.NdefTLVByte - 1) + 4))) + { + + phFriNfc_MfUL_CalcByteNum(NdefMap); +#if 0 + for (i = 0; i < 16; i++) + { + if ((NdefMap->MifareULContainer.ReadBuf[i] == + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_T) && + ((NdefMap->MifareULContainer.ReadBuf[i + 1] == + NdefMap->TLVStruct.ActualSize) || + (NdefMap->MifareULContainer.ReadBuf[i + 1] == 0xFF))) + { + if (NdefMap->MifareULContainer.ReadBuf[i + 1] == 0xFF) + { + TemLength = NdefMap->MifareULContainer.ReadBuf[i + 2] | + ((uint16_t)NdefMap->MifareULContainer.ReadBuf[i + 3] << 8); + + if (TemLength == NdefMap->TLVStruct.ActualSize) + { + NdefMap->MifareULContainer.ByteNumber = i + 1; + break; + } + } + else + { + NdefMap->MifareULContainer.ByteNumber = i + 1; + break; + } + } + } +#endif + + if (NdefMap->MifareULContainer.ReadBuf + [NdefMap->MifareULContainer.ByteNumber] == 0xFF) + { + NdefMap->MifareULContainer.ByteNumber = + NdefMap->MifareULContainer.ByteNumber + 3; + } + else + { + NdefMap->MifareULContainer.ByteNumber = + NdefMap->MifareULContainer.ByteNumber + 1; + } + + Status = phFriNfc_MfUL_H_CpDataToUserBuf(NdefMap); + if (NdefMap->MifareULContainer.CurrentSector > 0) + { + NdefMap->MifareULContainer.CurrentSector = 0; + NdefMap->PrevState = PH_FRINFC_NDEFMAP_MFUL_STATE_READ; + + Status = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 1, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RESET_1); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING )? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + } + else + { + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + } + else + { + Status = phFriNfc_MfUL_H_Rd16Bytes(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + } + } + else + { + + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + } + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_WRITE: + Status = phFriNfc_MfUL_H_ProWrittenBytes(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_FND_NDEF_COMP: + if (*NdefMap->SendRecvLength == + PH_FRINFC_NDEFMAP_MFUL_RDBYTES_16) + { + switch(NdefMap->PrevOperation) + { + case PH_FRINFC_NDEFMAP_CHECK_OPE: + case PH_FRINFC_NDEFMAP_READ_OPE: + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + if(NdefMap->TLVStruct.NoLbytesinTLV > + PH_FRINFC_NDEFMAP_MFUL_VAL0) + { + Status = phFriNfc_MfUL_H_ChkRemainTLV(NdefMap, &CRFlag); + } + else + { + if(NdefMap->TLVStruct.NdefTLVFoundFlag != + PH_FRINFC_NDEFMAP_MFUL_FLAG1) + { + /* Find the NDEF TLV */ + Status = phFriNfc_MfUL_H_findNDEFTLV(NdefMap, &CRFlag); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING )? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + } + } + if((NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_NDEFMAP_MFUL_FLAG1) && + (NdefMap->TLVStruct.NoLbytesinTLV == + PH_FRINFC_NDEFMAP_MFUL_VAL0)) + { + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + /* Ndef TLV found, so call the next function depending on the + check/read/write ndef operation */ + + if (NdefMap->MifareULContainer.CurrentSector > 0) + { + NdefMap->MifareULContainer.CurrentSector = 0; + NdefMap->PrevState = PH_FRINFC_NDEFMAP_MFUL_STATE_FND_NDEF_COMP; + + Status = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 1, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RESET_1); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING )? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + } + else + { + /* Sector is 0 no need to send sector select */ + Status = phFriNfc_MfUL_H_NxtOp(NdefMap, &CRFlag); + } + } + +#ifdef PH_HAL4_ENABLE + if ((Status != NFCSTATUS_PENDING ) && + (Status != NFCSTATUS_SUCCESS) && + (PH_FRINFC_NDEFMAP_CHECK_OPE == + NdefMap->PrevOperation)) + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } +#endif /* #ifdef PH_HAL4_ENABLE */ + break; + + case PH_FRINFC_NDEFMAP_WRITE_OPE: + /* Remove UpdateWrLen */ + Status = ((NdefMap->TLVStruct.WrLenFlag == + PH_FRINFC_NDEFMAP_MFUL_FLAG1)? + phFriNfc_MfUL_H_UpdateWrLen(NdefMap): + phFriNfc_MfUL_H_CallWrOp(NdefMap)); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + break; + + default: + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + break; + + } + } + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_TERM_TLV: + Status = phFriNfc_MfUL_H_UpdateWrLen(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_WR_LEN_TLV: + if(((((NdefMap->TLVStruct.NdefTLVByte - + PH_FRINFC_NDEFMAP_MFUL_VAL1) == + PH_FRINFC_NDEFMAP_MFUL_VAL3) && + (NdefMap->MifareULContainer.CurrentBlock == + (NdefMap->TLVStruct.NdefTLVBlock + + PH_FRINFC_NDEFMAP_MFUL_VAL1))) || + (((NdefMap->TLVStruct.NdefTLVByte - + PH_FRINFC_NDEFMAP_MFUL_VAL1) < + PH_FRINFC_NDEFMAP_MFUL_VAL3) && ( + NdefMap->MifareULContainer.CurrentBlock == + NdefMap->TLVStruct.NdefTLVBlock)))) + { + (void)memcpy(NdefMap->MifareULContainer.InternalBuf, + NdefMap->MifareULContainer.Buffer, + NdefMap->MifareULContainer.InternalLength); + } + (void)memcpy(NdefMap->TLVStruct.NdefTLVBuffer, + NdefMap->MifareULContainer.Buffer, + PH_FRINFC_NDEFMAP_MFUL_VAL4); + + NdefMap->CardState =(uint8_t) ((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INITIALIZED)? + PH_NDEFMAP_CARD_STATE_READ_WRITE: + NdefMap->CardState); + NdefMap->ApduBuffIndex = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->NumOfBytesWritten = PH_FRINFC_NDEFMAP_MFUL_VAL0; + + if (NdefMap->MifareULContainer.CurrentSector > 0) + { + /* Reset sector */ + NdefMap->MifareULContainer.CurrentSector = 0; + NdefMap->PrevState = PH_FRINFC_NDEFMAP_MFUL_STATE_WR_LEN_TLV; + + Status = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 1, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RESET_1); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + } + else + { + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_CHK_1: + /* check the received bytes size equals 1 byte*/ + if (*NdefMap->SendRecvLength == + PH_FRINFC_NDEFMAP_MFUL_VAL1) + { + if (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] == 0x0A) + { + /* Send second command */ + Status = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 2, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_CHK_2); + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + + } + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_CHK_2: + { + NdefMap->MifareULContainer.CurrentBlock += + PH_FRINFC_NDEFMAP_MFUL_BLOCK4; + + Status = phFriNfc_MfUL_H_RdCardfindNdefTLV(NdefMap, + NdefMap->MifareULContainer.CurrentBlock); + } + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_READ_1: + /* check the received bytes size equals 1 byte*/ + if (*NdefMap->SendRecvLength == + PH_FRINFC_NDEFMAP_MFUL_VAL1) + { + if (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] == 0x0A) + { + /* Send second command */ + Status = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 2, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_READ_2); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG0; + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + + } + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_READ_2: + { + if (NdefMap->MifareULContainer.CurrentBlock == 0xFF) + { + NdefMap->MifareULContainer.CurrentBlock = 0; + } + else + { + NdefMap->MifareULContainer.CurrentBlock = + (NdefMap->TLVStruct.NdefTLVBlock / 4) * 4; + } + + Status = phFriNfc_MfUL_H_Rd16Bytes(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + } + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_WRITE_1: + /* check the received bytes size equals 1 byte*/ + if (*NdefMap->SendRecvLength == + PH_FRINFC_NDEFMAP_MFUL_VAL1) + { + if (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] == 0x0A) + { + /* Send second command */ + Status = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 2, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_WRITE_2); + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + + } + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_WRITE_2: + { + NdefMap->MifareULContainer.CurrentBlock = 0; + Status = phFriNfc_MfUL_H_fillSendBufToWr(NdefMap); + + if((Status == NFCSTATUS_SUCCESS) && + (NdefMap->TLVStruct.SetTermTLVFlag != + PH_FRINFC_NDEFMAP_MFUL_FLAG1) && + (NdefMap->MifareULContainer.RemainingSize > + PH_FRINFC_NDEFMAP_MFUL_VAL0)) + { + Status = phFriNfc_MfUL_H_WrTermTLV(NdefMap); + } + else + { + if((Status == NFCSTATUS_SUCCESS) && + (NdefMap->TLVStruct.SetTermTLVFlag == + PH_FRINFC_NDEFMAP_MFUL_FLAG1)) + { + Status = phFriNfc_MfUL_H_UpdateWrLen(NdefMap); + } + } + + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + } + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_WRITE_INIT_1: + /* check the received bytes size equals 1 byte*/ + if (*NdefMap->SendRecvLength == + PH_FRINFC_NDEFMAP_MFUL_VAL1) + { + if (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] == 0x0A) + { + /* Send second command */ + Status = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 2, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_WRITE_INIT_2); + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + + } + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_WRITE_INIT_2: + { + Status = ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + phFriNfc_MfUL_H_RdBeforeWrite(NdefMap): + phFriNfc_MfUL_H_fillSendBufToWr(NdefMap)); + + + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + } + break; + + + case PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RW_1: + /* check the received bytes size equals 1 byte*/ + if (*NdefMap->SendRecvLength == + PH_FRINFC_NDEFMAP_MFUL_VAL1) + { + if (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] == 0x0A) + { + /* Send second command */ + Status = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 2, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RW_2); + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + + } + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RW_2: + { + NdefMap->MifareULContainer.CurrentBlock = 0; + + NdefMap->SendRecvBuf[index] = + NdefMap->MifareULContainer.CurrentBlock; + index++; + NdefMap->SendRecvBuf[index] = + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_L; + index++; + + if((((NdefMap->TLVStruct.NdefTLVByte - + PH_FRINFC_NDEFMAP_MFUL_VAL1) == PH_FRINFC_NDEFMAP_MFUL_VAL0) || + ((NdefMap->TLVStruct.NdefTLVByte - PH_FRINFC_NDEFMAP_MFUL_VAL1) + == PH_FRINFC_NDEFMAP_MFUL_VAL3))) + { + /* Length to know how many bytes has to be written to the card */ + TemLength = (((NdefMap->TLVStruct.NdefTLVByte - PH_FRINFC_NDEFMAP_MFUL_VAL1) == + PH_FRINFC_NDEFMAP_MFUL_VAL0)? + PH_FRINFC_NDEFMAP_MFUL_VAL2: + PH_FRINFC_NDEFMAP_MFUL_VAL3); + + if(NdefMap->ApduBufferSize >= TemLength) + { + /* Prepare the receive buffer */ + (void)memcpy(&(NdefMap->SendRecvBuf[ + index]), + &(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + TemLength); + + /* Number of bytes written to the card from user buffer */ + NdefMap->NumOfBytesWritten = TemLength; + + index = index+(uint8_t)TemLength; + /* Exact number of bytes written in the card including TLV */ + *NdefMap->DataCount = (index - PH_FRINFC_NDEFMAP_MFUL_VAL1); + } + else + { + /* Prepare the receive buffer */ + (void)memcpy(&(NdefMap->SendRecvBuf[ + index]), + &(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + (uint16_t)NdefMap->ApduBufferSize); + + /* Number of bytes written to the card from user buffer */ + NdefMap->NumOfBytesWritten = (uint16_t)NdefMap->ApduBufferSize; + + index= index +(uint8_t)NdefMap->ApduBufferSize; + /* Exact number of bytes written in the card including TLV */ + *NdefMap->DataCount = (index - PH_FRINFC_NDEFMAP_MFUL_VAL1); + + for(i = index; i < PH_FRINFC_NDEFMAP_MFUL_WR_A_BLK; i++) + { + NdefMap->SendRecvBuf[i] = (uint8_t)((i == index)? + PH_FRINFC_NDEFMAP_MFUL_TERMTLV: + PH_FRINFC_NDEFMAP_MFUL_NULLTLV); + NdefMap->TLVStruct.SetTermTLVFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + } + + /* store the bytes in buffer till the bytes are + written in a block */ + (void)memcpy(NdefMap->MifareULContainer.Buffer, + &(NdefMap->SendRecvBuf[ + PH_FRINFC_NDEFMAP_MFUL_VAL1]), + (PH_FRINFC_NDEFMAP_MFUL_WR_A_BLK - + PH_FRINFC_NDEFMAP_MFUL_VAL1)); + + (void)memcpy(NdefMap->TLVStruct.NdefTLVBuffer, + NdefMap->MifareULContainer.Buffer, + (PH_FRINFC_NDEFMAP_MFUL_WR_A_BLK - + PH_FRINFC_NDEFMAP_MFUL_VAL1)); + + /* Change the state to check ndef compliancy */ + NdefMap->State = PH_FRINFC_NDEFMAP_MFUL_STATE_WRITE; + + Status = phFriNfc_MfUL_H_Wr4bytes(NdefMap); + } + + + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + } + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RESET_1: + /* check the received bytes size equals 1 byte*/ + if (*NdefMap->SendRecvLength == + PH_FRINFC_NDEFMAP_MFUL_VAL1) + { + if (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] == 0x0A) + { + /* Send second command */ + Status = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 2, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RESET_2); + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + + } + break; + + case PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RESET_2: + { + if (NdefMap->PrevState == PH_FRINFC_NDEFMAP_MFUL_STATE_FND_NDEF_COMP) + { + Status = phFriNfc_MfUL_H_NxtOp(NdefMap, &CRFlag); + } + else if (NdefMap->PrevState == PH_FRINFC_NDEFMAP_MFUL_STATE_READ) + { + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + else if (NdefMap->PrevState == PH_FRINFC_NDEFMAP_MFUL_STATE_WRITE) + { + Status = phFriNfc_MfUL_H_UpdateWrLen(NdefMap); + CRFlag = (uint8_t)((Status != NFCSTATUS_PENDING)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + } + else if (NdefMap->PrevState == PH_FRINFC_NDEFMAP_MFUL_STATE_WR_LEN_TLV) + { + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + else + { + /* read error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_READ_FAILED); + CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + + } + } + break; + + default: + /*set the invalid state*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_DEVICE_REQUEST); + phFriNfc_MifareUL_H_Complete(NdefMap, Status); + break; + } + if(CRFlag == PH_FRINFC_NDEFMAP_MFUL_FLAG1) + { + /* call the CR routine*/ + phFriNfc_MifareUL_H_Complete(NdefMap, Status); + } + } + else + { + phFriNfc_MifareUL_H_Complete(NdefMap,Status); + } +} + +static NFCSTATUS phFriNfc_MfUL_H_ChkCCBytes(phFriNfc_NdefMap_t *NdefMap ) +{ + NFCSTATUS Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + +#ifdef LOCK_BITS_CHECK_ENABLE + switch(NdefMap->SendRecvBuf[7]) +#else + switch(NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_BYTE3]) +#endif /* #ifdef LOCK_BITS_CHECK_ENABLE */ + { + case PH_FRINFC_NDEFMAP_MFUL_CC_BYTE3_RW: + /* This state can be either INITIALISED or READWRITE. but default + is INITIALISED */ + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED; + break; + + case PH_FRINFC_NDEFMAP_MFUL_CC_BYTE3_RO: + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY; + break; + + default : + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } + + + + /* Check for Ndef compliancy : 0 and 1 byte spcifies the ndef compliancy + 2 byte specifies the version of the MF UL tag*/ +#ifdef LOCK_BITS_CHECK_ENABLE + if(( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_BYTE4] == +#else + if(( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_BYTE0] == +#endif /* #ifdef LOCK_BITS_CHECK_ENABLE */ + PH_FRINFC_NDEFMAP_MFUL_CC_BYTE0) && ( + (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INITIALIZED) || + (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_ONLY))) + { + /* Check the version number */ + Result =phFriNfc_MapTool_ChkSpcVer( NdefMap, +#ifdef LOCK_BITS_CHECK_ENABLE + 5); + +#else + PH_FRINFC_NDEFMAP_MFUL_BYTE1); + +#endif /* #ifdef LOCK_BITS_CHECK_ENABLE */ +#if 0 +#ifdef PH_NDEF_MIFARE_ULC + if (Result == NFCSTATUS_SUCCESS) + { +#ifdef LOCK_BITS_CHECK_ENABLE + + if (NdefMap->SendRecvBuf[6] == 0x06) + { + NdefMap->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD; + } + else if (NdefMap->SendRecvBuf[6] == 0x12) + { +// NdefMap->CardType = PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD; + NdefMap->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD; + } + +#else /* #ifdef LOCK_BITS_CHECK_ENABLE */ + + if (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_BYTE2] == 0x06) + { + NdefMap->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD; + } + else if (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_BYTE2] == 0x12) + { +// NdefMap->CardType = PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD; + NdefMap->CardType = PH_FRINFC_NDEFMAP_MIFARE_UL_CARD; + } + +#endif /* #ifdef LOCK_BITS_CHECK_ENABLE */ + else + { + Result = PHNFCSTVAL( CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + } + } +#else + + /* Check the CC header size: Only valid ones are + 0x06 for 48 bytes. */ +#ifdef LOCK_BITS_CHECK_ENABLE + Result = ((( NdefMap->SendRecvBuf[6] != +#else /* #ifdef LOCK_BITS_CHECK_ENABLE */ + Result = ((( NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_BYTE2] != +#endif /* #ifdef LOCK_BITS_CHECK_ENABLE */ + PH_FRINFC_NDEFMAP_MFUL_CC_BYTE2) || (Result != + NFCSTATUS_SUCCESS))? + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE)): + Result); +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ +#endif + NdefMap->MifareULContainer.RemainingSize = + NdefMap->CardMemSize = ((Result == NFCSTATUS_SUCCESS)? +#ifdef LOCK_BITS_CHECK_ENABLE + (NdefMap->SendRecvBuf[6] * +#else /* #ifdef LOCK_BITS_CHECK_ENABLE */ + (NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_BYTE2] * +#endif /* #ifdef LOCK_BITS_CHECK_ENABLE */ + PH_FRINFC_NDEFMAP_MFUL_MUL8): + NdefMap->CardMemSize); + + if (NdefMap->CardMemSize > 256) + { + NdefMap->CardMemSize = NdefMap->CardMemSize - 2; + NdefMap->MifareULContainer.RemainingSize = NdefMap->CardMemSize; + } + + } + else + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } + + + return Result; +} + +/*! + * \brief this shall notify the integration software with respective + * success/error status along with the completion routines. + * + * This routine is called from the mifareul process function. + * + */ + +static void phFriNfc_MifareUL_H_Complete(phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Status) +{ + if(NdefMap!=NULL) + { + if((PH_FRINFC_NDEFMAP_MFUL_STATE_WRITE == NdefMap->State) + && (NFCSTATUS_SUCCESS != Status)) + { + *NdefMap->WrNdefPacketLength = 0; + } + /* set the state back to the Reset_Init state*/ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; + + /* set the completion routine*/ + NdefMap->CompletionRoutine[NdefMap->MifareULContainer.CRindex]. + CompletionRoutine(NdefMap->CompletionRoutine->Context, Status); + } +} + +static NFCSTATUS phFriNfc_MfUL_H_Rd16Bytes( phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + + NdefMap->State = PH_FRINFC_NDEFMAP_MFUL_STATE_READ; + + /* Set the previous operation flag to read. */ + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + + /* Have we already read the entire file? */ + if(NdefMap->ApduBuffIndex < NdefMap->ApduBufferSize) + { + /* set the data for additional data exchange */ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] = + NdefMap->MifareULContainer.CurrentBlock; + NdefMap->SendLength = PH_FRINFC_NDEFMAP_MFUL_VAL1; + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + /* + * Changed + * Description: replace with phHal_eMifareRead + */ + + NdefMap->Cmd.MfCmd = phHal_eMifareRead; + + /* Call the overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + } + return Result; +} + +static NFCSTATUS phFriNfc_MfUL_H_Wr4bytes( phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* set the receive length*/ + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + + /* + * Changed + * Description: phHal_eMifareCmdListMifareWrite4 replace with phHal_eMifareWrite4 + */ + /* set the cmd to mifare read*/ + NdefMap->Cmd.MfCmd = phHal_eMifareWrite4; + + /* Set the CR and context for Mifare operations*/ + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_MifareUL_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + NdefMap->SendLength = PH_FRINFC_NDEFMAP_MFUL_WR_A_BLK; + /*Call the Overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive(NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + return Result; +} + +static NFCSTATUS phFriNfc_MfUL_H_findNDEFTLV(phFriNfc_NdefMap_t *NdefMap, + uint8_t *CRFlag) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint16_t ShiftLength = PH_FRINFC_NDEFMAP_MFUL_VAL0, + TemLength = PH_FRINFC_NDEFMAP_MFUL_VAL0, + Temp16Bytes = PH_FRINFC_NDEFMAP_MFUL_VAL0; + Temp16Bytes = ((NdefMap->TLVStruct.NdefTLVByte > PH_FRINFC_NDEFMAP_MFUL_VAL0)? + (NdefMap->TLVStruct.NdefTLVByte - PH_FRINFC_NDEFMAP_MFUL_VAL1): + NdefMap->TLVStruct.NdefTLVByte); + for(;;) + { + if(NdefMap->SendRecvBuf[Temp16Bytes] == + PH_FRINFC_NDEFMAP_MFUL_NULLTLV) + { + NdefMap->MifareULContainer.RemainingSize -= + PH_FRINFC_NDEFMAP_MFUL_VAL1; +#ifdef PH_HAL4_ENABLE + /* This check is added to know the remaining size in + the card is not 0, if this is 0, then complete card has + been read */ + if (NdefMap->MifareULContainer.RemainingSize == + PH_FRINFC_NDEFMAP_MFUL_VAL0) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + else + { + Result = NFCSTATUS_SUCCESS; + } +#else + Result = ((NdefMap->MifareULContainer.RemainingSize == + PH_FRINFC_NDEFMAP_MFUL_VAL0)? + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT)): + NFCSTATUS_SUCCESS); +#endif /* #ifdef PH_HAL4_ENABLE */ + Temp16Bytes++; +#ifdef PH_HAL4_ENABLE + /* This code is added to read next 16 bytes. This means previous + 16 bytes read contains only NULL TLV, so read further to get the + NDEF TLV */ + Result = phFriNfc_MfUL_H_Chk16Bytes(NdefMap, + Temp16Bytes); + if(NFCSTATUS_SUCCESS != Result) + { + NdefMap->TLVStruct.NdefTLVBlock = + NdefMap->TLVStruct.NdefTLVBlock + PH_FRINFC_NDEFMAP_MFUL_VAL4; + break; + } +#endif /* #ifdef PH_HAL4_ENABLE */ + } + else + { + Result = ((NdefMap->SendRecvBuf[Temp16Bytes] == + PH_FRINFC_NDEFMAP_MFUL_TERMTLV)? + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT)): + NFCSTATUS_SUCCESS); + + if(Result != NFCSTATUS_SUCCESS) + { + *CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + break; + } + +#ifdef PH_NDEF_MIFARE_ULC + if ((NdefMap->SendRecvBuf[Temp16Bytes] == + PH_FRINFC_NDEFMAP_MFUL_LOCK_CTRL_TLV) || + (NdefMap->SendRecvBuf[Temp16Bytes] == + PH_FRINFC_NDEFMAP_MFUL_MEM_CTRL_TLV) || + (NdefMap->SendRecvBuf[Temp16Bytes] == + PH_FRINFC_NDEFMAP_MFUL_PROPRIETRY_TLV)) + { + + NdefMap->TLVStruct.NdefTLVByte = + ((Temp16Bytes % + PH_FRINFC_NDEFMAP_MFUL_VAL4) + + PH_FRINFC_NDEFMAP_MFUL_VAL1); + + Result = phFriNfc_MfUL_H_Chk16Bytes(NdefMap, + Temp16Bytes); + if(Result != NFCSTATUS_SUCCESS) + { + NdefMap->TLVStruct.TcheckedinTLVFlag = + PH_FRINFC_NDEFMAP_MFUL_FLAG1; + NdefMap->TLVStruct.NoLbytesinTLV = + PH_FRINFC_NDEFMAP_MFUL_VAL3; + break; + } + Temp16Bytes++; + NdefMap->MifareULContainer.RemainingSize -= + PH_FRINFC_NDEFMAP_MFUL_VAL1; + + if(NdefMap->MifareULContainer.RemainingSize == + PH_FRINFC_NDEFMAP_MFUL_VAL0) + { + Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT)); + break; + } + + Result = phFriNfc_MfUL_H_Chk16Bytes(NdefMap, + Temp16Bytes); + if(Result != NFCSTATUS_SUCCESS) + { + NdefMap->TLVStruct.TcheckedinTLVFlag = + PH_FRINFC_NDEFMAP_MFUL_FLAG1; + NdefMap->TLVStruct.NoLbytesinTLV = + PH_FRINFC_NDEFMAP_MFUL_VAL3; + break; + } + + + /* If the value of the Length(L) in TLV is FF then enter else + check for the card memory */ + if((NdefMap->SendRecvBuf[Temp16Bytes] == + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_LFF) || + ((NdefMap->SendRecvBuf[Temp16Bytes] == + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_L) && + (NdefMap->TLVStruct.NdefTLVFoundFlag != + PH_FRINFC_NDEFMAP_MFUL_FLAG1))) + { + /* In the present case, the card space is not greater + than 0xFF */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + + *CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + break; + } + else + { + NdefMap->TLVStruct.BytesRemainLinTLV = + NdefMap->SendRecvBuf[Temp16Bytes]; + + NdefMap->TLVStruct.ActualSize = + NdefMap->SendRecvBuf[Temp16Bytes]; + + if((NdefMap->MifareULContainer.RemainingSize < + NdefMap->SendRecvBuf[Temp16Bytes]) || + (NdefMap->MifareULContainer.RemainingSize < + PH_FRINFC_NDEFMAP_MFUL_VAL2) || + (NdefMap->TLVStruct.BytesRemainLinTLV > + (NdefMap->MifareULContainer.RemainingSize)) || + ((NdefMap->TLVStruct.BytesRemainLinTLV == + PH_FRINFC_NDEFMAP_MFUL_VAL0) && + (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE))) + { + /* No NDEF TLV found */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + *CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + break; + } + + if(NdefMap->TLVStruct.NdefTLVFoundFlag != + PH_FRINFC_NDEFMAP_MFUL_FLAG1) + { + NdefMap->TLVStruct.NdefTLVByte = + (((Temp16Bytes + PH_FRINFC_NDEFMAP_MFUL_VAL1 + + NdefMap->SendRecvBuf[Temp16Bytes]) % + PH_FRINFC_NDEFMAP_MFUL_VAL4) + + PH_FRINFC_NDEFMAP_MFUL_VAL1); +#if 0 + NdefMap->TLVStruct.NdefTLVBlock = + (uint8_t)(NdefMap->TLVStruct.NdefTLVBlock + + ((Temp16Bytes + + NdefMap->SendRecvBuf[Temp16Bytes] + 1)/ + PH_FRINFC_NDEFMAP_MFUL_VAL4)); +#endif + NdefMap->TLVStruct.NdefTLVBlock = + (uint8_t)(((NdefMap->TLVStruct.NdefTLVBlock / PH_FRINFC_NDEFMAP_MFUL_VAL4) * + PH_FRINFC_NDEFMAP_MFUL_VAL4) + + ((Temp16Bytes + NdefMap->SendRecvBuf[Temp16Bytes] + 1)/ + PH_FRINFC_NDEFMAP_MFUL_VAL4)); + + + TemLength = (Temp16Bytes + + NdefMap->SendRecvBuf[Temp16Bytes]); + + NdefMap->MifareULContainer.RemainingSize = + (NdefMap->MifareULContainer.RemainingSize - + (NdefMap->SendRecvBuf[Temp16Bytes] + + PH_FRINFC_NDEFMAP_MFUL_VAL1)); + + /* If the Length (L) in TLV < 16 bytes */ + Temp16Bytes = ((TemLength >= + PH_FRINFC_NDEFMAP_MFUL_RDBYTES_16)? + PH_FRINFC_NDEFMAP_MFUL_VAL0: + (TemLength + + PH_FRINFC_NDEFMAP_MFUL_VAL1)); + + Result = ((TemLength >= + PH_FRINFC_NDEFMAP_MFUL_RDBYTES_16)? + phFriNfc_MfUL_H_RdCardfindNdefTLV(NdefMap, + NdefMap->TLVStruct.NdefTLVBlock): + NFCSTATUS_SUCCESS); + + if(TemLength >= PH_FRINFC_NDEFMAP_MFUL_RDBYTES_16) + { + break; + } + TemLength = Temp16Bytes; + } + } + + + + +#if 0 + + NdefMap->MifareULContainer.RemainingSize = + (NdefMap->MifareULContainer.RemainingSize - + (NdefMap->SendRecvBuf[Temp16Bytes + 1] + + PH_FRINFC_NDEFMAP_MFUL_VAL2)); + + NdefMap->TLVStruct.NdefTLVBlock = + (uint8_t)(NdefMap->TLVStruct.NdefTLVBlock + + ((Temp16Bytes + + NdefMap->SendRecvBuf[Temp16Bytes + 1] + 2)/ + PH_FRINFC_NDEFMAP_MFUL_VAL4)); + + + Temp16Bytes = Temp16Bytes + + NdefMap->SendRecvBuf[Temp16Bytes + 1] + 2; +#endif + } +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + else { + + /* Check the byte for 0x03 Type of NDEF TLV */ + NdefMap->TLVStruct.NdefTLVFoundFlag = + ((NdefMap->SendRecvBuf[Temp16Bytes] == + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_T)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + + if(NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_NDEFMAP_MFUL_FLAG1) + { + ShiftLength = (Temp16Bytes + + NdefMap->SendRecvBuf[Temp16Bytes]); + + NdefMap->TLVStruct.NdefTLVByte = + ((Temp16Bytes % + PH_FRINFC_NDEFMAP_MFUL_VAL4) + + PH_FRINFC_NDEFMAP_MFUL_VAL1); + + NdefMap->TLVStruct.NdefTLVBlock = + (uint8_t)(((NdefMap->TLVStruct.NdefTLVBlock /4) * 4) + + (Temp16Bytes)/ + PH_FRINFC_NDEFMAP_MFUL_VAL4); + + NdefMap->TLVStruct.NdefTLVSector = NdefMap->MifareULContainer.CurrentSector; + + } +#ifdef PH_HAL4_ENABLE + else + { + /* if the Type of the NDEF TLV is not found, then return + error saying no ndef TLV found*/ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; +#if 0 + /* This change is added to continue the loop, if the Type of the + NDEF TLV is not found + 16 bytes are read, so for each byte, there is a check for the + Type (T) of the TLV, if T != 0x03, then increment the byte + count and restart the loop, till the T = 0x03 is found or all + the bytes in the card is completely read. + */ + Temp16Bytes = (uint16_t)(Temp16Bytes + 1); + NdefMap->MifareULContainer.RemainingSize -= + PH_FRINFC_NDEFMAP_MFUL_VAL1; + if (NdefMap->MifareULContainer.RemainingSize == + PH_FRINFC_NDEFMAP_MFUL_VAL0) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + else + { + Result = NFCSTATUS_SUCCESS; + Result = phFriNfc_MfUL_H_Chk16Bytes(NdefMap, + Temp16Bytes); + if(NFCSTATUS_PENDING == Result) + { + break; + } + continue; + } +#endif /* #if 0 */ + } +#endif /* #ifdef PH_HAL4_ENABLE */ + + Result = phFriNfc_MfUL_H_Chk16Bytes(NdefMap, + Temp16Bytes); + if(Result != NFCSTATUS_SUCCESS) + { + NdefMap->TLVStruct.TcheckedinTLVFlag = + PH_FRINFC_NDEFMAP_MFUL_FLAG1; + NdefMap->TLVStruct.NoLbytesinTLV = + PH_FRINFC_NDEFMAP_MFUL_VAL3; + break; + } + Temp16Bytes++; + NdefMap->MifareULContainer.RemainingSize -= + PH_FRINFC_NDEFMAP_MFUL_VAL1; + + if(NdefMap->MifareULContainer.RemainingSize == + PH_FRINFC_NDEFMAP_MFUL_VAL0) + { + Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT)); + break; + } + + Result = phFriNfc_MfUL_H_Chk16Bytes(NdefMap, + Temp16Bytes); + if(Result != NFCSTATUS_SUCCESS) + { + NdefMap->TLVStruct.TcheckedinTLVFlag = + PH_FRINFC_NDEFMAP_MFUL_FLAG1; + NdefMap->TLVStruct.NoLbytesinTLV = + PH_FRINFC_NDEFMAP_MFUL_VAL3; + break; + } + + /* If the value of the Length(L) in TLV is FF then enter else + check for the card memory */ + if((NdefMap->SendRecvBuf[Temp16Bytes] == + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_LFF) || + ((NdefMap->SendRecvBuf[Temp16Bytes] == + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_L) && + (NdefMap->TLVStruct.NdefTLVFoundFlag != + PH_FRINFC_NDEFMAP_MFUL_FLAG1))) + { + /* In the present case, the card space is not greater + than 0xFF */ + /* + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + + *CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + break; + */ + + Temp16Bytes++; + Result = phFriNfc_MfUL_H_Chk16Bytes(NdefMap, + Temp16Bytes); + if(Result != NFCSTATUS_SUCCESS) + { + NdefMap->TLVStruct.TcheckedinTLVFlag = + PH_FRINFC_NDEFMAP_MFUL_FLAG1; + NdefMap->TLVStruct.NoLbytesinTLV = + PH_FRINFC_NDEFMAP_MFUL_VAL2; + + break; + } + + ShiftLength = (uint16_t) NdefMap->SendRecvBuf[Temp16Bytes]; + NdefMap->MifareULContainer.RemainingSize--; + + Temp16Bytes++; + Result = phFriNfc_MfUL_H_Chk16Bytes(NdefMap, + Temp16Bytes); + if(Result != NFCSTATUS_SUCCESS) + { + NdefMap->TLVStruct.TcheckedinTLVFlag = + PH_FRINFC_NDEFMAP_MFUL_FLAG1; + NdefMap->TLVStruct.NoLbytesinTLV = + PH_FRINFC_NDEFMAP_MFUL_VAL1; + NdefMap->TLVStruct.prevLenByteValue = + NdefMap->SendRecvBuf[Temp16Bytes - 1]; + break; + } + + + ShiftLength = + (uint16_t) (NdefMap->SendRecvBuf[Temp16Bytes] + | (ShiftLength << PH_FRINFC_NDEFMAP_MFUL_SHIFT8)); + + // NdefMap->MifareULContainer.RemainingSize--; + + if(ShiftLength > (NdefMap->MifareULContainer.RemainingSize)) + { + // Size in the Length(L) of TLV is greater + //than the actual size of the card + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + *CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + break; + } + + // NdefMap->MifareULContainer.RemainingSize--; + /* + NdefMap->TLVStruct.NdefTLVByte = + (NdefMap->SendRecvBuf[Temp16Bytes] % + PH_FRINFC_NDEFMAP_MFUL_VAL4); + + NdefMap->TLVStruct.NdefTLVBlock = + (uint8_t)(NdefMap->MifareULContainer.CurrentBlock + + (Temp16Bytes/PH_FRINFC_NDEFMAP_MFUL_VAL4)); + */ + + NdefMap->TLVStruct.ActualSize = + NdefMap->TLVStruct.BytesRemainLinTLV = ShiftLength; + + NdefMap->TLVStruct.NdefTLVFoundFlag = 1; + + NdefMap->TLVStruct.NdefTLVSector = NdefMap->MifareULContainer.CurrentSector; + + + Result = ((NdefMap->TLVStruct.NoLbytesinTLV == + PH_FRINFC_NDEFMAP_MFUL_VAL0)? + phFriNfc_MapTool_SetCardState( NdefMap, ShiftLength): + Result); +/* + Result = phFriNfc_MfUL_H_RdCardfindNdefTLV(NdefMap, + NdefMap->TLVStruct.NdefTLVBlock); +*/ + break; + } + else + { + NdefMap->TLVStruct.BytesRemainLinTLV = + NdefMap->SendRecvBuf[Temp16Bytes]; + + NdefMap->TLVStruct.ActualSize = + NdefMap->SendRecvBuf[Temp16Bytes]; + + if((NdefMap->MifareULContainer.RemainingSize < + NdefMap->SendRecvBuf[Temp16Bytes]) || + (NdefMap->MifareULContainer.RemainingSize < + PH_FRINFC_NDEFMAP_MFUL_VAL2) || + (NdefMap->TLVStruct.BytesRemainLinTLV > + (NdefMap->MifareULContainer.RemainingSize)) || + ((NdefMap->TLVStruct.BytesRemainLinTLV == + PH_FRINFC_NDEFMAP_MFUL_VAL0) && + (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE))) + { + /* No NDEF TLV found */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + *CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + break; + } + + if(NdefMap->TLVStruct.NdefTLVFoundFlag != + PH_FRINFC_NDEFMAP_MFUL_FLAG1) + { + NdefMap->TLVStruct.NdefTLVByte = + (((Temp16Bytes + PH_FRINFC_NDEFMAP_MFUL_VAL1 + + NdefMap->SendRecvBuf[Temp16Bytes]) % + PH_FRINFC_NDEFMAP_MFUL_VAL4) + + PH_FRINFC_NDEFMAP_MFUL_VAL1); + NdefMap->TLVStruct.NdefTLVBlock = + (uint8_t)(NdefMap->TLVStruct.NdefTLVBlock + + ((Temp16Bytes + + NdefMap->SendRecvBuf[Temp16Bytes] + 1)/ + PH_FRINFC_NDEFMAP_MFUL_VAL4)); + + TemLength = (Temp16Bytes + + NdefMap->SendRecvBuf[Temp16Bytes]); + + NdefMap->MifareULContainer.RemainingSize = + (NdefMap->MifareULContainer.RemainingSize - + (NdefMap->SendRecvBuf[Temp16Bytes] + + PH_FRINFC_NDEFMAP_MFUL_VAL1)); + + /* If the Length (L) in TLV < 16 bytes */ + Temp16Bytes = ((TemLength >= + PH_FRINFC_NDEFMAP_MFUL_RDBYTES_16)? + PH_FRINFC_NDEFMAP_MFUL_VAL0: + (TemLength + + PH_FRINFC_NDEFMAP_MFUL_VAL1)); + + Result = ((TemLength >= + PH_FRINFC_NDEFMAP_MFUL_RDBYTES_16)? + phFriNfc_MfUL_H_RdCardfindNdefTLV(NdefMap, + NdefMap->TLVStruct.NdefTLVBlock): + NFCSTATUS_SUCCESS); + + if(TemLength >= PH_FRINFC_NDEFMAP_MFUL_RDBYTES_16) + { + break; + } + TemLength = Temp16Bytes; + } + } + if(NdefMap->TLVStruct.NdefTLVFoundFlag == + PH_FRINFC_NDEFMAP_MFUL_FLAG1) + { +#if 0 + NdefMap->TLVStruct.NdefTLVBlock = + (uint8_t)(NdefMap->TLVStruct.NdefTLVBlock + + ((Temp16Bytes + 1)/ + PH_FRINFC_NDEFMAP_MFUL_VAL4)) - 1; +#endif + NdefMap->MifareULContainer.RemainingSize = + (NdefMap->MifareULContainer.RemainingSize - + PH_FRINFC_NDEFMAP_MFUL_VAL1); + ShiftLength = NdefMap->SendRecvBuf[Temp16Bytes]; + Result = ((NdefMap->TLVStruct.NoLbytesinTLV == + PH_FRINFC_NDEFMAP_MFUL_VAL0)? + phFriNfc_MapTool_SetCardState( NdefMap, ShiftLength): + Result); + + break; + } + } + } + } + + return Result; +} + + +static NFCSTATUS phFriNfc_MfUL_H_Chk16Bytes(phFriNfc_NdefMap_t *NdefMap, + uint16_t TempLength) +{ + uint16_t localCurrentBlock; + + NFCSTATUS Result = NFCSTATUS_SUCCESS; + if(TempLength == PH_FRINFC_NDEFMAP_MFUL_RDBYTES_16) + { + localCurrentBlock = NdefMap->MifareULContainer.CurrentBlock + + PH_FRINFC_NDEFMAP_MFUL_BLOCK4; + + if (localCurrentBlock < 256) + { + NdefMap->MifareULContainer.CurrentBlock += + PH_FRINFC_NDEFMAP_MFUL_BLOCK4; + + Result = phFriNfc_MfUL_H_RdCardfindNdefTLV(NdefMap, + NdefMap->MifareULContainer.CurrentBlock); + } + else + { + /* Go to next sector */ + NdefMap->MifareULContainer.CurrentSector++; + + Result = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 1, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_CHK_1); + } + } + + return Result; +} + + +static void phFriNfc_MfUL_H_UpdateCrc( uint8_t ch, + uint16_t *lpwCrc ) +{ + ch = (ch^(uint8_t)((*lpwCrc) & 0x00FF)); + ch = (ch^(ch<<4)); + *lpwCrc = (*lpwCrc >> 8)^((uint16_t)ch << 8)^ \ + ((uint16_t)ch<<3)^((uint16_t)ch>>4); + + return; +} + +static void phFriNfc_MfUL_H_ComputeCrc( int CRCType, + uint8_t *Data, + int Length, + uint8_t *TransmitFirst, + uint8_t *TransmitSecond + ) +{ + uint8_t chBlock; + uint16_t wCrc; + switch(CRCType) + { + case CRC_A: + wCrc = 0x6363; /* ITU-V.41 */ + break; + case CRC_B: + wCrc = 0xFFFF; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ + break; + default: + return; + } + + do + { + chBlock = *Data++; + phFriNfc_MfUL_H_UpdateCrc(chBlock, &wCrc); + } while (--Length); + *TransmitFirst = (uint8_t) (wCrc & 0xFF); + *TransmitSecond = (uint8_t) ((wCrc >> 8) & 0xFF); + return; +} + + + +static NFCSTATUS phFriNfc_MfUL_H_SelectSector(phFriNfc_NdefMap_t *NdefMap, + uint8_t SectorNo, + uint8_t CmdNo, + uint8_t NextState) +{ + + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* set the data for additional data exchange */ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_NDEFMAP_MFUL_VAL0; + + NdefMap->State = NextState; + + if (CmdNo == 1) + { + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] = 0x00; + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL1] = 0x00; + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL2] = 0xC2; + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL3] = 0xFF; + NdefMap->SendLength = PH_FRINFC_NDEFMAP_MFUL_VAL4; + } + else + { + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] = 0x00; + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL1] = 0x00; + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL2] = SectorNo; + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL3] = 0; + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL4] = 0; + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL5] = 0; + NdefMap->SendLength = PH_FRINFC_NDEFMAP_MFUL_VAL5 + 1; + } + + /* Calculate CRC */ + + phFriNfc_MfUL_H_ComputeCrc(CRC_A, &NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL2], + NdefMap->SendLength - 2, + &NdefMap->SendRecvBuf[NdefMap->SendLength], + &NdefMap->SendRecvBuf[NdefMap->SendLength + 1]); + + NdefMap->SendLength += PH_FRINFC_NDEFMAP_MFUL_VAL2; + + + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + + NdefMap->Cmd.MfCmd = phHal_eMifareRaw; + + /* Call the overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + return Result; +} + + +static NFCSTATUS phFriNfc_MfUL_H_RdCardfindNdefTLV( phFriNfc_NdefMap_t *NdefMap, + uint8_t BlockNo) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + NdefMap->State = PH_FRINFC_NDEFMAP_MFUL_STATE_FND_NDEF_COMP; + /* set the data for additional data exchange */ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] = + BlockNo; + NdefMap->SendLength = PH_FRINFC_NDEFMAP_MFUL_VAL1; + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + + /* + * Changed + * Description: phHal_eMifareCmdListMifareRead replace with phHal_eMifareRead + */ + NdefMap->Cmd.MfCmd = phHal_eMifareRead; + + /* Call the overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + return Result; +} + +static NFCSTATUS phFriNfc_MfUL_H_ChkRemainTLV(phFriNfc_NdefMap_t *NdefMap, + uint8_t *CRFlag) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint16_t TempLength = PH_FRINFC_NDEFMAP_MFUL_VAL0, + ShiftLength = PH_FRINFC_NDEFMAP_MFUL_VAL0; + + switch(NdefMap->TLVStruct.NoLbytesinTLV) + { + case PH_FRINFC_NDEFMAP_MFUL_VAL1: + case PH_FRINFC_NDEFMAP_MFUL_VAL2: + ShiftLength = ((NdefMap->TLVStruct.NoLbytesinTLV == + PH_FRINFC_NDEFMAP_MFUL_VAL1)? + NdefMap->TLVStruct.prevLenByteValue: + NdefMap->SendRecvBuf[TempLength]); + ShiftLength = ((NdefMap->TLVStruct.NoLbytesinTLV == + PH_FRINFC_NDEFMAP_MFUL_VAL1)? + (((uint16_t)(NdefMap->SendRecvBuf[TempLength]) << + PH_FRINFC_NDEFMAP_MFUL_SHIFT8) | + ShiftLength): + (((uint16_t)(NdefMap->SendRecvBuf[(TempLength + + PH_FRINFC_NDEFMAP_MFUL_VAL1)]) << + PH_FRINFC_NDEFMAP_MFUL_SHIFT8) | + ShiftLength)); + + NdefMap->MifareULContainer.RemainingSize -= + PH_FRINFC_NDEFMAP_MFUL_VAL1; + + NdefMap->TLVStruct.ActualSize = + NdefMap->TLVStruct.BytesRemainLinTLV = ShiftLength; + + /* Check for remaining free space in the card with the + length (L) of TLV OR length(L) of TLV is less than + 255 bytes (The length (L) of TLV for 3 byte should not + be less than 255) */ + Result = ((((NdefMap->MifareULContainer.RemainingSize)<= + ShiftLength) || (ShiftLength < + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_LFF))? + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER)): + Result); + + + Result = ((Result == NFCSTATUS_SUCCESS)? + phFriNfc_MapTool_SetCardState( NdefMap, ShiftLength): + Result); + + *CRFlag = (uint8_t)((Result == (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER)))? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + + + if(Result == NFCSTATUS_SUCCESS) + { + + NdefMap->MifareULContainer.RemainingSize= NdefMap->MifareULContainer.RemainingSize- + NdefMap->TLVStruct.NoLbytesinTLV; +/* + NdefMap->TLVStruct.NdefTLVByte = ((ShiftLength% + PH_FRINFC_NDEFMAP_MFUL_VAL4) + + PH_FRINFC_NDEFMAP_MFUL_VAL1); + + NdefMap->TLVStruct.NdefTLVBlock = + (uint8_t)(NdefMap->MifareULContainer.CurrentBlock + + (ShiftLength/PH_FRINFC_NDEFMAP_MFUL_VAL4)); + NdefMap->MifareULContainer.CurrentBlock = + NdefMap->TLVStruct.NdefTLVBlock; + + Result = phFriNfc_MfUL_H_RdCardfindNdefTLV(NdefMap, + NdefMap->TLVStruct.NdefTLVBlock); + */ + } + break; + + default: + if((NdefMap->SendRecvBuf[TempLength] == + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_LFF) || + ((NdefMap->SendRecvBuf[TempLength] == + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_L) && + (NdefMap->TLVStruct.NdefTLVFoundFlag != + PH_FRINFC_NDEFMAP_MFUL_FLAG1))) + { + /* In the present case, the card space is not greater + than 0xFF */ +/* + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + + *CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + +*/ + + ShiftLength = NdefMap->SendRecvBuf[(TempLength + PH_FRINFC_NDEFMAP_MFUL_VAL1)]; + ShiftLength = (((uint16_t)(NdefMap->SendRecvBuf[(TempLength + PH_FRINFC_NDEFMAP_MFUL_VAL2)]) + << PH_FRINFC_NDEFMAP_MFUL_SHIFT8) | + ShiftLength); + Result = ((ShiftLength > (NdefMap->MifareULContainer.RemainingSize))? + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER)): + Result); + + + Result = ((Result == NFCSTATUS_SUCCESS)? + phFriNfc_MapTool_SetCardState( NdefMap, ShiftLength): + Result); + + NdefMap->TLVStruct.ActualSize = + NdefMap->TLVStruct.BytesRemainLinTLV = ShiftLength; + + if(Result == NFCSTATUS_SUCCESS) + { + + NdefMap->MifareULContainer.RemainingSize= NdefMap->MifareULContainer.RemainingSize- + NdefMap->TLVStruct.NoLbytesinTLV; +/* + NdefMap->TLVStruct.NdefTLVByte = ((ShiftLength% + PH_FRINFC_NDEFMAP_MFUL_VAL4) + + PH_FRINFC_NDEFMAP_MFUL_VAL1); + + NdefMap->TLVStruct.NdefTLVBlock = + (uint8_t)(NdefMap->MifareULContainer.CurrentBlock + + (ShiftLength/PH_FRINFC_NDEFMAP_MFUL_VAL4)); + + NdefMap->MifareULContainer.CurrentBlock = + NdefMap->TLVStruct.NdefTLVBlock; + + Result = phFriNfc_MfUL_H_RdCardfindNdefTLV(NdefMap, + NdefMap->TLVStruct.NdefTLVBlock); +*/ + } + } + else + { + /* length (L) value in TLV shall not be greater than + remaining free space in the card */ + Result = ((NdefMap->SendRecvBuf[TempLength] > + NdefMap->MifareULContainer.RemainingSize)? + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER)): + Result); + + NdefMap->TLVStruct.ActualSize = + NdefMap->TLVStruct.BytesRemainLinTLV = + NdefMap->SendRecvBuf[TempLength]; + NdefMap->MifareULContainer.RemainingSize--; + + if((Result == NFCSTATUS_SUCCESS) && + (NdefMap->TLVStruct.NdefTLVFoundFlag != + PH_FRINFC_NDEFMAP_MFUL_FLAG1)) + { + phFriNfc_MfUL_H_UpdateLen(NdefMap, + (uint16_t)NdefMap->SendRecvBuf[TempLength]); + + NdefMap->MifareULContainer.CurrentBlock = + NdefMap->TLVStruct.NdefTLVBlock; + TempLength=TempLength+(NdefMap->SendRecvBuf[TempLength]); + Result =((TempLength < PH_FRINFC_NDEFMAP_MFUL_RDBYTES_16)? + phFriNfc_MfUL_H_findNDEFTLV(NdefMap, CRFlag): + phFriNfc_MfUL_H_RdCardfindNdefTLV(NdefMap, + NdefMap->TLVStruct.NdefTLVBlock)); + } + } + break; + } + NdefMap->TLVStruct.NoLbytesinTLV = PH_FRINFC_NDEFMAP_MFUL_VAL0; + + Result = phFriNfc_MapTool_SetCardState( NdefMap, NdefMap->TLVStruct.ActualSize); + + return Result; +} + +static void phFriNfc_MfUL_H_UpdateLen(phFriNfc_NdefMap_t *NdefMap, + uint16_t DataLen) +{ + NdefMap->MifareULContainer.RemainingSize= NdefMap->MifareULContainer.RemainingSize-DataLen; + NdefMap->TLVStruct.NdefTLVByte = ((DataLen % + PH_FRINFC_NDEFMAP_MFUL_VAL4) + + PH_FRINFC_NDEFMAP_MFUL_VAL1); + NdefMap->TLVStruct.NdefTLVBlock = + (uint8_t)(NdefMap->MifareULContainer.CurrentBlock + + (DataLen/PH_FRINFC_NDEFMAP_MFUL_VAL4)); +} + + static NFCSTATUS phFriNfc_MfUL_H_NxtOp(phFriNfc_NdefMap_t *NdefMap, + uint8_t *CRFlag) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + switch(NdefMap->PrevOperation) + { + case PH_FRINFC_NDEFMAP_CHECK_OPE: + *CRFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + /* Fix to check if the actual size in the TLV is greater than card */ + if (NdefMap->TLVStruct.ActualSize > (NdefMap->CardMemSize - 2)) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + break; + + case PH_FRINFC_NDEFMAP_READ_OPE: + if (NdefMap->TLVStruct.NdefTLVSector == 1) + { + /* Goto sector 1 */ + NdefMap->MifareULContainer.CurrentSector = 1; + NdefMap->MifareULContainer.CurrentBlock = 0; + + Result = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 1, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_READ_1); + } + else + { + NdefMap->MifareULContainer.CurrentBlock = (NdefMap->TLVStruct.NdefTLVBlock / 4) * 4; + + Result = phFriNfc_MfUL_H_Rd16Bytes(NdefMap); + } +#if 0 + NdefMap->MifareULContainer.CurrentBlock = + PH_FRINFC_NDEFMAP_MFUL_VAL4; + + Result = phFriNfc_MfUL_H_Rd16Bytes(NdefMap); +#endif + + + *CRFlag = (uint8_t)((Result != NFCSTATUS_PENDING)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + break; + + case PH_FRINFC_NDEFMAP_WRITE_OPE: + break; + + default: + break; + } + return Result; +} + + + +static NFCSTATUS phFriNfc_MfUL_H_CopyRdBytes(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint16_t localCurrentBlock; + +#ifndef NDEF_READ_CHANGE + uint16_t v_field_byte = 0; + + if (NdefMap->MifareULContainer.CurrentBlock + == NdefMap->TLVStruct.NdefTLVBlock) + { + if (NdefMap->CardMemSize > (0x12 * PH_FRINFC_NDEFMAP_MFUL_MUL8)) + { + v_field_byte = NdefMap->TLVStruct.NdefTLVByte; + } + + /* Calculate the Value field of the TLV to read */ + if (NdefMap->TLVStruct.ActualSize >= 0xFF) + { + + /* here + 3 is the 3 LENGTH bytes to skip + 4 is the block size + 1 is to increment the byte number + */ + v_field_byte = (uint16_t) + (((v_field_byte + 3) % 4) + 1); + } + else + { + /* less than 0xFF */ +#if 0 + if ((0x03 == v_field_byte) + || (0x04 == v_field_byte)) + { + /* + here + 1 is the 1 LENGTH byte to skip + 4 is the block size + 1 is to increment the byte number + */ + v_field_byte = (uint16_t) + (((v_field_byte + 1) % 4) + 1); + } + else + { + v_field_byte = (uint16_t) + (v_field_byte + 1); + } +#endif /* #if 0 */ + } + } +#endif /* #ifndef NDEF_READ_CHANGE */ + +#ifndef NDEF_READ_CHANGE + (void)memcpy(&(NdefMap->MifareULContainer.ReadBuf[ + NdefMap->MifareULContainer.ReadBufIndex]), + (void *)(NdefMap->SendRecvBuf + v_field_byte), + (*NdefMap->SendRecvLength - v_field_byte)); + + NdefMap->MifareULContainer.ReadBufIndex = (uint16_t) + (NdefMap->MifareULContainer.ReadBufIndex + + (*NdefMap->SendRecvLength - v_field_byte)); +#else /* #ifndef NDEF_READ_CHANGE */ + + (void)memcpy(&(NdefMap->MifareULContainer.ReadBuf[ + NdefMap->MifareULContainer.ReadBufIndex]), + NdefMap->SendRecvBuf, + *NdefMap->SendRecvLength); + + NdefMap->MifareULContainer.ReadBufIndex=NdefMap->MifareULContainer.ReadBufIndex +*NdefMap->SendRecvLength; +#endif /* #ifndef NDEF_READ_CHANGE */ + + localCurrentBlock = NdefMap->MifareULContainer.CurrentBlock+ + (uint8_t)((NdefMap->MifareULContainer.ReadBufIndex != + NdefMap->CardMemSize)? + PH_FRINFC_NDEFMAP_MFUL_BLOCK4: + PH_FRINFC_NDEFMAP_MFUL_VAL0); + if (localCurrentBlock < 256) + { + NdefMap->MifareULContainer.CurrentBlock = NdefMap->MifareULContainer.CurrentBlock+ + (uint8_t)((NdefMap->MifareULContainer.ReadBufIndex != + NdefMap->CardMemSize)? + PH_FRINFC_NDEFMAP_MFUL_BLOCK4: + PH_FRINFC_NDEFMAP_MFUL_VAL0); + } + else + { + /* Go to next sector */ + if (NdefMap->MifareULContainer.CurrentSector == 0) + { + NdefMap->MifareULContainer.CurrentSector++; + NdefMap->MifareULContainer.CurrentBlock = 0xff; + + Result = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 1, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_READ_1); + } + } + + return Result; +} + +static NFCSTATUS phFriNfc_MfUL_H_CpDataToUserBuf(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Check the user buffer size with the + L value of TLV */ + if(NdefMap->ApduBufferSize >= + NdefMap->TLVStruct.BytesRemainLinTLV) + { + (void)memcpy(NdefMap->ApduBuffer, + &(NdefMap->MifareULContainer.ReadBuf[ + NdefMap->MifareULContainer.ByteNumber]), + NdefMap->TLVStruct.BytesRemainLinTLV); + + *(NdefMap->NumOfBytesRead) = + NdefMap->TLVStruct.BytesRemainLinTLV; + NdefMap->MifareULContainer.ByteNumber = + PH_FRINFC_NDEFMAP_MFUL_VAL0; + NdefMap->MifareULContainer.ReadWriteCompleteFlag = + PH_FRINFC_NDEFMAP_MFUL_FLAG1; + NdefMap->MifareULContainer.RemainingSize = NdefMap->MifareULContainer.RemainingSize- + NdefMap->TLVStruct.BytesRemainLinTLV; + NdefMap->TLVStruct.BytesRemainLinTLV = + PH_FRINFC_NDEFMAP_MFUL_VAL0; + } + else + { + (void)memcpy(NdefMap->ApduBuffer, + &(NdefMap->MifareULContainer.ReadBuf[ + NdefMap->MifareULContainer.ByteNumber]), + NdefMap->ApduBufferSize); + + *(NdefMap->NumOfBytesRead) = + NdefMap->ApduBufferSize; + NdefMap->MifareULContainer.ByteNumber = NdefMap->MifareULContainer.ByteNumber+ + (uint16_t)NdefMap->ApduBufferSize; + NdefMap->MifareULContainer.RemainingSize=NdefMap->MifareULContainer.RemainingSize- + (uint16_t)NdefMap->ApduBufferSize; + NdefMap->TLVStruct.BytesRemainLinTLV = NdefMap->TLVStruct.BytesRemainLinTLV- + (uint16_t)NdefMap->ApduBufferSize; + } + return Result; +} + +static NFCSTATUS phFriNfc_MfUL_H_RdBeforeWrite(phFriNfc_NdefMap_t *NdefMap) +{ + uint16_t localCurrentBlock = NdefMap->TLVStruct.NdefTLVBlock; + + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t index = PH_FRINFC_NDEFMAP_MFUL_VAL0, + i = PH_FRINFC_NDEFMAP_MFUL_VAL0; + /* BytesToWrite = PH_FRINFC_NDEFMAP_MFUL_VAL0;*/ + uint16_t TemLength = PH_FRINFC_NDEFMAP_MFUL_VAL0; + + switch((NdefMap->TLVStruct.NdefTLVByte - PH_FRINFC_NDEFMAP_MFUL_VAL1)) + { + case PH_FRINFC_NDEFMAP_MFUL_VAL0: + /* go the NDEF TLV block to start write */ + NdefMap->MifareULContainer.CurrentBlock = + NdefMap->TLVStruct.NdefTLVBlock; + /* fill send buffer for write */ + NdefMap->SendRecvBuf[index] = + NdefMap->MifareULContainer.CurrentBlock; + index++; + NdefMap->SendRecvBuf[index] = + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_T; + index++; + if (NdefMap->ApduBufferSize > 254) + { + NdefMap->SendRecvBuf[index] = 0xFF; + index++; + NdefMap->SendRecvBuf[index] = + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_L; + index++; + NdefMap->SendRecvBuf[index] = + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_L; + index++; + } + else + { + NdefMap->SendRecvBuf[index] = + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_L; + index++; + } + + + break; + + case PH_FRINFC_NDEFMAP_MFUL_VAL1: + case PH_FRINFC_NDEFMAP_MFUL_VAL2: + /* read to get the previous bytes */ + Result = phFriNfc_MfUL_H_RdCardfindNdefTLV(NdefMap, + NdefMap->TLVStruct.NdefTLVBlock); + break; + + case PH_FRINFC_NDEFMAP_MFUL_VAL3: + + localCurrentBlock = (NdefMap->MifareULContainer.CurrentBlock + + PH_FRINFC_NDEFMAP_MFUL_VAL1); + + if (localCurrentBlock < 256) + { + + NdefMap->MifareULContainer.CurrentBlock = + (NdefMap->MifareULContainer.CurrentBlock + + PH_FRINFC_NDEFMAP_MFUL_VAL1); + NdefMap->SendRecvBuf[index] = + NdefMap->MifareULContainer.CurrentBlock; + index++; + + if (NdefMap->ApduBufferSize > 254) + { + NdefMap->SendRecvBuf[index] = 0xFF; + index++; + NdefMap->SendRecvBuf[index] = + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_L; + index++; + NdefMap->SendRecvBuf[index] = + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_L; + index++; + } + else + { + NdefMap->SendRecvBuf[index] = + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_L; + index++; + } + } + else + { + /* Go to next sector */ + NdefMap->MifareULContainer.CurrentSector++; + + Result = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 1, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RW_1); + } + break; + + default: + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + break; + } + + if((((NdefMap->TLVStruct.NdefTLVByte - + PH_FRINFC_NDEFMAP_MFUL_VAL1) == PH_FRINFC_NDEFMAP_MFUL_VAL0) || + ((NdefMap->TLVStruct.NdefTLVByte - PH_FRINFC_NDEFMAP_MFUL_VAL1) + == PH_FRINFC_NDEFMAP_MFUL_VAL3)) && localCurrentBlock < 256) + { + /* Length to know how many bytes has to be written to the card */ + TemLength = (((NdefMap->TLVStruct.NdefTLVByte - PH_FRINFC_NDEFMAP_MFUL_VAL1) == + PH_FRINFC_NDEFMAP_MFUL_VAL0)? + PH_FRINFC_NDEFMAP_MFUL_VAL2: + PH_FRINFC_NDEFMAP_MFUL_VAL3); + + if (NdefMap->ApduBufferSize > 254) + { + TemLength -= 2; + } + + if(NdefMap->ApduBufferSize >= TemLength) + { + /* Prepare the receive buffer */ + (void)memcpy(&(NdefMap->SendRecvBuf[ + index]), + &(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + TemLength); + + /* Number of bytes written to the card from user buffer */ + NdefMap->NumOfBytesWritten = TemLength; + + index = index+(uint8_t)TemLength; + /* Exact number of bytes written in the card including TLV */ + if (index >= 1) + { + *NdefMap->DataCount = (index - PH_FRINFC_NDEFMAP_MFUL_VAL1); + } + else + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + } + } + else + { + /* Prepare the receive buffer */ + (void)memcpy(&(NdefMap->SendRecvBuf[ + index]), + &(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + (uint16_t)NdefMap->ApduBufferSize); + + /* Number of bytes written to the card from user buffer */ + NdefMap->NumOfBytesWritten = (uint16_t)NdefMap->ApduBufferSize; + + index= index +(uint8_t)NdefMap->ApduBufferSize; + /* Exact number of bytes written in the card including TLV */ + *NdefMap->DataCount = (index - PH_FRINFC_NDEFMAP_MFUL_VAL1); + + for(i = index; i < PH_FRINFC_NDEFMAP_MFUL_WR_A_BLK; i++) + { + NdefMap->SendRecvBuf[i] = (uint8_t)((i == index)? + PH_FRINFC_NDEFMAP_MFUL_TERMTLV: + PH_FRINFC_NDEFMAP_MFUL_NULLTLV); + NdefMap->TLVStruct.SetTermTLVFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + } + + /* store the bytes in buffer till the bytes are + written in a block */ + (void)memcpy(NdefMap->MifareULContainer.Buffer, + &(NdefMap->SendRecvBuf[ + PH_FRINFC_NDEFMAP_MFUL_VAL1]), + (PH_FRINFC_NDEFMAP_MFUL_WR_A_BLK - + PH_FRINFC_NDEFMAP_MFUL_VAL1)); + + (void)memcpy(NdefMap->TLVStruct.NdefTLVBuffer, + NdefMap->MifareULContainer.Buffer, + (PH_FRINFC_NDEFMAP_MFUL_WR_A_BLK - + PH_FRINFC_NDEFMAP_MFUL_VAL1)); + + /* Change the state to check ndef compliancy */ + NdefMap->State = PH_FRINFC_NDEFMAP_MFUL_STATE_WRITE; + + Result = phFriNfc_MfUL_H_Wr4bytes(NdefMap); + } + return Result; +} + +static NFCSTATUS phFriNfc_MfUL_H_CallWrOp(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + /* uint8_t index = PH_FRINFC_NDEFMAP_MFUL_VAL1;*/ + + + NdefMap->MifareULContainer.CurrentBlock = + NdefMap->TLVStruct.NdefTLVBlock; + + (void)memcpy(&(NdefMap->SendRecvBuf[ + PH_FRINFC_NDEFMAP_MFUL_VAL1]), + NdefMap->SendRecvBuf, + PH_FRINFC_NDEFMAP_MFUL_VAL4); + + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] = + NdefMap->MifareULContainer.CurrentBlock; + + if (NdefMap->ApduBufferSize > 254) + { + NdefMap->SendRecvBuf[(NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_NDEFMAP_MFUL_VAL1)] = 0xFF; + + + if((NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_NDEFMAP_MFUL_VAL1) < + PH_FRINFC_NDEFMAP_MFUL_VAL4) + { + NdefMap->SendRecvBuf[(NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_NDEFMAP_MFUL_VAL2 )] = 0x00; + + NdefMap->NumOfLReminWrite = 1; + + } + else + { + NdefMap->NumOfLReminWrite = 2; + } + NdefMap->NumOfBytesWritten = 0; + } + else + { + /* Write the length value = 0 */ + NdefMap->SendRecvBuf[(NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_NDEFMAP_MFUL_VAL1)] = + PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_L; + + if((NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_NDEFMAP_MFUL_VAL1) < + PH_FRINFC_NDEFMAP_MFUL_VAL4) + { + /* Only one byte */ + (void)memcpy(&(NdefMap->SendRecvBuf[ + PH_FRINFC_NDEFMAP_MFUL_VAL4]), + &(NdefMap->ApduBuffer[ + NdefMap->ApduBuffIndex]), + PH_FRINFC_NDEFMAP_MFUL_VAL1); + /* Number of bytes written to the card from user buffer */ + NdefMap->NumOfBytesWritten = PH_FRINFC_NDEFMAP_MFUL_VAL1; + } + } + + (void)memcpy(NdefMap->MifareULContainer.Buffer, + &(NdefMap->SendRecvBuf[ + PH_FRINFC_NDEFMAP_MFUL_VAL1]), + PH_FRINFC_NDEFMAP_MFUL_VAL4); + + /* Copy the Ndef TLV buffer to send buffer */ + (void)memcpy(NdefMap->TLVStruct.NdefTLVBuffer, + NdefMap->MifareULContainer.Buffer, + PH_FRINFC_NDEFMAP_MFUL_BYTE4); + + /* Exact number of bytes written in the card including TLV */ + *NdefMap->DataCount = PH_FRINFC_NDEFMAP_MFUL_VAL4; + + /* Change the state to check ndef compliancy */ + NdefMap->State = PH_FRINFC_NDEFMAP_MFUL_STATE_WRITE; + + Result = phFriNfc_MfUL_H_Wr4bytes(NdefMap); + + return Result; +} + +static NFCSTATUS phFriNfc_MfUL_H_ProWrittenBytes(phFriNfc_NdefMap_t *NdefMap) +{ + uint16_t localCurrentBlock; + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + + if(NdefMap->ApduBuffIndex < NdefMap->ApduBufferSize) + { + NdefMap->ApduBuffIndex = NdefMap->ApduBuffIndex+NdefMap->NumOfBytesWritten; + if(*NdefMap->DataCount < + PH_FRINFC_NDEFMAP_MFUL_VAL4) + { + (void)memcpy(NdefMap->MifareULContainer.InternalBuf, + NdefMap->MifareULContainer.Buffer, + *NdefMap->DataCount); + + NdefMap->MifareULContainer.InternalLength = *NdefMap->DataCount; + } + else + { + NdefMap->MifareULContainer.InternalLength = + PH_FRINFC_NDEFMAP_MFUL_VAL0; + } + + NdefMap->MifareULContainer.RemainingSize= NdefMap->MifareULContainer.RemainingSize- + NdefMap->NumOfBytesWritten; + if((NdefMap->ApduBuffIndex == NdefMap->ApduBufferSize) || + (NdefMap->MifareULContainer.RemainingSize == + PH_FRINFC_NDEFMAP_MFUL_VAL0)) + { + Result = NFCSTATUS_SUCCESS; + NdefMap->MifareULContainer.ReadWriteCompleteFlag = + (uint8_t)((NdefMap->MifareULContainer.RemainingSize == + PH_FRINFC_NDEFMAP_MFUL_VAL0)? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + + NdefMap->TLVStruct.SetTermTLVFlag = + (uint8_t)(((NdefMap->MifareULContainer.RemainingSize == + PH_FRINFC_NDEFMAP_MFUL_VAL0) || + (NdefMap->TLVStruct.SetTermTLVFlag == + PH_FRINFC_NDEFMAP_MFUL_FLAG1))? + PH_FRINFC_NDEFMAP_MFUL_FLAG1: + PH_FRINFC_NDEFMAP_MFUL_FLAG0); + + NdefMap->MifareULContainer.CurrentBlock = NdefMap->MifareULContainer.CurrentBlock+ + (uint8_t)((NdefMap->MifareULContainer.InternalLength != + PH_FRINFC_NDEFMAP_MFUL_VAL0)? + PH_FRINFC_NDEFMAP_MFUL_VAL0: + PH_FRINFC_NDEFMAP_MFUL_VAL1); + + *NdefMap->WrNdefPacketLength = NdefMap->ApduBuffIndex; + } + else + { + localCurrentBlock = NdefMap->MifareULContainer.CurrentBlock + 1; + if (localCurrentBlock < 256) + { + NdefMap->MifareULContainer.CurrentBlock++; + Result = phFriNfc_MfUL_H_fillSendBufToWr(NdefMap); + } + else + { + /* Go to next sector */ + NdefMap->MifareULContainer.CurrentSector++; + + Result = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 1, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_WRITE_1); + } + } + } + + if((Result == NFCSTATUS_SUCCESS) && + (NdefMap->TLVStruct.SetTermTLVFlag != + PH_FRINFC_NDEFMAP_MFUL_FLAG1) && + (NdefMap->MifareULContainer.RemainingSize > + PH_FRINFC_NDEFMAP_MFUL_VAL0)) + { + Result = phFriNfc_MfUL_H_WrTermTLV(NdefMap); + } + else + { + if((Result == NFCSTATUS_SUCCESS) && + (NdefMap->TLVStruct.SetTermTLVFlag == + PH_FRINFC_NDEFMAP_MFUL_FLAG1)) + { + Result = phFriNfc_MfUL_H_UpdateWrLen(NdefMap); + } + } + return Result; +} +static NFCSTATUS phFriNfc_MfUL_H_fillSendBufToWr(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint16_t RemainingBytes = PH_FRINFC_NDEFMAP_MFUL_VAL0, + BytesToWrite = PH_FRINFC_NDEFMAP_MFUL_VAL0; + uint8_t index = PH_FRINFC_NDEFMAP_MFUL_VAL0; + + RemainingBytes = (uint16_t)(( (NdefMap->ApduBufferSize - NdefMap->ApduBuffIndex) <= + NdefMap->MifareULContainer.RemainingSize)? + (uint16_t)(NdefMap->ApduBufferSize - + NdefMap->ApduBuffIndex): + NdefMap->MifareULContainer.RemainingSize); + + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] = + NdefMap->MifareULContainer.CurrentBlock; + + /* Get the number of bytes that can be written after copying + the internal buffer */ + BytesToWrite = ((RemainingBytes < + (PH_FRINFC_NDEFMAP_MFUL_BYTE4 - + NdefMap->MifareULContainer.InternalLength))? + RemainingBytes: + (PH_FRINFC_NDEFMAP_MFUL_BYTE4 - + NdefMap->MifareULContainer.InternalLength)); + + if (NdefMap->NumOfBytesWritten == 0 && NdefMap->NumOfLReminWrite > 0) + { + BytesToWrite = BytesToWrite - NdefMap->NumOfLReminWrite; + + if (NdefMap->NumOfLReminWrite == 1) + { + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL1] = 0x00; + } + else + { + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL1] = 0x00; + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL2] = 0x00; + } + } + + if(NdefMap->MifareULContainer.InternalLength > + PH_FRINFC_NDEFMAP_MFUL_VAL0) + { + /* copy the internal buffer to the send buffer */ + (void)memcpy(&(NdefMap->SendRecvBuf[ + PH_FRINFC_NDEFMAP_MFUL_VAL1]), + NdefMap->MifareULContainer.InternalBuf, + NdefMap->MifareULContainer.InternalLength); + + } + + /* Copy Bytes to write in the send buffer */ + (void)memcpy(&(NdefMap->SendRecvBuf[ + (PH_FRINFC_NDEFMAP_MFUL_VAL1 + + NdefMap->MifareULContainer.InternalLength) + + NdefMap->NumOfLReminWrite]), + &(NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]), + BytesToWrite); + + /* update number of bytes written from the user buffer */ + NdefMap->NumOfBytesWritten = BytesToWrite; + + /* check the exact number of bytes written to a block including the + internal length */ + *NdefMap->DataCount = + (BytesToWrite + NdefMap->MifareULContainer.InternalLength + + NdefMap->NumOfLReminWrite); + + + /* if total bytes to write in the card is less than 4 bytes then + pad zeroes till 4 bytes */ + if((BytesToWrite + NdefMap->MifareULContainer.InternalLength + + NdefMap->NumOfLReminWrite) + < PH_FRINFC_NDEFMAP_MFUL_BYTE4) + { + for(index = (uint8_t)((BytesToWrite + NdefMap->MifareULContainer.InternalLength + NdefMap->NumOfLReminWrite) + + PH_FRINFC_NDEFMAP_MFUL_VAL1); + index < PH_FRINFC_NDEFMAP_MFUL_WR_A_BLK; + index++) + { + NdefMap->SendRecvBuf[index] = (uint8_t)((index == + ((BytesToWrite + + NdefMap->MifareULContainer.InternalLength + NdefMap->NumOfLReminWrite) + + PH_FRINFC_NDEFMAP_MFUL_VAL1))? + PH_FRINFC_NDEFMAP_MFUL_TERMTLV: + PH_FRINFC_NDEFMAP_MFUL_NULLTLV); + + NdefMap->TLVStruct.SetTermTLVFlag = PH_FRINFC_NDEFMAP_MFUL_FLAG1; + } + } + + /* A temporary buffer to hold four bytes of data that is + written to the card */ + (void)memcpy(NdefMap->MifareULContainer.Buffer, + &(NdefMap->SendRecvBuf[ + PH_FRINFC_NDEFMAP_MFUL_VAL1]), + PH_FRINFC_NDEFMAP_MFUL_BYTE4); + + + + if((NdefMap->TLVStruct.NdefTLVByte - PH_FRINFC_NDEFMAP_MFUL_VAL1) < + PH_FRINFC_NDEFMAP_MFUL_VAL3) + { + if (NdefMap->TLVStruct.NdefTLVSector == + NdefMap->MifareULContainer.CurrentSector) + { + if(NdefMap->MifareULContainer.CurrentBlock == + NdefMap->TLVStruct.NdefTLVBlock) + { + (void)memcpy(NdefMap->TLVStruct.NdefTLVBuffer, + NdefMap->MifareULContainer.Buffer, + PH_FRINFC_NDEFMAP_MFUL_BYTE4); + } + } + + if ((NdefMap->TLVStruct.NdefTLVSector == + NdefMap->MifareULContainer.CurrentSector) || + (NdefMap->TLVStruct.NdefTLVBlock == 0xFF)) + { + if(NdefMap->MifareULContainer.CurrentBlock == + (NdefMap->TLVStruct.NdefTLVBlock + PH_FRINFC_NDEFMAP_MFUL_VAL1)) + { + (void)memcpy(NdefMap->TLVStruct.NdefTLVBuffer1, + NdefMap->MifareULContainer.Buffer, + PH_FRINFC_NDEFMAP_MFUL_BYTE4); + } + } + } + else + { + if (NdefMap->TLVStruct.NdefTLVSector == + NdefMap->MifareULContainer.CurrentSector) + { + if(NdefMap->MifareULContainer.CurrentBlock == + (NdefMap->TLVStruct.NdefTLVBlock + + PH_FRINFC_NDEFMAP_MFUL_VAL1)) + { + (void)memcpy(NdefMap->TLVStruct.NdefTLVBuffer, + NdefMap->MifareULContainer.Buffer, + PH_FRINFC_NDEFMAP_MFUL_BYTE4); + } + } + + if ((NdefMap->TLVStruct.NdefTLVSector == + NdefMap->MifareULContainer.CurrentSector)|| + (NdefMap->TLVStruct.NdefTLVBlock == 0xFF)) + { + if(NdefMap->MifareULContainer.CurrentBlock == + (NdefMap->TLVStruct.NdefTLVBlock + PH_FRINFC_NDEFMAP_MFUL_VAL2)) + { + (void)memcpy(NdefMap->TLVStruct.NdefTLVBuffer1, + NdefMap->MifareULContainer.Buffer, + PH_FRINFC_NDEFMAP_MFUL_BYTE4); + } + } + } + + + /* Change the state to check ndef compliancy */ + NdefMap->State = PH_FRINFC_NDEFMAP_MFUL_STATE_WRITE; + + NdefMap->NumOfLReminWrite = 0; + + /* Start writing to the current block */ + Result = phFriNfc_MfUL_H_Wr4bytes(NdefMap); + + return Result; +} +static NFCSTATUS phFriNfc_MfUL_H_WrTermTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t index = PH_FRINFC_NDEFMAP_MFUL_VAL0, + i = PH_FRINFC_NDEFMAP_MFUL_VAL0; + + /* Change the state to check ndef compliancy */ + NdefMap->State = PH_FRINFC_NDEFMAP_MFUL_STATE_TERM_TLV; + + NdefMap->SendRecvBuf[index] = + (NdefMap->MifareULContainer.CurrentBlock + + PH_FRINFC_NDEFMAP_MFUL_VAL0); + index++; + NdefMap->SendRecvBuf[index] = PH_FRINFC_NDEFMAP_MFUL_TERMTLV; + index++; + + for(i = index; i < PH_FRINFC_NDEFMAP_MFUL_VAL4; i++) + { + NdefMap->SendRecvBuf[i] = PH_FRINFC_NDEFMAP_MFUL_NULLTLV; + } + + Result = phFriNfc_MfUL_H_Wr4bytes(NdefMap); + return Result; +} + +static NFCSTATUS phFriNfc_MfUL_H_UpdateWrLen(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint16_t BlockNo = PH_FRINFC_NDEFMAP_MFUL_VAL0, + ByteNo = PH_FRINFC_NDEFMAP_MFUL_VAL0; + + if ((NdefMap->TLVStruct.NdefTLVSector == + NdefMap->MifareULContainer.CurrentSector) || + ((NdefMap->TLVStruct.NdefTLVBlock == 0xFF) && + (NdefMap->TLVStruct.NdefTLVByte == 4) && + (NdefMap->TLVStruct.NdefTLVSector == 0))) + { + BlockNo = (((NdefMap->TLVStruct.NdefTLVByte - + PH_FRINFC_NDEFMAP_MFUL_VAL1) != + PH_FRINFC_NDEFMAP_MFUL_VAL3)? + NdefMap->TLVStruct.NdefTLVBlock: + (NdefMap->TLVStruct.NdefTLVBlock + + PH_FRINFC_NDEFMAP_MFUL_VAL1)); + + ByteNo = (((NdefMap->TLVStruct.NdefTLVByte - + PH_FRINFC_NDEFMAP_MFUL_VAL1) == + PH_FRINFC_NDEFMAP_MFUL_VAL3)? + PH_FRINFC_NDEFMAP_MFUL_VAL1: + (NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_NDEFMAP_MFUL_VAL1)); + + if (NdefMap->NumOfLReminWrite > 0) + { + BlockNo++; + + /* Copy the Ndef TLV buffer to send buffer */ + (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL1]), + NdefMap->TLVStruct.NdefTLVBuffer1, + PH_FRINFC_NDEFMAP_MFUL_BYTE4); + + if (NdefMap->NumOfLReminWrite == 1) + { + /* NdefMap->SendRecvBuf[1] = (uint8_t) ((NdefMap->ApduBuffIndex & 0xFF00) >> 8); */ + NdefMap->SendRecvBuf[1] = (uint8_t) NdefMap->ApduBuffIndex; + + } + else if (NdefMap->NumOfLReminWrite == 2) + { + NdefMap->SendRecvBuf[1] = (uint8_t) ((NdefMap->ApduBuffIndex & 0xFF00) >> 8); + NdefMap->SendRecvBuf[2]= (uint8_t) (NdefMap->ApduBuffIndex); + + } + else + { + + } + NdefMap->NumOfLReminWrite = 0; + } + else + { + /* Copy the Ndef TLV buffer to send buffer */ + (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL1]), + NdefMap->TLVStruct.NdefTLVBuffer, + PH_FRINFC_NDEFMAP_MFUL_BYTE4); + + + if (NdefMap->ApduBuffIndex > 254) + { + ByteNo++; + if ((ByteNo == 3) || (ByteNo == 2)) + { + NdefMap->SendRecvBuf[ByteNo]= (uint8_t) ((NdefMap->ApduBuffIndex & 0xFF00) >> 8); + ByteNo++; + NdefMap->SendRecvBuf[ByteNo] = (uint8_t) (NdefMap->ApduBuffIndex); + ByteNo++; + NdefMap->NumOfLReminWrite = 0; + } + else if (ByteNo == 4) + { + /* NdefMap->SendRecvBuf[ByteNo]= (uint8_t) (NdefMap->ApduBuffIndex); */ + NdefMap->SendRecvBuf[ByteNo]= (uint8_t) ((NdefMap->ApduBuffIndex & 0xFF00) >> 8); + ByteNo++; + NdefMap->NumOfLReminWrite = 1; + } + else + { + NdefMap->NumOfLReminWrite = 2; + } + } + else + { + NdefMap->SendRecvBuf[ByteNo]= + (uint8_t)((NdefMap->Offset == + PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + (uint8_t)NdefMap->ApduBuffIndex: + (NdefMap->ApduBuffIndex + + NdefMap->SendRecvBuf[ByteNo])); + } + } + + (void)memcpy(NdefMap->MifareULContainer.Buffer, + &(NdefMap->SendRecvBuf[ + PH_FRINFC_NDEFMAP_MFUL_VAL1]), + PH_FRINFC_NDEFMAP_MFUL_BYTE4); + + NdefMap->SendRecvBuf[PH_FRINFC_NDEFMAP_MFUL_VAL0] = (uint8_t)BlockNo; + Result = phFriNfc_MfUL_H_Wr4bytes(NdefMap); + + if (NdefMap->NumOfLReminWrite == 0) + { + NdefMap->State = PH_FRINFC_NDEFMAP_MFUL_STATE_WR_LEN_TLV; + } + else + { + NdefMap->State = PH_FRINFC_NDEFMAP_MFUL_STATE_TERM_TLV; + } + } + else if (NdefMap->TLVStruct.NdefTLVSector == 0) + { + /* Reset sector */ + NdefMap->MifareULContainer.CurrentSector = 0; + NdefMap->PrevState = PH_FRINFC_NDEFMAP_MFUL_STATE_WRITE; + + Result = phFriNfc_MfUL_H_SelectSector(NdefMap, + NdefMap->MifareULContainer.CurrentSector, 1, + PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RESET_1); + + } + else + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_DEVICE_REQUEST); + } + + + return Result; +} +#ifdef UNIT_TEST +extern void phFriNfc_MifareUL_UnitTest(void *Context,uint32_t Length) +{ + uint8_t value=10; + uint8_t* CrFlag=&value; + phFriNfc_NdefMap_t *pNdefMap=(phFriNfc_NdefMap_t*)Context; + phFriNfc_MfUL_H_UpdateLen(pNdefMap,(uint16_t) Length); + phFriNfc_MfUL_H_WrTermTLV(pNdefMap); + phFriNfc_MfUL_H_CallWrOp(pNdefMap); + phFriNfc_MfUL_H_UpdateWrLen(pNdefMap); + phFriNfc_MfUL_H_ChkRemainTLV(pNdefMap,CrFlag); + phFriNfc_MfUL_H_ProWrittenBytes(pNdefMap); + + pNdefMap->PrevOperation=PH_FRINFC_NDEFMAP_READ_OPE; + phFriNfc_MfUL_H_NxtOp(pNdefMap,CrFlag); + + pNdefMap->PrevOperation=PH_FRINFC_NDEFMAP_WRITE_OPE; + phFriNfc_MfUL_H_NxtOp(pNdefMap,CrFlag); + + pNdefMap->TLVStruct.NoLbytesinTLV=PH_FRINFC_NDEFMAP_MFUL_VAL1; + phFriNfc_MfUL_H_ChkRemainTLV(pNdefMap,CrFlag); + + pNdefMap->SendRecvBuf[0x00]= PH_FRINFC_NDEFMAP_MFUL_NULLTLV; + phFriNfc_MfUL_H_findNDEFTLV(pNdefMap,CrFlag); + + + pNdefMap->SendRecvBuf[0x00]= PH_FRINFC_NDEFMAP_MFUL_NULLTLV; + phFriNfc_MfUL_H_findNDEFTLV(pNdefMap,CrFlag); + + + phFriNfc_MfUL_H_RdBeforeWrite(pNdefMap); + pNdefMap->TLVStruct.NdefTLVByte=1; + phFriNfc_MfUL_H_RdBeforeWrite(pNdefMap); + + pNdefMap->TLVStruct.NdefTLVByte=3; + phFriNfc_MfUL_H_RdBeforeWrite(pNdefMap); + + pNdefMap->TLVStruct.NdefTLVByte=4; + phFriNfc_MfUL_H_RdBeforeWrite(pNdefMap); + + + phFriNfc_MifareUL_H_Complete(pNdefMap,NFCSTATUS_SUCCESS); + phFriNfc_MifareUL_H_Complete(NULL,NFCSTATUS_SUCCESS); + phFriNfc_MifareUL_H_Complete(pNdefMap,NFCSTATUS_SUCCESS); + pNdefMap->State=PH_FRINFC_NDEFMAP_MFUL_STATE_WRITE; + phFriNfc_MifareUL_H_Complete(pNdefMap,NFCSTATUS_SUCCESS); + + phFriNfc_MifareUL_H_Complete(pNdefMap,NFCSTATUS_FAILED); + phFriNfc_MifareUL_H_Complete(NULL,NFCSTATUS_SUCCESS); + phFriNfc_MifareUL_H_Complete(pNdefMap,NFCSTATUS_FAILED); + + *pNdefMap->DataCount=0x3; + phFriNfc_MfUL_H_ProWrittenBytes(pNdefMap); + + pNdefMap->ApduBuffIndex=0x31; + phFriNfc_MfUL_H_ProWrittenBytes(pNdefMap); + + + +} + +#endif +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED */ + diff --git a/libnfc-nxp/phFriNfc_MifareULMap.h b/libnfc-nxp/phFriNfc_MifareULMap.h new file mode 100644 index 0000000..abdf135 --- /dev/null +++ b/libnfc-nxp/phFriNfc_MifareULMap.h @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* + * \file phFriNfc_MifareULMap.h + * \brief NFC Ndef Mapping For Mifare UL Card. + * + * Project: NFC-FRI + * + * $Date: Fri Aug 7 13:06:49 2009 $ + * $Author: ing07336 $ + * $Revision: 1.9 $ + * $Aliases: NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PHFRINFC_MIFAREULMAP_H +#define PHFRINFC_MIFAREULMAP_H + +#include +#if !defined PH_HAL4_ENABLE +#include +#endif +#include +#include +#include + +#define PH_FRINFC_NDEFMAP_MIFAREMAP_FILEREVISION "$Revision: 1.9 $" +#define PH_FRINFC_NDEFMAP_MIFAREMAP_FILEALIASES "$Aliases: NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" + + +/*! + * \name Mifare UL - states of the Finite State machine + * + */ +/*@{*/ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_READ 1 /*!< Read State */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_WRITE 2 /*!< Write is going on*/ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_CHK_NDEF_COMP 3 /*!< Check Ndef is going on */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_FND_NDEF_COMP 4 /*!< to find the NDEF TLV */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_TERM_TLV 5 /*!< to write the terminator TLV */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_WR_LEN_TLV 6 /*!< Write L value of TLV */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_CHK_1 7 /*!< to send sector select command 1 */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_CHK_2 8 /*!< to send sector select command 2 */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RESET_1 9 /*!< to send sector select command 1 for resetting sector 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RESET_2 10 /*!< to send sector select command 2 for resetting sector 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_READ_1 11 /*!< to send sector select command 1 for resetting sector 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_READ_2 12 /*!< to send sector select command 2 for resetting sector 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_WRITE_1 13 /*!< to send sector select command 1 for resetting sector 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_WRITE_2 14 /*!< to send sector select command 2 for resetting sector 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RW_1 15 /*!< to send sector select command 1 for resetting sector 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_RW_2 16 /*!< to send sector select command 2 for resetting sector 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_WRITE_INIT_1 17 /*!< to send sector select command 1 for resetting sector 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_STATE_SELECT_SECTOR_WRITE_INIT_2 18 /*!< to send sector select command 2 for resetting sector 0 */ + + +/*@}*/ + +/*! + * \name Mifare - constants for the capability container + * + */ +/*@{*/ +#define PH_FRINFC_NDEFMAP_MFUL_CC_BYTE0 0xE1 /*!< Capability container byte 0 = 0xE1 */ +#define PH_FRINFC_NDEFMAP_MFUL_CC_BYTE1 0x10 /*!< Capability container byte 1 = 0x10 */ +#define PH_FRINFC_NDEFMAP_MFUL_CC_BYTE2 0x06 /*!< Capability container byte 2 = 0x06 */ +#define PH_FRINFC_NDEFMAP_MFUL_CC_BYTE3_RW 0x00 /*!< Capability container byte 3 = 0x00 for + READ WRITE/INITIALISED card state*/ +#define PH_FRINFC_NDEFMAP_MFUL_CC_BYTE3_RO 0x0F /*!< Capability container byte 3 = 0x0F for + READ only card state*/ +/*@}*/ + +/*! + * \name Mifare - constants for Flags + * + */ +/*@{*/ +#define PH_FRINFC_NDEFMAP_MFUL_FLAG0 0 /*!< Flag value = 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_FLAG1 1 /*!< Flag value = 1 */ +/*@}*/ + +/*! + * \name Mifare - constants for left shift + * + */ +/*@{*/ +#define PH_FRINFC_NDEFMAP_MFUL_SHIFT8 8 /*!< Flag value = 0 */ +/*@}*/ + +/*! + * \name Mifare - TLV related constants + * + */ +/*@{*/ +#define PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_T 0x03 /*!< Type value of TLV = 0x03 */ +#define PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_L 0x00 /*!< Length value of TLV = 0x00 */ +#define PH_FRINFC_NDEFMAP_MFUL_NDEFTLV_LFF 0xFF /*!< Length value of TLV = 0xFF */ +#define PH_FRINFC_NDEFMAP_MFUL_TERMTLV 0xFE /*!< Terminator TLV value = 0xFE */ +#define PH_FRINFC_NDEFMAP_MFUL_NULLTLV 0x00 /*!< Null TLV value = 0x00 */ +#define PH_FRINFC_NDEFMAP_MFUL_LOCK_CTRL_TLV 0x01 /*!< Lock Control TLV value = 0x01 */ +#define PH_FRINFC_NDEFMAP_MFUL_MEM_CTRL_TLV 0x02 /*!< Memory Control TVL value = 0x02 */ +#define PH_FRINFC_NDEFMAP_MFUL_PROPRIETRY_TLV 0xFD /*!< Proprietry TVL value = 0xFD */ + + +/*@}*/ + + +/*! + * \name Mifare - Standard constants + * + */ +/*@{*/ +#define PH_FRINFC_NDEFMAP_MFUL_WR_A_BLK 0x05 /*!< Send Length for Write Ndef */ +#define PH_FRINFC_NDEFMAP_MFUL_MAX_SEND_BUF_TO_READ 0x01 /*!< Send Length for Read Ndef */ +#define PH_FRINFC_NDEFMAP_MFUL_CHECK_RESP 0x04 /*!< Value of the Sense Response for Mifare UL */ +#define PH_FRINFC_NDEFMAP_MFUL_OTP_OFFSET 3 /*!< To initialise the Offset */ +#define PH_FRINFC_NDEFMAP_MFUL_MUL8 8 /*!< Multiply by 8 */ +#define PH_FRINFC_NDEFMAP_MFUL_VAL0 0 /*!< Value 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_VAL1 1 /*!< Value 1 */ +#define PH_FRINFC_NDEFMAP_MFUL_VAL2 2 /*!< Value 2 */ +#define PH_FRINFC_NDEFMAP_MFUL_VAL3 3 /*!< Value 3 */ +#define PH_FRINFC_NDEFMAP_MFUL_VAL4 4 /*!< Value 4 */ +#define PH_FRINFC_NDEFMAP_MFUL_VAL5 5 /*!< Value 5 */ +#define PH_FRINFC_NDEFMAP_MFUL_VAL64 64 /*!< Value 64 */ +#define PH_FRINFC_NDEFMAP_MFUL_BYTE0 0x00 /*!< Byte number 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_BYTE1 0x01 /*!< Byte number 1 */ +#define PH_FRINFC_NDEFMAP_MFUL_BYTE2 0x02 /*!< Byte number 2 */ +#define PH_FRINFC_NDEFMAP_MFUL_BYTE3 0x03 /*!< Byte number 3 */ +#define PH_FRINFC_NDEFMAP_MFUL_BYTE4 0x04 /*!< Byte number 4 */ +#define PH_FRINFC_NDEFMAP_MFUL_BLOCK0 0x00 /*!< Block number 0 */ +#define PH_FRINFC_NDEFMAP_MFUL_BLOCK1 0x01 /*!< Block number 1 */ +#define PH_FRINFC_NDEFMAP_MFUL_BLOCK2 0x02 /*!< Block number 2 */ +#define PH_FRINFC_NDEFMAP_MFUL_BLOCK3 0x03 /*!< Block number 3 */ +#define PH_FRINFC_NDEFMAP_MFUL_BLOCK4 0x04 /*!< Block number 4 */ +#define PH_FRINFC_NDEFMAP_MFUL_BLOCK5 0x05 /*!< Block number 5 */ + +#define PH_FRINFC_NDEFMAP_MFUL_RDBYTES_16 0x10 /*!< Read Bytes 16 */ +#define PH_FRINFC_NDEFMAP_STMFUL_MAX_CARD_SZ 48 /*!< For static maximum memory size is 48 bytes */ +#define PH_FRINFC_NDEFMAP_MFUL_WR_BUF_STR 0x04 /*!< To store the block of data written to the card */ +/*@}*/ + +/*! + * \brief \copydoc page_reg Resets the component instance to the initial state and lets the component forget about + * the list of registered items. Moreover, the lower device is set. + * + * \param[in] NdefMap Pointer to a valid or uninitialised instance of \ref phFriNfc_NdefMap_t . + * + * \note This function has to be called at the beginning, after creating an instance of + * \ref phFriNfc_NdefMap_t . Use this function to reset the instance and/or switch + * to a different underlying device (different NFC device or device mode, or different + * Remote Device). + */ +NFCSTATUS phFriNfc_MifareUL_H_Reset( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_ovr Initiates Reading of NDEF information from the Remote Device. + * + * The function initiates the reading of NDEF information from a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that receives the NDEF Packet. + * + * \param[in,out] PacketDataLength Pointer to a variable receiving the length of the NDEF packet. + * + * \param[in] Offset Indicates whether the read operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start reading from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start reading + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED No Space in the File to read. + * \retval NFCSTATUS_MORE_INFORMATION There are more bytes to read in the card. + * \retval NFCSTATUS_SUCCESS Last Byte of the card read. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_MifareUL_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + +/*! + * \brief \copydoc page_ovr Initiates Writing of NDEF information to the Remote Device. + * + * The function initiates the writing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that holds the prepared NDEF Packet. + * + * \param[in,out] PacketDataLength Variable specifying the length of the prepared NDEF packet. + * + * \param[in] Offset Indicates whether the write operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start writing from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start writing + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED Last byte is written to the card after this + * no further writing is possible. + * \retval NFCSTATUS_SUCCESS Buffer provided by the user is completely written + * into the card. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_MifareUL_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + +/*! + * \brief \copydoc page_ovr Check whether a particulat Remote Device is NDEF compliant. + * + * The function checks whether the peer device is NDEF compliant. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_MifareUL_ChkNdef( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_cb Completion Routine, Processing function, needed to avoid long blocking. + * + * The function call scheme is according to \ref grp_interact. No State reset is performed during operation. + * + * \copydoc pphFriNfc_Cr_t + * + * \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion + * Routine in order to be able to notify the component that an I/O has finished and data are + * ready to be processed. + * + */ + +void phFriNfc_MifareUL_Process( void *Context, + NFCSTATUS Status); + + +#endif /* PHFRINFC_MIFAREULMAP_H */ diff --git a/libnfc-nxp/phFriNfc_NdefMap.c b/libnfc-nxp/phFriNfc_NdefMap.c new file mode 100644 index 0000000..7e195f2 --- /dev/null +++ b/libnfc-nxp/phFriNfc_NdefMap.c @@ -0,0 +1,1496 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phFriNfcNdefMap.c +* \brief NFC Ndef Mapping For Different Smart Cards. +* +* Project: NFC-FRI +* +* $Date: Mon Dec 13 14:14:12 2010 $ +* $Author: ing02260 $ +* $Revision: 1.39 $ +* $Aliases: $ +* +*/ + + +#include + +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED +#include +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED*/ + +#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED +#include +#endif /* PH_FRINFC_MAP_TOPAZ_DISABLED */ + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED +#include +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED +#include +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED +#include +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + +#ifndef PH_FRINFC_MAP_ISO15693_DISABLED +#include +#endif /* PH_FRINFC_MAP_ISO15693_DISABLED */ + +#ifdef PHFRINFC_OVRHAL_MOCKUP +#include +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + + +#include + +/*! \ingroup grp_file_attributes +* \name NDEF Mapping +* +* File: \ref phFriNfcNdefMap.c +* +*/ +/*@{*/ +#define PHFRINFCNDEFMAP_FILEREVISION "$Revision: 1.39 $" +#define PHFRINFCNDEFMAP_FILEALIASES "$Aliases: $" +/*@}*/ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED +/* Desfire capability Container Reset Helper */ +static void phFriNfc_DesfCapCont_HReset(phFriNfc_NdefMap_t *NdefMap); +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED +/* Felica Smart Tag Reset Helper */ +static void phFriNfc_Felica_HReset(phFriNfc_NdefMap_t *NdefMap); +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + + +/* \note This function has to be called at the beginning, after creating an +* instance of \ref phFriNfc_NdefMap_t . Use this function to reset +* the instance and/or switch to a different underlying device ( +* different NFC device or device mode, or different Remote Device). +*/ + +NFCSTATUS phFriNfc_NdefMap_Reset( phFriNfc_NdefMap_t *NdefMap, + void *LowerDevice, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phHal_sDevInputParam_t *psDevInputParam, + uint8_t *TrxBuffer, + uint16_t TrxBufferSize, + uint8_t *ReceiveBuffer, + uint16_t *ReceiveLength, + uint16_t *DataCount) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t index; + + if ( (ReceiveLength == NULL) || (NdefMap == NULL) || (psRemoteDevInfo == NULL) || + (TrxBuffer == NULL) || (TrxBufferSize == 0) || (LowerDevice == NULL) || + (*ReceiveLength == 0) || (ReceiveBuffer == NULL) || (DataCount == NULL) || + (psDevInputParam == NULL) || + (*ReceiveLength < PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE )) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Initialise the state to Init */ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; + + for(index = 0;indexCompletionRoutine[index].CompletionRoutine = NULL; + /* Initialise the NdefMap Completion Routine context to Null */ + NdefMap->CompletionRoutine[index].Context = NULL; + } + + /* Lower Device(Always Overlapped HAL Struct initialised in application + is registred in NdefMap Lower Device) */ + NdefMap->LowerDevice = LowerDevice; + + /* Remote Device info received from Manual Device Discovery is registered here */ + NdefMap->psRemoteDevInfo = psRemoteDevInfo; + + /* Transfer Buffer registered */ + NdefMap->ApduBuffer = TrxBuffer; + + /* Set the MaxApduBufferSize */ + NdefMap->ApduBufferSize = TrxBufferSize; + + /* Set APDU Buffer Index */ + NdefMap->ApduBuffIndex = 0; + + /* Register Transfer Buffer Length */ + NdefMap->SendLength = 0; + + /* Register Receive Buffer */ + NdefMap->SendRecvBuf = ReceiveBuffer; + + /* Register Receive Buffer Length */ + NdefMap->SendRecvLength = ReceiveLength; + + /* Register Temporary Receive Buffer Length */ + NdefMap->TempReceiveLength = *ReceiveLength; + + /* Register Data Count variable and set it to zero */ + NdefMap->DataCount = DataCount; + *NdefMap->DataCount = 0; + + /* Reset the PageOffset */ + NdefMap->Offset = 0; + + /* Reset the NumOfBytesRead*/ + NdefMap->NumOfBytesRead = 0; + + /* Reset the NumOfBytesWritten*/ + NdefMap->NumOfBytesWritten = 0; + + /* Reset the Card Type */ + NdefMap->CardType = 0; + + /* Reset the Memory Card Size*/ + NdefMap->CardMemSize = 0; + + /* Reset the Previous Operation*/ + NdefMap->PrevOperation = 0; + + /* Reset the Desfire Operation Flag*/ + NdefMap->DespOpFlag = 0; + + /* Reset MapCompletion Info*/ + NdefMap->MapCompletionInfo.CompletionRoutine = NULL; + NdefMap->MapCompletionInfo.Context = NULL; + + /* Reset the ReadingForWriteOperation flag. */ + NdefMap->ReadingForWriteOperation = 0; /* FALSE */ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED + /*Reset Desfire Cap Container elements*/ + phFriNfc_DesfCapCont_HReset(NdefMap); +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED + /*Reset Mifare Standard Container elements*/ + NdefMap->StdMifareContainer.DevInputParam = psDevInputParam; + status = phFriNfc_MifareStdMap_H_Reset(NdefMap); +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED + /*Reset Felica Tag elements*/ + NdefMap->FelicaPollDetails.DevInputParam = psDevInputParam; + phFriNfc_Felica_HReset(NdefMap); +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + +#if !(defined(PH_FRINFC_MAP_TOPAZ_DISABLED ) || defined (PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED )) + + phFriNfc_TopazMap_H_Reset(NdefMap); +#endif /* PH_FRINFC_MAP_TOPAZ_DISABLED || PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED */ + + +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED + status = phFriNfc_MifareUL_H_Reset(NdefMap); +#endif + +#ifdef PHFRINFC_OVRHAL_MOCKUP + /*Reset Desfire Cap Container elements*/ + phFriNfc_Mockup_H_Reset(NdefMap); +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + + /* + * Fix for PR - 0001256 + * Date- 08-08-08 + */ + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } + + return (status); +} + +/*! +* Registering the Completion Routine. +* +* This function requires the caller to set a Completion Routine +* which serves as notifier for the upper component. +* NOTE: Please refer the header file for more information. +* +*/ + +NFCSTATUS phFriNfc_NdefMap_SetCompletionRoutine(phFriNfc_NdefMap_t *NdefMap, + uint8_t FunctionID, + pphFriNfc_Cr_t CompletionRoutine, + void *CompletionRoutineContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if ( ( NdefMap == NULL ) || (FunctionID >= PH_FRINFC_NDEFMAP_CR) || + ( CompletionRoutine == NULL) || (CompletionRoutineContext == NULL)) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Register the application callback with the NdefMap Completion Routine */ + NdefMap->CompletionRoutine[FunctionID].CompletionRoutine = CompletionRoutine; + + /* Register the application context with the NdefMap Completion Routine context */ + NdefMap->CompletionRoutine[FunctionID].Context = CompletionRoutineContext; + } + + return status; +} + +/*! +* Initiates Reading of NDEF information from the Remote Device. +* +* Remote Peer device may be of type any card. Ex: desfire,felica,jewel +* mifareUL,mifare 1K etc. The function initiates the reading of NDEF +* information from a Remote Device. +* +* This is the main NdefMap read function call.Internally,depending upon +* the CardType,respective mifare/desfire read functions are called. +* In future this can be extended to support any types of card. +* +* It performs a reset of the state and triggers/starts the raed action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action +* has been triggered. +* +* NOTE: Please refer the header file for more information. +* +*/ + +NFCSTATUS phFriNfc_NdefMap_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + + /* check for validity of input parameters*/ + if (( PacketData == NULL ) + || ( NdefMap == NULL ) + || ( PacketDataLength == NULL ) + || ( *PacketDataLength == 0 ) + || ( ( Offset != PH_FRINFC_NDEFMAP_SEEK_CUR) && (Offset != PH_FRINFC_NDEFMAP_SEEK_BEGIN )) + || (NdefMap->CompletionRoutine->CompletionRoutine == NULL) + || (NdefMap->CompletionRoutine->Context == NULL ) + ) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else if (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INVALID) + { + /* Card is in invalid state, cannot have any read/write + operations*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_FORMAT); + } + else if(NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INITIALIZED) + { + /* Can't read any data from the card:TLV length is zero*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + + NdefMap->NumOfBytesRead = PacketDataLength; + *NdefMap->NumOfBytesRead = 0; + + + } + else if ( (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE) && (Offset != PH_FRINFC_NDEFMAP_SEEK_BEGIN )) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_DEVICE_REQUEST); + } + else + { + /* Check the offset given by the user + If the offset is 1 (SEEK_BEGIN), reset everything and start + reading from the first Page of the card. + else if offset is 0 (PH_FRINFC_NDEFMAP_SEEK_CUR), continue reading + No need to reset the parameters. */ + + if ( Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN ) + { + NdefMap->ApduBuffIndex = 0; + *NdefMap->DataCount = 0; + } + + if ( (NdefMap->CardType == PH_FRINFC_NDEFMAP_ISO14443_4A_CARD) && + (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && (*NdefMap->DataCount == 0 )) + { + + /* A READ operation cannot be done if the previuos operation was WRITE + unless the offset is set to PH_FRINFC_NDEFMAP_SEEK_BEGIN Or + Read Operation with Offset set to Continue & DataCount set to 0 */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_DEVICE_REQUEST); + } + else + { + switch ( NdefMap->CardType) + { +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED + case PH_FRINFC_NDEFMAP_MIFARE_UL_CARD : + /* Mifare card selected. Call Mifare read */ + status = phFriNfc_MifareUL_RdNdef ( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED */ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED + case PH_FRINFC_NDEFMAP_ISO14443_4A_CARD : +#ifdef DESFIRE_EV1 + case PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 : +#endif /* #ifdef DESFIRE_EV1 */ + /* Desfire card selected. Call Desfire read */ + status = phFriNfc_Desfire_RdNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED + case PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD : + case PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD : + /* Mifare card selected. Call Mifare read */ + status = phFriNfc_MifareStdMap_RdNdef ( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED + case PH_FRINFC_NDEFMAP_FELICA_SMART_CARD : + /* Desfire card selected. Call Desfire Write */ + status = phFriNfc_Felica_RdNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + +#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED + case PH_FRINFC_NDEFMAP_TOPAZ_CARD : + /* Topaz card selected. Call Topaz read */ + status = phFriNfc_TopazMap_RdNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#ifndef PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED + case PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD : + /* Topaz card selected. Call Topaz read */ + status = phFriNfc_TopazDynamicMap_RdNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED */ +#endif /* PH_FRINFC_MAP_TOPAZ_DISABLED */ + +#ifndef PH_FRINFC_MAP_ISO15693_DISABLED + case PH_FRINFC_NDEFMAP_ISO15693_CARD: + status = phFriNfc_ISO15693_RdNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* #ifndef PH_FRINFC_MAP_ISO15693_DISABLED */ + +#ifdef PHFRINFC_OVRHAL_MOCKUP + case PH_FRINFC_NDEFMAP_MOCKUP_CARD : + /* Mockup card selected. Call Mockup Write */ + status = phFriNfc_Mockup_RdNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + + default : + /* Unknown card type. Return error */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_REMOTE_DEVICE); + + break; + } + } + } + return status; +} + +/*! +* Initiates Writing of NDEF information to the Remote Device. +* +* The function initiates the writing of NDEF information to a Remote Device +* +* Remote Peer device may be of type any card. Ex: desfire,felica,jewel +* mifareUL,mifare 1K etc. The function initiates the reading of NDEF +* information from a Remote Device. +* +* This is a main write api.Internally,depending upon the CardType, +* respective mifare/desfire write apis are called.In future this can be +* extended to support any types of card. +* +* It performs a reset of the state and starts the action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once +* the action has been triggered. +* +* NOTE: Please refer the header file for more information. +* +*/ + + +NFCSTATUS phFriNfc_NdefMap_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint8_t StatusChk=0; + + if ( (PacketData == NULL) + || ( NdefMap == NULL ) + /* + Mantis 442 */ + || ( PacketDataLength == NULL ) + /* - Mantis 442 */ + || ( *PacketDataLength == 0 ) + || ((Offset != PH_FRINFC_NDEFMAP_SEEK_CUR) && (Offset != PH_FRINFC_NDEFMAP_SEEK_BEGIN )) + || (NdefMap->CompletionRoutine->CompletionRoutine == NULL) + || (NdefMap->CompletionRoutine->Context == NULL) + ) + { + /* Invalid input parameter error */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_PARAMETER); + } + else if (( NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INVALID) && + (PH_FRINFC_NDEFMAP_TOPAZ_CARD != NdefMap->CardType) && + (PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD != NdefMap->CardType)) + { + /* Card is in invalid state, cannot have any read/write + operations*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_FORMAT); + } + + else if ( NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_ONLY ) + + { + /*Can't write to the card :No Grants */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_NOT_ALLOWED); + + /* set the no. bytes written is zero*/ + NdefMap->WrNdefPacketLength = PacketDataLength; + *NdefMap->WrNdefPacketLength = 0; + + } + else + { + /* Check the offset given by the user + If the offset is 1 (SEEK_BEGIN), reset everything and start + writing from the first Byte of the card. + else if offset is 0 (PH_FRINFC_NDEFMAP_SEEK_CUR), continue writing + No need to reset the parameters. */ + if (( NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INVALID) && + (PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD == NdefMap->CardType)) + { + /* If Topaz Dynamic card CC bytes are not valid then also allow writing, + If card is really good then writing will be done properly and reading can be performed, + otherwise writing or reading will fail. so, setting card state to + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE */ + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE; + } + + if ( Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN ) + { + NdefMap->ApduBuffIndex = 0; + *NdefMap->DataCount = 0; + } + + if ( (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_UL_CARD) || + (NdefMap->CardType == PH_FRINFC_NDEFMAP_ISO14443_4A_CARD)) + { + if (( (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE) && (Offset != PH_FRINFC_NDEFMAP_SEEK_BEGIN )) || + ( (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && (*NdefMap->DataCount == 0 ))) + { + /* A WRITE operation cannot be done if the previuos operation was READ + unless the offset is set to PH_FRINFC_NDEFMAP_SEEK_BEGIN OR + Write Operation with Offset set to Continue & DataCount set to 0 */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_DEVICE_REQUEST); + StatusChk = 1; + } + } + if(StatusChk != 1) + { + NdefMap->WrNdefPacketLength = PacketDataLength; + switch ( NdefMap->CardType) + { +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED + case PH_FRINFC_NDEFMAP_MIFARE_UL_CARD : + /* Mifare card selected. Call Mifare Write */ + status = phFriNfc_MifareUL_WrNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED */ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED + case PH_FRINFC_NDEFMAP_ISO14443_4A_CARD : +#ifdef DESFIRE_EV1 + case PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 : +#endif /* #ifdef DESFIRE_EV1 */ + /* Desfire card selected. Call Desfire Write */ + status = phFriNfc_Desfire_WrNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED + case PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD : + case PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD : + /* Mifare card selected. Call Mifare read */ + status = phFriNfc_MifareStdMap_WrNdef ( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED + case PH_FRINFC_NDEFMAP_FELICA_SMART_CARD : + /* Desfire card selected. Call Desfire Write */ + status = phFriNfc_Felica_WrNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + +#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED + case PH_FRINFC_NDEFMAP_TOPAZ_CARD : + /* Topaz card selected. Call Topaz Write */ + status = phFriNfc_TopazMap_WrNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#ifndef PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED + case PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD : + /* Topaz card selected. Call Topaz Write */ + status = phFriNfc_TopazDynamicMap_WrNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED */ +#endif /* PH_FRINFC_MAP_TOPAZ_DISABLED */ + +#ifndef PH_FRINFC_MAP_ISO15693_DISABLED + case PH_FRINFC_NDEFMAP_ISO15693_CARD: + status = phFriNfc_ISO15693_WrNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* #ifndef PH_FRINFC_MAP_ISO15693_DISABLED */ + + +#ifdef PHFRINFC_OVRHAL_MOCKUP + case PH_FRINFC_NDEFMAP_MOCKUP_CARD : + /* Mockup card selected. Call Mockup Write */ + status = phFriNfc_Mockup_WrNdef( NdefMap, + PacketData, + PacketDataLength, + Offset); + break; +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + default : + /* Unknown card type. Return error */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + break; + } + } + } + return status; +} + +#ifdef FRINFC_READONLY_NDEF + +NFCSTATUS +phFriNfc_NdefMap_ConvertToReadOnly ( + phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS result = NFCSTATUS_PENDING; + + + /* Check for ndefmap context and relevant state. Else return error*/ + if (NULL == NdefMap) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else if ((NdefMap->CompletionRoutine->CompletionRoutine == NULL) + || (NdefMap->CompletionRoutine->Context == NULL)) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else + { + switch (NdefMap->CardType) + { + case PH_FRINFC_NDEFMAP_TOPAZ_CARD: + { + result = phFriNfc_TopazMap_ConvertToReadOnly (NdefMap); + break; + } + + case PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD: + { + result = phFriNfc_TopazDynamicMap_ConvertToReadOnly (NdefMap); + break; + } + + case PH_FRINFC_NDEFMAP_ISO15693_CARD: + { + result = phFriNfc_ISO15693_ConvertToReadOnly (NdefMap); + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + break; + } + } + } + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/*! +* Check whether a particular Remote Device is NDEF compliant. +* +* The function initiates the ndef compliancy check. +* +* This is a main check ndef api.Internally,depending upon the different +* opmodes,respective mifare/desfire checkNdef apis are called. +* In future this can be extended to check any types of card ndef +* compliancy. +* +* It performs a reset of the state and starts the action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once +* the action has been triggered. +* +* NOTE: Please refer the header file for more information. +* +*/ + +NFCSTATUS phFriNfc_NdefMap_ChkNdef( phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint8_t sak; + + + /* Check for ndefmap context and relevant state. Else return error*/ + if ( NdefMap == NULL ) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( (NdefMap->State != PH_FRINFC_NDEFMAP_STATE_RESET_INIT) || + (NdefMap->psRemoteDevInfo->SessionOpened != 0x01 ) ) + /* Harsha: If SessionOpened is not 1, this means that connect has not happened */ + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_DEVICE_REQUEST); + } + else if ( (NdefMap->CompletionRoutine->CompletionRoutine == NULL) || (NdefMap->CompletionRoutine->Context == NULL )) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* + * 1.Changed + * CardInfo106 Replace with the ReaderA_Info. + */ + + sak = NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak; + + /* + * 3. Changed + * Description: Opmode replace with RemDevType. + */ + + + switch ( NdefMap->psRemoteDevInfo->RemDevType ) + { +#ifndef PH_FRINFC_MAP_ISO15693_DISABLED + case phHal_eISO15693_PICC: + { + status = phFriNfc_ISO15693_ChkNdef (NdefMap); + break; + } +#else /* #ifndef PH_FRINFC_MAP_ISO15693_DISABLED */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* #ifndef PH_FRINFC_MAP_ISO15693_DISABLED */ + + case phHal_eMifare_PICC: + case phHal_eISO14443_3A_PICC: + /* Remote device is Mifare card . Check for Mifare + NDEF compliancy */ + if(0x00 == sak) + { + /* The SAK/Sel_Res says the card is of the type + Mifare UL */ +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED + status = phFriNfc_MifareUL_ChkNdef( NdefMap); +#else /* PH_FRINFC_MAP_MIFAREUL_DISABLED*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED*/ + } + else if ((0x08 == (sak & 0x18)) || + (0x18 == (sak & 0x18)) || + (0x01 == sak)) + { + /* The SAK/Sel_Res says the card is of the type + Mifare Standard */ +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED + status = phFriNfc_MifareStdMap_ChkNdef( NdefMap); +#else /* PH_FRINFC_MAP_MIFARESTD_DISABLED*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED*/ + } + else + { + /* Invalid Mifare UL card, as the remote device + info - opmode says its a Mifare UL card but, + The SAK/Sel_Res is wrong */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + } + break; + case phHal_eISO14443_B_PICC: + { + status = phFriNfc_Desfire_ChkNdef(NdefMap); + } + break; + case phHal_eISO14443_A_PICC : + /* Remote device is Desfire card . Check for Desfire + NDEF compliancy */ + if(0x20 == (sak & 0x20)) + { + /* The SAK/Sel_Res says the card is of the type + ISO14443_4A */ +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED + status = phFriNfc_Desfire_ChkNdef(NdefMap); +#else /* PH_FRINFC_MAP_DESFIRE_DISABLED*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED*/ + } + else + { + /* Invalid Desfire card, as the remote device + info - opmode says its a desfire card but, + The SAK/Sel_Res is wrong */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + } + break; + + case phHal_eFelica_PICC: + + /*Set the OpMode Type Flag*/ +#ifndef PH_FRINFC_MAP_FELICA_DISABLED +#ifndef PH_HAL4_ENABLE + NdefMap->OpModeType[0] = phHal_eOpModesFelica212; + NdefMap->OpModeType[1] = phHal_eOpModesArrayTerminator; +#endif /* #ifndef PH_HAL4_ENABLE */ + status = phFriNfc_Felica_ChkNdef(NdefMap); +#else /* PH_FRINFC_MAP_FELICA_DISABLED*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_MAP_FELICA_DISABLED*/ + + break; + +#ifndef PH_HAL4_ENABLE +#ifndef PH_FRINFC_MAP_FELICA_DISABLED + case phHal_eFelica424: + /*Set the OpMode Ttype Flag*/ + NdefMap->OpModeType[0] = phHal_eOpModesFelica424; + NdefMap->OpModeType[1] = phHal_eOpModesArrayTerminator; + status = phFriNfc_Felica_ChkNdef(NdefMap); +#else /* PH_FRINFC_MAP_FELICA_DISABLED*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_MAP_FELICA_DISABLED*/ + break; +#endif + + case phHal_eJewel_PICC : + /* Remote device is Topaz card . Check for Topaz + NDEF compliancy */ +#ifdef PH_HAL4_ENABLE +#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED + /* Decide on the Header bytes to know the + Type of the Topaz card.Card could be Static or + Dynamic type. These are of type NFFC-NDEF Data Application*/ + if ( NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.HeaderRom0 + == PH_FRINFC_TOPAZ_HEADROM0_VAL) + { + + status = phFriNfc_TopazMap_ChkNdef(NdefMap); + } +#ifndef PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED + else if( NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.HeaderRom0 + == PH_FRINFC_TOPAZ_DYNAMIC_HEADROM0_VAL) + { + + status = phFriNfc_TopazDynamicMap_ChkNdef(NdefMap); + } +#endif + else + { + + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + + } +#endif + + +#else + if(0xC2 == sak) + { + /* The SAK/Sel_Res says the card is of the type + ISO14443_4A */ +#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED + status = phFriNfc_TopazMap_ChkNdef(NdefMap); +#else /* PH_FRINFC_MAP_TOPAZ_DISABLED*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_MAP_TOPAZ_DISABLED*/ + } + else + { + /* Invalid Topaz card, as the remote device + info - opmode says its a desfire card but, + The SAK/Sel_Res is wrong */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + } +#endif + break; + +#ifdef PHFRINFC_OVRHAL_MOCKUP + case phHal_eOpModesMockup : + /*Set the OpMode Ttype Flag*/ + NdefMap->OpModeType[0] = phHal_eOpModesMockup; + NdefMap->OpModeType[1] = phHal_eOpModesArrayTerminator; + status = phFriNfc_Mockup_ChkNdef(NdefMap); + break; +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + + default : + /* Remote device is not recognised. + Probably not NDEF compliant */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + break; + } + } + } + return status; +} + + +/*! +* \brief Completion Routine, Processing function, needed to avoid long blocking. +* \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion +* Routine in order to be able to notify the component that an I/O has finished and data are +* ready to be processed. +* This is a main Ndef Map Process api.Internally,depending upon the different +* CardTypes,respective mifare/desfire process functions are called. +* +*/ + +void phFriNfc_NdefMap_Process( void *Context, + NFCSTATUS Status) +{ + + if ( Context != NULL ) + { + phFriNfc_NdefMap_t *NdefMap = (phFriNfc_NdefMap_t *)Context; + /* + * 4 Changed + * Description: Opmode replace with RevDevTyp. + */ + + switch ( NdefMap->psRemoteDevInfo->RemDevType ) + { + case phHal_eMifare_PICC : + case phHal_eISO14443_3A_PICC: + + if((NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD) || + (NdefMap->CardType == PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD)) + { +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED + /* Remote device is Mifare Standard card */ + phFriNfc_MifareStdMap_Process(NdefMap,Status); +#else /* PH_FRINFC_MAP_MIFARESTD_DISABLED*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED*/ + } + else + { +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED + /* Remote device is Mifare UL card */ + phFriNfc_MifareUL_Process(NdefMap,Status); +#else /* PH_FRINFC_MAP_MIFAREUL_DISABLED*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED*/ + } + break; + + case phHal_eISO14443_A_PICC : +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED + /* Remote device is Desfire card */ + phFriNfc_Desfire_Process(NdefMap, Status); +#else /* PH_FRINFC_MAP_DESFIRE_DISABLED*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED*/ + break; + case phHal_eISO14443_B_PICC: + /* Remote device is Desfire card */ + phFriNfc_Desfire_Process(NdefMap, Status); + break; + + case phHal_eFelica_PICC : +#ifndef PH_FRINFC_MAP_FELICA_DISABLED + /* Remote device is Felica Smart card */ + phFriNfc_Felica_Process(NdefMap, Status); +#else /* PH_FRINFC_MAP_FELICA_DISABLED*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_MAP_FELICA_DISABLED*/ + break; + + case phHal_eJewel_PICC: +#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED + if ( NdefMap->CardType == PH_FRINFC_NDEFMAP_TOPAZ_CARD ) + { + /* Remote device is Topaz Smart card */ + phFriNfc_TopazMap_Process(NdefMap, Status); + } +#ifndef PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED + else if ( NdefMap->CardType == PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD ) + { + /* Remote device is Topaz Smart card */ + phFriNfc_TopazDynamicMap_Process(NdefMap, Status); + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + + } + break; +#endif /* PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED*/ +#endif + + +#ifdef PHFRINFC_OVRHAL_MOCKUP + case phHal_eOpModesMockup: + /* Remote device is Desfire card */ + phFriNfc_Mockup_Process(NdefMap, Status); + break; +#endif /* PHFRINFC_OVRHAL_MOCKUP*/ + default : + /* Remote device opmode not recognised. + Probably not NDEF compliant */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + /* set the state back to the Reset_Init state*/ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; + + /* set the completion routine*/ + NdefMap->CompletionRoutine[PH_FRINFC_NDEFMAP_CR_INVALID_OPE]. + CompletionRoutine(NdefMap->CompletionRoutine->Context, Status); + break; + } + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_PARAMETER); + /* The control should not come here. As Context itself is NULL , + Can't call the CR*/ + } +} + +#if 0 + +NFCSTATUS phFriNfc_ChkAndParseTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + switch ( NdefMap->CardType ) + { +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED + case PH_FRINFC_NDEFMAP_MIFARE_UL_CARD : + + + break; +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED */ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED + case PH_FRINFC_NDEFMAP_ISO14443_4A_CARD : + status = phFriNfc_Desf_ChkAndParseTLV(NdefMap); + return (status); + + break; +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED + case PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD : + case PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD : + + break; +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED + case PH_FRINFC_NDEFMAP_FELICA_SMART_CARD : + ; + break; +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + + default : + /* Unknown card type. Return error */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_REMOTE_DEVICE); + + break; + } + + return ( status); +} +#endif + + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED +static void phFriNfc_DesfCapCont_HReset(phFriNfc_NdefMap_t *NdefMap) +{ + /* Initialise/reset the desfire capability contatiner structure variables*/ + NdefMap->DesfireCapContainer.DesfVersion = 0; + NdefMap->DesfireCapContainer.NdefMsgFid = 0; + NdefMap->DesfireCapContainer.NdefFileSize = 0; + NdefMap->DesfireCapContainer.MaxCmdSize = 0; + NdefMap->DesfireCapContainer.MaxRespSize = 0; + NdefMap->DesfireCapContainer.ReadAccess = 0; + NdefMap->DesfireCapContainer.WriteAccess = 0; +} +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED +static void phFriNfc_Felica_HReset(phFriNfc_NdefMap_t *NdefMap) +{ + uint8_t index=0; + + /* Initialise/reset the different felica structure variables*/ + /* Reset all the felica Basic staruture variables*/ + NdefMap->Felica.CurBlockNo = 0; + + for(index = 0;indexFelica.Rd_BytesToCopyBuff[index] = 0; + NdefMap->Felica.Wr_RemainedBytesBuff[index] = 0; + } + NdefMap->Felica.Rd_NoBytesToCopy = 0; + NdefMap->Felica.Wr_BytesRemained = 0; + + + /* Reset all the felica attribute information staruture variables*/ + for(index = 0;indexFelicaAttrInfo.LenBytes[index] = 0; + } + + NdefMap->FelicaAttrInfo.Nmaxb = 0; + NdefMap->FelicaAttrInfo.Nbr = 0; + NdefMap->FelicaAttrInfo.Nbw= 0; + NdefMap->FelicaAttrInfo.RdWrFlag = 0; + NdefMap->FelicaAttrInfo.WriteFlag = 0; + NdefMap->Felica.CurrBytesRead=0; + + /* Reset all the felica manufacture details staruture variables*/ + for(index = 0;indexFelicaManufDetails.ManufID[index] = 0; + NdefMap->FelicaManufDetails.ManufParameter[index] = 0; + } + NdefMap->Felica.NoBlocksWritten=0; +} +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + +NFCSTATUS phFriNfc_NdefMap_EraseNdef(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + static uint8_t PktData[3] = PH_FRINFC_NDEFMAP_EMPTY_NDEF_MSG; + uint8_t MemOffset = PH_FRINFC_NDEFMAP_SEEK_BEGIN; + static uint32_t PacketDataLength = sizeof(PktData); + + if (NdefMap == NULL ) + { + /* Invalid input parameter error */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_PARAMETER); + } + else + { + switch ( NdefMap->CardType) + { +#ifdef PHFRINFC_OVRHAL_MOCKUP + case PH_FRINFC_NDEFMAP_MOCKUP_CARD : +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + case PH_FRINFC_NDEFMAP_MIFARE_UL_CARD : + case PH_FRINFC_NDEFMAP_ISO14443_4A_CARD : +#ifdef DESFIRE_EV1 + case PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 : +#endif /* #ifdef DESFIRE_EV1 */ + case PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD : + case PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD : +#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED + case PH_FRINFC_NDEFMAP_TOPAZ_CARD : +#ifndef PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED + case PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD : +#endif +#ifndef PH_FRINFC_MAP_ISO15693_DISABLED + case PH_FRINFC_NDEFMAP_ISO15693_CARD: +#endif +#endif + /* Mifare card selected. Call Mifare Write */ + status = phFriNfc_NdefMap_WrNdef( NdefMap, + PktData, + &PacketDataLength, + MemOffset); + break; + + case PH_FRINFC_NDEFMAP_FELICA_SMART_CARD : + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED + /* Felica card selected. Call to write EMPTY NDEF Msg */ + status = phFriNfc_Felica_EraseNdef( NdefMap ); +#else /* PH_FRINFC_MAP_FELICA_DISABLED*/ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_MAP_FELICA_DISABLED*/ + + break; + default : + /* Unknown card type. Return error */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE); + break; + } + } + return status; +} +/* Harsha: Fix for the mantis entry 0000420: NDEF_MAP: Size of NDEF data: +no abstracted way for user to know how many bytes to read/write */ + +/*! +* \brief Helper API, exposed to the user to enable him to know the size +* of the NDEF data that he can write in to the card. +*/ +NFCSTATUS phFriNfc_NdefMap_GetContainerSize(const phFriNfc_NdefMap_t *NdefMap,uint32_t *maxSize, uint32_t *actualSize) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t sect_index = 0; + uint8_t actual_sect_index = 0; + uint8_t count_index = 0; + + if( (NdefMap == NULL) || (maxSize == NULL) || (actualSize == NULL)) + { + /* Invalid input parameter error */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Which card ? */ + switch(NdefMap->CardType) + { +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED + case PH_FRINFC_NDEFMAP_MIFARE_UL_CARD : + /* Mifare UL card */ + /* The integration needs to ensure that the checkNdef + function has been called before calling this function, + otherwise NdefMap->CardMemSize will be 0 */ + *maxSize = NdefMap->MifareULContainer.RemainingSize; + /* In Mifare UL card, the actual size is the length field + value of the TLV */ + *actualSize = NdefMap->TLVStruct.ActualSize; + break; +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED */ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED + case PH_FRINFC_NDEFMAP_ISO14443_4A_CARD : +#ifdef DESFIRE_EV1 + case PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 : +#endif /* #ifdef DESFIRE_EV1 */ + /* Desfire card */ + /* The integration needs to ensure that the checkNdef + function has been called before calling this function, + otherwise NdefMap->DesfireCapContainer.NdefFileSize + will be 0 */ + /* -2 bytes represents the size field bytes*/ + *maxSize = NdefMap->DesfireCapContainer.NdefFileSize - 2; + /* In Desfire card, the actual size cant be calculated so + the actual size is given as 0xFFFFFFFF */ + *actualSize = NdefMap->DesfireCapContainer.NdefDataLen; + break; +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED + case PH_FRINFC_NDEFMAP_TOPAZ_CARD : + /* Topaz card */ + /* The integration needs to ensure that the checkNdef + function has been called before calling this function, + otherwise NdefMap->CardMemSize will be 0 */ + *maxSize = NdefMap->TopazContainer.RemainingSize; + /* In Topaz card, the actual size is the length field value of the + TLV */ + *actualSize = NdefMap->TLVStruct.BytesRemainLinTLV; + break; +#ifndef PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED + case PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD : + /* Topaz 512 card */ + /* The integration needs to ensure that the checkNdef + function has been called before calling this function, + otherwise NdefMap->CardMemSize will be 0 */ + *maxSize = NdefMap->TopazContainer.NDEFRWSize; + /* In Topaz card, the actual size is the length field value of the + TLV */ + *actualSize = NdefMap->TopazContainer.ActualNDEFMsgSize; + break; + +#endif /* PH_FRINFC_MAP_TOPAZ_DISABLED */ +#endif /* PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED */ +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED + case PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD : + case PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD : + /* Mifare std card */ + + /* Max size is the number of NDEF compliant blocks in the card + multiplied by 16 bytes */ +#ifndef PH_HAL4_ENABLE + + *maxSize = NdefMap->StdMifareContainer.remainingSize; + +#else /* #ifndef PH_HAL4_ENABLE */ + + while ((PH_FRINFC_MIFARESTD_NDEF_COMP == + NdefMap->StdMifareContainer.aid[count_index]) && + (count_index < + PH_FRINFC_NDEFMAP_MIFARESTD_TOTALNO_BLK)) + { + actual_sect_index++; + count_index++; + } + /* Total number of sectors in 1k = 16 (0 to 15, MAD sector number = 0) + Total number of sectors in 4k = 40 (0 to 39, + MAD sector number = 0 and 16, After block number 31, each sector + has 16 blocks) + Every last block of the sector is the sector header, So the blocks + that can be read or written in each sector is always + (number of blocks in each sector - 1) + No of blocks in the one sector till the sector number 0 to 31 + (total 32 sectors) = + 4 blocks, So blocks that can be read/write = (4 - 1 = 3 blocks) + No of blocks in the one sector after the sector number 31 to 39 = + 16 blocks, So blocks that can be read/write = (16 - 1 = 15 blocks) + Each block has 16 bytes + To calculate number of bytes in the sector, depending on the number + of blocks multiplied by 16 + */ + if (PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD == + NdefMap->CardType) + { + if (actual_sect_index > 32) + { + sect_index = (actual_sect_index - 32); + /* Here, 30 is used because block number 0 and 16 are MAD blocks + which cannot be used for reading and writing data + 3 and 15 are blocks in each sector which can be read/write + 3 indicates the sector is in between (0 and 31) + 15 indicates the sector is in between (32 to 39) + 16 is always number of bytes in each block + 4 is used because each NDEF write has to write using the + TLV format and T & L takes 4 bytes length and V is the + input data + */ + *maxSize = (((30 * (16 * 3)) + (sect_index * (16 * 15))) - 4); + } + else if (actual_sect_index <= 16) + { + *maxSize = (((actual_sect_index - 1) * (16 * 3)) - 4); + } + else + { + *maxSize = (((actual_sect_index - 2) * (16 * 3)) - 4); + } + } + else + { + /* Here, 16 is always number of bytes in each block + 3 indicates the sector is in between (0 and 31) */ + if (actual_sect_index > NdefMap->StdMifareContainer.SectorIndex) + { + actual_sect_index = NdefMap->StdMifareContainer.SectorIndex; + } + *maxSize = (((actual_sect_index - 1) * (16 * 3)) - 4); + } + +#endif /* #ifndef PH_HAL4_ENABLE */ + *actualSize = NdefMap->TLVStruct.BytesRemainLinTLV; + + break; +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED + case PH_FRINFC_NDEFMAP_FELICA_SMART_CARD : + /* Felica card */ + + *maxSize = NdefMap->FelicaAttrInfo.Nmaxb * 0x10; + + /* In Felica Card, actual size is calculated using the Length Bytes */ + *actualSize = NdefMap->FelicaAttrInfo.LenBytes[0]; + *actualSize = *actualSize << 16; + *actualSize += NdefMap->FelicaAttrInfo.LenBytes[1]; + *actualSize = *actualSize << 8; + *actualSize += NdefMap->FelicaAttrInfo.LenBytes[2]; + break; +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + +#ifndef PH_FRINFC_MAP_ISO15693_DISABLED + case PH_FRINFC_NDEFMAP_ISO15693_CARD: + { +#if 1 + uint16_t block_no = 0; + uint8_t byte_no = 0; + + block_no = (uint16_t) + ISO15693_GET_VALUE_FIELD_BLOCK_NO ( + NdefMap->ISO15693Container.ndef_tlv_type_blk, + NdefMap->ISO15693Container.ndef_tlv_type_byte, + NdefMap->ISO15693Container.actual_ndef_size); + byte_no = (uint8_t) + ISO15693_GET_VALUE_FIELD_BYTE_NO ( + NdefMap->ISO15693Container.ndef_tlv_type_blk, + NdefMap->ISO15693Container.ndef_tlv_type_byte, + NdefMap->ISO15693Container.actual_ndef_size); + + *maxSize = (NdefMap->ISO15693Container.max_data_size - + ((block_no * ISO15693_BYTES_PER_BLOCK) + byte_no)); +#else /* #if 1 */ + /* 2 is used to exclude the T and L part of the TLV */ + *maxSize = (NdefMap->ISO15693Container.max_data_size + - ISO15693_BYTES_PER_BLOCK - 2); +#endif /* #if 1 */ + *actualSize = NdefMap->ISO15693Container.actual_ndef_size; + break; + } +#endif + +#ifdef PHFRINFC_OVRHAL_MOCKUP + case PH_FRINFC_NDEFMAP_MOCKUP_CARD : + *maxSize = 0xFFFFFFFF; + /* In Desfire card, the actual size cant be calculated so + the actual size is given as 0xFFFFFFFF */ + *actualSize = 0xFFFFFFFF; + break; +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + + default : + /* Unknown card type. Return error */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,\ + NFCSTATUS_INVALID_REMOTE_DEVICE); + break; + } + } + return(result); +} + +#ifdef PHFRINFC_OVRHAL_MOCKUP +NFCSTATUS phFriNfc_NdefMap_MockupCardSetter(phFriNfc_NdefMap_t *NdefMap, + uint8_t *NdefData, + uint32_t NdefActualSize, + uint32_t NdefMaxSize, + uint32_t CardSize) +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + // First check all parameters + if((NdefData != NULL) && (NdefMap != NULL)) + { + // OK we can set + NdefMap->MochupContainer.NdefData = NdefData; + NdefMap->MochupContainer.NdefActualSize = NdefActualSize; + NdefMap->MochupContainer.NdefMaxSize = NdefMaxSize; + NdefMap->MochupContainer.CardSize = CardSize; + NdefMap->MochupContainer.CurrentBlock = 0; + + } else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, NFCSTATUS_INVALID_PARAMETER); + } + return Status; +} + +NFCSTATUS phFriNfc_NdefMap_MockupNDefModeEn(uint8_t *pNdefCompliancy, uint8_t *pCardType, uint8_t Enable) +{ + *pNdefCompliancy = Enable; + *pCardType = PH_FRINFC_NDEFMAP_MOCKUP_CARD; + return NFCSTATUS_SUCCESS; +} +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + + + + + + + + diff --git a/libnfc-nxp/phFriNfc_NdefMap.h b/libnfc-nxp/phFriNfc_NdefMap.h new file mode 100644 index 0000000..4c4ab45 --- /dev/null +++ b/libnfc-nxp/phFriNfc_NdefMap.h @@ -0,0 +1,1336 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_NdefMap.h + * \brief NFC Ndef Mapping For Different Smart Cards. + * + * Project: NFC-FRI + * + * $Date: Mon Dec 13 14:14:14 2010 $ + * $Author: ing02260 $ + * $Revision: 1.25 $ + * $Aliases: $ + * + */ + +#ifndef PHFRINFC_NDEFMAP_H +#define PHFRINFC_NDEFMAP_H + + +/*include files*/ +#include +#include +#include +#ifdef PH_HAL4_ENABLE + #include +#else + #include +#endif + + +#include + +#ifndef PH_FRINFC_EXCLUDE_FROM_TESTFW /* */ + +/** + * \name NDEF Mapping + * + * File: \ref phFriNfc_NdefMap.h + * + */ +/*@{*/ +#define PH_FRINFC_NDEFMAP_FILEREVISION "$Revision: 1.25 $" /**< \ingroup grp_file_attributes */ +#define PH_FRINFC_NDEFMAP_FILEALIASES "$Aliases: $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +#endif /* PH_FRINFC_EXCLUDE_FROM_TESTFW */ + + +/** \defgroup grp_fri_nfc_ndef_map NDEF Mapping Component + * + * This component implements the read/write/check NDEF functions for remote devices. + * NDEF data, as defined by the NFC Forum NDEF specification are written to or read from + * a remote device that can be a smart- or memory card. \n\n + * Please notice that the NDEF mapping command sequence must + * be \b contiguous (after correct initialisation): \n + * \b Examples: + * - Checking and Reading + * - \ref phFriNfc_NdefMap_ChkNdef + * - \ref phFriNfc_NdefMap_RdNdef + * . + * - Checking and Writing + * - \ref phFriNfc_NdefMap_ChkNdef + * - \ref phFriNfc_NdefMap_WrNdef + * . + * - Checking, Reading and Writing + * - \ref phFriNfc_NdefMap_ChkNdef + * - \ref phFriNfc_NdefMap_RdNdef + * - \ref phFriNfc_NdefMap_WrNdef + * . + * . + * There must be \b no \b other FRI or HAL call between these mapping commands. Exceptions to this + * rule are specific to the NDEF mapping of certain card / remote device types and separately noted, + * typically for true multi-activation capable devices. + * + */ + +/** + * \name NDEF Mapping - specifies the different card types + * These are the only recognised card types in this version. + * + */ +/*@{*/ + +#define DESFIRE_EV1 + +#define PH_FRINFC_NDEFMAP_MIFARE_UL_CARD 1 /**< \internal Mifare UL */ +#define PH_FRINFC_NDEFMAP_ISO14443_4A_CARD 2 /**< \internal Iso 14443-4A */ +#define PH_FRINFC_NDEFMAP_MIFARE_STD_1K_CARD 3 /**< \internal Mifare Standard */ +#define PH_FRINFC_NDEFMAP_MIFARE_STD_4K_CARD 4 /**< \internal Mifare Standard */ +#define PH_FRINFC_NDEFMAP_FELICA_SMART_CARD 5 /**< \internal Felica Smart Tag */ +#define PH_FRINFC_NDEFMAP_TOPAZ_CARD 7 /**< \internal Felica Smart Tag */ +#define PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD 8 /**< \internal Felica Smart Tag */ +#ifdef DESFIRE_EV1 +#define PH_FRINFC_NDEFMAP_ISO14443_4A_CARD_EV1 9 /**< \internal Iso 14443-4A EV1 */ +#endif /* #ifdef DESFIRE_EV1 */ + +#define PH_FRINFC_NDEFMAP_ISO15693_CARD 10 /**< \internal ISO 15693 */ + + +#ifdef PH_NDEF_MIFARE_ULC +#define PH_FRINFC_NDEFMAP_MIFARE_ULC_CARD 8 /**< \internal Mifare UL */ +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + +#define PH_FRINFC_NDEFMAP_EMPTY_NDEF_MSG {0xD0, 0x00, 0x00} /**< \internal Empty ndef message */ + + +#ifdef PHFRINFC_OVRHAL_MOCKUP /* */ +#define PH_FRINFC_NDEFMAP_MOCKUP_CARD 6 /**< \internal Mocup*/ +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + + + +/* Enum reperesents the different card state*/ +typedef enum +{ + PH_NDEFMAP_CARD_STATE_INITIALIZED, + PH_NDEFMAP_CARD_STATE_READ_ONLY, + PH_NDEFMAP_CARD_STATE_READ_WRITE, + PH_NDEFMAP_CARD_STATE_INVALID +}phNDEF_CARD_STATE; + + +/*@}*/ + + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED +/** + * \name NDEF Mapping - specifies the Compliant Blocks in the Mifare 1k and 4k card types + * + */ +/*@{*/ +#define PH_FRINFC_NDEFMAP_MIFARESTD_1KNDEF_COMPBLOCK 45 /**< \internal Total Ndef Compliant blocks Mifare 1k */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_4KNDEF_COMPBLOCK 210 /**< \internal Total Ndef Compliant blocks Mifare 4k */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_RDWR_SIZE 16 /**< \internal Bytes read/write for one read/write operation*/ +#define PH_FRINFC_NDEFMAP_MIFARESTD_TOTALNO_BLK 40 /**< \internal Total number of sectors in Mifare 4k */ +#define PH_FRINFC_NDEFMAP_MIFARESTD_ST15_BYTES 15 /**< \internal To store 15 bytes after reading a block */ +/*@}*/ +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED +/** + * \name NDEF Mapping - specifies the Compliant Blocks in the Mifare 1k and 4k card types + * + */ +/*@{*/ +#define PH_FRINFC_NDEFMAP_TOPAZ_MAX_SIZE 256 /**< \internal Total Memory size = 96 bytes (newer version have mode) */ +#define PH_FRINFC_NDEFMAP_TOPAZ_UID_SIZE 0x04 /**< \internal UID size returned by READID command = 4 bytes */ +/*@}*/ +#endif /* PH_FRINFC_MAP_TOPAZ_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED +/* Felica Mapping - Constants */ +#define PH_FRINFC_NDEFMAP_FELICA_BLOCK_SIZE 16 +#define PH_FRINFC_NDEFMAP_FELICA_ATTR_NDEF_DATA_LEN 3 +#define PH_FRINFC_NDEFMAP_FELICA_MANUF_ID_DATA_LEN 8 +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + +/* MifareUL/Type2 specific constants*/ +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED + +#ifdef PH_NDEF_MIFARE_ULC +#define PH_FRINFC_NDEFMAP_MFUL_64BYTES_BUF 2048 /**< \internal To store 2048 bytes after reading entire card */ +#else +#define PH_FRINFC_NDEFMAP_MFUL_64BYTES_BUF 64 /**< \internal To store 64 bytes after reading entire card */ +#endif /*#ifdef PH_NDEF_MIFARE_ULC */ + +#define PH_FRINFC_NDEFMAP_MFUL_4BYTES_BUF 4 /**< \internal To store 4 bytes after write */ + +#endif /*#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED*/ + +#ifdef PHFRINFC_OVRHAL_MOCKUP /* */ + +#define PH_FRINFC_NDEFMAP_MOCKUP_4096BYTES_BUF 4096 /**< \internal To store 4 bytes after write */ + +#endif /*#ifndef PH_FRINFC_MAP_MOCKUP_DISABLED*/ + +/** + * \name Completion Routine Indices + * + * These are the indices of the completion routine pointers within the component context. + * Completion routines belong to upper components. + * + */ +/*@{*/ +/** \ingroup grp_fri_nfc_ndef_map + * Completion Routine Index for \ref phFriNfc_NdefMap_ChkNdef */ +#define PH_FRINFC_NDEFMAP_CR_CHK_NDEF 0 /* */ +/** \ingroup grp_fri_nfc_ndef_map + * Completion Routine Index for \ref phFriNfc_NdefMap_RdNdef */ +#define PH_FRINFC_NDEFMAP_CR_RD_NDEF 1 /* */ +/** \ingroup grp_fri_nfc_ndef_map + * Completion Routine Index for \ref phFriNfc_NdefMap_WrNdef */ +#define PH_FRINFC_NDEFMAP_CR_WR_NDEF 2 /* */ +/** \ingroup grp_fri_nfc_ndef_map + * Completion Routine Index for \ref phFriNfc_NdefMap_EraseNdef */ +#define PH_FRINFC_NDEFMAP_CR_ERASE_NDEF 3 /* */ +/** \ingroup grp_fri_nfc_ndef_map Completion + * Routine Index for Unknown States/Operations */ +#define PH_FRINFC_NDEFMAP_CR_INVALID_OPE 4 /* */ +/** \ingroup grp_fri_nfc_ndef_map + * Number of completion routines that have to be initialised */ +#define PH_FRINFC_NDEFMAP_CR 5 /* */ +/*@}*/ + +/** + * \name File Offset Attributes + * + * Following values are used to determine the offset value for Read/Write. This specifies whether + * the Read/Write operation needs to be restarted/continued from the last offset set. + * + */ +/*@{*/ +/** \ingroup grp_fri_nfc_ndef_map + * Read/Write operation shall start from the last offset set */ +#define PH_FRINFC_NDEFMAP_SEEK_CUR 0 /* */ +/** \ingroup grp_fri_nfc_ndef_map + * Read/Write operation shall start from the begining of the file/card */ +#define PH_FRINFC_NDEFMAP_SEEK_BEGIN 1 /* */ +/*@}*/ + + +/** + * \name Buffer Size Definitions + * + */ +/*@{*/ +/** \ingroup grp_fri_nfc_ndef_map Minimum size of the TRX buffer required */ +#define PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE 252 /* */ +/** \internal The size of s MIFARE block */ +#define PH_FRINFC_NDEFMAP_MF_READ_BLOCK_SIZE 16 /* */ + + +#ifndef PH_FRINFC_EXCLUDE_FROM_TESTFW /* */ + + +#ifndef PH_FRINFC_MAP_ISO15693_DISABLED + +#define ISO15693_MAX_DATA_TO_STORE 0x04U + +typedef struct phFriNfc_ISO15693Cont +{ + /**< \internal block number that is executed */ + uint16_t current_block; + /**< \internal The state of the operation */ + uint8_t state; + /**< \internal Completion routine index */ + uint8_t cr_index; + /**< \internal Execution sequence */ + uint8_t ndef_seq; + /**< \internal NDEF TLV size */ + uint16_t actual_ndef_size; + /**< \internal NDEF TLV size */ + uint16_t max_data_size; + /**< \internal NDEF TLV TYPE block number */ + uint16_t ndef_tlv_type_blk; + /**< \internal NDEF TLV TYPE byte number in the + "ndef_tlv_type_blk" */ + uint8_t ndef_tlv_type_byte; + /**< \internal Store the remaining bytes that can be used for + READ with continue option */ + uint8_t store_read_data[ISO15693_MAX_DATA_TO_STORE]; + uint8_t store_length; + /**< \internal Remaining size that can be read */ + uint16_t remaining_size_to_read; + uint8_t read_capabilities; + + +}phFriNfc_ISO15693Cont_t; + +#endif /* #ifndef PH_FRINFC_MAP_ISO15693_DISABLED */ + + + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED +/** + * \ingroup grp_fri_nfc_ndef_map + * \brief Felica Basic structure which details the different vaiables + * used for Reading/writing. + * + */ +typedef struct phFriNfc_Felica +{ + /**< Current block being read or written*/ + uint8_t CurBlockNo; + + /**< No. Of Written*/ + uint8_t NoBlocksWritten; + + /**< Following are different variables used for write operation*/ + uint8_t Wr_BytesRemained; /* No of bytes to pad*/ + + /**< Buffer to store odd number of block data */ + uint8_t Wr_RemainedBytesBuff[PH_FRINFC_NDEFMAP_FELICA_BLOCK_SIZE]; + + /**< Following are different variables used for read operation*/ + uint8_t Rd_NoBytesToCopy; /*specifies the extra number of read bytes */ + + /**< stores extra read data bytes*/ + uint8_t Rd_BytesToCopyBuff[PH_FRINFC_NDEFMAP_FELICA_BLOCK_SIZE]; + + /**< Flag determines Intermediate Copy Operation*/ + uint8_t IntermediateCpyFlag; + + /**< Stores Intermediate Copy data len*/ + uint8_t IntermediateCpyLen; + + /**< Flag specifies Pad Byte Information*/ + uint8_t PadByteFlag; + + /**< Flag specifies Intermediate WR Information*/ + uint8_t IntermediateWrFlag; + + /**< Flag specifies Intermediate Rd Information*/ + uint8_t IntermediateRdFlag; + + /**< Flag specifies Last Block Reached Information*/ + uint8_t LastBlkReachedFlag; + + /**< Specifies how many bytes read from the card*/ + uint16_t CurrBytesRead; + + /**< Flag specifies EOF card reached Information*/ + uint8_t EofCardReachedFlag; + + /**< Flag specifies different Operation Types*/ + uint8_t OpFlag; + + /**< Specifies Offset*/ + uint8_t Offset; + + /**< Specifies TrxLen Information*/ + uint16_t TrxLen; + +}phFriNfc_Felica_t; + +/** + * \ingroup grp_fri_nfc_ndef_map + * \brief Felica structure which details the different vaiables + * used to store the poll related information. + * + */ +typedef struct phFriNfc_Felica_PollDetails +{ + phHal_sDevInputParam_t *DevInputParam; +#ifndef PH_HAL4_ENABLE + phHal_eOpModes_t *OpMode; +#endif + /**< Temporary place holder to the Remote Device + Information, required to store the Felica + session opened information. */ + phHal_sRemoteDevInformation_t psTempRemoteDevInfo; +}phFriNfc_Felica_PollDetails_t; + +/** + * \ingroup grp_fri_nfc_ndef_map + * \brief Felica structure which details the attribute related information. + * + */ +typedef struct phFriNfc_Felica_AttrInfo +{ + /** Version of the Ndefmap document*/ + uint8_t Version; + /** Nbr for check cmd*/ + uint8_t Nbr; + /** Nbw for update cmd*/ + uint8_t Nbw; + /** Maximum number of blocks to store Ndef data*/ + uint16_t Nmaxb; + /** Flag to indicate the status of the write operation*/ + uint8_t WriteFlag; + /** Flag to indicate the status of the read/write operation*/ + uint8_t RdWrFlag; + /** Represents the length of Ndef data : 3 bytes*/ + uint8_t LenBytes[PH_FRINFC_NDEFMAP_FELICA_ATTR_NDEF_DATA_LEN]; + /** Specifies the ERASE NDEF Message Operation */ + uint8_t EraseMsgFlag; + +}phFriNfc_Felica_AttrInfo_t; + +/** + * \ingroup grp_fri_nfc_ndef_map + * \brief Felica structure which details the different vaiables + * used to store the Card Manufacturer details. + */ +typedef struct phFriNfc_Felica_ManufDetails +{ + /** Manufacture identifier*/ + uint8_t ManufID[PH_FRINFC_NDEFMAP_FELICA_MANUF_ID_DATA_LEN]; + /** Manufacture Parameters*/ + uint8_t ManufParameter[PH_FRINFC_NDEFMAP_FELICA_MANUF_ID_DATA_LEN]; +}phFriNfc_Felica_ManufDetails_t; +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED +typedef struct phFriNfc_MifareStdCont +{ + /** Device input parameter for poll and connect after failed authentication */ + phHal_sDevInputParam_t *DevInputParam; + /** to store bytes that will be used in the + next write/read operation, if any */ + uint8_t internalBuf[PH_FRINFC_NDEFMAP_MIFARESTD_ST15_BYTES]; + /** to Store the length of the internalBuf */ + uint16_t internalLength; + /** holds the block number which is presently been used */ + uint8_t currentBlock; + /** the number of Ndef Compliant blocks written/read */ + uint8_t NdefBlocks; + /** Total Number of Ndef Complaint Blocks */ + uint16_t NoOfNdefCompBlocks; + /** used in write ndef, to know that internal bytes + are accessed */ + uint8_t internalBufFlag; + /** used in write ndef, to know that last 16 bytes + are used to write*/ + uint8_t RemainingBufFlag; + /** indicates that Read has reached the end of the + card */ + uint8_t ReadWriteCompleteFlag; + /** indicates that Read has reached the end of the + card */ + uint8_t ReadCompleteFlag; + /** indicates that Write is possible or not */ + uint8_t WriteFlag; + /** indicates that Write is possible or not */ + uint8_t ReadFlag; + /** indicates that Write is possible or not */ + uint8_t RdBeforeWrFlag; + /** Authentication Flag indicating that a particular + sector is authenticated or not */ + uint8_t AuthDone; + /** to store the last Sector ID in Check Ndef */ + uint8_t SectorIndex; + /** to read the access bits of each sector */ + uint8_t ReadAcsBitFlag; + /** Flag to check if Acs bit was written in this call */ + uint8_t WriteAcsBitFlag; + /** Buffer to store 16 bytes */ + uint8_t Buffer[PH_FRINFC_NDEFMAP_MIFARESTD_RDWR_SIZE]; + /** to store the AIDs of Mifare 1k or 4k */ + uint8_t aid[PH_FRINFC_NDEFMAP_MIFARESTD_TOTALNO_BLK]; + /** flag to write with offset begin */ + uint8_t WrNdefFlag; + /** flag to read with offset begin */ + uint8_t ReadNdefFlag; + /** flag to check with offset begin */ + uint8_t ChkNdefFlag; + /** To store the remaining size of the Mifare 1k or 4k card */ + uint16_t remainingSize; + /** To update the remaining size when writing to the Mifare 1k or 4k card */ + uint8_t remSizeUpdFlag; + /** The flag is to know that there is a different AID apart from + NFC forum sector AID */ + uint16_t aidCompleteFlag; + /** The flag is to know that there is a a NFC forum sector exists + in the card */ + uint16_t NFCforumSectFlag; + /** The flag is to know that the particular sector is a proprietary + NFC forum sector */ + uint16_t ProprforumSectFlag; + /** The flag is set after reading the MAD sectors */ + uint16_t ChkNdefCompleteFlag; + /** Flag to store the current block */ + uint8_t TempBlockNo; + /** Completion routine index */ + uint8_t CRIndex; + /** Bytes remaining to write for one write procedure */ + uint16_t WrLength; + /** Flag to read after write */ + uint8_t RdAfterWrFlag; + /** Flag to say that poll is required before write ndef (authentication) */ + uint8_t PollFlag; + /** Flag is to know that this is first time the read has been called. This + is required when read is called after write (especially for the card formatted + with the 2nd configuration) */ + uint8_t FirstReadFlag; + /** Flag is to know that this is first time the write has been called. This + is required when the card formatted with the 3rd configuration */ + uint8_t FirstWriteFlag; + /** Indicates the sector trailor id for which the convert + to read only is currently in progress*/ + uint8_t ReadOnlySectorIndex; + /** Indicates the total number of sectors on the card */ + uint8_t TotalNoSectors; + /** Indicates the block number of the sector trailor on the card */ + uint8_t SectorTrailerBlockNo; + /** Secret key B to given by the application */ + uint8_t UserScrtKeyB[6]; +}phFriNfc_MifareStdCont_t; +/*@}*/ +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED +/** + * \ingroup grp_fri_nfc_ndef_map + * \brief Capability Container. + * + * The Capability Container structure required for smart card operations. + * + */ +typedef struct phFriNfc_DesfireCapCont +{ + uint16_t DesfVersion; /**< \internal Desfire Version . */ + uint16_t NdefMsgFid; /**< \internal Ndef Message file pointer*/ + uint16_t NdefFileSize; /**< \internal Holds Desfire File Size */ + uint8_t ReadAccess; /**< \internal Read Access Information. */ + uint8_t WriteAccess; /**< \internal Write Access Information. */ + uint16_t MaxRespSize; /**< \internal Maximum expected response size. */ + uint16_t MaxCmdSize; /**< \internal Maximum command size. */ + uint16_t NdefDataLen; /**< \internal Holds actual NDEF Data Len.*/ + uint8_t IsNlenPresentFlag; /**< \internal specifies NLEN presence .*/ + uint8_t SkipNlenBytesFlag; /**< \internal sets on presence of NLEN.*/ +} phFriNfc_DesfireCapCont_t; +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED +/** + * \ingroup grp_fri_nfc_ndef_map + * \brief Mifare UL Basic structure which details the different vaiables + * used for Reading/writing. + * + */ +typedef struct phFriNfc_MifareULCont +{ + /** to store bytes that will be used in the + next write/read operation, if any */ + uint8_t InternalBuf[PH_FRINFC_NDEFMAP_MFUL_4BYTES_BUF]; + /** to Store the length of the internalBuf */ + uint16_t InternalLength; + /** holds the sector number which is presently been used */ + uint8_t CurrentSector; + /** holds the block number which is presently been used */ + uint8_t CurrentBlock; + /** to know the completion routine */ + uint8_t CRindex; + /** This stores the free memory size left in the card */ + uint16_t RemainingSize; + /** Copy all the data(including non NDEF TLVs) from the card */ + uint8_t ReadBuf[PH_FRINFC_NDEFMAP_MFUL_64BYTES_BUF]; + /** index of the above buffer */ + uint16_t ReadBufIndex; + /** This variable stores the index of the "ReadBuf" from which actual + data has to be copied into the user buffer */ + uint16_t ByteNumber; + /** indicates that read/write has reached the end of the + card */ + uint8_t ReadWriteCompleteFlag; + /** Buffer to store 4 bytes of data which is written to a block */ + uint8_t Buffer[PH_FRINFC_NDEFMAP_MFUL_4BYTES_BUF]; +}phFriNfc_MifareULCont_t; +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED */ + +#ifdef PHFRINFC_OVRHAL_MOCKUP /* */ +/** + * \ingroup grp_fri_nfc_ndef_map + * \brief Mifare UL Basic structure which details the different vaiables + * used for Reading/writing. + * + */ +typedef struct phFriNfc_MockupCont +{ + /** to store bytes that will be used in the + next write/read operation, if any */ + uint8_t *NdefData; + /** to Store the length of the internalBuf */ + uint32_t NdefActualSize; + /** to Store the length of the internalBuf */ + uint32_t NdefMaxSize; + /** to Store the length of the internalBuf */ + uint32_t CardSize; + /** holds the block number which is presently been used */ + uint32_t CurrentBlock; +} phFriNfc_MockupCont_t; +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + +#endif /* PH_FRINFC_EXCLUDE_FROM_TESTFW */ + +/** + * \ingroup grp_fri_nfc_ndef_map + * \brief NDEF TLV structure which details the different vaiables + * used for TLV. + * + */ +typedef struct phFriNfc_NDEFTLVCont +{ + /** Flag is to know that the TLV Type Found */ + uint8_t NdefTLVFoundFlag; + /** Sector number of the next/present available TLV */ + uint8_t NdefTLVSector; + /** Following two variables are used to store the + T byte and the Block number in which the T is + found in Tag */ + /** Byte number of the next/present available TLV */ + uint16_t NdefTLVByte; + /** Block number of the next/present available TLV */ + uint8_t NdefTLVBlock; + /** Authentication flag for NDEF TLV Block */ + uint8_t NdefTLVAuthFlag; + /** if the 16th byte of the last read is type (T) of TLV + and next read contains length (L) bytes of TLV. This flag + is set when the type (T) of TLV is found in the last read */ + uint8_t TcheckedinTLVFlag; + /** if the 16th byte of the last read is Length (L) of TLV + and next read contains length (L) bytes of TLV. This flag + is set when the Length (L) of TLV is found in the last read */ + uint8_t LcheckedinTLVFlag; + /** This flag is set, if Terminator TLV is already written + and next read contains value (V) bytes of TLV. This flag + is set when the value (V) of TLV is found in the last read */ + uint8_t SetTermTLVFlag; + /** To know the number of Length (L) field is present in the + next block */ + uint8_t NoLbytesinTLV; + /** The value of 3 bytes length(L) field in TLV. In 3 bytes + length field, 2 bytes are in one block and other 1 byte + is in the next block. To store the former block length + field value, this variable is used */ + uint16_t prevLenByteValue; + /** The value of length(L) field in TLV. */ + uint16_t BytesRemainLinTLV; + /** Actual size to read and write. This will be always equal to the + length (L) of TLV as there is only one NDEF TLV . */ + uint16_t ActualSize; + /** Flag is to write the length (L) field of the TLV */ + uint8_t WrLenFlag; + /** Flag is to write the length (L) field of the TLV */ + uint16_t NULLTLVCount; + /** Buffer to store 4 bytes of data which is written to a block */ + uint8_t NdefTLVBuffer[PH_FRINFC_NDEFMAP_MFUL_4BYTES_BUF]; + /** Buffer to store 4 bytes of data which is written to a next block */ + uint8_t NdefTLVBuffer1[PH_FRINFC_NDEFMAP_MFUL_4BYTES_BUF]; +}phFriNfc_NDEFTLVCont_t; + +/** + * \ingroup grp_fri_nfc_ndef_map + * \brief Lock Control TLV structure which stores the Position, + * Size and PageCntrl details. + */ + +typedef struct phFriNfc_LockCntrlTLVCont +{ + /** Specifies the Byte Position of the lock cntrl tlv + in the card memory*/ + uint16_t ByteAddr; + + /** Specifies the Size of the lock area in terms of + bits/bytes*/ + uint16_t Size; + + /** Specifies the Bytes per Page*/ + uint8_t BytesPerPage; + + /** Specifies the BytesLockedPerLockBit */ + uint8_t BytesLockedPerLockBit; + + /** Specifies the index of Lock cntrl TLV*/ + uint8_t LockTlvBuffIdx; + + /** Store the content of Lock cntrl TLV*/ + uint8_t LockTlvBuff[8]; + + /** Specifies the Block number Lock cntrl TLV*/ + uint16_t BlkNum; + + /** Specifies the Byte Number position of Lock cntrl TLV*/ + uint16_t ByteNum; + + +}phFriNfc_LockCntrlTLVCont_t; + + +/** + * \ingroup grp_fri_nfc_ndef_map + * \brief Memeory Control TLV structure which stores the Position, + * Size and PageCntrl details of the reserved byte area. + */ + +typedef struct phFriNfc_ResMemCntrlTLVCont +{ + /** Specifies the Byte Position of the lock cntrl tlv + in the card memory*/ + uint16_t ByteAddr; + + /** Specifies the Size of the lock area in terms of + bits/bytes*/ + uint16_t Size; + + /** Store the content of Memory cntrl TLV*/ + uint8_t MemCntrlTlvBuff[8]; + + /** Specifies the Bytes per Page*/ + uint8_t BytesPerPage; + + /** Specifies the index of Mem cntrl TLV*/ + uint8_t MemTlvBuffIdx; + + /** Specifies the Block number Lock cntrl TLV*/ + uint16_t BlkNum; + + /** Specifies the Byte Number position of Lock cntrl TLV*/ + uint16_t ByteNum; + + + +}phFriNfc_ResMemCntrlTLVCont_t; + +#if !(defined(PH_FRINFC_MAP_TOPAZ_DISABLED ) || defined (PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED )) + +/** + * \ingroup grp_fri_nfc_ndef_map + * \brief Topaz container structure which details the different vaiables + * used for Topaz card mapping. + * + */ +typedef struct phFriNfc_TopazCont +{ + /** This stores the free memory size left in the card. In case of topaz, + this is updated only during check ndef */ + uint16_t RemainingSize; + /** Stores the current block number */ + uint8_t CurrentBlock; + /** Stores the current block number */ + uint8_t ByteNumber; + /** To know the completion routine call */ + uint8_t CRIndex; + + uint8_t ReadWriteCompleteFlag; + /** This state is used for write */ + uint8_t InternalState; + /** This state is used for write */ + uint8_t SkipLockBlkFlag; + /** To store the UID */ + uint8_t UID[PH_FRINFC_NDEFMAP_TOPAZ_UID_SIZE]; + /** To CC bytes length */ + uint8_t CCByteBuf[4]; + /** Store the Buffer Index */ + uint16_t Cur_RW_Index; + + /* No of bytes read or write*/ + uint16_t ByteRWFrmCard; + + /* Cuurent Segment */ + uint8_t CurrentSeg; + + /** Store the read bytes */ + uint8_t ReadBuffer[PH_FRINFC_NDEFMAP_TOPAZ_MAX_SIZE]; + + /** Size to know the exact data filled in the ReadBuffer. Useful, when the + offset = PH_FRINFC_NDEFMAP_SEEK_CUR */ + uint8_t ReadBufferSize; + + /** NDEF TLV byte address, This stores the byte address of + TYPE field of the TLV */ + uint16_t NdefTLVByteAddress; + + /** Expected sequence */ + uint8_t ExpectedSeq; + + /** Write sequence */ + uint8_t WriteSeq; + + /** Actual NDEF message size */ + uint16_t ActualNDEFMsgSize; + + /** NDEF Read Write size in the card, this excludes lock and reserved bytes, + mentioned in the LOCK and MEMORY control TLVs */ + uint16_t NDEFRWSize; + + /** Remaining read size in the card, after reading the card. + User has asked for the data less than " ActualNDEFMsgSize ", + then remaining read bytes are stored in this variable. + If the next read is with offset = PH_FRINFC_NDEFMAP_SEEK_CUR, + then this variable is used. + */ + uint16_t RemainingReadSize; +#ifdef FRINFC_READONLY_NDEF + uint8_t read_only_seq; + uint8_t lock_bytes_written; +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +}phFriNfc_TopazCont_t; + +#endif /* PH_FRINFC_MAP_TOPAZ_DISABLED */ +/** + * \ingroup grp_fri_nfc_ndef_map + * \brief NFC NDEF Mapping Component Context Structure + * + * This structure is used to store the current context information of the instance. + * + */ +typedef struct phFriNfc_NdefMap +{ + /**< \internal The state of the operation. */ + uint8_t State; + + /**< \internal Completion Routine Context. */ + phFriNfc_CplRt_t CompletionRoutine[PH_FRINFC_NDEFMAP_CR]; + + /**< \internal Pointer to the lower (HAL) instance. */ + void *LowerDevice; + + /**<\internal Holds the device additional informations*/ + phHal_sDepAdditionalInfo_t psDepAdditionalInfo; + + /**<\internal Holds the completion routine informations of the Map Layer*/ + phFriNfc_CplRt_t MapCompletionInfo; + + /**< \internal Pointer to the Remote Device Information */ + phHal_sRemoteDevInformation_t *psRemoteDevInfo; + + /**<\internal Holds the Command Type(read/write)*/ + phHal_uCmdList_t Cmd; + + /**< \internal Pointer to a temporary buffer. Could be + used for read/write purposes */ + uint8_t *ApduBuffer; + + /**< \internal Size allocated to the ApduBuffer. */ + uint32_t ApduBufferSize; + + /**< \internal Index to the APDU Buffer. Used for internal calculations */ + uint16_t ApduBuffIndex; + + /**< \internal Pointer to the user-provided Data Size to be written trough WrNdef function. */ + uint32_t *WrNdefPacketLength; + + + /**< \internal Holds the length of the received data. */ + uint16_t *SendRecvLength; + + /**<\internal Holds the ack of some intial commands*/ + uint8_t *SendRecvBuf; + + /**< \internal Holds the length of the data to be sent. */ + uint16_t SendLength; + + /**< \internal Data Byte Count, which gives the offset to the integration.*/ + uint16_t *DataCount; + + /**< \ internal Holds the previous operation on the card*/ + uint8_t PrevOperation; + + /**< \ internal Holds the previous state on the card*/ + uint8_t PrevState; + + /**< \internal Stores the type of the smart card. */ + uint8_t CardType; + + /**< \internal Stores the card state. */ + uint8_t CardState; + + /**< \internal Stores the memory size of the card */ + uint16_t CardMemSize; + + /**<\internal to Store the page offset on the mifare ul card*/ + uint8_t Offset; + + /** \internal specifies the desfire operation to be performed*/ + uint8_t DespOpFlag; + + /** \internal Used to remeber how many bytes were written, to update + the dataCount and the BufferIndex */ + uint16_t NumOfBytesWritten; + + /**\internal used to remember number of L byte Remaining to be written */ + uint16_t NumOfLReminWrite; + + /** \internal Pointer Used to remeber and return how many bytes were read, + to update the PacketDataLength in case of Read operation */ + /* Fix for 0000238: [gk] MAP: Number of bytes actually read out is + not returned. */ + uint32_t *NumOfBytesRead; + + /** \internal Flag used to tell the process function that WRITE has + requested for an internal READ.*/ + uint8_t ReadingForWriteOperation; + + /** \internal Buffer of 5 bytes used for the write operation for the + Mifare UL card.*/ + uint8_t BufferForWriteOp[5]; + + /** \internal Temporary Receive Length to update the Receive Length + when every time the Overlapped HAL is called. */ + uint16_t TempReceiveLength; + + uint8_t NoOfDevices ; + + /** \internal stores operating mode type of the felica smart tag */ + /* phHal_eOpModes_t OpModeType[2]; */ + + /** \internal stores the type of the TLV found */ + uint8_t TLVFoundFlag; + + /** \internal stores the TLV structure related informations */ + phFriNfc_NDEFTLVCont_t TLVStruct; + + + /** \internal stores the Lock Contrl Tlv related informations */ + phFriNfc_LockCntrlTLVCont_t LockTlv; + + /** \internal stores the Mem Contrl Tlv related informations */ + phFriNfc_ResMemCntrlTLVCont_t MemTlv; + + + + /** Capabilitity Containers: */ + #ifndef PH_FRINFC_EXCLUDE_FROM_TESTFW /* */ + /** \internal Desfire capability Container Structure. */ +#ifndef PH_FRINFC_MAP_DESFIRE_DISABLED + phFriNfc_DesfireCapCont_t DesfireCapContainer; +#endif /* PH_FRINFC_MAP_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED + /** \internal Pointer to the Mifare Standard capability Container Structure. */ + phFriNfc_MifareStdCont_t StdMifareContainer; +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_MAP_FELICA_DISABLED + /** \internal Following are the Felica Smart tag related strucutre & variables */ + phFriNfc_Felica_t Felica; + + /** \internal Struture Stores the dev i/p , opmode informations of smart tag */ + phFriNfc_Felica_PollDetails_t FelicaPollDetails; + + /** \internal Struture Stores the different attribute informations of smart tag */ + phFriNfc_Felica_AttrInfo_t FelicaAttrInfo; + + /** \internal Struture Stores the PMm,IDm informations of smart tag */ + phFriNfc_Felica_ManufDetails_t FelicaManufDetails; +#endif /* PH_FRINFC_MAP_FELICA_DISABLED */ +#ifndef PH_FRINFC_MAP_MIFAREUL_DISABLED + /** \internal Mifare UL capability container structure. */ + phFriNfc_MifareULCont_t MifareULContainer; +#endif /* PH_FRINFC_MAP_MIFAREUL_DISABLED */ +#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED + /** \internal Mifare UL capability container structure. */ + phFriNfc_TopazCont_t TopazContainer; +#endif /* PH_FRINFC_MAP_TOPAZ_DISABLED */ + +#ifndef PH_FRINFC_MAP_ISO15693_DISABLED + phFriNfc_ISO15693Cont_t ISO15693Container; +#endif /* #ifndef PH_FRINFC_MAP_ISO15693_DISABLED */ + +#ifdef PHFRINFC_OVRHAL_MOCKUP + phFriNfc_MockupCont_t MochupContainer; +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + + #endif /* PH_FRINFC_EXCLUDE_FROM_TESTFW */ + +} phFriNfc_NdefMap_t; + + +#ifndef PH_FRINFC_EXCLUDE_FROM_TESTFW /* */ + +/** + * \ingroup grp_fri_nfc_ndef_map + * + * \brief Ndef Mapping \b Reset function + * + * \copydoc page_reg Resets the component instance to the initial state and initialises the + * internal variables. + * + * \param[in] NdefMap is a Pointer to a valid and initialised or uninitialised instance + * of \ref phFriNfc_NdefMap_t . + * \param[in] LowerDevice Overlapped HAL reference, pointing at a valid instance of this + * underlying component. + * \param[in] psRemoteDevInfo Points to the Remote Device Information structure encapsulating + * the information about the device (Smart card, NFC device) to access. + * \param[in] psDevInputParam The Device input parameter, as used for the HAL POLL function. + * This parameter is needed by the component in special cases, when an internal call + * to POLL is required again, such as for FeliCa. The storage of the structure behind + * the pointer must be retained by the calling software. The component itself only + * keeps the reference. No change is applied to the structure's content. + * \param[in] TrxBuffer Pointer to an internally used buffer. The buffer has to be allocated by + * the integrating software (not done by the component). The purpose of + * this storage is to serve as an intermediate buffer for data frame + * composition and analysis. + * The size shall be at least \ref PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE . + * \param[in] TrxBufferSize The size of TrxBuffer: + * The size shall be at least \ref PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE . + * \param[in] ReceiveBuffer Pointer to a buffer that the component uses internally use to + * store the data received from the lower component. + * The size shall be at least \ref PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE . + * \param[in] ReceiveLength The size of ReceiveBuffer. This specifies the actual length + * of the data received from the lower component. + * The size shall be at least \ref PH_FRINFC_NDEFMAP_MAX_SEND_RECV_BUF_SIZE . + * \param[in] DataCount Specifies the offset count during read/write operations. This can be + * used by the integrating software to know about the total number of bytes read/written + * from/to the card. The caller shall set the value behind the pointer to zero + * before calling this function. + * + * \retval NFCSTATUS_SUCCESS Operation successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * + * \note The DataCount variable is internally updated by the module and must not be changed by the + * embedding software. + * \note This function has to be called at the beginning, after creating an instance of + * \ref phFriNfc_NdefMap_t . Use this function to reset the instance and/or to switch + * to a different underlying device (different NFC device or device mode). + */ +NFCSTATUS phFriNfc_NdefMap_Reset(phFriNfc_NdefMap_t *NdefMap, + void *LowerDevice, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phHal_sDevInputParam_t *psDevInputParam, + uint8_t *TrxBuffer, + uint16_t TrxBufferSize, + uint8_t *ReceiveBuffer, + uint16_t *ReceiveLength, + uint16_t *DataCount); + + +/** + * \ingroup grp_fri_nfc_ndef_map + * + * \brief Ndef Mapping \b Set \b Completion \b Routine function + * + * \copydoc page_reg Setting of the Completion Routine. + * + * This function sets the Completion Routine for the specified function ID:\n + * The completion routine is a function of an upper layer in the stack that needs to be notified + * when the current instance has completed an I/O operation and data and/or an I/O status value + * is available. The list of valid function IDs can be found under the section + * "Completion Routine Indices", like e.g. \ref PH_FRINFC_NDEFMAP_CR_CHK_NDEF. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure + * serving as the component context. + * \param[in] FunctionID ID of the component API function to set a with a completion routine for. + * A valid routine has to be assigned for each function ID. + * Use the "Completion Routine Indices", such as \ref PH_FRINFC_NDEFMAP_CR_CHK_NDEF . + * \param[in] CompletionRoutine Pointer to a completion routine (part of a component of the upper layer) + * to be called when the non-blocking opertaion has finished. + * \param[in] CompletionRoutineContext Pointer to the context of the (upper) component where the + * particular completion routine is located. + * + * \retval NFCSTATUS_SUCCESS Operation successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * + * \note This function has to be called after \ref phFriNfc_NdefMap_Reset . + */ +NFCSTATUS phFriNfc_NdefMap_SetCompletionRoutine(phFriNfc_NdefMap_t *NdefMap, + uint8_t FunctionID, + pphFriNfc_Cr_t CompletionRoutine, + void *CompletionRoutineContext); + + +/** + * \ingroup grp_fri_nfc_ndef_map + * + * \brief Ndef Mapping \b Read \b Ndef function + * + * \copydoc page_ovr Initiates Reading of NDEF information from the Remote Device. + * + * The function initiates the reading of NDEF information from a Remote Device. + * It performs a reset of the state and restarts the state machine. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t + * component context structure. + * \param[in,out] PacketData Pointer to a location that shall receive the NDEF Packet. + * \param[in,out] PacketDataLength Pointer to a variable that shall receive the length of the NDEF packet. + * The caller has to provide the maximum length, the function fills + * in the actual number of bytes received. + * \param[in] Offset Indicates whether the read operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context (Data Count) variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start reading from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start reading + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_SUCCESS Operation Successful. + * + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_REMOTE_DEVICE Card Type is unsupported. + * \retval NFCSTATUS_EOF_CARD_REACHED No Space in the File to read. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ +NFCSTATUS phFriNfc_NdefMap_RdNdef(phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + + +/** + * \ingroup grp_fri_nfc_ndef_map + * + * \brief Ndef Mapping \b Check \b Ndef function + * + * \copydoc page_ovr Initiates Writing of NDEF information to the Remote Device. + * + * The function initiates the writing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t + * component context structure. + * \param[in] PacketData Pointer to a location that holds the prepared NDEF Packet. + * \param[in,out] PacketDataLength Pointer to a variable that shall specify the length of the prepared NDEF packet. + * The caller has to provide the length, the function fills + * in the actual number of bytes received. + * \param[in] Offset Indicates whether the write operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context (Data Count) variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start writing from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start writing + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_SUCCESS Operation Successful. + * + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_REMOTE_DEVICE Card Type is unsupported. + * \retval NFCSTATUS_EOF_CARD_REACHED No Space in the File to write. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +extern NFCSTATUS phFriNfc_NdefMap_WrNdef(phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + + +/** + * \ingroup grp_fri_nfc_ndef_map + * + * \brief Ndef Mapping \b Check \b NDEF function + * + * \copydoc page_ovr Check whether a particular Remote Device is NDEF compliant. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t + * component context structure. + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_REMOTE_DEVICE Card Type is unsupported. + * \retval NFCSTATUS_INVALID_PARAMETER Completion Routine is NULL. + * \retval NFCSTATUS_INVALID_REMOTE_DEVICE OpModes invalid. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ +NFCSTATUS phFriNfc_NdefMap_ChkNdef(phFriNfc_NdefMap_t *NdefMap); + +#ifdef FRINFC_READONLY_NDEF +/*! + * \ingroup grp_fri_smart_card_formatting + * + * \brief Initiates the conversion of the already NDEF formatted tag to READ ONLY. + * + * \copydoc page_ovr The function initiates the conversion of the already NDEF formatted + * tag to READ ONLY.After this formation, remote card would be properly Ndef Compliant and READ ONLY. + * Depending upon the different card type, this function handles formatting procedure. + * This function supports only for the TOPAZ tags. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval Other values An error has occurred. + * + */ +NFCSTATUS +phFriNfc_NdefMap_ConvertToReadOnly ( + phFriNfc_NdefMap_t *NdefMap); + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/** + * \ingroup grp_fri_nfc_ndef_map + * + * \brief Ndef Mapping \b Erase \b NDEF function + * + * \copydoc page_ovr find the position of the existing NDEF TLV and overwrite with \b empty NDEF + * message \b at that position. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t + * component context structure. + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_REMOTE_DEVICE Card Type is unsupported. + * \retval NFCSTATUS_INVALID_PARAMETER Completion Routine is NULL. + * \retval NFCSTATUS_INVALID_REMOTE_DEVICE OpModes invalid. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ +NFCSTATUS phFriNfc_NdefMap_EraseNdef(phFriNfc_NdefMap_t *NdefMap); + +/** + * \ingroup grp_fri_nfc_ndef_map + * + * \brief Ndef Mapping \b Get Container size function + * + * \copydoc page_ovr Returns the size of the NDEF data that the card can hold to the caller. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t + * component context structure. + * + * \param[out] size Pointer to a uint32_t variable, which receives the size of the NDEF data + * + * \retval NFCSTATUS_SUCCESS The size has been successfully calculated. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_REMOTE_DEVICE Card Type is unsupported. + * + */ + +NFCSTATUS phFriNfc_NdefMap_GetContainerSize(const phFriNfc_NdefMap_t *NdefMap,uint32_t *maxSize, uint32_t *actualSize); + +/** + * \ingroup grp_fri_nfc_ndef_map + * + * \brief Ndef Mapping \b Completion \b Routine or \b Process function + * + * \copydoc page_cb Completion Routine: This function is called by the lower layer (OVR HAL) + * when an I/O operation has finished. The internal state machine decides + * whether to call into the lower device again or to complete the process + * by calling into the upper layer's completion routine, stored within this + * component's context (\ref phFriNfc_NdefMap_t). + * + * The function call scheme is according to \ref grp_interact. No State reset is performed during + * operation. + * + * \param[in] Context The context of the current (not the lower/upper) instance, as set by the lower, + * calling layer, upon its completion. + * \param[in] Status The completion status of the lower layer (to be handled by the implementation of + * the state machine of this function like a regular return value of an internally + * called function). + * + * \note For general information about the completion routine interface please see \ref pphFriNfc_Cr_t . * The Different Status Values are as follows + * + */ +void phFriNfc_NdefMap_Process(void *Context, + NFCSTATUS Status); + + + +/** + * \ingroup grp_fri_nfc_ndef_map + * + * \brief Ndef Mapping \b Check And Parse TLV Structure \b NDEF function + * + * \copydoc page_ovr Checks the presence of a valid TLV's(NDEF/Propritery). + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t + * component context structure. + * + * \retval NFCSTATUS_INVALID_FORMAT No valid TLV Found. + * \retval NFCSTATUS_SUCCESS Operation Successful. + * + */ +NFCSTATUS phFriNfc_ChkAndParseTLV(phFriNfc_NdefMap_t *NdefMap); + + +#ifdef PHFRINFC_OVRHAL_MOCKUP /* */ + +/** + * \ingroup grp_fri_nfc_ndef_map + * + * \brief Set data NDEF in mockup mode + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t component context structure. + * \param[in] NdefData Pointer to card mockup data + * \param[in] NdefActualSize The actual data length + * \param[in] NdefMaxSize The max data length + * \param[in] NdefCardSize The total card size + * + * \retval NFCSTATUS_SUCCESS The operation is ok. + * + */ +NFCSTATUS phFriNfc_NdefMap_MockupCardSetter(phFriNfc_NdefMap_t *NdefMap, uint8_t *NdefData, uint32_t NdefActualSize, uint32_t NdefMaxSize, uint32_t CardSize); +NFCSTATUS phFriNfc_NdefMap_MockupNDefModeEn(uint8_t *pNdefCompliancy, uint8_t *pCardType, uint8_t Enable); +#endif /*#ifndef PH_FRINFC_MAP_MOCKUP_DISABLED*/ + + +/** + * \internal + * \name States of the FSM. + * + */ +/*@{*/ +#define PH_FRINFC_NDEFMAP_STATE_RESET_INIT 0 /**< \internal Initial state */ +#define PH_FRINFC_NDEFMAP_STATE_CR_REGISTERED 1 /**< \internal CR has been registered */ +#define PH_FRINFC_NDEFMAP_STATE_EOF_CARD 2 /**< \internal EOF card reached */ +/*@}*/ + +/* Following values specify the previous operation on the card. This value is assigned to + the context structure variable: PrevOperation. */ + +/**< Previous operation is check*/ +#define PH_FRINFC_NDEFMAP_CHECK_OPE 1 +/**< Previous operation is read*/ +#define PH_FRINFC_NDEFMAP_READ_OPE 2 +/**< Previous operation is write */ +#define PH_FRINFC_NDEFMAP_WRITE_OPE 3 +/**< Previous operation is Actual size */ +#define PH_FRINFC_NDEFMAP_GET_ACTSIZE_OPE 4 + +/* This flag is set when there is a need of write operation on the odd positions + ex: 35,5 etc. This is used with MfUlOp Flag */ +#define PH_FRINFC_MFUL_INTERNAL_READ 3 /**< \internal Read/Write control*/ + + +#endif /* PH_FRINFC_EXCLUDE_FROM_TESTFW */ + +#endif /* PHFRINFC_NDEFMAP_H */ diff --git a/libnfc-nxp/phFriNfc_NdefRecord.c b/libnfc-nxp/phFriNfc_NdefRecord.c new file mode 100644 index 0000000..29be434 --- /dev/null +++ b/libnfc-nxp/phFriNfc_NdefRecord.c @@ -0,0 +1,915 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc_NdefRecord.c + * \brief NFC Ndef Record component file. + * + * Project: NFC-FRI + * + * $Date: Thu Jun 25 11:01:24 2009 $ + * $Author: ing07336 $ + * $Revision: 1.4 $ + * $Aliases: NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + + +/*! \ingroup grp_file_attributes + * \name \name NDEF Record Tools Header + * + * File: \ref phFriNfc_NdefRecord.h + * + */ +/*@{*/ +#define PHFRINFCNDEFRECORD_FILEREVISION "$Revision: 1.4 $" +#define PHFRINFCNDEFRECORD_FILEALIASES "$Aliases: NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" +/*@}*/ + +#include +#include +#include + +/* Harsha: To Fix: 0000358: phFriNfc_NdefRecord.h: includes should be moved */ +#include + +static uint8_t phFriNfc_NdefRecord_TypeNameFormat ( uint8_t *Record); +static uint8_t phFriNfc_NdefRecord_RecordFlag ( uint8_t *Record); +static NFCSTATUS phFriNfc_NdefRecord_RecordIDCheck ( uint8_t *Record, + uint8_t *TypeLength, + uint8_t *TypeLengthByte, + uint8_t *PayloadLengthByte, + uint32_t *PayloadLength, + uint8_t *IDLengthByte, + uint8_t *IDLength); + +/*! + * + * Get a specific NDEF record from the data, provided by the caller. The data is a buffer holding + * one or more (nested) NDEF records within a NDEF packet (received via the NFC link, for example). + * + * \param[in] Buffer The data buffer holding the NDEF Message, as provided by the caller. + * \param[in] BufferLength The data length, as provided by the caller. + * \param[in,out] RawRecords Array of pointers, receiving the references to the found Ndef Records + * in the Message. The caller has to provide the array of pointers. + * The array is filled with valid pointers up to the number of records + * found or the array size if the number of found records exceeds the size. + * If the value is NULL the function only yields the number of records + * without filling in pointers. + * \param[in] IsChunked This boolean tells the user that the record of a certain position within + * an array has the CHUNKED flag set (is a partial record). The number + * of caller-provided array positions has to be the same as "NumberOfRawRecords". + * In case that this parameter is NULL the function ignores it. + * \param[in,out] NumberOfRawRecords Length of the Record pointer array. The caller has to provide + * the number of pointers provided in the NDEF Type array. \n + * The value is set by the extracting function to the actual number of + * records found in the data. If the user specifies 0 (zero) the function + * only yields the number of records without filling in pointers.\n + * The value of NULL is invalid. + * + * \retval NFCSTATUS_SUCCESS Operation successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * + * \note The correct number of found records is returned by the function also in case that: + * - The "RawRecords" array is too short to hold all values: It is filled up to the allowed maximum. + * - The "RawRecords" array is NULL: Only the number is returned. + * - The "NumberOfRawRecords" parameter is 0 (zero): The array is not filled, just the number is returned. + * . + * This can be exploited for targeted memory allocation: Specify NULL for "RawRecords" and/or + * 0 (zero) for "NumberOfRawRecords" and the function yields the correct array size to allocate + * for a second call. + * + */ + NFCSTATUS phFriNfc_NdefRecord_GetRecords( uint8_t *Buffer, + uint32_t BufferLength, + uint8_t *RawRecords[], + uint8_t IsChunked[], + uint32_t *NumberOfRawRecords) +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + uint8_t PayloadLengthByte = 0, + TypeLengthByte = 0, + TypeLength = 0, + IDLengthByte = 0, + NoOfRecordsReturnFlag = 0, + IDLength = 0; + uint32_t Count = 0, + PayloadLength = 0, + BytesTraversed = 0; + + /* Validate the input parameters */ + if (Buffer == NULL || BufferLength == 0 || NumberOfRawRecords == NULL) + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_PARAMETER); + return Status; + } + + if((*NumberOfRawRecords) > 0) + { + /* The number of caller-provided array positions for the array IsChunked + has to be the same as NumberOfRawRecords. Hence, + if NumberOfRawRecords > 0, the array IsChunked cannot be null */ + if(IsChunked == NULL) + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_PARAMETER); + return Status; + } + } + + /* Check Raw Records input is NULL and Number of Raw records is 0*/ + if ( RawRecords == NULL || *NumberOfRawRecords == 0) + { + /* This flag is set, to return only number of records + this is done when the Raw Records is NULL or + Number of Raw records is 0 */ + NoOfRecordsReturnFlag = 1; + } + + /* Check for the MB bit*/ + if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) != + PH_FRINFC_NDEFRECORD_FLAGS_MB ) + { + /* MB Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + + /* Number of valid records found in the message is 0 */ + *NumberOfRawRecords = 0; + return Status; + } + + /* Check for Tnf bits 0x07 is reserved for future use */ + if ((*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == + PH_FRINFC_NDEFRECORD_TNF_RESERVED) + { + /* TNF 07 Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + /* Number of valid records found in the message is 0 */ + *NumberOfRawRecords = 0; + return Status; + } + + /* Check the First Record(MB = 0) for TNF = 0x06(Unchanged) */ + if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB && + (*Buffer & PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + /* Number of valid records found in the message is 0 */ + *NumberOfRawRecords = 0; + return Status; + } + + /* First Record i.e., MB = 1, TNF != 0x05 and TypeLength = 0 */ + if ( (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB && + (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) != PH_FRINFC_NDEFRECORD_TNF_UNKNOWN && + (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) != PH_FRINFC_NDEFRECORD_TNF_EMPTY && + *(Buffer + 1) == 0) + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + /* Number of valid records found in the message is 0 */ + *NumberOfRawRecords = 0; + return Status; + } + + /* Check till Buffer Length exceeds */ + while ( BytesTraversed < BufferLength ) + { + if (Buffer == NULL) + { + break; + } + + /* For Each Record Check whether it contains the ME bit set and CF bit Set + if YES return ERROR*/ + if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) == + PH_FRINFC_NDEFRECORD_FLAGS_CF && + (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) == + PH_FRINFC_NDEFRECORD_FLAGS_ME) + { + /* CF and ME Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + break; + } + + if (NoOfRecordsReturnFlag == 0) + { + /* Harsha: Fix for 0000241: [gk], NDEF Tools: GetRecords() overshoots + a given array boundary if the number of records != 0. */ + /* Actual Number of Records should not exceed Number of records + required by caller*/ + if(Count >= *NumberOfRawRecords) + { + break; + } + /* To fix the mantis entry 0388 */ + if((Buffer != NULL)&&(RawRecords!=NULL))/*QMOR FIX*/ + { + RawRecords[Count] = Buffer; + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_PARAMETER); + break; + } + } + + /* To Calculate the IDLength and PayloadLength for + short or normal record */ + Status = phFriNfc_NdefRecord_RecordIDCheck ( Buffer, + &TypeLength, + &TypeLengthByte, + &PayloadLengthByte, + &PayloadLength, + &IDLengthByte, + &IDLength); + if (Status != NFCSTATUS_SUCCESS) + { + break; + } + + /* Check for the Chunk Flag */ + if (NoOfRecordsReturnFlag == 0) + { + /* If NoOfRecordsReturnFlag = 0, that means we have enough space */ + /* in the array IsChunked, to write */ + if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) == + PH_FRINFC_NDEFRECORD_FLAGS_CF) + { + IsChunked [Count] = PHFRINFCNDEFRECORD_CHUNKBIT_SET; + } + else + { + IsChunked [Count] = PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO; + } + } + + /* Check the record is not the first record */ + if (Count > 0) + { + /* Not a first record, if chunk record is present and IL bit is set + also if the MB bit is set */ + if(((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_CF) == PH_FRINFC_NDEFRECORD_FLAGS_CF && + (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL && + (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) || + (*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB) + { + /* IL or MB Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + break; + } + + /* Check for the Chunk Flag */ + if (NoOfRecordsReturnFlag == 0) + { + /* If NoOfRecordsReturnFlag = 0, that means the array IsChunked + contains valid values. So, cannot check the value + of IsChunked if NoOfRecordsReturnFlag = 1. */ + + /* Check whether the previous record has the chunk flag and + TNF of present record is not 0x06 */ + if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET && + (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) != + PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) + { + /* CF or TNF Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + break; + } + + /* Check whether the previous record doesnot have the chunk flag and + TNF of present record is 0x06 */ + if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO && + (*Buffer & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == + PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) + { + /* CF or TNF Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + break; + } + + /* Check for the last chunk */ + if (IsChunked [Count - 1] == PHFRINFCNDEFRECORD_CHUNKBIT_SET && + IsChunked [Count] == PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO) + { + /* Check for the TypeLength, IDLength = 0 */ + if (TypeLength != 0 || IDLength != 0) + { + /* last chunk record Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + break; + } + } + } /* if (NoOfRecordsReturnFlag == 0) */ + } /* if (Count > 0) */ + + /* Calculate the bytes already traversed. */ + BytesTraversed = (BytesTraversed + PayloadLengthByte + IDLengthByte + TypeLength + + IDLength + TypeLengthByte + PayloadLength + + PH_FRINFC_NDEFRECORD_BUF_INC1); + + if(BytesTraversed == BufferLength) + { + /* We have reached the last record, and everything is fine. */ + /* Check for the ME Byte */ + if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) == + PH_FRINFC_NDEFRECORD_FLAGS_ME) + { + Count++; + break; + } + else + { + /* Each message must have ME flag in the last record, Since + ME is not set raise an error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + break; + } + } + else + { + /* Buffer Overshoot: Inconsistency in the message length + and actual value of the bytes in the message detected. + Report error.*/ + if(BytesTraversed > BufferLength) + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + break; + } + } + /* For Each Record Check whether it contains the ME bit set + if YES return*/ + if ((*Buffer & PH_FRINFC_NDEFRECORD_FLAGS_ME) == + PH_FRINFC_NDEFRECORD_FLAGS_ME) + { + Count++; + break; + } + + /* +1 is for first byte */ + Buffer = (Buffer + PayloadLengthByte + IDLengthByte + TypeLength + + TypeLengthByte + IDLength + PayloadLength + + PH_FRINFC_NDEFRECORD_BUF_INC1); + + /* Increment the number of valid records found in the message */ + Count++; + } + + /* Whatever is the error, update the NumberOfRawRecords with the number + of proper records found till the error was detected in the message. */ + *NumberOfRawRecords = Count; + return Status; +} + +/* to check the bitfields in the Flags Byte and return the status flag */ +static uint8_t phFriNfc_NdefRecord_NdefFlag(uint8_t Flags,uint8_t Mask) +{ + uint8_t check_flag = 0x00; + check_flag = Flags & Mask; + return check_flag; +} + +uint32_t phFriNfc_NdefRecord_GetLength(phFriNfc_NdefRecord_t *Record) +{ + uint32_t RecordLength=1; + uint8_t FlagCheck=0; + + FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK); + /* Type length is present only for following TNF + PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN + PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE + PH_FRINFC_NDEFRECORD_TNF_ABSURI + PH_FRINFC_NDEFRECORD_TNF_NFCEXT + */ + + /* ++ is for the Type Length Byte */ + RecordLength++; + if( FlagCheck != PH_FRINFC_NDEFRECORD_TNF_EMPTY && + FlagCheck != PH_FRINFC_NDEFRECORD_TNF_UNKNOWN && + FlagCheck != PH_FRINFC_NDEFRECORD_TNF_UNCHANGED ) + { + RecordLength += Record->TypeLength; + } + + /* to check if payloadlength is 8bit or 32bit*/ + FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR); + if(FlagCheck!=0) + { + /* ++ is for the Payload Length Byte */ + RecordLength++;/* for short record*/ + } + else + { + /* + PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE is for the Payload Length Byte */ + RecordLength += PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE;/* for normal record*/ + } + + /* for non empty record */ + FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK); + if(FlagCheck != PH_FRINFC_NDEFRECORD_TNF_EMPTY) + { + RecordLength += Record->PayloadLength; + } + + /* ID and IDlength are present only if IL flag is set*/ + FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL); + if(FlagCheck!=0) + { + RecordLength +=Record->IdLength; + /* ++ is for the ID Length Byte */ + RecordLength ++; + } + return RecordLength; +} + +/*! + * + * Extract a specific NDEF record from the data, provided by the caller. The data is a buffer holding + * at least the entire NDEF record (received via the NFC link, for example). + * + * \param[out] Record The NDEF record structure. The storage for the structure has to be provided by the + * caller matching the requirements for \b Extraction, as described in the compound + * documentation. + * \param[in] RawRecord The Pointer to the buffer, selected out of the array returned by + * the \ref phFriNfc_NdefRecord_GetRecords function. + * + * \retval NFCSTATUS_SUCCESS Operation successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * + * \note There are some caveats: + * - The "RawRecord" Data buffer must exist at least as long as the function execution time plus the time + * needed by the caller to evaluate the extracted information. No copying of the contained data is done. + * - Using the "RawRecord" and "RawRecordMaxSize" parameters the function internally checks whether the + * data to extract are within the bounds of the buffer. + * + * + */ +NFCSTATUS phFriNfc_NdefRecord_Parse(phFriNfc_NdefRecord_t *Record, + uint8_t *RawRecord) +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + uint8_t PayloadLengthByte = 0, + TypeLengthByte = 0, + TypeLength = 0, + IDLengthByte = 0, + IDLength = 0, + Tnf = 0; + uint32_t PayloadLength = 0; + + if (Record == NULL || RawRecord == NULL) + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_PARAMETER); + } + + else + { + + /* Calculate the Flag Value */ + Record->Flags = phFriNfc_NdefRecord_RecordFlag ( RawRecord); + + /* Calculate the Type Namr format of the record */ + Tnf = phFriNfc_NdefRecord_TypeNameFormat( RawRecord); + if(Tnf != 0xFF) + { + Record->Tnf = Tnf; + /* To Calculate the IDLength and PayloadLength for short or normal record */ + Status = phFriNfc_NdefRecord_RecordIDCheck ( RawRecord, + &TypeLength, + &TypeLengthByte, + &PayloadLengthByte, + &PayloadLength, + &IDLengthByte, + &IDLength); + Record->TypeLength = TypeLength; + Record->PayloadLength = PayloadLength; + Record->IdLength = IDLength; + RawRecord = (RawRecord + PayloadLengthByte + IDLengthByte + TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1); + Record->Type = RawRecord; + + RawRecord = (RawRecord + Record->TypeLength); + + if (Record->IdLength != 0) + { + Record->Id = RawRecord; + } + + RawRecord = RawRecord + Record->IdLength; + Record->PayloadData = RawRecord; + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_PARAMETER); + } + } + return Status; +} + + + +/*! + * The function writes one NDEF record to a specified memory location. Called within a loop, it is possible to + * write more records into a contiguous buffer, in each cycle advancing by the number of bytes written for + * each record. + * + * \param[in] Record The Array of NDEF record structures to append. The structures + * have to be filled by the caller matching the requirements for + * \b Composition, as described in the documentation of + * the \ref phFriNfc_NdefRecord_t "NDEF Record" structure. + * \param[in] Buffer The pointer to the buffer. + * \param[in] MaxBufferSize The data buffer's maximum size, provided by the caller. + * \param[out] BytesWritten The actual number of bytes written to the buffer. This can be used by + * the caller to serialise more than one record into the same buffer before + * handing it over to another instance. + * + * \retval NFCSTATUS_SUCCESS Operation successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The data buffer, provided by the caller is to small to + * hold the composed NDEF record. The existing content is not changed. + * + */ + NFCSTATUS phFriNfc_NdefRecord_Generate(phFriNfc_NdefRecord_t *Record, + uint8_t *Buffer, + uint32_t MaxBufferSize, + uint32_t *BytesWritten) +{ + uint8_t FlagCheck, + TypeCheck=0, + *temp, + i; + uint32_t i_data=0; + + if(Record==NULL ||Buffer==NULL||BytesWritten==NULL||MaxBufferSize == 0) + { + return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_PARAMETER)); + } + + if (Record->Tnf == PH_FRINFC_NDEFRECORD_TNF_RESERVED) + { + return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_FORMAT)); + } + + /* calculate the length of the record and check with the buffersize if it exceeds return */ + i_data=phFriNfc_NdefRecord_GetLength(Record); + if(i_data > MaxBufferSize) + { + return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_BUFFER_TOO_SMALL)); + } + *BytesWritten = i_data; + + /*fill the first byte of the message(all the flags) */ + /*increment the buffer*/ + *Buffer = ( (Record->Flags & PH_FRINFC_NDEFRECORD_FLAG_MASK) | (Record->Tnf & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)); + Buffer++; + + /* check the TypeNameFlag for PH_FRINFC_NDEFRECORD_TNF_EMPTY */ + FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK); + if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_EMPTY) + { + /* fill the typelength idlength and payloadlength with zero(empty message)*/ + for(i=0;i<3;i++) + { + *Buffer=PH_FRINFC_NDEFRECORD_BUF_TNF_VALUE; + Buffer++; + } + return (PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS)); + } + + /* check the TypeNameFlag for PH_FRINFC_NDEFRECORD_TNF_RESERVED */ + /* TNF should not be reserved one*/ + FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK); + if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_RESERVED) + { + return (PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, NFCSTATUS_INVALID_PARAMETER)); + } + + /* check for TNF Unknown or Unchanged */ + FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Tnf,PH_FRINFC_NDEFRECORD_TNFBYTE_MASK); + if(FlagCheck == PH_FRINFC_NDEFRECORD_TNF_UNKNOWN || \ + FlagCheck == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) + { + *Buffer = PH_FRINFC_NDEFRECORD_BUF_TNF_VALUE; + Buffer++; + } + else + { + *Buffer = Record->TypeLength; + Buffer++; + TypeCheck=1; + } + + /* check for the short record bit if it is then payloadlength is only one byte */ + FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR); + if(FlagCheck!=0) + { + *Buffer = (uint8_t)(Record->PayloadLength & 0x000000ff); + Buffer++; + } + else + { + /* if it is normal record payloadlength is 4 byte(32 bit)*/ + *Buffer = (uint8_t)((Record->PayloadLength & 0xff000000) >> PHNFCSTSHL24); + Buffer++; + *Buffer = (uint8_t)((Record->PayloadLength & 0x00ff0000) >> PHNFCSTSHL16); + Buffer++; + *Buffer = (uint8_t)((Record->PayloadLength & 0x0000ff00) >> PHNFCSTSHL8); + Buffer++; + *Buffer = (uint8_t)((Record->PayloadLength & 0x000000ff)); + Buffer++; + } + + /*check for IL bit set(Flag), if so then IDlength is present*/ + FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL); + if(FlagCheck!=0) + { + *Buffer=Record->IdLength; + Buffer++; + } + + /*check for TNF and fill the Type*/ + temp=Record->Type; + if(TypeCheck!=0) + { + for(i=0;i<(Record->TypeLength);i++) + { + *Buffer = *temp; + Buffer++; + temp++; + } + } + + /*check for IL bit set(Flag), if so then IDlength is present and fill the ID*/ + FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_IL); + temp=Record->Id; + if(FlagCheck!=0) + { + for(i=0;i<(Record->IdLength);i++) + { + *Buffer = *temp; + Buffer++; + temp++; + } + } + + temp=Record->PayloadData; + /*check for SR bit and then correspondingly use the payload length*/ + FlagCheck=phFriNfc_NdefRecord_NdefFlag(Record->Flags,PH_FRINFC_NDEFRECORD_FLAGS_SR); + for(i_data=0;i_data < (Record->PayloadLength) ;i_data++) + { + *Buffer = *temp; + Buffer++; + temp++; + } + + return (PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS)); +} + +/* Calculate the Flags of the record */ +static uint8_t phFriNfc_NdefRecord_RecordFlag ( uint8_t *Record) +{ + uint8_t flag = 0; + + if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_MB) == PH_FRINFC_NDEFRECORD_FLAGS_MB ) + { + flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_MB; + } + if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_ME) == PH_FRINFC_NDEFRECORD_FLAGS_ME ) + { + flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_ME; + } + if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_CF) == PH_FRINFC_NDEFRECORD_FLAGS_CF ) + { + flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_CF; + } + if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) == PH_FRINFC_NDEFRECORD_FLAGS_SR ) + { + flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_SR; + } + if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL ) + { + flag = flag | PH_FRINFC_NDEFRECORD_FLAGS_IL; + } + return flag; +} + +/* Calculate the Type Name Format for the record */ +static uint8_t phFriNfc_NdefRecord_TypeNameFormat ( uint8_t *Record) +{ + uint8_t tnf = 0; + + switch (*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) + { + case PH_FRINFC_NDEFRECORD_TNF_EMPTY: + tnf = PH_FRINFC_NDEFRECORD_TNF_EMPTY; + break; + + case PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN: + tnf = PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN; + break; + + case PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE: + tnf = PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE; + break; + + case PH_FRINFC_NDEFRECORD_TNF_ABSURI: + tnf = PH_FRINFC_NDEFRECORD_TNF_ABSURI; + break; + + case PH_FRINFC_NDEFRECORD_TNF_NFCEXT: + tnf = PH_FRINFC_NDEFRECORD_TNF_NFCEXT; + break; + + case PH_FRINFC_NDEFRECORD_TNF_UNKNOWN: + tnf = PH_FRINFC_NDEFRECORD_TNF_UNKNOWN; + break; + + case PH_FRINFC_NDEFRECORD_TNF_UNCHANGED: + tnf = PH_FRINFC_NDEFRECORD_TNF_UNCHANGED; + break; + + case PH_FRINFC_NDEFRECORD_TNF_RESERVED: + tnf = PH_FRINFC_NDEFRECORD_TNF_RESERVED; + break; + default : + tnf = 0xFF; + break; + } + + return tnf; +} + + +static NFCSTATUS phFriNfc_NdefRecord_RecordIDCheck ( uint8_t *Record, + uint8_t *TypeLength, + uint8_t *TypeLengthByte, + uint8_t *PayloadLengthByte, + uint32_t *PayloadLength, + uint8_t *IDLengthByte, + uint8_t *IDLength) +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + + /* Check for Tnf bits 0x07 is reserved for future use */ + if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == + PH_FRINFC_NDEFRECORD_TNF_RESERVED) + { + /* TNF 07 Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + return Status; + } + + /* Check for Type Name Format depending on the TNF, Type Length value is set*/ + if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)== + PH_FRINFC_NDEFRECORD_TNF_EMPTY) + { + *TypeLength = *(Record + PH_FRINFC_NDEFRECORD_BUF_INC1); + + if (*(Record + PH_FRINFC_NDEFRECORD_BUF_INC1) != 0) + { + /* Type Length Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + return Status; + } + + *TypeLengthByte = 1; + + /* Check for Short Record */ + if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) == PH_FRINFC_NDEFRECORD_FLAGS_SR) + { + /* For Short Record, Payload Length Byte is 1 */ + *PayloadLengthByte = 1; + /* 1 for Header byte */ + *PayloadLength = *(Record + *TypeLengthByte + 1); + if (*PayloadLength != 0) + { + /* PayloadLength Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + return Status; + } + } + else + { + /* For Normal Record, Payload Length Byte is 4 */ + *PayloadLengthByte = PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE; + *PayloadLength = ((((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC2))) << PHNFCSTSHL24) + + (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC3))) << PHNFCSTSHL16) + + (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC4))) << PHNFCSTSHL8) + + *(Record + PH_FRINFC_NDEFRECORD_BUF_INC5)); + if (*PayloadLength != 0) + { + /* PayloadLength Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + return Status; + } + } + + /* Check for ID Length existence */ + if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) == PH_FRINFC_NDEFRECORD_FLAGS_IL) + { + /* Length Byte exists and it is 1 byte */ + *IDLengthByte = 1; + /* 1 for Header byte */ + *IDLength = (uint8_t)*(Record + *PayloadLengthByte + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1); + if (*IDLength != 0) + { + /* IDLength Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + return Status; + } + } + else + { + *IDLengthByte = 0; + *IDLength = 0; + } + } + else + { + if ((*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK)== PH_FRINFC_NDEFRECORD_TNF_UNKNOWN + || (*Record & PH_FRINFC_NDEFRECORD_TNFBYTE_MASK) == + PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) + { + if (*(Record + PH_FRINFC_NDEFRECORD_BUF_INC1) != 0) + { + /* Type Length Error */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_RECORD, + NFCSTATUS_INVALID_FORMAT); + return Status; + } + *TypeLength = 0; + *TypeLengthByte = 1; + } + else + { + /* 1 for Header byte */ + *TypeLength = *(Record + PH_FRINFC_NDEFRECORD_BUF_INC1); + *TypeLengthByte = 1; + } + + /* Check for Short Record */ + if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_SR) == + PH_FRINFC_NDEFRECORD_FLAGS_SR) + { + /* For Short Record, Payload Length Byte is 1 */ + *PayloadLengthByte = 1; + /* 1 for Header byte */ + *PayloadLength = *(Record + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1); + } + else + { + /* For Normal Record, Payload Length Byte is 4 */ + *PayloadLengthByte = PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE; + *PayloadLength = ((((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC2))) << PHNFCSTSHL24) + + (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC3))) << PHNFCSTSHL16) + + (((uint32_t)(*(Record + PH_FRINFC_NDEFRECORD_BUF_INC4))) << PHNFCSTSHL8) + + *(Record + PH_FRINFC_NDEFRECORD_BUF_INC5)); + } + + /* Check for ID Length existence */ + if ((*Record & PH_FRINFC_NDEFRECORD_FLAGS_IL) == + PH_FRINFC_NDEFRECORD_FLAGS_IL) + { + *IDLengthByte = 1; + /* 1 for Header byte */ + *IDLength = (uint8_t)*(Record + *PayloadLengthByte + *TypeLengthByte + PH_FRINFC_NDEFRECORD_BUF_INC1); + } + else + { + *IDLengthByte = 0; + *IDLength = 0; + } + } + return Status; +} + diff --git a/libnfc-nxp/phFriNfc_NdefRecord.h b/libnfc-nxp/phFriNfc_NdefRecord.h new file mode 100644 index 0000000..c888b6e --- /dev/null +++ b/libnfc-nxp/phFriNfc_NdefRecord.h @@ -0,0 +1,461 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_NdefRecord.h + * \brief NFC Ndef Record component header file. + * + * Project: NFC-FRI + * + * $Date: Wed Jun 17 14:17:53 2009 $ + * $Author: ing01697 $ + * $Revision: 1.6 $ + * $Aliases: NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PHFRINFC_NDEFRECORD_H +#define PHFRINFC_NDEFRECORD_H + +#ifndef PH_FRINFC_EXCLUDE_FROM_TESTFW /* */ + +/** + * \name NDEF Record Tools Header + * + * File: \ref phFriNfc_NdefRecord.h + * + */ +/*@{*/ +#define PHFRINFC_NDEFRECORD_FILEREVISION "$Revision: 1.6 $" /**< \ingroup grp_file_attributes */ +#define PHFRINFC_NDEFRECORD_FILEALIASES "$Aliases: NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +#endif /* PH_FRINFC_EXCLUDE_FROM_TESTFW */ + +#include +#include +/* Mantis 0000214 - Platform and language dependency found in some files */ +/* To Fix: 0000358: phFriNfc_NdefRecord.h: includes should be moved */ +/* stdlib.h and string.h - header file inclusion removed */ + +/** + * This component implements Ndef Message composing and processing routines. + * + * The Ndef Record is a data structure used by NFC Forum compliant devices for data transfer. + * \n\n + * The capabilities of this module are: + * \li Interprete a given buffer by listing the embedded NDEF records + * \li Extract a Ndef record from a given buffer + * \li Compose a NDEF record and optionally append it to an existing buffer/message + * + */ +/*@{*/ + +/** + * \brief The TNF specifies the structure of the NDEF Record TYPE field. + * + * \name NDEF Record Type Name Format + * + */ +/*@{*/ +#define PH_FRINFC_NDEFRECORD_TNF_EMPTY ((uint8_t)0x00) /**< Empty Record, no type, ID or payload present. */ +#define PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN ((uint8_t)0x01) /**< NFC well-known type (RTD). */ +#define PH_FRINFC_NDEFRECORD_TNF_MEDIATYPE ((uint8_t)0x02) /**< Media Type. */ +#define PH_FRINFC_NDEFRECORD_TNF_ABSURI ((uint8_t)0x03) /**< Absolute URI. */ +#define PH_FRINFC_NDEFRECORD_TNF_NFCEXT ((uint8_t)0x04) /**< Nfc Extenal Type (following the RTD format). */ +#define PH_FRINFC_NDEFRECORD_TNF_UNKNOWN ((uint8_t)0x05) /**< Unknown type; Contains no Type information. */ +#define PH_FRINFC_NDEFRECORD_TNF_UNCHANGED ((uint8_t)0x06) /**< Unchanged: Used for Chunked Records. */ +#define PH_FRINFC_NDEFRECORD_TNF_RESERVED ((uint8_t)0x07) /**< RFU, must not be used. */ +/*@}*/ + + +/** + * \brief These are the flags specifying the content, structure or purpose of a NDEF Record. + * \name NDEF Record Header Flags + * + * Flags of the first record byte, as defined by the NDEF specification. + * + */ +/*@{*/ +#define PH_FRINFC_NDEFRECORD_FLAGS_MB ((uint8_t)0x80) /**< This marks the begin of a NDEF Message. */ +#define PH_FRINFC_NDEFRECORD_FLAGS_ME ((uint8_t)0x40) /**< Set if the record is at the Message End. */ +#define PH_FRINFC_NDEFRECORD_FLAGS_CF ((uint8_t)0x20) /**< Chunk Flag: The record is a record chunk only. */ +#define PH_FRINFC_NDEFRECORD_FLAGS_SR ((uint8_t)0x10) /**< Short Record: Payload Length is encoded in ONE byte only. */ +#define PH_FRINFC_NDEFRECORD_FLAGS_IL ((uint8_t)0x08) /**< The ID Length Field is present. */ +/*@}*/ + +/* Internal: + * NDEF Record #defines for constant value + */ +#define PHFRINFCNDEFRECORD_CHUNKBIT_SET 1 /** \internal Chunk Bit is set. */ +#define PHFRINFCNDEFRECORD_CHUNKBIT_SET_ZERO 0 /** \internal Chunk Bit is not set. */ +#define PHNFCSTSHL16 16 /** \internal Shift 16 bits(left or right). */ +#define PHNFCSTSHL24 24 /** \internal Shift 24 bits(left or right). */ +#define PHFRINFCNDEFRECORD_NORMAL_RECORD_BYTE 4 /** \internal Normal record. */ +#define PH_FRINFC_NDEFRECORD_TNFBYTE_MASK ((uint8_t)0x07) /** \internal For masking */ +#define PH_FRINFC_NDEFRECORD_BUF_INC1 1 /** \internal Increment Buffer Address by 1 */ +#define PH_FRINFC_NDEFRECORD_BUF_INC2 2 /** \internal Increment Buffer Address by 2 */ +#define PH_FRINFC_NDEFRECORD_BUF_INC3 3 /** \internal Increment Buffer Address by 3 */ +#define PH_FRINFC_NDEFRECORD_BUF_INC4 4 /** \internal Increment Buffer Address by 4 */ +#define PH_FRINFC_NDEFRECORD_BUF_INC5 5 /** \internal Increment Buffer Address by 5 */ +#define PH_FRINFC_NDEFRECORD_BUF_TNF_VALUE ((uint8_t)0x00) /** \internal If TNF = Empty, Unknown and Unchanged, the id, type and payload length is ZERO */ +#define PH_FRINFC_NDEFRECORD_FLAG_MASK ((uint8_t)0xF8) /** \internal To Mask the Flag Byte */ + + + +/** + *\ingroup grp_lib_nfc + *\brief NFC NDEF Record structure definition. + * + *The NDEF Record Compound used for: + *\li \b Extraction: The calling function(-ality) receives the NDEF data of an extracted + * record in this structure. + *\li \b Composition The caller is required to specify the data to write within this structure + * in order to have it serialized into a new NDEF record. + * The structure offers a user-friendly way to accomplish this. + */ +typedef struct phFriNfc_NdefRecord +{ + /** + * The flags control (or inform about) the structure of a record. + * + * \li \b Extraction: The component fills in the flags, extracted from the NDEF record. + * \li \b Composition: The caller has to specify the proper flags (OR'ing of the individual + * flag definitions (such as \ref PH_FRINFC_NDEFRECORD_FLAGS_MB). This + * information goes into the generated (composed) record. The caller + * is responsible for applying the correct flags in order to mark the + * begin or end of a message or other conditions. + */ + uint8_t Flags; + + /** + * The Type Name Format, according to the NDEF specification, e.g. \ref PH_FRINFC_NDEFRECORD_TNF_NFCWELLKNOWN . + * + * \li \b Extraction: The component fills the TNF value, extracted from the NDEF record. + * \li \b Composition: The caller needs to specify the TNF according to the definitions in the + * NDEF specification. + */ + uint8_t Tnf; + + /** + * The length of the Type field. See \ref phFriNfc_NdefRecord_t::Tnf and + * \ref phFriNfc_NdefRecord_t::Type . + * + * \li \b Extraction: If the TNF indicates that a type field is present this + * member contains its length. Otherwise the length is set + * to zero by the library. + * \li \b Composition: If the caller specifies via TNF that a Type field is present + * the length of the Type has to be specified in this member. + * Otherwise, this member is ignored by the library. + */ + uint8_t TypeLength; + + /** + * Contained record type: This is a buffer holding the Type + * as defined in the NDEF specification of the NFC Forum. + * No zero-termination is present, the length is determined by + * \ref phFriNfc_NdefRecord_t::TypeLength . + * + * \li \b Extraction: If the record holds a type (see TNF) the function sets the pointer to the + * beginning of the Type field of the record. Otherwise, if no type is present + * this member is set to NULL by the library. + * \li \b Composition: The caller has to specify a pointer to a buffer holding the record type. If the + * caller specifies that the record is without type (TNF) this member is ignored + * by the library. + */ + uint8_t *Type; + + /** + * The length of the ID field. See \ref phFriNfc_NdefRecord_t::Flags . + * + * \li \b Extraction: If the IL flag indicates that an ID field is present this + * member contains its length. Otherwise the length is set + * to zero by the library. + * \li \b Composition: If the caller specifies via IL that an ID field is present + * the length of the ID has to be specified in this member. + * Otherwise, this member is ignored by the library. + */ + uint8_t IdLength; + + /** + * Record ID: This is a buffer holding the ID + * as written in the NDEF specification of the NFC Forum. + * No zero-termination is present, the length is determined by + * \ref phFriNfc_NdefRecord_t::IdLength . + * + * \li \b Extraction: If the record holds an ID (IL Flag) the function sets the pointer to the + * beginning of the ID field of the record. Otherwise, if no ID is present + * this member is set to NULL by the library. + * \li \b Composition: The caller has to specify a pointer to a buffer holding the record ID. If the + * caller specifies that the record is without ID (IL Flag) this member is ignored + * by the library. + */ + uint8_t *Id; + + + /** + * The length of the Payload, in bytes. The maximum length is 2^32 - 1. + * + * \li \b Extraction: The value is set by the function. In case that the extraction encounters + * an error, this member is set to zero. + * \li \b Composition: The value must be different from ZERO and and less than 2^32 and has to be + * provided by the caller. + */ + uint32_t PayloadLength; + + /** + * Payload Data, pointer to a buffer containing the payload data. + * + * \li \b Extraction: The pointer is set to the beginning of the payload. + * No pre-set is required before the extraction function call. + * \li \b Composition: The referenced data is copied to buffer where the library composes the record. + * The pointer is provided by the caller and must not be NULL and valid. + */ + uint8_t *PayloadData; + +} phFriNfc_NdefRecord_t; + + +#ifndef PH_FRINFC_EXCLUDE_FROM_TESTFW /* */ + + + /** + *\ingroup grp_lib_nfc + *\brief NDEF Record \b Get \b Records function. + * + * + * Get a list of NDEF records from the raw data as provided by the caller. This data is a + * buffer holding one or more NDEF records within a NDEF message (received from a NFC peer + * device, for example). The function returns the NumberOfRawRecords present in the message + * with pointers to the records stored in the array RawRecords. The function also tells + * whether a record is chunked. + * + * \param[in] Buffer The data buffer holding the NDEF Message, as provided + * by the caller. + * \param[in] BufferLength The data length, as provided by the caller. + * \param[in,out] RawRecords Array of pointers, receiving the references to the found + * Ndef Records in the given Message. The caller has to provide the + * array of pointers. The array is filled with valid pointers + * up to the number of records found or the array size if the + * number of found records exceeds the size.\n + * If this parameter is set to NULL by the caller it is ignored. + * \param[in,out] IsChunked This array of booleans indicates whether a record has the + * CHUNKED flag set (is a partial record). + * The number of caller-provided array positions has to be the same + * as "NumberOfRawRecords". + * If the caller sets this parameter to NULL it is ignored. + * \param[in,out] NumberOfRawRecords Length of the RawRecords array and IsChunked list. + * The value is set by the extracting function to the actual number + * of records found in the data. If the user specifies 0 (zero) + * the function only yields the number of records without filling + * in pointers.\n The value NULL is invalid. + * + * \retval NFCSTATUS_SUCCESS Operation successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_FORMAT This error is returned in the following scenarios + * + *
1. There is no Message Begin (MB) Bit in the Message. + *
2. Type Name Format (TNF) Bits are set to 0x07 (Reserved) + * which is reserved and has not to be used. + *
3. MB Bit is set to 1 and TNF bits are set to 0x06 (unchanged). + *
4. MB Bit is set to 1 and TNF bits are not set to 0x05 or 0x00 (unknown or Empty). However,Type Length equals 0. + *
5. Message End Bit is set to 1 and Chunked Flag(CF)is set to 1 in the same record. + *
6. Not a First Record, either the MB Bit OR the CF bit is set to 1. IDLength (IL) Bit is set to 1 and TNF bits are set to 0x06 (Unchanged). + *
7. Not a First Record, the CF Bit of previous record is set to 1 and TNF bits are not set to 0x06 (unchanged) OR\n The CF Bit of the previous record is not set to 1 and TNF bits are not set to 0x06 (unchanged). + *
8. Check for Last Chunk, CF Bit of previous record is set to 1 and CF Bit of present record is set to 0, but Type Length or ID Length is not equal to zero. + *
9. Inconsistency between the calculated length of the message and the length provided by the caller.or if TNF bits are set to 0x00 or 0x05 or 0x06 (Empty,Unknown and Unchanged), but Type Length is not equal to zero + *
10.TNF bits are set to 0x00 (Empty), but Payload Length is not equal to zero. + *
11.TNF bits are set to 0x00 (Empty),but ID Length is not equal to zero. + * + * \note The correct number of found records is returned by the function also in case that: + * - The "RawRecords" array is too short to hold all values: It is filled up to the allowed maximum. + * - The "RawRecords" array is NULL: Only the number is returned. + * - The "NumberOfRawRecords" parameter is zero: The array is not filled, just the number is returned. + * . + * This can be used for targeted memory allocation: Specify NULL for "RawRecords" and/or + * zero for "NumberOfRawRecords" and the function just yields the correct array size to allocate + * for a second call. + * \note \b Security: This function verifies the given NDEF message buffer integrity. Its purpose is to + * initially check incoming data and taking this effort away from \ref phFriNfc_NdefRecord_Parse. + * It is a strong requirement for \ref phFriNfc_NdefRecord_GetRecords to be called to check incoming data + * before it is handed over to further processing stages. + * + *\msc + *LibNfcClient,LibNfc; + *--- [label="Tag discovered and tag found to be NDEF compliant "]; + *LibNfcClient=>LibNfc [label="phLibNfc_Ndef_Read()",URL="\ref phLibNfc_Ndef_Read"]; + *LibNfcClient<LibNfc [label="phFriNfc_NdefRecord_GetRecords(pBuffer,BufferLength,NULL,)",URL="\ref phFriNfc_NdefRecord_GetRecords"]; + *LibNfcClient<LibNfc [label="phFriNfc_NdefRecord_GetRecords()",URL="\ref phFriNfc_NdefRecord_GetRecords"]; + *LibNfcClient<NDEF Record \b Parse function + * + * + * Extract a specific NDEF record from the data, provided by the caller. The data is a buffer holding + * at least the entire NDEF record (received via the NFC link, for example). + * + * \param[out] Record The NDEF record structure. The storage for the structure has to + * be provided by the caller matching the requirements for \b Extraction, + * as described in the compound documentation. It is important to note + * that all the pointers inside the extracted record structure direct + * to the \b original buffer and not to a copy (see notes) after extraction. + * \param[in] RawRecord The Pointer to the record location, selected out of the records array, + * returned by the \ref phFriNfc_NdefRecord_GetRecords function. + * + * \retval NFCSTATUS_SUCCESS Operation successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_FORMAT This error is returned in the following scenarios + *
1. Type Name Format (TNF) Bits are set to 0x07 (Reserved) which is reserved and has not to be used. + *
2. TNF bits are set to 0x00 or 0x05 or 0x06 (Empty,Unknown and Unchanged), but Type Length is not + * equal to 0. + *
3. TNF bits are set to 0x00 (Empty),but Payload Length is not equal to 0. + *
4. TNF bits are set to 0x00 (Empty),but ID Length is not equal to 0. + * + * \note There are some caveats: + * \li The "RawRecord" Data buffer must exist at least as long as the function execution time + * plus the time needed by the caller to evaluate the extracted information. No copying of + * the contained data is done internally. + * \li \b Security: It is not allowed to feed an unchecked NDEF message into the RawRecord + * parameter of the function in an attempt to extract just the first record. The + * rule is always to use \ref phFriNfc_NdefRecord_GetRecords in order to retrieve the + * verified pointers to the individual records within a raw message. A violation of this + * rule leads to the loss of buffer boundary overflow protection. + * + *\msc + *LibNfcClient,LibNfc; + *--- [label="Tag discovered and tag found to be NDEF compliant "]; + *LibNfcClient=>LibNfc [label="phLibNfc_Ndef_Read()",URL="\ref phLibNfc_Ndef_Read"]; + *LibNfcClient<LibNfc [label="phFriNfc_NdefRecord_GetRecords(pBuffer,BufferLength,NULL,)",URL="\ref phFriNfc_NdefRecord_GetRecords "]; + *LibNfcClient<LibNfc [label="phFriNfc_NdefRecord_GetRecords()",URL="\ref phFriNfc_NdefRecord_GetRecords "]; + *LibNfcClient<LibNfc [label="phFriNfc_NdefRecord_Parse(pRawRecords[i],pRawRecord)",URL="\ref phFriNfc_NdefRecord_Parse "]; + *LibNfcClient<NDEF Record \b Generate function + * + * The function writes one NDEF record to a specified memory location. Called within a loop, it is + * possible to write more records into a contiguous buffer, in each cycle advancing by the number + * of bytes written for each record. + * + * \param[in] Record The NDEF record structure to append. The structure + * has to be initialized by the caller matching the requirements for + * \b Composition, as described in the documentation of + * the \ref phFriNfc_NdefRecord_t "NDEF Record" structure. + * \param[in] Buffer The pointer to the buffer to which the record shall be written. + * \param[in] MaxBufferSize The data buffer's (remaining) maximum size, provided by the caller. + * This must be the \b actual number of bytes that can be written into + * the buffer. The user must update this value for each call. + * \param[out] BytesWritten The actual number of bytes written to the buffer during the recent call. + * This can be used by the caller to serialize more than one record + * into the same buffer (composing a NDEF message). + * + * \retval NFCSTATUS_SUCCESS Operation successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The data buffer, provided by the caller is to small to + * hold the composed NDEF record. The existing content is + * not changed, no data have been written. + * + * \note The Caller of this function must take care that, with each call, the parameters are + * updated correctly: + * \li MaxBufferSize must decreased by the previous call number of \b BytesWritten + * \li Pointer to Buffer is advanced by the previous call number of \b BytesWritten. + * + *\msc + *LibNfcClient,LibNfc; + *--- [label="Tag discovered and tag found to be NDEF compliant "]; + *--- [label="Create NDEF raw buffer based of NDEF record details"]; + *LibNfcClient=>LibNfc [label="phFriNfc_NdefRecord_Generate()",URL="\ref phFriNfc_NdefRecord_Generate "]; + *LibNfcClient<LibNfc [label="phLibNfc_Ndef_Write()",URL="\ref phLibNfc_Ndef_Write "]; + *LibNfcClient<This is not a user API. This should not be exposed in the SDK. + */ +uint32_t phFriNfc_NdefRecord_GetLength(phFriNfc_NdefRecord_t* pRecord); + +/** \internal + * + * This is a sub function to the Parse Function. This function will get only Type Name Format bits in a Packet + * and omit the other Flags bits. No Error Checks done here. + * + * \note This is not a user API. This should not be exposed in the SDK. + * \param[in] s1 String to compare. + * \param[out] s2 String to compare. + * \param[out] count Number of characters to compare. + */ + +int16_t phFriNfc_NdefReg_Strnicmp(const int8_t *s1, const int8_t *s2, uint32_t count); + +/*@}*/ /* defgroup */ + +#endif /* PH_FRINFC_EXCLUDE_FROM_TESTFW */ + +#endif /* PHFRINFC_NDEFRECORD_H */ + diff --git a/libnfc-nxp/phFriNfc_NdefReg.c b/libnfc-nxp/phFriNfc_NdefReg.c new file mode 100644 index 0000000..b39bf04 --- /dev/null +++ b/libnfc-nxp/phFriNfc_NdefReg.c @@ -0,0 +1,679 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc_NdefReg.c + * \Contains Registry and module functions. + * + * Project: NDEFT + * + * $Date: Mon May 25 13:59:32 2009 $ + * $Author: ing08150 $ + * $Revision: 1.4 $ + * $Aliases: NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + + +#include "phNfcTypes.h" +#include "phNfcStatus.h" +#include "phNfcCompId.h" +#include "phNfcHalTypes.h" +#include "phFriNfc.h" +#include "phFriNfc_NdefReg.h" +#include "phFriNfc_NdefRecord.h" + +/* Harsha: To Fix: 0000358: phFriNfc_NdefRecord.h: includes should be moved */ +#include +static int16_t phFriNfc_NdefReg_Strncmp (const int8_t *s1, const int8_t *s2, uint32_t count); + +/********* String functions *********/ + +static int16_t phFriNfc_NdefReg_Strncmp (const int8_t *s1, const int8_t *s2, uint32_t count) +{ + return (int16_t)strncmp((const char*)s1,(const char*)s2, count); +} +int16_t phFriNfc_NdefReg_Strnicmp(const int8_t *s1, const int8_t *s2, uint32_t count) +{ + int8_t c1, c2; + int16_t returnvalue; + do + { + c1 = *s1; + s1++; + if (c1 >=97) + c1 = (c1 - 32); + c2 = *s2; + s2++; + if (c2 >=97) + c2 = (c2 - 32); + --count; + } + while ( (c1 == c2) && (c1 != '\0') && (c2 != '\0') && (count > 0) ); + + if ( (count == 0) || (c1 == c2) ) + returnvalue = 0; + + else if ( (c1 > c2) ) + returnvalue = 1; + else + returnvalue = -1; + + return(returnvalue); +} + +/********* REGISTRY AND LISTENER MODULE *********/ + +NFCSTATUS phFriNfc_NdefReg_Reset(phFriNfc_NdefReg_t *NdefReg, + uint8_t **NdefTypesarray, + phFriNfc_NdefRecord_t *RecordsExtracted, + phFriNfc_NdefReg_CbParam_t *CbParam, + uint8_t *ChunkedRecordsarray, + uint32_t NumberOfRecords) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* Reset/Initialise the values of the Context structure */ + /* Store the required pointers in the context structure */ + if(NdefReg == NULL || NdefTypesarray == NULL || RecordsExtracted == NULL || CbParam == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_REGISTRY, NFCSTATUS_INVALID_PARAMETER); + } + else + { + NdefReg->State=PH_FRINFC_NDEFREG_STATE_INIT; + NdefReg->NdefData=NULL; + NdefReg->NdefDataLength=0; + NdefReg->NdefTypeList=NULL; + NdefReg->NdefTypes = NdefTypesarray ; + NdefReg->RecordsExtracted = RecordsExtracted; + NdefReg->CbParam = CbParam; + NdefReg->validPreviousTnf = 0xff; + NdefReg->IsChunked = ChunkedRecordsarray; + NdefReg->NumberOfRecords = NumberOfRecords; + NdefReg->newRecordextracted = 0; + NdefReg->MainTnfFound = 0; + } + return(status); +} + +/* Adds a NDEF type listener to the internal list of listeners*/ +/*Libraray does no allocation of the memory*/ +NFCSTATUS phFriNfc_NdefReg_AddCb(phFriNfc_NdefReg_t *NdefReg, + phFriNfc_NdefReg_Cb_t *NdefCb) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NdefReg == NULL || NdefCb ==NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_REGISTRY, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Check whether we can accomodate all these records in a single node */ + if(NdefCb->NumberOfRTDs <= PH_FRINFC_NDEFREG_MAX_RTD_REGISTERED) + { + /* Yes, all these Records can be accomodated in a single node */ + /* No existing node. This will be the first Node */ + if(NdefReg->NdefTypeList==NULL) + { + NdefCb->Previous =NULL; + NdefCb->Next =NULL; + NdefReg->NdefTypeList = NdefCb; + } + else + { + /* Some nodes are existing. Add the new CB node at the front + of the List and update pointers */ + NdefCb->Next = NdefReg->NdefTypeList; + NdefCb->Previous = NULL; + NdefReg->NdefTypeList->Previous = NdefCb; + NdefReg->NdefTypeList = NdefReg->NdefTypeList->Previous; + } + } + else + { + /* We cannot accomodate more records than PH_FRINFC_NDEFREG_MAX_RTD_REGISTERED + in this node. + So return warning NFCSTATUS_INVALID_PARAMETER. */ + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_REGISTRY, + NFCSTATUS_INVALID_PARAMETER); + } + } + + return(status); +} + +/*Removes a specific listener from the list. The element to remove is specified by its address.*/ +/*Libraray does no deallocation of the memory*/ +NFCSTATUS phFriNfc_NdefReg_RmCb(phFriNfc_NdefReg_t *NdefReg, + phFriNfc_NdefReg_Cb_t *NdefCb) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phFriNfc_NdefReg_Cb_t *tempNode; + uint8_t found=0;/* to check for the node present or not */ + + if( NdefReg==NULL || NdefCb ==NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_REGISTRY, NFCSTATUS_INVALID_PARAMETER); + } + else + { + tempNode = NdefReg->NdefTypeList; + /* if the list is empty */ + if(NdefReg->NdefTypeList == NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_REGISTRY, NFCSTATUS_NOT_REGISTERED); + } + else + { + while(tempNode!=NULL) + { + if(NdefCb == tempNode) + { + found=1;/* if the node is present */ + + /* node is present in the front of the list so + update the NdefReg->NdefTypeList pointer */ + if(tempNode->Previous==NULL && tempNode->Next!=NULL) + { + NdefReg->NdefTypeList =NdefReg->NdefTypeList->Next; + NdefReg->NdefTypeList->Previous = NULL; + break; + } + /* only one node in the list so update the head node */ + if(tempNode->Next==NULL && tempNode->Previous==NULL) + { + NdefReg->NdefTypeList=NULL; + break; + } + if (tempNode->Previous != NULL) + { + tempNode->Previous->Next = tempNode->Next; + } + if (tempNode->Next != NULL) + { + tempNode->Next->Previous = tempNode->Previous; + } + break; + } + /* move to the next node */ + tempNode = tempNode->Next; + } + } + if(!found ) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_REGISTRY, NFCSTATUS_NOT_REGISTERED); + } + } + return(status); +} + +/* Copy the relevant pointers to the context structure, change the +FSM state, so as to trigger the process and return pending. This function is non-blocking, +it returns once the operation is initiated or an error occurs */ + +NFCSTATUS phFriNfc_NdefReg_DispatchPacket(phFriNfc_NdefReg_t *NdefReg, + uint8_t *PacketData, + uint16_t PacketDataLength) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if(NdefReg==NULL ||PacketData==NULL || PacketDataLength==0) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_REGISTRY, NFCSTATUS_INVALID_PARAMETER); + } + else + { + NdefReg->NdefData = PacketData; + NdefReg->NdefDataLength = PacketDataLength; + NdefReg->State = PH_FRINFC_NDEFREG_STATE_DIS_PKT; + NdefReg->NumberOfNdefTypes = 0; + NdefReg->RecordIndex = 0; + NdefReg->RtdIndex = 0; + status = PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS); + } + return(status); +} + +/* Copy the relevant pointers to the context structure, change the +FSM state, so as to trigger the process and return pending */ +NFCSTATUS phFriNfc_NdefReg_DispatchRecord(phFriNfc_NdefReg_t *NdefReg, + phFriNfc_NdefRecord_t *RecordsExtracted) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if(NdefReg==NULL || RecordsExtracted==NULL) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_REGISTRY, NFCSTATUS_INVALID_PARAMETER); + } + else + { + NdefReg->RecordsExtracted = RecordsExtracted; + NdefReg->State = PH_FRINFC_NDEFREG_STATE_DIS_RCD; + + status = PHNFCSTVAL(CID_NFC_NONE, NFCSTATUS_SUCCESS); + } + return(status); +} + +uint8_t phFriNfc_NdefReg_Process(phFriNfc_NdefReg_t *NdefReg, + NFCSTATUS *Status) +{ + uint8_t count = 0, + ret_val=0, + TnfMatchFound = 0, + index = 0, + matchFound = 0; + + + + if(NdefReg->NdefTypeList == NULL) + { + /* No Nodes added. Return error */ + *Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_REGISTRY, NFCSTATUS_NOT_REGISTERED); + return(1); + } + + *Status = NFCSTATUS_SUCCESS; + switch(NdefReg->State) + { + case PH_FRINFC_NDEFREG_STATE_DIS_RCD: + + /* for START ( each node in the list NdefReg->NdefTypeList), do the following */ + for(index=0;indexNdefTypeList->NumberOfRTDs;index++) + { + /* First, Match should be done with The TNF*/ + if( (NdefReg->NdefTypeList->Tnf[index] & PH_FRINFC_NDEFRECORD_TNF_MASK ) == + (NdefReg->RecordsExtracted->Tnf & PH_FRINFC_NDEFRECORD_TNF_MASK ) ) + { + /* Second, Match should be done with The Typelength*/ + if( NdefReg->NdefTypeList->NdeftypeLength[index] == \ + NdefReg->RecordsExtracted->TypeLength ) + { + /* Third, Match should be done with The Type*/ + matchFound = 0; + switch(NdefReg->NdefTypeList->Tnf[index]) + { + case 1: + /* TNF = 0X01 NFC Forum well-known type : Case sensitive */ + /* comparison is to be made. */ + if( !phFriNfc_NdefReg_Strncmp( (const int8_t *)NdefReg->NdefTypeList->NdefType[index] , + (const int8_t *)(NdefReg->RecordsExtracted->Type), + NdefReg->RecordsExtracted->TypeLength)) + { + matchFound = 1; + } + break; + + case 2: + case 4: + /* For TNF = 0X02 Media-type as defined in RFC 2046 + From iana.org, it has never been found any registered media type + with non-ascii character ==> Comparison to be used for *types* in + *registry*: case INSENSITIVE comparison. + + For TNF = 0X04 NFC Forum external type : ==> Comparison to be used + for *types* in *registry* : case INSENSITIVE comparison */ + if( !phFriNfc_NdefReg_Strnicmp( (int8_t *)NdefReg->NdefTypeList->NdefType[index] , + (int8_t *)(NdefReg->RecordsExtracted->Type), + NdefReg->RecordsExtracted->TypeLength)) + { + matchFound = 1; + } + break; + + case 3: + /* TNF = 0X03 Absolute URI as defined in RFC 3986 [RFC 3986] + Big issue concerning the Encoding, which is actually determined + by the application.Conclusion is that: Comparison to be used for + *types* in *registry*: NONE. only TNF ; type should be ignored, + and its comparison shall be done by the application. */ + matchFound = 1; + break; + default: + break; + } + if(matchFound) + { + /* Copy the chunked flag info to the callback parameter */ + NdefReg->CbParam->Chunked[count] = (NdefReg->RecordsExtracted->Flags & \ + PH_FRINFC_NDEFRECORD_FLAGS_CF ); + + /* NOTE: Raw record and the raw record size cannot be + copied as this itself is an extracted record ! */ + + /* Copy the record in the format phFriNfc_NdefRecord_t + to the callback parameter */ + (void) memcpy( &NdefReg->CbParam->Records[count], + NdefReg->RecordsExtracted, + sizeof(phFriNfc_NdefRecord_t)); + count++; + } + } + } + } + + /* now, we have all the matching entries for the RTDs present + in this particular node NdefReg->NdefTypeList. + call the callback */ + if(count>0) + { + NdefReg->CbParam->Count = count; + NdefReg->CbParam->CbContext = NdefReg->NdefTypeList->CbContext; + NdefReg->NdefTypeList->NdefCallback (NdefReg->CbParam); + } + else + { + NdefReg->CbParam->Count = 0; + } + + /* for END ( each node in the list NdefReg->NdefTypeList), do the following */ + if(NdefReg->NdefTypeList->Next==NULL) + { + NdefReg->State = PH_FRINFC_NDEFREG_STATE_INIT; + while(NdefReg->NdefTypeList->Previous!=NULL) + { + NdefReg->NdefTypeList = NdefReg->NdefTypeList->Previous; + } + /* No further node present in the list. End of process function call */ + ret_val=1; + } + else + { + /* Move the linked list by one node.*/ + NdefReg->NdefTypeList = NdefReg->NdefTypeList->Next; + /* list is not empty so come again */ + ret_val=0; + } + break; + + case PH_FRINFC_NDEFREG_STATE_DIS_PKT: + + if(NdefReg->NumberOfNdefTypes == 0) + { + /* First, Get all the records present in the data packet NdefReg->NdefData + using NDEF tool library */ + /* and, get the NumberOfNdefTypes from NdefData */ + *Status = phFriNfc_NdefRecord_GetRecords( NdefReg->NdefData, + NdefReg->NdefDataLength, + NULL, + NdefReg->IsChunked, + &NdefReg->NumberOfNdefTypes); + if((*Status)!= NFCSTATUS_SUCCESS) + { + /* Error in the Packet. Exit from the process */ + ret_val = 1; + NdefReg->NumberOfNdefTypes = 0; + break; + } + + if(NdefReg->NumberOfNdefTypes > NdefReg->NumberOfRecords) + { + /* There is not enough space in the arrays NdefReg->NdefTypes + and NdefReg->IsChunked, to write NdefReg->NumberOfRecords + number of records. Return error. */ + *Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_REGISTRY, NFCSTATUS_BUFFER_TOO_SMALL); + ret_val = 1; + NdefReg->NumberOfNdefTypes = 0; + break; + } + + /* Now, get the NdefTypes */ + *Status = phFriNfc_NdefRecord_GetRecords( NdefReg->NdefData, + NdefReg->NdefDataLength, + NdefReg->NdefTypes, + NdefReg->IsChunked, + &NdefReg->NumberOfNdefTypes); + if((*Status)!= NFCSTATUS_SUCCESS) + { + /* Error in the Packet. Exit from the process */ + ret_val = 1; + NdefReg->NumberOfNdefTypes = 0; + break; + } + } + + /* For each record, in the arry NdefReg->NdefTypes, check + whether it matches with any of the registered RTD in the + present node. If it matches, copy this to the Callback + parameter array and increment count. + If count is 8, call the callback function. + Remember the record index that we last processed, before + calling the callback. */ + + /* for each record in the Message */ + while(NdefReg->RecordIndex < NdefReg->NumberOfNdefTypes) + { + /* Extract a record from the Message */ + *Status = phFriNfc_NdefRecord_Parse(NdefReg->RecordsExtracted, + NdefReg->NdefTypes[NdefReg->RecordIndex]); + if((*Status)!= NFCSTATUS_SUCCESS) + { + /* Error in the Record. Exit from the process */ + NdefReg->NumberOfNdefTypes = 0; + return 1; + } + + NdefReg->newRecordextracted = 1; + + /* for each RTD in the present node */ + while(NdefReg->RtdIndex < NdefReg->NdefTypeList->NumberOfRTDs) + { + /* Harsha: Fix for 0000243: [JF] phFriNfc_NdefReg_Process + won't parse correctly chunked records */ + + /* Check whether the TNF = 0x06 + PH_FRINFC_NDEFRECORD_TNF_UNCHANGED */ + + if((NdefReg->RecordsExtracted->Tnf & PH_FRINFC_NDEFRECORD_TNF_MASK ) == + PH_FRINFC_NDEFRECORD_TNF_UNCHANGED) + { + if(NdefReg->MainTnfFound == 1) + { + /* Matching RTD is there */ + TnfMatchFound = 1; + } + } + else + { + if(NdefReg->newRecordextracted) + { + NdefReg->MainTnfFound = 0; + } + /* This is a tnf other than 0x06. + that means, this is a valid tnf */ + NdefReg->validPreviousTnf = NdefReg->RecordsExtracted->Tnf; + + /* First, Match should be done with The TNF*/ + /* Second, Match should be done with The Typelength*/ + /* Third, Match should be done with The Type*/ + if((NdefReg->NdefTypeList->Tnf[NdefReg->RtdIndex] & + PH_FRINFC_NDEFRECORD_TNF_MASK ) == + (NdefReg->RecordsExtracted->Tnf & PH_FRINFC_NDEFRECORD_TNF_MASK ) && + (NdefReg->NdefTypeList->NdeftypeLength[NdefReg->RtdIndex] == + NdefReg->RecordsExtracted->TypeLength)) + { + matchFound = 0; + switch(NdefReg->NdefTypeList->Tnf[NdefReg->RtdIndex]) + { + case 1: + /* TNF = 0X01 NFC Forum well-known type : Case sensitive + comparison is to be made. */ + if(!phFriNfc_NdefReg_Strncmp((const int8_t *)NdefReg->NdefTypeList->NdefType[NdefReg->RtdIndex], + (const int8_t *)(NdefReg->RecordsExtracted->Type), + NdefReg->RecordsExtracted->TypeLength)) + { + matchFound = 1; + } + break; + + case 2: + case 4: + /* For TNF = 0X02 Media-type as defined in RFC 2046 + From iana.org, it has never been found any registered media type + with non-ascii character ==> Comparison to be used for *types* in + *registry*: case INSENSITIVE comparison. */ + + /* For TNF = 0X04 NFC Forum external type : ==> Comparison to be used + for *types* in *registry* : case INSENSITIVE comparison */ + if( !phFriNfc_NdefReg_Strnicmp( (int8_t *)NdefReg->NdefTypeList->NdefType[NdefReg->RtdIndex], + (int8_t *)(NdefReg->RecordsExtracted->Type), + NdefReg->RecordsExtracted->TypeLength)) + { + matchFound = 1; + } + break; + + case 3: + /* TNF = 0X03 Absolute URI as defined in RFC 3986 [RFC 3986] + Big issue concerning the Encoding, which is actually determined + by the application.Conclusion is that: Comparison to be used for + *types* in *registry*: NONE. only TNF ; type should be ignored, + and its comparison shall be done by the application. */ + matchFound = 1; + break; + default: + break; + } + if(matchFound == 1) + { + TnfMatchFound = 1; + NdefReg->MainTnfFound = 1; + } + else + { + TnfMatchFound = 0; + } + } + else + { + TnfMatchFound = 0; + } + } + + /* we have found a matching TNF */ + if(TnfMatchFound == 1) + { + /* Copy the chunked flag info to the callback parameter */ + NdefReg->CbParam->Chunked[count] = NdefReg->IsChunked[NdefReg->RecordIndex]; + + /* Copy the raw record to the callback parameter */ + NdefReg->CbParam->RawRecord[count] = NdefReg->NdefTypes[NdefReg->RecordIndex]; + + /* Copy the raw record size to the callback parameter */ + NdefReg->CbParam->RawRecordSize[count] = phFriNfc_NdefRecord_GetLength(NdefReg->RecordsExtracted); + + /* Copy the record in the format phFriNfc_NdefRecord_t + to the callback parameter */ + (void) memcpy( &NdefReg->CbParam->Records[count], + NdefReg->RecordsExtracted, + sizeof(phFriNfc_NdefRecord_t)); + + + /*if count is greater than PH_FRINFC_NDEFREG_MAX_RTD (presently 8) + then call the callback since there can be more than + PH_FRINFC_NDEFREG_MAX_RTD of a single type with in the packet,as a result + call the callback and initialize count to zero.This may also happen + when there are chunked records */ + + count++; + if(count >= PH_FRINFC_NDEFREG_MAX_RTD ) + { + NdefReg->CbParam->Count = count; + NdefReg->CbParam->CbContext = NdefReg->NdefTypeList->CbContext; + NdefReg->NdefTypeList->NdefCallback (NdefReg->CbParam); + count=0; + /* Only one callback per node. */ + NdefReg->RecordIndex++; + return(0); + } + } + + /* If the match is already found for the UNCHANGED_TNF, + don't comapre it again */ + if((NdefReg->RecordsExtracted->Tnf & PH_FRINFC_NDEFRECORD_TNF_MASK ) + == PH_FRINFC_NDEFRECORD_TNF_UNCHANGED && + TnfMatchFound == 1) + { + TnfMatchFound = 0; + break; + } + + NdefReg->RtdIndex++; + + NdefReg->newRecordextracted = 0; + } /* for each RTD in the present node + while(NdefReg->RtdIndex < NdefReg->NdefTypeList->NumberOfRTDs) */ + + /* One Record processing done for this node */ + + NdefReg->RtdIndex = 0; + NdefReg->RecordIndex++; + } /* while(NdefReg->RecordIndexNumberOfNdefTypes) */ + + /* One node has been checked. Move to the next node */ + + if(count>0) + { + NdefReg->CbParam->Count = count; + NdefReg->CbParam->CbContext = NdefReg->NdefTypeList->CbContext; + NdefReg->NdefTypeList->NdefCallback (NdefReg->CbParam); + } + else + { + NdefReg->CbParam->Count = 0; + } + + if(NdefReg->NdefTypeList->Next==NULL) + { + /* All the nodes have been checked. Return */ + NdefReg->State = PH_FRINFC_NDEFREG_STATE_INIT; + while(NdefReg->NdefTypeList->Previous!=NULL) + { + NdefReg->NdefTypeList = NdefReg->NdefTypeList->Previous; + } + /* No further node present in the list. + End of Dispatch packet function. Return TRUE*/ + ret_val = 1; + } + else + { + /* Move the linked list by one node.*/ + NdefReg->NdefTypeList = NdefReg->NdefTypeList->Next; + /* list is not empty so come again */ + ret_val = 0; + } + + /* Start from the first record again. */ + NdefReg->RecordIndex = 0; + NdefReg->RtdIndex = 0; + + break; + + default: + /* return error */ + *Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_REGISTRY, NFCSTATUS_INVALID_DEVICE_REQUEST); + /* Unknown state Error exit from the process function */ + ret_val= 1; + break; + + } + + return(ret_val); + +} + + diff --git a/libnfc-nxp/phFriNfc_NdefReg.h b/libnfc-nxp/phFriNfc_NdefReg.h new file mode 100644 index 0000000..5a4b86d --- /dev/null +++ b/libnfc-nxp/phFriNfc_NdefReg.h @@ -0,0 +1,456 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_NdefReg.h + * \brief NFC Ndef Registration / Listening. + * + * Project: NFC-FRI + * + * $Date: Fri Oct 5 10:10:07 2007 $ + * $Author: frq05303 $ + * $Revision: 1.1 $ + * $Aliases: NFC_FRI1.1_WK826_PREP1,NFC_FRI1.1_WK826_R1,NFC_FRI1.1_WK826_R2,NFC_FRI1.1_WK830_PREP1,NFC_FRI1.1_WK830_PREP2,NFC_FRI1.1_WK830_R5_1,NFC_FRI1.1_WK830_R5_2,NFC_FRI1.1_WK830_R5_3,NFC_FRI1.1_WK832_PREP1,NFC_FRI1.1_WK832_PRE2,NFC_FRI1.1_WK832_PREP2,NFC_FRI1.1_WK832_PREP3,NFC_FRI1.1_WK832_R5_1,NFC_FRI1.1_WK832_R6_1,NFC_FRI1.1_WK834_PREP1,NFC_FRI1.1_WK834_PREP2,NFC_FRI1.1_WK834_R7_1,NFC_FRI1.1_WK836_PREP1,NFC_FRI1.1_WK836_R8_1,NFC_FRI1.1_WK838_PREP1,NFC_FRI1.1_WK838_R9_PREP2,NFC_FRI1.1_WK838_R9_1,NFC_FRI1.1_WK840_R10_PREP1,NFC_FRI1.1_WK840_R10_1,NFC_FRI1.1_WK842_R11_PREP1,NFC_FRI1.1_WK842_R11_PREP2,NFC_FRI1.1_WK842_R11_1,NFC_FRI1.1_WK844_PREP1,NFC_FRI1.1_WK844_R12_1,NFC_FRI1.1_WK846_PREP1,NFC_FRI1.1_WK846_R13_1,NFC_FRI1.1_WK848_PREP1,NFC_FRI1.1_WK848_R14_1,NFC_FRI1.1_WK850_PACK1,NFC_FRI1.1_WK851_PREP1,NFC_FRI1.1_WK850_R15_1,NFC_FRI1.1_WK902_PREP1,NFC_FRI1.1_WK902_R16_1,NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PHFRINFC_NDEFREG_H +#define PHFRINFC_NDEFREG_H + +#ifndef PH_FRINFC_EXCLUDE_FROM_TESTFW /* */ + +/** + * \name NDEF Registry and Listening + * + */ +/*@{*/ +#define PH_FRINFC_NDEFREG_FILEREVISION "$Revision: 1.1 $" /** \ingroup grp_file_attributes */ +#define PH_FRINFC_NDEFREG_FILEALIASES "$Aliases: NFC_FRI1.1_WK826_PREP1,NFC_FRI1.1_WK826_R1,NFC_FRI1.1_WK826_R2,NFC_FRI1.1_WK830_PREP1,NFC_FRI1.1_WK830_PREP2,NFC_FRI1.1_WK830_R5_1,NFC_FRI1.1_WK830_R5_2,NFC_FRI1.1_WK830_R5_3,NFC_FRI1.1_WK832_PREP1,NFC_FRI1.1_WK832_PRE2,NFC_FRI1.1_WK832_PREP2,NFC_FRI1.1_WK832_PREP3,NFC_FRI1.1_WK832_R5_1,NFC_FRI1.1_WK832_R6_1,NFC_FRI1.1_WK834_PREP1,NFC_FRI1.1_WK834_PREP2,NFC_FRI1.1_WK834_R7_1,NFC_FRI1.1_WK836_PREP1,NFC_FRI1.1_WK836_R8_1,NFC_FRI1.1_WK838_PREP1,NFC_FRI1.1_WK838_R9_PREP2,NFC_FRI1.1_WK838_R9_1,NFC_FRI1.1_WK840_R10_PREP1,NFC_FRI1.1_WK840_R10_1,NFC_FRI1.1_WK842_R11_PREP1,NFC_FRI1.1_WK842_R11_PREP2,NFC_FRI1.1_WK842_R11_1,NFC_FRI1.1_WK844_PREP1,NFC_FRI1.1_WK844_R12_1,NFC_FRI1.1_WK846_PREP1,NFC_FRI1.1_WK846_R13_1,NFC_FRI1.1_WK848_PREP1,NFC_FRI1.1_WK848_R14_1,NFC_FRI1.1_WK850_PACK1,NFC_FRI1.1_WK851_PREP1,NFC_FRI1.1_WK850_R15_1,NFC_FRI1.1_WK902_PREP1,NFC_FRI1.1_WK902_R16_1,NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /** \ingroup grp_file_attributes */ +/*@}*/ +#include + +#endif /* Exclude from test fw */ + +/* + * NDEF Registration And Listening - States of the Finite State machine + * + */ +#define PH_FRINFC_NDEFREG_STATE_INIT 0 /**< \internal Init state. The start-up state */ +#define PH_FRINFC_NDEFREG_STATE_DIS_PKT 1 /**< \internal Dispatch Packet is in progress */ +#define PH_FRINFC_NDEFREG_STATE_DIS_RCD 2 /**< \internal Dispatch Record is in progress */ + +/* + * NDEF Registration And Listening internal definitions + */ +#define PH_FRINFC_NDEFRECORD_TNF_MASK 0x07 /**< \internal */ +#define PH_FRINFC_NDEFREG_CH_FLG_ARR_INDEX 50 /**< \internal */ + + + + +/** \defgroup grp_fri_nfc_ndef_reg NDEF Registry + * + * This component implements the NDEF Registration and Listening functionality. + */ +/*@{*/ + +/* + * \name NDEF Registration And Listening callback and node definitions + * + * \ref PH_FRINFC_NDEFREG_MAX_RTD_REGISTERED is the maximum number of RTDs + * that can be registered in a node.\n + * \ref PH_FRINFC_NDEFREG_MAX_RTD is the maximum number of Records that can + * be present in a single callback function. + */ +/*@{*/ +#define PH_FRINFC_NDEFREG_MAX_RTD_REGISTERED 64 /**< Maximum number of RTDs per node */ +#define PH_FRINFC_NDEFREG_MAX_RTD 8 /**< Maximum number of RTDs per callback function. */ +/*@}*/ + +/** + * \brief NDEF Callback + * + * \copydoc page_reg + * + * Upon reception of a NDEF record the component calls into the function registered as a listener + * for a NDEF type. The function must be compatible to the declaration of the pointer described in + * this section. + * + * \par Parameter + * The underlying type of the callback parameter (void pointer) is \ref phFriNfc_NdefReg_CbParam_t . + * + * \note On systems, requiring non-blocking operation, the user-defined callback function must not block, + * but just deliver the data and return immediately. In this case the CB must make a copy of the + * parameter structure (\ref phFriNfc_NdefReg_CbParam_t) and store it within the environment of the + * registered listener. A copy is needed because once the CB returns the values behind the parameter + * pointer become invalid. We observe the following rules: + * - This component does not rely on lower layers (e.g. HAL), therefore it doesn't need to handle + * completion routines. + * - This library gets a NDEF message and extracts the records using the NDEF Record (Tools) Library. + * - Alternatively, this component can process pre-extracted NDEF records. + * - This library only handles TOP level records, cascaded content is ignored. + * - Functions do not block: The \ref phFriNfc_NdefReg_Process "Process" function needs to be called + * periodically until completion. + * . + */ +typedef void(*pphFriNfc_NdefReg_Cb_t)(void*); + + +/** + * \brief Callback Parameter. This parameter is provided to the CB function that serves + * as the notifier for services/applicatioon/software components registered for a specific + * NDEF Type. + * + * All information required to perform the \ref pphFriNfc_Cr_t "callback" operation is contained + * within the structure. The members of the structure may only be read, changing them is not allowed. + * + * + */ +typedef struct phFriNfc_NdefReg_CbParam +{ + /** + * Number of array Positions. Each array position carries data from a NDEF Record. The maximum + * number is \ref PH_FRINFC_NDEFREG_MAX_RTD . + */ + uint8_t Count; + + /** + * The records that matched with the registred RTDs for this callback. + * The number of records here will be equal to the first parameter Count. + */ + phFriNfc_NdefRecord_t Records[PH_FRINFC_NDEFREG_MAX_RTD]; + + /** Indicates whether a record is chunked or not. */ + uint8_t Chunked[PH_FRINFC_NDEFREG_MAX_RTD]; + + /** Pointer to the raw record. */ + uint8_t *RawRecord[PH_FRINFC_NDEFREG_MAX_RTD]; + + /** Size of the raw record */ + uint32_t RawRecordSize[PH_FRINFC_NDEFREG_MAX_RTD]; + + /** Pointer for usage by the registering entity. The software component that registers for + a specific RTD can specify this \b context pointer. With the help of the pointer + the component is able to resolve its own address, context or object, respectively.\n + \b Example: \ref grp_fri_nfc_ndef_reg "This SW component" is embedded into a C++ system + that has one object registered for a certain RTD. \ref grp_fri_nfc_ndef_reg "This library" + itself is written in C and therefore it requires a pure "C" callback that can be provided by + C++ through a \b static member function. The registering C++ object will consequently set the + \ref phFriNfc_NdefReg_CbParam_t::CbContext pointer to its \c this pointer. When the static + member function of the C++ class is called it immediately knows the instance and can + call into one of the C++ instance members again (\ref phFriNfc_NdefReg_CbParam_t::CbContext + needs to be casted back to the original C++ class type). + */ + void *CbContext; +} phFriNfc_NdefReg_CbParam_t; + + + +/** + * \brief Registration of a Callback - Parameter Structure + * + * This structure is used by the registering software. The registering listener has to \b initialise + * \b all \b members of the structure that are \b not \b internal. Members for \b internal use \b must + * \b not be set by the registering entity. Used by \ref phFriNfc_NdefReg_CbParam_t . + * + */ +typedef struct phFriNfc_NdefReg_Cb +{ + /** + * Number of array Positions. Each array position carries data specifying a RTD. The maximum number + * is \ref PH_FRINFC_NDEFREG_MAX_RTD . + * + * \li Needs to be set by the registering entity. + */ + uint8_t NumberOfRTDs; + /** + * The Type Name Format, according to the NDEF specification, see the NDEF Record (Tools) component. + * + * \li Needs to be set by the registering entity. + */ + uint8_t Tnf[PH_FRINFC_NDEFREG_MAX_RTD_REGISTERED]; + + /** + * Array of pointers to the individual RTD buffers. + * + * \li Needs to be set by the registering entity. + */ + uint8_t *NdefType[PH_FRINFC_NDEFREG_MAX_RTD_REGISTERED]; + + /** + * Array of length indicators of the RTD buffers. + * + * \li Needs to be set by the registering entity. + */ + uint8_t NdeftypeLength[PH_FRINFC_NDEFREG_MAX_RTD_REGISTERED]; + + /** + * Function pointer to the C-style function within the registering entity. + * + * \li Needs to be set by the registering entity. + */ + pphFriNfc_NdefReg_Cb_t NdefCallback; + + /** + * Context pointer of the registering entity (see \ref phFriNfc_NdefReg_CbParam_t). + * + * \li Needs to be set by the registering entity. + */ + void *CbContext; + + /** \internal + * This member is required by the library to link to the previous registered item. In case of the + * first item this member is NULL. + */ + struct phFriNfc_NdefReg_Cb *Previous; + /** \internal + * This member is required by the library to link to the next registered item. In case of the + * last item this member is NULL. + */ + struct phFriNfc_NdefReg_Cb *Next; +} phFriNfc_NdefReg_Cb_t; + + +/** + * \brief NFC NDEF Registry Compound + * + * The NDEF Registry Compound. This is the context structure of the NDEF Registry and + * Listener. + * + */ +typedef struct phFriNfc_NdefReg +{ + phFriNfc_NdefReg_Cb_t *NdefTypeList; /**< \internal List of Callback Structures (Listeners). */ + uint8_t *NdefData; /**< \internal Data to process. */ + uint32_t NdefDataLength; /**< \internal Length of the NDEF data. */ + uint8_t State; /**< \internal The state of the library. */ + uint8_t **NdefTypes; /**< \internal */ + + phFriNfc_NdefRecord_t *RecordsExtracted; /**< \internal */ + + phFriNfc_NdefReg_CbParam_t *CbParam; /**< \internal */ + + /* Harsha: Fix for 0000252: [JF] Buffer overshoot in phFriNfc_NdefRecord_GetRecords */ + uint8_t *IsChunked; /**< \internal Array of chunked flags */ + + /* Harsha: Fix for 0000252: [JF] Buffer overshoot + in phFriNfc_NdefRecord_GetRecords */ + uint32_t NumberOfRecords; /**< \internal Space available in NdefTypes + and IsChunked arrays */ + + /* Harsha: Fix for 0000243: [JF] phFriNfc_NdefReg_Process + won't parse correctly chunked records */ + /* Used to remember the last valid TNF */ + uint8_t validPreviousTnf; /**< \internal The last valid TNF that we had. */ + + uint32_t NumberOfNdefTypes;/**< \internal */ + + uint32_t RecordIndex; /**< \internal */ + + uint32_t RtdIndex; /**< \internal */ + + /* This flag is used to remember whether we have found a + TNF which matches with the Registered RTD */ + uint8_t MainTnfFound; /**< \internal */ + + /* This flag is used to tell whether the present record + being processed is newly extracted */ + uint8_t newRecordextracted;/**< \internal */ + +}phFriNfc_NdefReg_t; + + +#ifndef PH_FRINFC_EXCLUDE_FROM_TESTFW /* */ + +/** + * \brief Ndef Registry \b Reset function + * + * \copydoc page_reg + * + * Resets the component instance to the initial state and lets the component forget about + * the list of registered items. Does basic initialisation. + * + * \param[in] NdefReg Pointer to a valid or uninitialised instance of \ref phFriNfc_NdefReg_t . + * + * \param[in] NdefTypesarray Array of pointers to individual NDEF Types. Later used to store + * the NdefTypes + * + * \param[in] RecordsExtracted Pointer to an uninitialised instance of the NDEF Record structure + * that is later used to retrieve the record information. + * + * \param[in] CbParam Pointer to an un-initialised instance of \ref phFriNfc_NdefReg_CbParam_t + * structure, which is later used to store the callback parameters. + * + * \param[in] ChunkedRecordsarray Pointer to an array of bytes. Later used to store the + * Chunked record flags. + * + * \param[in] NumberOfRecords The number of members in the arrays NdefTypesarray and ChunkedRecordsarray. + * + * \retval NFCSTATUS_SUCCESS The operation has been successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * + * \note This function has to be called at the beginning, after creating an instance of + * \ref phFriNfc_NdefReg_t . + */ +NFCSTATUS phFriNfc_NdefReg_Reset(phFriNfc_NdefReg_t *NdefReg, + uint8_t **NdefTypesarray, + phFriNfc_NdefRecord_t *RecordsExtracted, + phFriNfc_NdefReg_CbParam_t *CbParam, + uint8_t *ChunkedRecordsarray, + uint32_t NumberOfRecords); + + +/** + * \brief Ndef Registry \b Add \b Callback function + * + * \copydoc page_reg + * + * Adds an NDEF type listener to the (internal) list of listeners: + * The registering caller or embedding SW must create an instance of \ref phFriNfc_NdefReg_Cb_t and + * hand the reference over to this function. The library does no allocation of memory. + * + * \param[in] NdefReg Pointer to an initialised instance of \ref phFriNfc_NdefReg_t that holds the + * context of the current component instance. + * + * \param[in] NdefCb Pointer to a caller-initialised structure describing the context of a Listener + * that requests its registration. + * + * \retval NFCSTATUS_SUCCESS The operation has been successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function + * is invalid. or Number of RTDs in NdefCb + * Structure is greater than + * PH_FRINFC_NDEFREG_MAX_RTD_REGISTERED + * + * \note This function returns once the listener is registered successfully or an error occurs. + */ +NFCSTATUS phFriNfc_NdefReg_AddCb(phFriNfc_NdefReg_t *NdefReg, + phFriNfc_NdefReg_Cb_t *NdefCb); + + +/** + * \brief NDEF Registry \b Remove \b Callback function + * + * \copydoc page_reg + * + * Removes a specific listener from the list: The element to remove is specified by its address. + * As the library does no de-allocation the caller of this function needs to take care of the + * correct disposal of the removed \ref phFriNfc_NdefReg_Cb_t instance once this function returns + * successfully. + * + * \param[in] NdefReg Pointer to an initialised instance of \ref phFriNfc_NdefReg_t that holds the + * context of this component. + * + * \param[in] NdefCb Pointer to a caller-initialised structure describing the context of a Listener + * that requests its un-registration. + * + * \retval NFCSTATUS_SUCCESS The operation has been successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_NODE_NOT_FOUND If the internal list is NULL or a list node is not found. + * + * \note This function returns once the listener is removed successfully or an error occurs. + */ +NFCSTATUS phFriNfc_NdefReg_RmCb(phFriNfc_NdefReg_t *NdefReg, + phFriNfc_NdefReg_Cb_t *NdefCb); + + + +/** + * \brief NDEF Registry \b Dispatch \b Packet function + * + * \copydoc page_reg + * + * The entry point for NDEF \b PACKETS retrieved from the Peer (Remote) Device: + * The function performs a reset of the state. It starts the action (state machine). For actual + * processing a periodic call of \ref phFriNfc_NdefReg_Process has to be done. This + * function parses the Message, isolates the record, looks for a match with the registered + * RTDs and if a match is found, it calls the related callback. This procedure is done for each + * record in the Message + * + * \param[in] NdefReg Pointer to an initialised instance of \ref phFriNfc_NdefReg_t that holds the + * context of this component. + * + * \param[in] PacketData Pointer to a NDEF Packet that has been received. + * + * \param[in] PacketDataLength Length of the NDEF packet to process. + * + * \retval NFCSTATUS_SUCCESS The operation has been successfully initiated. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * + * \note This function returns once the operation is initiated or an error occurs. + * + */ +NFCSTATUS phFriNfc_NdefReg_DispatchPacket(phFriNfc_NdefReg_t *NdefReg, + uint8_t *PacketData, + uint16_t PacketDataLength); + + +/** + * \brief NDEF Registry \b Dispatch \b Record function + * + * \copydoc page_reg + * + * The entry point for NDEF \b RECORDS retrieved from the Peer (Remote) Device: + * The function performs a reset of the state. It starts the action (state machine). For actual + * processing a periodic call of \ref phFriNfc_NdefReg_Process has to be done. This + * function compares the given record with the registered RTDs and if a match is found it calls + * the related callback. + * + * \param[in] NdefReg Pointer to an initialised instance of \ref phFriNfc_NdefReg_t that holds the + * context of this component. + * + * \param[in] RecordsExtracted Pointer to a NDEF Record that has been received. + * + * \retval NFCSTATUS_SUCCESS The operation has been successfully initiated. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * + * \note This function returns once the process is initiated or an error occurs. + */ +NFCSTATUS phFriNfc_NdefReg_DispatchRecord(phFriNfc_NdefReg_t *NdefReg, + phFriNfc_NdefRecord_t *RecordsExtracted); + + +/** + * \brief NDEF Registry \b Process function + * + * \copydoc page_reg + * + * Processing function, needed to avoid long blocking and to give control to other parts of the software + * between the internal dispatching of data. + * The function needs to be called during processing, within a message loop or a simple loop until its + * return value tells that it has finished. No State reset is performed during operation. + * + * \param NdefReg Pointer to a valid instance of the \ref phFriNfc_NdefReg_t structure describing + * the component context. + * + * \param Status Pointer to a variable receiving the final result of the NDEF data processing operation. + * There are the following values: + * \li NFCSTATUS_SUCCESS The operation has been successful. + * \li NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \li NFCSTATUS_NODE_NOT_FOUND If the List is NULL or Node is not found. + * \li NFCSTATUS_INVALID_DEVICE_REQUEST State other than the specified in the File. + * + * \retval FALSE Processing has finished, no more function call is needed. + * \retval TRUE Processing is ongoing, the function must be called again. + */ +uint8_t phFriNfc_NdefReg_Process(phFriNfc_NdefReg_t *NdefReg, + NFCSTATUS *Status); + +/*@}*/ /* defgroup */ + +#endif /* PH_FRINFC_EXCLUDE_FROM_TESTFW */ + +#endif /* PHFRINFCNDEFREG_H */ + diff --git a/libnfc-nxp/phFriNfc_OvrHal.c b/libnfc-nxp/phFriNfc_OvrHal.c new file mode 100644 index 0000000..07942aa --- /dev/null +++ b/libnfc-nxp/phFriNfc_OvrHal.c @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc_OvrHal.c + * \brief Overlapped HAL + * + * Project: NFC-FRI + * Creator: Gerald Kersch + * + * $Date: Wed May 5 10:47:27 2010 $ + * Changed by: $Author: ing02260 $ + * $Revision: 1.37 $ + * $Aliases: NFC_FRI1.1_WK1017_R34_3,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#include +#include +#include +#include + + +#ifdef PHFRINFC_OVRHAL_MOCKUP /* */ +//#include +#endif /* PHFRINFC_OVRHAL_MOCKUP */ +/* +* + +*/ +#define MAX_MIF_PACKET_LEN 0x0FU +#define MIFARE_PLUS_UID_INDEX_TO_COPY 0x03U +#define MIFARE_PLUS_UID_LENGTH 0x07U +#define MIFARE_CLASSIC_UID_LENGTH 0x04U +#define MIFARE_UID_LEN_TO_COPY 0x04U + +static void phFriNfc_OvrHal_CB_Send(void *context, + NFCSTATUS status); +static void phFriNfc_OvrHal_CB_Receive(void *context, + phNfc_sData_t *pDataInfo, + NFCSTATUS status); +static void phFriNfc_OvrHal_CB_Transceive(void *context, + phHal_sRemoteDevInformation_t *RemoteDevHandle, + phNfc_sData_t *pRecvdata, + NFCSTATUS status + ); +static void phFriNfc_OvrHal_CB_ConnectDisconnect(void *context, + phHal_sRemoteDevInformation_t *RemoteDevHandle, + NFCSTATUS status + ); + +static void phFriNfc_OvrHal_SetComplInfo(phFriNfc_OvrHal_t *OvrHal, + phFriNfc_CplRt_t *CompletionInfo, + uint8_t Operation); + +NFCSTATUS phFriNfc_OvrHal_Transceive(phFriNfc_OvrHal_t *OvrHal, + phFriNfc_CplRt_t *CompletionInfo, + phHal_sRemoteDevInformation_t *RemoteDevInfo, + phHal_uCmdList_t Cmd, + phHal_sDepAdditionalInfo_t *DepAdditionalInfo, + uint8_t *SendBuf, + uint16_t SendLength, + uint8_t *RecvBuf, + uint16_t *RecvLength) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + uint8_t i = 0; + uint32_t length = SendLength; + + /* To remove "warning (VS C4100) : unreferenced formal parameter" */ + PHNFC_UNUSED_VARIABLE(DepAdditionalInfo); + + /* Check the Input Parameters */ + if ((NULL == OvrHal) || (NULL == CompletionInfo) || (NULL == RemoteDevInfo) + || (NULL == (void*)SendBuf) || (NULL == RecvBuf) || (NULL == RecvLength) + || ((phHal_eJewel_PICC != RemoteDevInfo->RemDevType) && (0 == SendLength))) + + { + status = PHNFCSTVAL(CID_FRI_NFC_OVR_HAL, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* 16 is the maximum data, that can be sent to the mifare standard */ + static uint8_t mif_send_buf[MAX_MIF_PACKET_LEN] = {0}; + /* Populate the Transfer info structure */ + OvrHal->TranceiveInfo.cmd = Cmd; + + /* Populate the Send Buffer Info */ + if((phHal_eMifare_PICC == RemoteDevInfo->RemDevType) + || (phHal_eISO14443_3A_PICC == RemoteDevInfo->RemDevType)) + { + OvrHal->TranceiveInfo.addr = SendBuf[i++]; + length = (SendLength - i); + + if ((phHal_eMifareAuthentA == Cmd.MfCmd) + || (phHal_eMifareAuthentB == Cmd.MfCmd)) + { + uint8_t uid_index = 0; + /* Authentication requires UID in the send buffer */ + uint8_t uid_len = + RemoteDevInfo->RemoteDevInfo.Iso14443A_Info.UidLength; + OvrHal->TranceiveInfo.sSendData.buffer = mif_send_buf; + + switch (uid_len) + { + case MIFARE_PLUS_UID_LENGTH: + { + uid_index = MIFARE_PLUS_UID_INDEX_TO_COPY; + uid_len = MIFARE_UID_LEN_TO_COPY; + break; + } + + case MIFARE_CLASSIC_UID_LENGTH: + { + uid_index = 0; + break; + } + + default: + { + status = PHNFCSTVAL (CID_FRI_NFC_OVR_HAL, + NFCSTATUS_READ_FAILED); + break; + } + } + + if (NFCSTATUS_PENDING == status) + { + /* copy uid to the send buffer for the authentication */ + (void)memcpy ((void *)mif_send_buf, + (void *)&RemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Uid[uid_index], + uid_len); + + (void)memcpy((mif_send_buf + uid_len), &(SendBuf[i]), length); + length += uid_len; + } + } + else + { + OvrHal->TranceiveInfo.sSendData.buffer = &SendBuf[i++]; + } + OvrHal->TranceiveInfo.sSendData.length = length; + } + else + { + OvrHal->TranceiveInfo.sSendData.buffer = &SendBuf[i++]; + OvrHal->TranceiveInfo.sSendData.length = length; + } + + if (NFCSTATUS_PENDING == status) + { + /* Populate the Receive buffer */ + OvrHal->TranceiveInfo.sRecvData.buffer = RecvBuf; + OvrHal->TranceiveInfo.sRecvData.length = *RecvLength; + OvrHal->pndef_recv_length = RecvLength; + phFriNfc_OvrHal_SetComplInfo(OvrHal,CompletionInfo, PH_FRINFC_OVRHAL_TRX); + + /* Call the HAL 4.0 Transceive Function */ + status = phHal4Nfc_Transceive (OvrHal->psHwReference, + &OvrHal->TranceiveInfo, RemoteDevInfo, + phFriNfc_OvrHal_CB_Transceive, (void *)OvrHal); + } + + } + return status; + +} + +NFCSTATUS phFriNfc_OvrHal_Receive(phFriNfc_OvrHal_t *OvrHal, + phFriNfc_CplRt_t *CompletionInfo, + phHal_sRemoteDevInformation_t *RemoteDevInfo, + uint8_t *RecvBuf, + uint16_t *RecvLength) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + /* Check the Input Parameters */ + if( (NULL==OvrHal) || (NULL==CompletionInfo) || (NULL==RemoteDevInfo) + || (NULL==RecvBuf) || (NULL==RecvLength) ) + { + status = PHNFCSTVAL(CID_FRI_NFC_OVR_HAL ,NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Get the remote dev type */ + OvrHal->TransactInfo.remotePCDType = RemoteDevInfo->RemDevType; + /* Save the receive buffer for use in callback */ + OvrHal->sReceiveData.buffer = RecvBuf; + OvrHal->sReceiveData.length = *RecvLength; + + OvrHal->pndef_recv_length = RecvLength; + + /* Set the callback */ + phFriNfc_OvrHal_SetComplInfo(OvrHal, CompletionInfo, PH_FRINFC_OVRHAL_RCV); + + /* Call the HAL 4.0 Receive Function */ + status = phHal4Nfc_Receive( OvrHal->psHwReference, + &OvrHal->TransactInfo, + phFriNfc_OvrHal_CB_Receive, + (void *)OvrHal); + } + return status; +} + +NFCSTATUS phFriNfc_OvrHal_Send(phFriNfc_OvrHal_t *OvrHal, + phFriNfc_CplRt_t *CompletionInfo, + phHal_sRemoteDevInformation_t *RemoteDevInfo, + uint8_t *SendBuf, + uint16_t SendLength) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + /* Check the Input Parameters */ + if( (NULL==OvrHal) || (NULL==CompletionInfo) || (NULL==RemoteDevInfo) || (NULL==SendBuf) ) + { + status = PHNFCSTVAL(CID_FRI_NFC_OVR_HAL ,NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Get the remote dev type */ + OvrHal->TransactInfo.remotePCDType = RemoteDevInfo->RemDevType; + /* Save the receive buffer for use in callback */ + OvrHal->sSendData.buffer = SendBuf; + OvrHal->sSendData.length = SendLength; + + /* Set the callback */ + phFriNfc_OvrHal_SetComplInfo(OvrHal, CompletionInfo, PH_FRINFC_OVRHAL_SND); + + /* Call the HAL 4.0 Receive Function */ + status = phHal4Nfc_Send( OvrHal->psHwReference, + &OvrHal->TransactInfo, + OvrHal->sSendData, + phFriNfc_OvrHal_CB_Send, + (void *)OvrHal); + } + return status; +} + +#ifndef PH_FRINFC_MAP_MIFARESTD_DISABLED + + +NFCSTATUS phFriNfc_OvrHal_Reconnect(phFriNfc_OvrHal_t *OvrHal, + phFriNfc_CplRt_t *CompletionInfo, + phHal_sRemoteDevInformation_t *RemoteDevInfo) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + /* Check the Input Parameters */ + if((NULL == OvrHal) || (NULL == CompletionInfo) || (NULL == RemoteDevInfo)) + { + status = PHNFCSTVAL(CID_FRI_NFC_OVR_HAL ,NFCSTATUS_INVALID_PARAMETER); + } + else + { + phFriNfc_OvrHal_SetComplInfo(OvrHal, CompletionInfo, PH_FRINFC_OVRHAL_DIS); + + status = phHal4Nfc_Connect( + OvrHal->psHwReference, + RemoteDevInfo, + phFriNfc_OvrHal_CB_ConnectDisconnect, + (void *)OvrHal); + } + + return status; +} + + + +NFCSTATUS phFriNfc_OvrHal_Connect(phFriNfc_OvrHal_t *OvrHal, + phFriNfc_CplRt_t *CompletionInfo, + phHal_sRemoteDevInformation_t *RemoteDevInfo, + phHal_sDevInputParam_t *DevInputParam) +{ + NFCSTATUS status = NFCSTATUS_PENDING; + + /* Check the Input Parameters */ + if((NULL == OvrHal) || (NULL == CompletionInfo) || (NULL == RemoteDevInfo) || + (NULL == DevInputParam)) + { + status = PHNFCSTVAL(CID_FRI_NFC_OVR_HAL ,NFCSTATUS_INVALID_PARAMETER); + } + else + { + phFriNfc_OvrHal_SetComplInfo(OvrHal, CompletionInfo, PH_FRINFC_OVRHAL_CON); + + status = phHal4Nfc_Connect( + OvrHal->psHwReference, + RemoteDevInfo, + phFriNfc_OvrHal_CB_ConnectDisconnect, + (void *)OvrHal + ); + } + + return status; +} + +#endif + +static void phFriNfc_OvrHal_CB_Transceive(void *context, + phHal_sRemoteDevInformation_t *RemoteDevHandle, + phNfc_sData_t *pRecvdata, + NFCSTATUS status + ) + +{ + phFriNfc_OvrHal_t *OvrHal = (phFriNfc_OvrHal_t *)context; + + if (NULL != OvrHal) + { + if(NULL != pRecvdata && OvrHal->TranceiveInfo.sRecvData.buffer != NULL && pRecvdata->buffer != NULL) + { + /* Work-around for the NFCIP Tranceive API */ + if (OvrHal->TranceiveInfo.sRecvData.buffer != pRecvdata->buffer) + { + memcpy(OvrHal->TranceiveInfo.sRecvData.buffer, pRecvdata->buffer, pRecvdata->length); + } + if (OvrHal->pndef_recv_length != NULL) + { + *OvrHal->pndef_recv_length = (uint16_t) pRecvdata->length; + } + } + + if (NULL != OvrHal->TemporaryCompletionInfo.CompletionRoutine) + { + OvrHal->TemporaryCompletionInfo.CompletionRoutine( + OvrHal->TemporaryCompletionInfo.Context, + status); + } + } +} + +static void phFriNfc_OvrHal_CB_Send(void *context, + NFCSTATUS status) +{ + phFriNfc_OvrHal_t *OvrHal = (phFriNfc_OvrHal_t *)context; + + if (NULL != OvrHal) + { + if (NULL != OvrHal->TemporarySndCompletionInfo.CompletionRoutine) + { + OvrHal->TemporarySndCompletionInfo.CompletionRoutine( + OvrHal->TemporarySndCompletionInfo.Context, + status); + } + } +} + +static void phFriNfc_OvrHal_CB_Receive(void *context, + phNfc_sData_t *pDataInfo, + NFCSTATUS status) +{ + phFriNfc_OvrHal_t *OvrHal = (phFriNfc_OvrHal_t *)context; + + if (NULL != OvrHal) + { + /* Copy the received buffer */ + if(NULL != pDataInfo && OvrHal->sReceiveData.buffer != NULL && pDataInfo->buffer != NULL) + { + memcpy(OvrHal->sReceiveData.buffer, pDataInfo->buffer, pDataInfo->length); + *OvrHal->pndef_recv_length = (uint16_t) pDataInfo->length; + } + + if (NULL != OvrHal->TemporaryRcvCompletionInfo.CompletionRoutine) + { + OvrHal->TemporaryRcvCompletionInfo.CompletionRoutine( + OvrHal->TemporaryRcvCompletionInfo.Context, + status); + } + } +} + +static void phFriNfc_OvrHal_CB_ConnectDisconnect(void *context, + phHal_sRemoteDevInformation_t *RemoteDevHandle, + NFCSTATUS status + ) + +{ + phFriNfc_OvrHal_t *OvrHal = (phFriNfc_OvrHal_t *)context; + + if (NULL != OvrHal) + { + if (RemoteDevHandle == NULL) + { + status = NFCSTATUS_FAILED; + } + + OvrHal->TemporaryCompletionInfo.CompletionRoutine( + OvrHal->TemporaryCompletionInfo.Context, status); + } + +} + +static void phFriNfc_OvrHal_SetComplInfo(phFriNfc_OvrHal_t *OvrHal, + phFriNfc_CplRt_t *CompletionInfo, + uint8_t Operation) + +{ + OvrHal->Operation = Operation; + switch(Operation) + { + case PH_FRINFC_OVRHAL_RCV: + { + OvrHal->TemporaryRcvCompletionInfo.CompletionRoutine = CompletionInfo->CompletionRoutine; + OvrHal->TemporaryRcvCompletionInfo.Context = CompletionInfo->Context; + break; + } + case PH_FRINFC_OVRHAL_SND: + { + OvrHal->TemporarySndCompletionInfo.CompletionRoutine = CompletionInfo->CompletionRoutine; + OvrHal->TemporarySndCompletionInfo.Context = CompletionInfo->Context; + break; + } + default: + { + OvrHal->TemporaryCompletionInfo.CompletionRoutine = CompletionInfo->CompletionRoutine; + OvrHal->TemporaryCompletionInfo.Context = CompletionInfo->Context; + break; + } + } +} diff --git a/libnfc-nxp/phFriNfc_OvrHal.h b/libnfc-nxp/phFriNfc_OvrHal.h new file mode 100644 index 0000000..2b9fdfc --- /dev/null +++ b/libnfc-nxp/phFriNfc_OvrHal.h @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_OvrHal.h + * \brief Overlapped HAL + * + * Project: NFC-FRI + * Creator: Gerald Kersch + * + * $Date: Tue May 19 10:30:18 2009 $ + * Changed by: $Author: ing07336 $ + * $Revision: 1.13 $ + * $Aliases: NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PHFRINFC_OVRHAL_H +#define PHFRINFC_OVRHAL_H + +#include +#ifdef PH_HAL4_ENABLE +#include +#else +#include +#endif +#include +#include + + +/** + * \name Overlapped HAL + * + * File: \ref phFriNfc_OvrHal.h + * + */ +/*@{*/ +#define PH_FRINFC_OVRHAL_FILEREVISION "$Revision: 1.13 $" /** \ingroup grp_file_attributes */ +#define PH_FRINFC_OVRHAL_FILEALIASES "$Aliases: NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /** \ingroup grp_file_attributes */ +/*@}*/ + + +/** \defgroup grp_fri_nfc_ovr_hal Overlapped HAL + * + * This component encapsulates the HAL functions, suited for the NFC-FRI overlapped way of operation. The HAL itself + * is used as it is, wrapped by this component. The purpose of the wrapper is to de-couple a blocking I/O, as used by + * the HAL, from the overlapped I/O operation mode the FRI is using. + * + * \par Device Based Functions + * NFC Device Based Functions are used to address the NFC device (local device) directly. + * These are all functions that use no Remote Device Information. + * + * \par Connection Based Functions + * Connection Based Functions use the Remote Device Information to describe a connection + * to a certain Remote Device. + * + * \par Component Instance Sharing + * FRI components accessing one NFC device share one instance of the Overlapped HAL. Therefore + * each calling FRI component must specify - together with the call - where to deliver the + * response of the overlapped operation. + * + * \par Lowest Layer + * The Overlapped HAL represents the NFC Device, the lowest layer of the FRI components. + * + * \par Completion Forced + * The \b HAL \b functions (and underlying functions) of this library must complete before a new call can + * be issued. No HAL operation must be pending. + * + */ +/*@{*/ + +/** + * \name OVR HAL Constants + */ +/*@{*/ +#define PH_FRINFC_OVRHAL_MAX_NUM_MOCKUP_PARAM 255 /**< Number of mockup indices that are are prepared. */ +/* Harsha: changed from 48 to 128, to work with the Mifare 4k TCs */ +#define PH_FRINFC_OVRHAL_MAX_NUM_MOCKUP_RDI 4 /**< Max. number of mockup RDIs. */ +#define PH_FRINFC_OVRHAL_MAX_TEST_DELAY 1000 /**< Max. test delay in OVR HAL. */ +#define PH_FRINFC_OVRHAL_POLL_PAYLOAD_LEN 5 /**< Length of the POLL payload. */ /* @GK/5.6.06 */ +/*@}*/ +/*@}*/ /* defgroup... */ + +/** \defgroup grp_ovr_hal_cmd Overlapped HAL Command List + * \ingroup grp_fri_nfc_ovr_hal + * These are the command definitions for the Overlapped HAL. They are used internally by the + * implementation of the component. + */ +/*@{*/ +#define PH_FRINFC_OVRHAL_NUL (0) /**< \brief We're in NO command */ + +#define PH_FRINFC_OVRHAL_ENU (1) /**< \brief Enumerate */ +#define PH_FRINFC_OVRHAL_OPE (2) /**< \brief Open */ +#define PH_FRINFC_OVRHAL_CLO (3) /**< \brief Close */ +#define PH_FRINFC_OVRHAL_GDC (4) /**< \brief Get Dev Caps */ +#define PH_FRINFC_OVRHAL_POL (5) /**< \brief Poll */ +#define PH_FRINFC_OVRHAL_CON (6) /**< \brief Connect */ +#define PH_FRINFC_OVRHAL_DIS (7) /**< \brief Disconnect */ +#define PH_FRINFC_OVRHAL_TRX (8) /**< \brief Transceive */ +#define PH_FRINFC_OVRHAL_STM (9) /**< \brief Start Target Mode */ +#define PH_FRINFC_OVRHAL_SND (10) /**< \brief Send */ +#define PH_FRINFC_OVRHAL_RCV (11) /**< \brief Receive */ +#define PH_FRINFC_OVRHAL_IOC (12) /**< \brief IOCTL */ + +#define PH_FRINFC_OVRHAL_TST (255) /**< \brief OVR HAL test-related command */ + +/** \ingroup grp_fri_nfc_ovr_hal + * \brief Post Message Function for Overlapped HAL + * + * \copydoc page_reg + * + * This is required by the Overlapped HAL in order to call the blocking (original HAL) in another + * thread. This function is required in addition to \ref pphFriNfc_OvrHalPresetParm to be + * implemented in the integrating software. + * + * \par First Parameter: Context of the Integration + * Set to the value, the Integration has provided when initialising this component. + */ +typedef void (*pphFriNfc_OvrHalPostMsg_t)(void*); + +/** \ingroup grp_fri_nfc_ovr_hal + * \brief Abort Function (to be defined/implemented by the Integration) + * + * \copydoc page_reg + * + * This is required by the Overlapped HAL in order abort a pending Overlapped HAL operation. This funtion will be + * internally called by the \ref phFriNfc_OvrHal_Abort function. + * + * \par First Parameter: Context of the Integration + * Set to the value, the Integration has provided when initialising this component. + * + * \par Return value: + * As defined by the integration + */ +typedef NFCSTATUS (*pphFriNfc_OvrHalAbort_t)(void*); + + +typedef void (*pphOvrHal_CB_t) (phHal_sRemoteDevInformation_t *RemoteDevHandle, + NFCSTATUS status, + phNfc_sData_t *pRecvdata, + void *context); + +/** \ingroup grp_fri_nfc_ovr_hal + * \brief Preset Function to prepare the parameters in the HAL + * + * \copydoc page_reg + * + * This function (pointer) is called by the Overlapped HAL to prepare the function call parameters + * in the HAL before posting the start message. As we have an asynchronously running FRI, but a + * synchronous HAL, the calls need to be "decoupled". This means, the HAL needs to run under + * a different time-base (or thread/task etc.). The consequence is that the data exchange between + * FRI and HAL must be done as required by the integration/system itself. The declaration + * of the function pointer allows for the integrating software to implement whatever functionality + * is required to convey the data. + * + * + * \par First Parameter + * Context of the Integration Set to the value, the Integration has provided when initialising + * this component. + * + * \par Second Parameter: + * \b HAL \b Command, as defined in the module \ref grp_ovr_hal_cmd. + * + * \par Third Parameter: + * \b Pointers to a specific structure containing the parameters of the HAL functions to be + * called. + * + * \par Forth parameter: + * Immediate Operation result (not the result of the HAL operation). Usually this is + * \ref NFCSTATUS_PENDING (for a successfully triggered HAL I/O or an error value that is + * returned by the HAL immediately, such as \ref NFCSTATUS_INVALID_PARAMETER. + * + * \par Return value: + * A boolean (\ref grp_special_conventions) value. The integration implementation must ensure + * that, if the function \b succeeds, the return value is \b TRUE, otherwise false. + */ +typedef uint8_t (*pphFriNfc_OvrHalPresetParm)(void*, uint16_t, void*, NFCSTATUS*); + +/** \ingroup grp_fri_nfc_ovr_hal + * \brief Overlapped HAL Context + * + * The Overlapped HAL structure. This structure contains the HAL "context" that + * is required by the FRI on a connection basis. Please note that the Overlapped HAL is + * a shared component, requiring a special completion notification mechanism. + * Read more in the description of this component. + * + */ +typedef struct phFriNfc_OvrHal +{ + /** Currently active operation of the component. If no operation is pending, the content of this member is + * \ref PH_FRINFC_OVRHAL_NUL . The component refuses a new call if the contenet is different, namely one + * of the other values defined in \ref grp_ovr_hal_cmd . + */ + uint8_t Operation; + + /** The \b temporary pointer to the completion routine information. The HAL needs - for each call - to be told about the + * completion routine of the upper (calling) component. This major difference to other components is because + * some functions of the HAL are connection-based and some are not. Moreover it is because the HAL is shared + * among the FRI components. So, with a variety of potential callers it is required for each caller to instruct + * the HAL about the "delivery" address of the response for each individual call. + */ + phFriNfc_CplRt_t TemporaryCompletionInfo; + phFriNfc_CplRt_t TemporaryRcvCompletionInfo; + phFriNfc_CplRt_t TemporarySndCompletionInfo; + + /** Points to a function within the Integration that presets the parameters for the actual + * HAL call. + */ + pphFriNfc_OvrHalPresetParm Presetparameters; + + /** Posts a message to the actual HAL integration, starting a NFC HAL I/O with the pre-set + * parameters. + */ + pphFriNfc_OvrHalPostMsg_t PostMsg; + + /** The context of the Integration (the SW around this component). This is needed to let + * the Overlapped HAL access the Integration's functionality to post a message to another + * thread. + */ + void *IntegrationContext; + + /** Device reference returned during enumeration: This has to be filled in by the integrating software after + a call to the HAL Enumerate function (not contained in the overlapped HAl API). */ + phHal_sHwReference_t *psHwReference; + + /** This flag is set by the ABORT function. The OVR HAL then does no I/O to the real HAL + * or to the mockup any more but just completed with the ABORTED status. + */ + uint8_t OperationAborted; + + /** Abort function to be implemented by the integration. This parameter can be (optionally) initialized + * via the call of \ref phFriNfc_OvrHal_Reset_Abort function. + * If it is not NULL, the function pointed by \ref will be internally called by the \ref phFriNfc_OvrHal_Abort function. + */ + pphFriNfc_OvrHalAbort_t AbortIntegrationFunction; + + /** Integration-defined Context passed as a parameter of the \ref AbortIntegrationFunction. + */ + void* AbortIntegrationContext; + + void* OvrCompletion; + + phHal_sTransceiveInfo_t TranceiveInfo; + + /** TODO + */ + phNfc_sData_t sReceiveData; + + /** TODO + */ + phNfc_sData_t sSendData; + + /** TODO + */ + phHal4Nfc_TransactInfo_t TransactInfo; + + uint16_t *pndef_recv_length; +} phFriNfc_OvrHal_t; + +/** + * \ingroup grp_fri_nfc_ovr_hal + * + * \brief Transceive Data to/from a Remote Device + * + * \copydoc page_ovr + * + * \param[in] OvrHal Component Context. + * \param[in] CompletionInfo \copydoc phFriNfc_OvrHal_t::TemporaryCompletionInfo + * \param[in,out] RemoteDevInfo Remote Device Information. + * \param[in] Cmd Command to perform. + * \param[out] DepAdditionalInfo Protocol Information. + * \param[in] SendBuf Pointer to the data to send. + * \param[in] SendLength Length, in bytes, of the Send Buffer. + * \param[out] RecvBuf Pointer to the buffer that receives the data. + * \param[in,out] RecvLength Length, in bytes, of the received data. + * + * \retval NFCSTATUS_PENDING The operation is pending. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST \copydoc phFriNfc_OvrHal_t::Operation + * \retval NFCSTATUS_SUCCESS Success. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters could not be + * properly interpreted. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + * \note Please refer to HAL Transceive for a detailed description of the + * underlying function and the propagated parameters. + * + */ + +NFCSTATUS phFriNfc_OvrHal_Transceive(phFriNfc_OvrHal_t *OvrHal, + phFriNfc_CplRt_t *CompletionInfo, + phHal_sRemoteDevInformation_t *RemoteDevInfo, + phHal_uCmdList_t Cmd, + phHal_sDepAdditionalInfo_t *DepAdditionalInfo, + uint8_t *SendBuf, + uint16_t SendLength, + uint8_t *RecvBuf, + uint16_t *RecvLength); + +/** + * \ingroup grp_fri_nfc_ovr_hal + * + * \brief TODO + * + */ +NFCSTATUS phFriNfc_OvrHal_Receive(phFriNfc_OvrHal_t *OvrHal, + phFriNfc_CplRt_t *CompletionInfo, + phHal_sRemoteDevInformation_t *RemoteDevInfo, + uint8_t *RecvBuf, + uint16_t *RecvLength); + +/** + * \ingroup grp_fri_nfc_ovr_hal + * + * \brief TODO + * + */ +NFCSTATUS phFriNfc_OvrHal_Send(phFriNfc_OvrHal_t *OvrHal, + phFriNfc_CplRt_t *CompletionInfo, + phHal_sRemoteDevInformation_t *RemoteDevInfo, + uint8_t *SendBuf, + uint16_t SendLength); + + +NFCSTATUS phFriNfc_OvrHal_Reconnect(phFriNfc_OvrHal_t *OvrHal, + phFriNfc_CplRt_t *CompletionInfo, + phHal_sRemoteDevInformation_t *RemoteDevInfo); + + +NFCSTATUS phFriNfc_OvrHal_Connect(phFriNfc_OvrHal_t *OvrHal, + phFriNfc_CplRt_t *CompletionInfo, + phHal_sRemoteDevInformation_t *RemoteDevInfo, + phHal_sDevInputParam_t *DevInputParam); + +#endif diff --git a/libnfc-nxp/phFriNfc_OvrHalCmd.h b/libnfc-nxp/phFriNfc_OvrHalCmd.h new file mode 100644 index 0000000..52e126c --- /dev/null +++ b/libnfc-nxp/phFriNfc_OvrHalCmd.h @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phFriNfc_OvrHalCmd.h + * \brief Overlapped HAL + * + * Project: NFC-FRI + * + * $Date: Fri Oct 5 10:09:57 2007 $ + * $Author: frq05303 $ + * $Revision: 1.1 $ + * $Aliases: NFC_FRI1.1_WK826_PREP1,NFC_FRI1.1_WK826_R1,NFC_FRI1.1_WK826_R2,NFC_FRI1.1_WK830_PREP1,NFC_FRI1.1_WK830_PREP2,NFC_FRI1.1_WK830_R5_1,NFC_FRI1.1_WK830_R5_2,NFC_FRI1.1_WK830_R5_3,NFC_FRI1.1_WK832_PREP1,NFC_FRI1.1_WK832_PRE2,NFC_FRI1.1_WK832_PREP2,NFC_FRI1.1_WK832_PREP3,NFC_FRI1.1_WK832_R5_1,NFC_FRI1.1_WK832_R6_1,NFC_FRI1.1_WK834_PREP1,NFC_FRI1.1_WK834_PREP2,NFC_FRI1.1_WK834_R7_1,NFC_FRI1.1_WK836_PREP1,NFC_FRI1.1_WK836_R8_1,NFC_FRI1.1_WK838_PREP1,NFC_FRI1.1_WK838_R9_PREP2,NFC_FRI1.1_WK838_R9_1,NFC_FRI1.1_WK840_R10_PREP1,NFC_FRI1.1_WK840_R10_1,NFC_FRI1.1_WK842_R11_PREP1,NFC_FRI1.1_WK842_R11_PREP2,NFC_FRI1.1_WK842_R11_1,NFC_FRI1.1_WK844_PREP1,NFC_FRI1.1_WK844_R12_1,NFC_FRI1.1_WK846_PREP1,NFC_FRI1.1_WK846_R13_1,NFC_FRI1.1_WK848_PREP1,NFC_FRI1.1_WK848_R14_1,NFC_FRI1.1_WK850_PACK1,NFC_FRI1.1_WK851_PREP1,NFC_FRI1.1_WK850_R15_1,NFC_FRI1.1_WK902_PREP1,NFC_FRI1.1_WK902_R16_1,NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1 $ + * + */ + +#ifndef PHFRINFC_OVRHALCMD_H +#define PHFRINFC_OVRHALCMD_H + +#include + +/** + * \name Overlapped HAL + * + * File: \ref phFriNfc_OvrHalCmd.h + * + */ +/*@{*/ +#define PH_FRINFC_OVRHALCMD_FILEREVISION "$Revision: 1.1 $" /** \ingroup grp_file_attributes */ +#define PH_FRINFC_OVRHALCMD_FILEALIASES "$Aliases: NFC_FRI1.1_WK826_PREP1,NFC_FRI1.1_WK826_R1,NFC_FRI1.1_WK826_R2,NFC_FRI1.1_WK830_PREP1,NFC_FRI1.1_WK830_PREP2,NFC_FRI1.1_WK830_R5_1,NFC_FRI1.1_WK830_R5_2,NFC_FRI1.1_WK830_R5_3,NFC_FRI1.1_WK832_PREP1,NFC_FRI1.1_WK832_PRE2,NFC_FRI1.1_WK832_PREP2,NFC_FRI1.1_WK832_PREP3,NFC_FRI1.1_WK832_R5_1,NFC_FRI1.1_WK832_R6_1,NFC_FRI1.1_WK834_PREP1,NFC_FRI1.1_WK834_PREP2,NFC_FRI1.1_WK834_R7_1,NFC_FRI1.1_WK836_PREP1,NFC_FRI1.1_WK836_R8_1,NFC_FRI1.1_WK838_PREP1,NFC_FRI1.1_WK838_R9_PREP2,NFC_FRI1.1_WK838_R9_1,NFC_FRI1.1_WK840_R10_PREP1,NFC_FRI1.1_WK840_R10_1,NFC_FRI1.1_WK842_R11_PREP1,NFC_FRI1.1_WK842_R11_PREP2,NFC_FRI1.1_WK842_R11_1,NFC_FRI1.1_WK844_PREP1,NFC_FRI1.1_WK844_R12_1,NFC_FRI1.1_WK846_PREP1,NFC_FRI1.1_WK846_R13_1,NFC_FRI1.1_WK848_PREP1,NFC_FRI1.1_WK848_R14_1,NFC_FRI1.1_WK850_PACK1,NFC_FRI1.1_WK851_PREP1,NFC_FRI1.1_WK850_R15_1,NFC_FRI1.1_WK902_PREP1,NFC_FRI1.1_WK902_R16_1,NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1 $" /** \ingroup grp_file_attributes */ +/*@}*/ + +/** \defgroup grp_ovr_hal_cmd Overlapped HAL Command List + * \ingroup grp_fri_nfc_ovr_hal + * These are the command definitions for the Overlapped HAL. They are used internally by the + * implementation of the component. + */ +/*@{*/ +#define PH_FRINFC_OVRHALCMD_NUL (0) /**< \brief We're in NO command */ + +#define PH_FRINFC_OVRHALCMD_ENU (1) /**< \brief Enumerate */ +#define PH_FRINFC_OVRHALCMD_OPE (2) /**< \brief Open */ +#define PH_FRINFC_OVRHALCMD_CLO (3) /**< \brief Close */ +#define PH_FRINFC_OVRHALCMD_GDC (4) /**< \brief Get Dev Caps */ +#define PH_FRINFC_OVRHALCMD_POL (5) /**< \brief Poll */ +#define PH_FRINFC_OVRHALCMD_CON (6) /**< \brief Connect */ +#define PH_FRINFC_OVRHALCMD_DIS (7) /**< \brief Disconnect */ +#define PH_FRINFC_OVRHALCMD_TRX (8) /**< \brief Transceive */ +#define PH_FRINFC_OVRHALCMD_STM (9) /**< \brief Start Target Mode */ +#define PH_FRINFC_OVRHALCMD_SND (10) /**< \brief Send */ +#define PH_FRINFC_OVRHALCMD_RCV (11) /**< \brief Receive */ +#define PH_FRINFC_OVRHALCMD_IOC (12) /**< \brief IOCTL */ + +#define PH_FRINFC_OVRHALCMD_TST (255) /**< \brief OVR HAL test-related command */ + + +/** \brief Parameter compound internally used for testing purpose + * + */ +typedef struct phFriNfc_OvrHalCmdVoid +{ + void *Div; + NFCSTATUS Status; + uint32_t Delay; +} phFriNfc_OvrHalCmdVoid_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_Enumerate + * + */ +typedef struct phFriNfc_OvrHalCmdEnu +{ + phHal_sHwReference_t *HwReference; + uint8_t *pNbrOfDevDetected; +} phFriNfc_OvrHalCmdEnu_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_Open + * + */ +typedef struct phFriNfc_OvrHalCmdOpe +{ + phHal_sHwReference_t *psHwReference; +} phFriNfc_OvrHalCmdOpe_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_Close + * + */ +typedef struct phFriNfc_OvrHalCmdClo +{ + phHal_sHwReference_t *psHwReference; +} phFriNfc_OvrHalCmdClo_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_GetDeviceCapabilities + * + */ +typedef struct phFriNfc_OvrHalCmdGdc +{ + phHal_sHwReference_t *psHwReference; + phHal_sDeviceCapabilities_t *psDevCapabilities; +} phFriNfc_OvrHalCmdGdc_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_Poll + * + */ +typedef struct phFriNfc_OvrHalCmdPol +{ + phHal_sHwReference_t *psHwReference; + phHal_eOpModes_t *OpModes; + phHal_sRemoteDevInformation_t *psRemoteDevInfoList; + uint8_t *NbrOfRemoteDev; + phHal_sDevInputParam_t *psDevInputParam; +} phFriNfc_OvrHalCmdPol_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_Connect + * + */ +typedef struct phFriNfc_OvrHalCmdCon +{ + phHal_sHwReference_t *psHwReference; + phHal_eOpModes_t OpMode; + phHal_sRemoteDevInformation_t *psRemoteDevInfo; + phHal_sDevInputParam_t *psDevInputParam; +} phFriNfc_OvrHalCmdCon_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_Disconnect + * + */ +typedef struct phFriNfc_OvrHalCmdDis +{ + phHal_sHwReference_t *psHwReference; + phHal_sRemoteDevInformation_t *psRemoteDevInfo; +} phFriNfc_OvrHalCmdDis_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_Transceive + * + */ +typedef struct phFriNfc_OvrHalCmdTrx +{ + phHal_sHwReference_t *psHwReference; + phHal_sRemoteDevInformation_t *psRemoteDevInfo; + phHal_uCmdList_t Cmd; + phHal_sDepAdditionalInfo_t *psDepAdditionalInfo; + uint8_t *pSendBuf; + uint16_t SendLength; + uint8_t *pRecvBuf; + uint16_t *pRecvLength; +} phFriNfc_OvrHalCmdTrx_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_StartTargetMode + * + */ +typedef struct phFriNfc_OvrHalCmdStm +{ + phHal_sHwReference_t *psHwReference; + phHal_sTargetInfo_t *pTgInfo; + phHal_eOpModes_t *OpModes; + uint8_t *pConnectionReq; + uint8_t *pConnectionReqBufLength; +} phFriNfc_OvrHalCmdStm_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_Receive + * + */ +typedef struct phFriNfc_OvrHalCmdRcv +{ + phHal_sHwReference_t *psHwReference; + phHal_sDepAdditionalInfo_t *psDepAdditionalInfo; + uint8_t *pRecvBuf; + uint16_t *pRecvLength; +} phFriNfc_OvrHalCmdRcv_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_Send + * + */ +typedef struct phFriNfc_OvrHalCmdSnd +{ + phHal_sHwReference_t *psHwReference; + phHal_sDepAdditionalInfo_t *psDepAdditionalInfo; + uint8_t *pSendBuf; + uint16_t SendLength; +} phFriNfc_OvrHalCmdSnd_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_Ioctl + * + */ +typedef struct phFriNfc_OvrHalCmdIoc +{ + phHal_sHwReference_t *psHwReference; + uint16_t IoctlCode; + uint8_t *pInBuf; + uint16_t InLength; + uint8_t *pOutBuf; + uint16_t *pOutLength; +} phFriNfc_OvrHalCmdIoc_t; + +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHal_Test + * + */ +typedef struct phFriNfc_OvrHalCmdTst +{ + phHal_sHwReference_t *psHwReference; + void *pTestParam; +} phFriNfc_OvrHalCmdTst_t; + + +#ifdef PHFRINFC_OVRHAL_MOCKUP /* */ +/** \brief Parameter compound internally used by \ref phFriNfc_OvrHalCmdMockup_t + * + */ +typedef struct phFriNfc_OvrHalCmdMockup +{ + phHal_sHwReference_t *psHwReference; + uint16_t IoctlCode; + uint8_t *pInBuf; + uint16_t InLength; + uint8_t *pOutBuf; + uint16_t *pOutLength; +} phFriNfc_OvrHalCmdMockup_t; +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + +/** \brief Placeholder for all parameter structures + * + */ +typedef union phFriNfc_OvrHalCmd +{ + phFriNfc_OvrHalCmdVoid_t CmdVoid; + + phFriNfc_OvrHalCmdEnu_t CmdEnu; + phFriNfc_OvrHalCmdOpe_t CmdOpe; + phFriNfc_OvrHalCmdClo_t CmdClo; + phFriNfc_OvrHalCmdGdc_t CmdGdc; + phFriNfc_OvrHalCmdPol_t CmdPol; + phFriNfc_OvrHalCmdCon_t CmdCon; + phFriNfc_OvrHalCmdDis_t CmdDis; + phFriNfc_OvrHalCmdTrx_t CmdTrx; + phFriNfc_OvrHalCmdIoc_t CmdIoc; + phFriNfc_OvrHalCmdStm_t CmdStm; + phFriNfc_OvrHalCmdSnd_t CmdSnd; + phFriNfc_OvrHalCmdRcv_t CmdRcv; + phFriNfc_OvrHalCmdTst_t CmdTst; +} phFriNfc_OvrHalCmd_t; + + +/*@}*/ +#endif /* PHFRINFC_OVRHALCMD_H */ diff --git a/libnfc-nxp/phFriNfc_SmtCrdFmt.c b/libnfc-nxp/phFriNfc_SmtCrdFmt.c new file mode 100644 index 0000000..fce302f --- /dev/null +++ b/libnfc-nxp/phFriNfc_SmtCrdFmt.c @@ -0,0 +1,530 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc_SmtCrdFmt.c + * \brief This component encapsulates different smart and simple tag formatting functionalities, + * for the mapping layer. + * + * Project: NFC-FRI + * + * $Date: Mon Dec 13 14:14:13 2010 $ + * $Author: ing02260 $ + * $Revision: 1.9 $ + * $Aliases: $ + * + */ + +#ifndef PH_FRINFC_CARD_FORMAT_DISABLED + +#include +#include +#include +#ifdef DISABLE_FORMAT +#include +#endif /* #ifdef DISABLE_FORMAT */ +#include +#include +#include +#ifndef PH_FRINFC_FMT_ISO15693_DISABLED + #include +#endif /* #ifndef PH_FRINFC_FMT_ISO15693_DISABLED */ + + +/*! \ingroup grp_file_attributes + * \name NDEF Mapping + * + * File: \ref phFriNfc_CardFormatFunctions.c + * + */ +/*@{*/ +// file versions +/*@}*/ + + + + +void phFriNfc_SmtCrdFmt_HCrHandler(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + NFCSTATUS Status) +{ + /* set the state back to the Reset_Init state*/ + NdefSmtCrdFmt->State = PH_FRINFC_SMTCRDFMT_STATE_RESET_INIT; + + /* set the completion routine*/ + NdefSmtCrdFmt->CompletionRoutine[PH_FRINFC_SMTCRDFMT_CR_FORMAT]. + CompletionRoutine(NdefSmtCrdFmt->CompletionRoutine->Context, Status); +} + +/*! + * \brief Used to Reset the context variables , before the actual smart card formatting + * procedure. + * + */ +NFCSTATUS phFriNfc_NdefSmtCrd_Reset(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + void *LowerDevice, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phHal_sDevInputParam_t *psDevInputParam, + uint8_t *SendRecvBuffer, + uint16_t *SendRecvBuffLen) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t index; + + if ( (SendRecvBuffLen == NULL) || (NdefSmtCrdFmt == NULL) || (psRemoteDevInfo == NULL) || + (SendRecvBuffer == NULL) || (LowerDevice == NULL) || + (*SendRecvBuffLen == 0) || (psDevInputParam == NULL) || + (*SendRecvBuffLen < PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE) ) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Initialise the state to Init */ + NdefSmtCrdFmt->State = PH_FRINFC_SMTCRDFMT_STATE_RESET_INIT; + + for(index = 0;indexCompletionRoutine[index].CompletionRoutine = NULL; + /* Initialise the NdefMap Completion Routine context to Null */ + NdefSmtCrdFmt->CompletionRoutine[index].Context = NULL; + } + + /* Lower Device(Always Overlapped HAL Struct initialised in application + is registred in NdefMap Lower Device) */ + NdefSmtCrdFmt->LowerDevice = LowerDevice; + + /* Remote Device info received from Manual Device Discovery is registered here */ + NdefSmtCrdFmt->psRemoteDevInfo = psRemoteDevInfo; + + /* Trx Buffer registered */ + NdefSmtCrdFmt->SendRecvBuf = SendRecvBuffer; + + /* Trx Buffer Size */ + NdefSmtCrdFmt->SendRecvLength = SendRecvBuffLen; + + /* Register Transfer Buffer Length */ + NdefSmtCrdFmt->SendLength = 0; + + /* Initialise the Format status flag*/ + NdefSmtCrdFmt->FmtProcStatus = 0; + + /* Reset the Card Type */ + NdefSmtCrdFmt->CardType = 0; + + /* Reset MapCompletion Info*/ + NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.CompletionRoutine = NULL; + NdefSmtCrdFmt->SmtCrdFmtCompletionInfo.Context = NULL; + +#ifndef PH_FRINFC_FMT_TOPAZ_DISABLED + phFriNfc_Topaz_Reset(NdefSmtCrdFmt); + +#endif /* PH_FRINFC_FMT_TOPAZ_DISABLED */ + +#ifndef PH_FRINFC_FMT_DESFIRE_DISABLED + /*Reset Desfire Cap Container elements*/ + phFriNfc_Desfire_Reset(NdefSmtCrdFmt); +#endif /* PH_FRINFC_FMT_DESFIRE_DISABLED */ + +#ifndef PH_FRINFC_FMT_MIFARESTD_DISABLED + /*Reset Mifare Standard Container elements*/ + NdefSmtCrdFmt->AddInfo.MfStdInfo.DevInputParam = psDevInputParam; + phFriNfc_MfStd_Reset(NdefSmtCrdFmt); +#endif /* PH_FRINFC_MAP_MIFARESTD_DISABLED */ + +#ifndef PH_FRINFC_FMT_MIFAREUL_DISABLED + phFriNfc_MfUL_Reset(NdefSmtCrdFmt); +#endif /* #ifndef PH_FRINFC_FMT_MIFAREUL_DISABLED */ + +#ifndef PH_FRINFC_FMT_ISO15693_DISABLED + phFriNfc_ISO15693_FmtReset (NdefSmtCrdFmt); +#endif /* #ifndef PH_FRINFC_FMT_ISO15693_DISABLED */ + +#ifdef PHFRINFC_OVRHAL_MOCKUP + /*Reset Desfire Cap Container elements*/ + // phFriNfc_Mockup_H_Reset(NdefSmtCrdFmt); +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + + } + return (result); + +} + +/*! + * \brief Completion Routine initialisation + * + */ +NFCSTATUS phFriNfc_NdefSmtCrd_SetCR(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint8_t FunctionID, + pphFriNfc_Cr_t CompletionRoutine, + void *CompletionRoutineContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if ((NdefSmtCrdFmt == NULL) || (FunctionID >= PH_FRINFC_SMTCRDFMT_CR) || + (CompletionRoutine == NULL) || (CompletionRoutineContext == NULL)) + { + status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Register the application callback with the NdefMap Completion Routine */ + NdefSmtCrdFmt->CompletionRoutine[FunctionID].CompletionRoutine = CompletionRoutine; + + /* Register the application context with the NdefMap Completion Routine context */ + NdefSmtCrdFmt->CompletionRoutine[FunctionID].Context = CompletionRoutineContext; + } + + return status; +} + +#ifdef FRINFC_READONLY_NDEF + +NFCSTATUS +phFriNfc_NdefSmtCrd_ConvertToReadOnly ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt) +{ + NFCSTATUS result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_PARAMETER); + uint8_t sak = 0; + + if((NdefSmtCrdFmt != NULL) + && (NdefSmtCrdFmt->CompletionRoutine->CompletionRoutine != NULL) + && (NdefSmtCrdFmt->CompletionRoutine->Context != NULL)) + { + sak = NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak; + switch (NdefSmtCrdFmt->psRemoteDevInfo->RemDevType) + { + case phHal_eMifare_PICC: + { + if (0x00 == sak) + { + result = phFriNfc_MfUL_ConvertToReadOnly (NdefSmtCrdFmt); + } + else + { + /* MIFARE classic 1k/4k is not supported */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); + } + break; + } + + case phHal_eISO14443_A_PICC: + { + result = phFriNfc_Desfire_ConvertToReadOnly (NdefSmtCrdFmt); + break; + } + + default : + { + /* Remote device is not recognised. + Probably not NDEF compliant */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); + break; + } + } + } + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + + +/*! + * \brief Used to format the different smart cards. + * + */ +NFCSTATUS phFriNfc_NdefSmtCrd_Format( phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, const uint8_t *ScrtKeyB ) +{ + /* Component ID needs to be changed */ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_PARAMETER); + uint8_t sak = 0; + + /* Check for the correct context structure */ + if((NdefSmtCrdFmt != NULL) && + (NdefSmtCrdFmt->CompletionRoutine->CompletionRoutine != NULL) && + (NdefSmtCrdFmt->CompletionRoutine->Context != NULL)) + { +#ifdef PH_HAL4_ENABLE + /* SAK (Select response) */ + sak = NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak; + + /* Depending on the Opmodes, call the respective card functions */ + switch ( NdefSmtCrdFmt->psRemoteDevInfo->RemDevType ) +#else + /* SAK (Select response) */ + sak = NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.CardInfo106. + Startup106.SelRes; + + /* Depending on the Opmodes, call the respective card functions */ + switch ( NdefSmtCrdFmt->psRemoteDevInfo->OpMode ) +#endif /* #ifdef PH_HAL4_ENABLE */ + { +#ifdef PH_HAL4_ENABLE + case phHal_eMifare_PICC : +#else + case phHal_eOpModesMifare : +#endif /* #ifdef PH_HAL4_ENABLE */ + /* Remote device is Mifare card . Check for Mifare + NDEF compliance */ + if(0x00 == sak) + { +#ifndef PH_FRINFC_FMT_MIFAREUL_DISABLED + /* The SAK/Sel_Res says the card is of the type + Mifare UL */ + NdefSmtCrdFmt->CardType = PH_FRINFC_SMTCRDFMT_MIFARE_UL_CARD; + if (NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.UidLength == 7 && + NdefSmtCrdFmt->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Uid[0] == 0x04) + { + + Result = phFriNfc_MfUL_Format( NdefSmtCrdFmt); + } + else + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); + } +#else + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* #ifndef PH_FRINFC_FMT_MIFAREUL_DISABLED */ + } + else if((0x08 == (sak & 0x18)) || + (0x18 == (sak & 0x18)) || + (0x01 == sak)) + { +#ifndef PH_FRINFC_FMT_MIFARESTD_DISABLED + NdefSmtCrdFmt->CardType = (uint8_t) + (((sak & 0x18) == 0x08)? + PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD: + PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD); + + /* The SAK/Sel_Res says the card is of the type + Mifare standard */ + Result = phFriNfc_MfStd_Format( NdefSmtCrdFmt, ScrtKeyB); +#else + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* #ifndef PH_FRINFC_FMT_MIFARESTD_DISABLED */ + } + else + { + /* Invalid Mifare card, as the remote device + info - opmode says its a Mifare card but, + The SAK/Sel_Res is wrong */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); + } + break; +#ifdef PH_HAL4_ENABLE + case phHal_eISO14443_A_PICC : +#else + case phHal_eOpModesISO14443_4A : +#endif /* #ifdef PH_HAL4_ENABLE */ + /* Remote device is Desfire card . Check for Desfire + NDEF compliancy */ + if(0x20 == (sak & 0xFF)) + { +#ifndef PH_FRINFC_FMT_DESFIRE_DISABLED + NdefSmtCrdFmt->CardType = PH_FRINFC_SMTCRDFMT_ISO14443_4A_CARD; + /* The SAK/Sel_Res says the card is of the type + ISO14443_4A */ + + Result = phFriNfc_Desfire_Format(NdefSmtCrdFmt); +#else + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* #ifndef PH_FRINFC_FMT_DESFIRE_DISABLED */ + } + else + { + /* Invalid Desfire card, as the remote device + info - opmode says its a desfire card but, + The SAK/Sel_Res is wrong */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); + } + break; +#ifdef PH_HAL4_ENABLE + case phHal_eJewel_PICC : +#else + case phHal_eOpModesJewel : +#endif /* #ifdef PH_HAL4_ENABLE */ + /* Remote device is Topaz card . Check for Topaz + NDEF compliancy */ + if(0xC2 == sak) + { +#ifndef PH_FRINFC_FMT_TOPAZ_DISABLED + NdefSmtCrdFmt->CardType = PH_FRINFC_SMTCRDFMT_TOPAZ_CARD; + /* The SAK/Sel_Res says the card is of the type + ISO14443_4A */ + Result = phFriNfc_Topaz_Format(NdefSmtCrdFmt); +#else + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* #ifndef PH_FRINFC_FMT_TOPAZ_DISABLED */ + + } + else + { + /* Invalid Topaz card, as the remote device + info - opmode says its a desfire card but, + The SAK/Sel_Res is wrong */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); + } + break; + +#ifdef PHFRINFC_OVRHAL_MOCKUP + case phHal_eOpModesMockup : + /*Set the OpMode Ttype Flag*/ + NdefSmtCrdFmt->OpModeType[0] = phHal_eOpModesMockup; + NdefSmtCrdFmt->OpModeType[1] = phHal_eOpModesArrayTerminator; + //Result = phFriNfc_Mockup_ChkNdef(NdefSmtCrdFmt); + break; +#endif /* PHFRINFC_OVRHAL_MOCKUP */ + +#ifndef PH_FRINFC_FMT_ISO15693_DISABLED + case phHal_eISO15693_PICC: + { + Result = phFriNfc_ISO15693_Format (NdefSmtCrdFmt); + break; + } +#endif /* #ifndef PH_FRINFC_FMT_ISO15693_DISABLED */ + default : + /* Remote device is not recognised. + Probably not NDEF compliant */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); + break; + } + } + return Result; +} +/*! + * \brief Handles different request and responses from the integration layer. + * + */ +void phFriNfc_NdefSmtCrd_Process(void *Context, + NFCSTATUS Status) +{ + if ( Context != NULL ) + { + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt = (phFriNfc_sNdefSmtCrdFmt_t *)Context; +#ifdef PH_HAL4_ENABLE + switch ( NdefSmtCrdFmt->psRemoteDevInfo->RemDevType ) +#else + switch ( NdefSmtCrdFmt->psRemoteDevInfo->OpMode ) +#endif /* #ifdef PH_HAL4_ENABLE */ + { +#ifdef PH_HAL4_ENABLE + case phHal_eMifare_PICC : +#else + case phHal_eOpModesMifare : +#endif /* #ifdef PH_HAL4_ENABLE */ + if((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD) || + (NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD)) + { +#ifndef PH_FRINFC_FMT_MIFARESTD_DISABLED + /* Remote device is Mifare Standard card */ + phFriNfc_MfStd_Process(NdefSmtCrdFmt,Status); + +#else /* PH_FRINFC_FMT_MIFARESTD_DISABLED*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_FMT_MIFARESTD_DISABLED*/ + } + else + { +#ifndef PH_FRINFC_FMT_MIFAREUL_DISABLED + /* Remote device is Mifare UL card */ + phFriNfc_MfUL_Process(NdefSmtCrdFmt,Status); +#else /* PH_FRINFC_FMT_MIFAREUL_DISABLED*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_FMT_MIFAREUL_DISABLED*/ + } + break; + +#ifdef PH_HAL4_ENABLE + case phHal_eISO14443_A_PICC : +#else + case phHal_eOpModesISO14443_4A : +#endif /* #ifdef PH_HAL4_ENABLE */ +#ifndef PH_FRINFC_FMT_DESFIRE_DISABLED + /* Remote device is Desfire card */ + phFriNfc_Desf_Process(NdefSmtCrdFmt, Status); +#else /* PH_FRINFC_FMT_DESFIRE_DISABLED*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_FMT_DESFIRE_DISABLED*/ + break; +#ifdef PH_HAL4_ENABLE + case phHal_eJewel_PICC : +#else + case phHal_eOpModesJewel: +#endif /* #ifdef PH_HAL4_ENABLE */ +#ifndef PH_FRINFC_FMT_TOPAZ_DISABLED + /* Remote device is Topaz Smart card */ + phFriNfc_Topaz_Process(NdefSmtCrdFmt, Status); +#else /* PH_FRINFC_FMT_TOPAZ_DISABLED*/ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); +#endif /* PH_FRINFC_FMT_TOPAZ_DISABLED*/ + break; + +#ifndef PH_FRINFC_FMT_ISO15693_DISABLED + case phHal_eISO15693_PICC : + { + phFriNfc_ISO15693_FmtProcess (NdefSmtCrdFmt, Status); + break; + } +#endif /* #ifndef PH_FRINFC_FMT_ISO15693_DISABLED */ + +#ifdef PHFRINFC_OVRHAL_MOCKUP + case phHal_eOpModesMockup: + /* Remote device is Desfire card */ + //phFriNfc_Mockup_Process(NdefSmtCrdFmt, Status); + break; +#endif /* PHFRINFC_OVRHAL_MOCKUP*/ + default : + /* Remote device opmode not recognised. + Probably not NDEF compliant */ + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, + NFCSTATUS_INVALID_REMOTE_DEVICE); + /* set the state back to the Reset_Init state*/ + NdefSmtCrdFmt->State = PH_FRINFC_SMTCRDFMT_STATE_RESET_INIT; + + /* set the completion routine*/ + NdefSmtCrdFmt->CompletionRoutine[PH_FRINFC_SMTCRDFMT_CR_INVALID_OPE]. + CompletionRoutine(NdefSmtCrdFmt->CompletionRoutine->Context, Status); + break; + } + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT,\ + NFCSTATUS_INVALID_PARAMETER); + /* The control should not come here. As Context itself is NULL , + Can't call the CR*/ + } +} + +#endif /* PH_FRINFC_CARD_FORMAT_DISABLED */ + diff --git a/libnfc-nxp/phFriNfc_SmtCrdFmt.h b/libnfc-nxp/phFriNfc_SmtCrdFmt.h new file mode 100644 index 0000000..4800c41 --- /dev/null +++ b/libnfc-nxp/phFriNfc_SmtCrdFmt.h @@ -0,0 +1,501 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phFriNfc_SmtCrdFmt.h + * \brief NFC-FRI Smart Card Formatting. + * + * Project: NFC-FRI + * + * $Date: Mon Dec 13 14:14:11 2010 $ + * $Author: ing02260 $ + * $Revision: 1.5 $ + * $Aliases: $ + * + */ + +#ifndef PHFRINFC_SMTCRDFMT_H +#define PHFRINFC_SMTCRDFMT_H + +/** + * \name Smart Card Formatting + * + * File: \ref phFri_CardFormatFunctions.h + * + */ +/*@{*/ +#define PHFRINFC_SMTCRDFMT_FILEREVISION "$Revision: 1.5 $" +#define PHFRINFC_SMTCRDFMT_FILEALIASES "$Aliases: $" +/*@}*/ + +/*! \defgroup grp_fri_smart_card_formatting NFC FRI Smart Card Formatting + * + * Smart Card Formatting functionality enables automatic formatting of any type of smart cards. + * This initializes the smart cards and makes them NDEF Compliant. + * Single API is provided to handle format/recovery management of different types cards. + * Following are different Types of cards supported by this module, currently. + * - Type1 ( Topaz) + * - Type2 ( Mifare UL) + * - Type4 ( Desfire) + * - Mifare Std. + */ +/*@{*/ +/** + * \ingroup grp_fri_smart_card_formatting + * \brief Macro definitions. + * \note + On requirement basis, new constants will be defined + during the implementation phase. +*/ + +#define DESFIRE_FMT_EV1 + + +#define PH_FRI_NFC_SMTCRDFMT_NFCSTATUS_FORMAT_ERROR 9 +#define PH_FRINFC_SMTCRDFMT_MSTD_DEFAULT_KEYA_OR_KEYB {0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF} +#define PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA {0xA0, 0xA1,0xA2,0xA3,0xA4,0xA5} +#define PH_FRINFC_SMTCRDFMT_NFCFORUMSECT_KEYA {0xD3, 0xF7,0xD3,0xF7,0xD3,0xF7} +#define PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_ACCESSBITS {0x78,0x77,0x88} +#define PH_FRINFC_SMTCRDFMT_MSTD_NFCFORUM_ACCESSBITS {0x7F,0x07,0x88} +#define PH_FRINFC_SMTCRDFMT_MAX_TLV_TYPE_SUPPORTED 1 + +#define PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE 252 + +#define PH_FRINFC_SMTCRDFMT_STATE_RESET_INIT 1 + +enum +{ + PH_FRINFC_SMTCRDFMT_MIFARE_UL_CARD, + PH_FRINFC_SMTCRDFMT_ISO14443_4A_CARD, + PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD, + PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD, + PH_FRINFC_SMTCRDFMT_TOPAZ_CARD +}; + +/** + * \name Completion Routine Indices + * + * These are the indices of the completion routine pointers within the component context. + * Completion routines belong to upper components. + * + */ +/*@{*/ +/** \ingroup grp_fri_nfc_ndef_map +* Completion Routine Index for \ref phFriNfc_SmtCrd_Format */ +#define PH_FRINFC_SMTCRDFMT_CR_FORMAT 0 /* */ +/** \ingroup grp_fri_nfc_ndef_map Completion + * Routine Index for Unknown States/Operations */ +#define PH_FRINFC_SMTCRDFMT_CR_INVALID_OPE 1 /* */ +/** \ingroup grp_fri_nfc_ndef_map + * Number of completion routines that have to be initialised */ +#define PH_FRINFC_SMTCRDFMT_CR 2 +/*@}*/ + + +/*@}*/ + +/* + * \ingroup grp_fri_smart_card_formatting + * + * \brief NFC Smart Card Formatting Component Type1 Additional Information Structure + * + * This structure is used to specify additional information required to format the Type1 card. + * \note + * On requirement basis,structure will be filled/modified with other parameters + * during the implementation phase. + * + */ +typedef struct phFriNfc_Type1_AddInfo +{ + /* Stores the CC byte values. For Ex: 0xE1, 0x10 , 0x0C, 0x00*/ + uint8_t CCBytes[5]; + uint8_t UID[4]; + uint8_t CCByteIndex; + +} phFriNfc_Type1_AddInfo_t; + +/* + * + * \ingroup grp_fri_smart_card_formatting + * \brief NFC Smart Card Formatting Component Type2 Additional Information Structure + * + * This structure is used to specify additional information required to format the Type2 card. + * \note + * On requirement basis,structure will be filled/modified with other parametes + * during the implementation phase. + * + */ +typedef struct phFriNfc_Type2_AddInfo +{ + /* Stores the CC byte values. For Ex: 0xE1, 0x10 , 0x10, 0x00*/ + uint8_t OTPBytes[4]; +#ifdef FRINFC_READONLY_NDEF + uint8_t LockBytes[4]; + +#ifdef PH_NDEF_MIFARE_ULC + uint8_t ReadData[16]; + uint8_t ReadDataIndex; + uint8_t DynLockBytes[4]; + uint8_t BytesLockedPerLockBit; + uint8_t LockBytesPerPage; + uint8_t LockByteNumber; + uint8_t LockBlockNumber; + uint8_t NoOfLockBits; + uint8_t DefaultLockBytesFlag; + uint8_t LockBitsWritten; +#endif /* #ifdef PH_NDEF_MIFARE_ULC */ + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + /* Current Block Address*/ + uint8_t CurrentBlock; +} phFriNfc_Type2_AddInfo_t; + +/* + * \ingroup grp_fri_smart_card_formatting + * \brief NFC Smart Card Formatting Component Type4 Additional Information Structure + * + * This structure is used to specify additional information required to format the type4 card. + * \note + * On requirement basis,structure will be filled/modified with other parametes + * during the implementation phase. + * + */ + +typedef struct phFriNfc_Type4_AddInfo +{ + /* Specifies Keys related to PICC/NFCForum Master Key settings*/ + /* Stores the PICC Master Key/NFC Forum MasterKey*/ + uint8_t PICCMasterKey[16]; + uint8_t NFCForumMasterkey[16]; + + /* To create the files follwoiing attributes are required*/ + uint8_t PrevState; + uint16_t FileAccessRights; + uint32_t CardSize; + uint16_t MajorVersion; + uint16_t MinorVersion; + +} phFriNfc_Type4_AddInfo_t; + +/* + * \ingroup grp_fri_smart_card_formatting + * \brief NFC Smart Card Formatting Component Mifare Std Additional Information Structure + * + * This structure is used to specify additional information required to format the Mifare Std card. + * \note + * On requirement basis,structure will be filled/modified with other parametes + * during the implementation phase. + * + */ + typedef struct phFriNfc_MfStd_AddInfo +{ + /** Device input parameter for poll and connect after failed authentication */ + phHal_sDevInputParam_t *DevInputParam; + + /* Stores the Default KeyA and KeyB values*/ + uint8_t Default_KeyA_OR_B[6]; + + /* Key A of MAD sector*/ + uint8_t MADSect_KeyA[6]; + + /* Key A of NFC Forum Sector sector*/ + uint8_t NFCForumSect_KeyA[6]; + + /* Access Bits of MAD sector*/ + uint8_t MADSect_AccessBits[3]; + + /* Access Bits of NFC Forum sector*/ + uint8_t NFCForumSect_AccessBits[3]; + + /* Secret key B to given by the application */ + uint8_t ScrtKeyB[6]; + + /* Specifies the status of the different authentication handled in + formatting procedure*/ + uint8_t AuthState; + + /* Stores the current block */ + uint16_t CurrentBlock; + + /* Stores the current block */ + uint8_t NoOfDevices; + + /* Store the compliant sectors */ + uint8_t SectCompl[40]; + + /* Flag to know that MAD sector */ + uint8_t WrMADBlkFlag; + + /* Fill the MAD sector blocks */ + uint8_t MADSectBlk[80]; + + /* Fill the MAD sector blocks */ + uint8_t UpdMADBlk; +} phFriNfc_MfStd_AddInfo_t; + + + /* + * \ingroup grp_fri_smart_card_formatting + * \brief NFC Smart Card Formatting Component ISO-15693 Additional Information Structure + * + * This structure is used to specify additional information required to format the ISO-15693 card. + * \note + * On requirement basis,structure will be filled/modified with other parametes + * during the implementation phase. + * + */ + typedef struct phFriNfc_ISO15693_AddInfo + { + /* Stores the current block executed */ + uint16_t current_block; + /* Sequence executed */ + uint8_t format_seq; + /* Maximum data size in the card */ + uint16_t max_data_size; + }phFriNfc_ISO15693_AddInfo_t; + +/** + * \ingroup grp_fri_smart_card_formatting + * + * \brief NFC Smart Card Formatting Component Additional Information Structure + * + * This structure is composed to have additional information of different type of tags + * Ex: Type1/Type2/Type4/Mifare 1k/4k + * + * \note + * On requirement basis, structure will be filled/modified with other parameters + * during the implementation phase. + */ +typedef struct phFriNfc_sNdefSmtCrdFmt_AddInfo +{ + phFriNfc_Type1_AddInfo_t Type1Info; + phFriNfc_Type2_AddInfo_t Type2Info; + phFriNfc_Type4_AddInfo_t Type4Info; + phFriNfc_MfStd_AddInfo_t MfStdInfo; + phFriNfc_ISO15693_AddInfo_t s_iso15693_info; + +}phFriNfc_sNdefSmtCrdFmt_AddInfo_t; + +/** + * \ingroup grp_fri_smart_card_formatting + * \brief NFC Smart Card Formatting Component Context Structure + * + * This structure is used to store the current context information of the instance. + * + * \note On requirement basis,structure will be filled/modified with other parameters + * during the implementation phase + * + */ +typedef struct phFriNfc_sNdefSmtCrdFmt +{ + /** Pointer to the lower (HAL) instance.*/ + void *LowerDevice; + + /** Holds the device additional informations*/ + phHal_sDepAdditionalInfo_t psDepAdditionalInfo; + + /** Pointer to the Remote Device Information */ + phHal_sRemoteDevInformation_t *psRemoteDevInfo; + + /** Stores the type of the smart card. */ + uint8_t CardType; + + /** Stores operating mode type of the MifareStd. */ + /* phHal_eOpModes_t OpModeType[2]; */ + + /**< \internal The state of the operation. */ + uint8_t State; + + /**< \internal Stores the card state Ex: Blank/Formatted etc. */ + uint8_t CardState; + + /**< \internal Completion Routine Context. */ + phFriNfc_CplRt_t CompletionRoutine[PH_FRINFC_SMTCRDFMT_CR]; + + /**<\internal Holds the completion routine informations of the Smart Card Formatting Layer*/ + phFriNfc_CplRt_t SmtCrdFmtCompletionInfo; + + /**<\internal Holds the Command Type(read/write)*/ + phHal_uCmdList_t Cmd; + + /**< \internal Holds the length of the received data. */ + uint16_t *SendRecvLength; + + /**<\internal Holds the ack of some intial commands*/ + uint8_t *SendRecvBuf; + + /**< \internal Holds the length of the data to be sent. */ + uint16_t SendLength; + + /**< \internal Stores the output/result of the format procedure. Ex: Formatted Successfully, + Format Error etc */ + NFCSTATUS FmtProcStatus; + + /** Stores Additional Information needed to format the different types of tags*/ + phFriNfc_sNdefSmtCrdFmt_AddInfo_t AddInfo; + + /* Stores NDEF message TLV*/ + /* This stores the different TLV messages for the different card types*/ + uint8_t TLVMsg[PH_FRINFC_SMTCRDFMT_MAX_TLV_TYPE_SUPPORTED][8]; + + +} phFriNfc_sNdefSmtCrdFmt_t; + +/** + * \ingroup grp_fri_smart_card_formatting + * \brief Smart Card Formatting \b Reset function + * + * \copydoc page_reg Resets the component instance to the initial state and initializes the + * internal variables. + * + * \param[in] NdefSmtCrdFmt is a Pointer to a valid and initialized or uninitialised instance + * of \ref phFriNfc_sNdefSmtCrdFmt_t . + * \param[in] LowerDevice Overlapped HAL reference, pointing at a valid instance of this + * underlying component. + * \param[in] psRemoteDevInfo Points to the Remote Device Information structure encapsulating + * the information about the device (Smart card, NFC device) to access. + * \param[in] psDevInputParam The Device input parameter, as used for the HAL POLL function. + * This parameter is needed by the component in special cases, when an internal call + * to POLL is required again, such as for FeliCa. The storage of the structure behind + * the pointer must be retained by the calling software. The component itself only + * keeps the reference. No change is applied to the structure's content. + * \param[in] ReceiveBuffer Pointer to a buffer that the component uses internally use to + * store the data received from the lower component. + * The size shall be at least \ref PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE . + * \param[in] ReceiveLength The size of ReceiveBuffer. This specifies the actual length + * of the data received from the lower component. + * The size shall be at least \ref PH_FRINFC_SMTCRDFMT_MAX_SEND_RECV_BUF_SIZE . + * + * \retval NFCSTATUS_SUCCESS Operation successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * + * \note This function has to be called at the beginning, after creating an instance of + * \ref phFriNfc_sNdefSmtCrdFmt_t . Use this function to reset the instance and/or to switch + * to a different underlying card types. + */ +NFCSTATUS phFriNfc_NdefSmtCrd_Reset(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + void *LowerDevice, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phHal_sDevInputParam_t *psDevInputParam, + uint8_t *SendRecvBuffer, + uint16_t *SendRecvBuffLen); + + + +/*! + * \ingroup grp_fri_smart_card_formatting + * + * \brief Setting of the Completion Routine. + * + * \copydoc page_ovr This function allows the caller to set a Completion Routine (notifier). + * + * \param[in] NdefSmtCrdFmt Pointer to a valid instance of the \ref phFriNfc_sNdefSmtCrdFmt_t structure describing + * the component context. + * + * \param CompletionRoutine Pointer to a valid completion routine being called when the non-blocking + * operation has finished. + * + * \param CompletionRoutineParam Pointer to a location with user-defined information that is submitted + * to the Completion Routine once it is called. + + * \retval NFCSTATUS_SUCCESS Operation successful. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * + */ +NFCSTATUS phFriNfc_NdefSmtCrd_SetCR(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + uint8_t FunctionID, + pphFriNfc_Cr_t CompletionRoutine, + void *CompletionRoutineContext); + + +/*! + * \ingroup grp_fri_smart_card_formatting + * + * \brief Initiates the card formatting procedure for Remote Smart Card Type. + * + * \copydoc page_ovr The function initiates and formats the Smart Card.After this formation, remote + * card would be properly initialized and Ndef Compliant. + * Depending upon the different card type, this function handles formatting procedure. + * This function also handles the different recovery procedures for different types of the cards. For both + * Format and Recovery Management same API is used. + * + * \param[in] phFriNfc_sNdefSmtCrdFmt_t Pointer to a valid instance of the \ref phFriNfc_sNdefSmartCardFmt_t + * structure describing the component context. + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval Other values An error has occurred. + * + */ +NFCSTATUS phFriNfc_NdefSmtCrd_Format(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, const uint8_t *ScrtKeyB); + + +#ifdef FRINFC_READONLY_NDEF +/*! + * \ingroup grp_fri_smart_card_formatting + * + * \brief Initiates the conversion of the already NDEF formatted tag to READ ONLY. + * + * \copydoc page_ovr The function initiates the conversion of the already NDEF formatted + * tag to READ ONLY.After this formation, remote card would be properly Ndef Compliant and READ ONLY. + * Depending upon the different card type, this function handles formatting procedure. + * This function supports only for the DESFIRE, MIFARE UL and TOPAZ tags. + * + * \param[in] phFriNfc_sNdefSmtCrdFmt_t Pointer to a valid instance of the \ref phFriNfc_sNdefSmartCardFmt_t + * structure describing the component context. + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval Other values An error has occurred. + * + */ +NFCSTATUS +phFriNfc_NdefSmtCrd_ConvertToReadOnly ( + phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt); + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + + +/** + *\ingroup grp_fri_smart_card_formatting + * + * \brief Smart card Formatting \b Completion \b Routine or \b Process function + * + * \copydoc page_ovr Completion Routine: This function is called by the lower layer (OVR HAL) + * when an I/O operation has finished. The internal state machine decides + * whether to call into the lower device again or to complete the process + * by calling into the upper layer's completion routine, stored within this + * component's context (\ref phFriNfc_sNdefSmtCrdFmt_t). + * + * The function call scheme is according to \ref grp_interact. No State reset is performed during + * operation. + * + * \param[in] Context The context of the current (not the lower/upper) instance, as set by the lower, + * calling layer, upon its completion. + * \param[in] Status The completion status of the lower layer (to be handled by the implementation of + * the state machine of this function like a regular return value of an internally + * called function). + * + * \note For general information about the completion routine interface please see \ref pphFriNfc_Cr_t . * The Different Status Values are as follows + * + */ +void phFriNfc_NdefSmtCrd_Process(void *Context, + NFCSTATUS Status); + +void phFriNfc_SmtCrdFmt_HCrHandler(phFriNfc_sNdefSmtCrdFmt_t *NdefSmtCrdFmt, + NFCSTATUS Status); + +/*@}*/ + +#endif /* PHFRINFC_SMTCRDFMT_H */ + + diff --git a/libnfc-nxp/phFriNfc_TopazDynamicMap.c b/libnfc-nxp/phFriNfc_TopazDynamicMap.c new file mode 100644 index 0000000..4fe02b1 --- /dev/null +++ b/libnfc-nxp/phFriNfc_TopazDynamicMap.c @@ -0,0 +1,4285 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phFriNfc_TopazDynamicMap.c +* \brief NFC Ndef Mapping For Remote Devices. +* +* Project: NFC-FRI +* +* $Date: Wed Oct 27 10:21:29 2010 $ +* $Author: ing02260 $ +* $Revision: 1.41 $ +* $Aliases: $ +* +*/ + + + +#include +#include +#include +#include + +#if !(defined(PH_FRINFC_MAP_TOPAZ_DISABLED ) || defined (PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED )) + +/*! \ingroup grp_file_attributes +* \name NDEF Mapping +* +* File: \ref phFriNfcNdefMap.c +* +*/ +/*@{*/ +#define PHFRINFCTOPAZMAP_FILEREVISION "$Revision: 1.41 $" +#define PHFRINFCTOPAZMAP_FILEALIASES "$Aliases: $" +/*@}*/ +/*! +* \name Topaz Mapping - Helper data structures and macros +* +*/ +/*@{*/ + +/********************************** Start of data structures *********************************/ +#ifdef FRINFC_READONLY_NDEF + + #define DYN_CC_BLOCK_NUMBER (0x01U) + #define DYN_STATIC_LOCK_BLOCK_NUM (0x0EU) + + #define DYN_STATIC_LOCK0_BYTE_NUM (0x00U) + #define DYN_STATIC_LOCK0_BYTE_VALUE (0xFFU) + + #define DYN_STATIC_LOCK1_BYTE_NUM (0x01U) + #define DYN_STATIC_LOCK1_BYTE_VALUE (0x7FU) + + #define DYN_CC_RWA_BYTE_NUMBER (0x03U) + #define DYN_CC_READ_ONLY_VALUE (0x0FU) + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/*! +* \brief \copydoc page_ovr enum for the topaz sequence of execution. +*/ +typedef enum phFriNfc_Tpz_ParseSeq +{ + LOCK_T_TLV, + LOCK_L_TLV, + LOCK_V_TLV, + MEM_T_TLV, + MEM_L_TLV, + MEM_V_TLV, + NDEF_T_TLV, + NDEF_L_TLV, + NDEF_V_TLV +}phFriNfc_Tpz_ParseSeq_t; + +typedef enum phFriNfc_Tpz_WrSeq +{ + WR_NDEF_T_TLV, + WR_NMN_0, + WR_LEN_1_0, + WR_LEN_2_0, + WR_LEN_3_0, + WR_DATA, + WR_DATA_READ_REQD, + WR_LEN_1_VALUE, + WR_LEN_2_VALUE, + WR_LEN_3_VALUE, + WR_NMN_E1 +}phFriNfc_Tpz_WrSeq_t; + +#ifdef FRINFC_READONLY_NDEF + +typedef enum phFriNfc_Tpz_RO_Seq +{ + WR_READONLY_CC, + RD_LOCK_BYTES, + WR_LOCK_BYTES, + RD_STATIC_LOCK_BYTE0, + WR_STATIC_LOCK_BYTE0, + WR_STATIC_LOCK_BYTE1 +}phFriNfc_Tpz_RO_Seq_t; + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/********************************** End of data structures *********************************/ + +/********************************** Start of Macros *********************************/ +/* New state for TOPAZ dynamic card*/ +#define PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF (0x10U) + +#ifdef FRINFC_READONLY_NDEF + #define PH_FRINFC_TOPAZ_STATE_READ_ONLY (0x11U) +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +#define NIBBLE_SIZE (0x04U) +/* Byte shifting for the topaz */ +#define TOPAZ_BYTE_SHIFT (0x08U) +/* Lock and memory control TLV length. Always 3 bytes */ +#define TOPAZ_MEM_LOCK_TLV_LENGTH (0x03U) +/* UID byte length */ +#define TOPAZ_UID_BYTES_LENGTH (0x08U) + +/* Number os static lock and reserved bytes */ +#define TOPAZ_STATIC_LOCK_RES_BYTES (0x18U) +/* Number of static lock and reserved memory. This value is 3 (because + block number D, E and F are lock and reserved blocks */ +#define TOPAZ_STATIC_LOCK_BLOCK_AREAS (0x03U) +/* First lock or reserved block in the static area of the card */ +#define TOPAZ_STATIC_LOCK_FIRST_BLOCK_NO (0x0DU) +/* First lock or reserved byte number in the static area of the card */ +#define TOPAZ_STATIC_LOCK_RES_START (0x68U) +/* End lock or reserved byte number in the static area of the card */ +#define TOPAZ_STATIC_LOCK_RES_END (0x78U) + +/* CC byte length */ +#define TOPAZ_CC_BYTES_LENGTH (0x04U) + +/* In TOPAZ card each block has 8 bytes */ +#define TOPAZ_BYTES_PER_BLOCK (0x08U) +/* Each byte has 8 bites */ +#define TOPAZ_BYTE_SIZE_IN_BITS (0x08U) + +/* This mask is to get the least significant NIBBLE from a BYTE */ +#define TOPAZ_NIBBLE_MASK (0x0FU) +/* This is used to mask the least significant BYTE from a TWO BYTE value */ +#define TOPAZ_BYTE_LENGTH_MASK (0x00FFU) + +/* Total segments in TOPAZ 512 bytes card. Each segment = 128 bytes, +so there are 4 segements in the card */ +#define TOPAZ_TOTAL_SEG_TO_READ (0x04U) +/* SPEC version value shall be 0x10 as per the TYPE 1 specification */ +#define TOPAZ_SPEC_VERSION (0x10U) + +/* Response length for READ SEGMENT command is 128 bytes */ +#define TOPAZ_SEGMENT_READ_LENGTH (0x80U) +/* Response length for WRITE-1E command is 1 byte */ +#define TOPAZ_WRITE_1_RESPONSE (0x01U) +/* Response length for WRITE-8E command is 8 bytes */ +#define TOPAZ_WRITE_8_RESPONSE (0x08U) +/* Response length for READ-8 command is 8 bytes */ +#define TOPAZ_READ_8_RESPONSE (0x08U) + +/* Data bytes that can be written for the WRITE-8E command is 8 bytes */ +#define TOPAZ_WRITE_8_DATA_LENGTH (0x08U) + +/* Get the exact byte address of the card from the segment number + and the parse index of each segment */ +#define TOPAZ_BYTE_ADR_FROM_SEG(seg, parse_index) \ + (((seg) * TOPAZ_SEGMENT_READ_LENGTH) + (parse_index)) + +/* Get the segment number of the card from the byte address */ +#define TOPAZ_SEG_FROM_BYTE_ADR(byte_addr) \ + ((byte_addr) / TOPAZ_SEGMENT_READ_LENGTH) +/* Get the block number of the card from the byte address */ +#define TOPAZ_BLK_FROM_BYTE_ADR(byte_addr) \ + ((byte_addr) / TOPAZ_BYTES_PER_BLOCK) +/* Get the block offset of a block number of the card from the byte address */ +#define TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR(byte_addr) \ + ((byte_addr) % TOPAZ_BYTES_PER_BLOCK) +/* Get the exact byte address of the card from the block number + and the byte offset of the block number */ +#define TOPAZ_BYTE_ADR_FROM_BLK(block_no, byte_offset) \ + (((block_no) * TOPAZ_BYTES_PER_BLOCK) + (byte_offset)) +/* To increment the block number and if block number overlaps with the + static lock and reserved blocks, then skip the blocks */ +#define TOPAZ_INCREMENT_SKIP_STATIC_BLOCK(block_no) \ + ((((block_no) + 1) == TOPAZ_STATIC_LOCK_FIRST_BLOCK_NO) ? \ + (((block_no) + 1) + TOPAZ_STATIC_LOCK_BLOCK_AREAS) : \ + ((block_no) + 1)) +/* Check topaz spec version number */ +#define TOPAZ_COMPARE_VERSION(device_ver, tag_ver) \ + ((device_ver & 0xF0) >= (tag_ver & 0xF0)) + +#ifdef FRINFC_READONLY_NDEF + +#define TOPAZ_CONVERT_BITS_TO_BYTES(bits_to_bytes) \ + (((bits_to_bytes % TOPAZ_BYTE_SIZE_IN_BITS) > 0) ? \ + ((bits_to_bytes / TOPAZ_BYTE_SIZE_IN_BITS) + 1) : \ + (bits_to_bytes / TOPAZ_BYTE_SIZE_IN_BITS)) + +#endif /* #ifdef FRINFC_READONLY_NDEF */ +/********************************** End of Macros *********************************/ + +/*@}*/ + + +/*! +* \name Topaz Mapping - Helper Functions +* +*/ +/*@{*/ + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall read defined +* bytes from the card. +*/ +static +NFCSTATUS +phFriNfc_Tpz_H_NxpRead ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall process +* received read id command. +*/ +static +NFCSTATUS +phFriNfc_Tpz_H_ChkReadID ( + phFriNfc_NdefMap_t *psNdefMap); + + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall process +* read response. +*/ +static +NFCSTATUS +phFriNfc_Tpz_H_ProReadResp ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function calls the +* completion routine +*/ +static +void +phFriNfc_Tpz_H_Complete ( + phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Status); + + +/*! +* \brief \copydoc page_ovr Helper function for Topaz check ndef. This function checks +* the lock bits and set a card state +*/ +static +NFCSTATUS +phFriNfc_Tpz_H_ChkLockBits ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function writes defined +* bytes into the card +*/ +static +NFCSTATUS +phFriNfc_Tpz_H_NxpWrite ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *p_write_data, + uint8_t wr_data_len); + + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function parses the read bytes +* till the NDEF TLV is found. Also, it returns error if it founds wrong TLVs. +*/ +static +NFCSTATUS +phFriNfc_Tpz_H_ParseTLVs ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function parses the read bytes + * till the TYPE of the LOCK control TLV is found. + * Also, it returns error if it founds wrong TYPE. + */ +static +NFCSTATUS +phFriNfc_Tpz_H_ParseLockTLVType ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *p_parse_data, + uint16_t *p_parse_index, + uint16_t total_len_to_parse, + phFriNfc_Tpz_ParseSeq_t *seq_to_execute); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function parses the read bytes + * till the TYPE of the MEMORY control TLV is found. + * Also, it returns error if it founds wrong TYPE. + */ +static +NFCSTATUS +phFriNfc_Tpz_H_ParseMemTLVType ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *p_parse_data, + uint16_t *p_parse_index, + uint16_t total_len_to_parse, + phFriNfc_Tpz_ParseSeq_t *seq_to_execute); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function parses the read bytes + * till the TYPE of the NDEF control TLV is found. + * Also, it returns error if it founds wrong TYPE. + */ +static +NFCSTATUS +phFriNfc_Tpz_H_ParseNdefTLVType ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *p_parse_data, + uint16_t *p_parse_index, + uint16_t total_len_to_parse, + phFriNfc_Tpz_ParseSeq_t *seq_to_execute); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function gets the lock bytes + * information. + */ +static +NFCSTATUS +phFriNfc_Tpz_H_GetLockBytesInfo ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *p_lock_info); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function gets the reserved bytes + * information. + */ +static +NFCSTATUS +phFriNfc_Tpz_H_GetMemBytesInfo ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *p_mem_info); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function copies and checks the CC bytes. + * This function checks for the lock bytes value and card state also. + */ +static +NFCSTATUS +phFriNfc_Tpz_H_CheckCCBytes ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function checks the CC bytes. + * If . + */ +static +NFCSTATUS +phFriNfc_Tpz_H_CheckCCBytesForWrite ( + phFriNfc_NdefMap_t *psNdefMap); + + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function copies the read bytes. + * This function also checks for the lock and reserved bytes and skips the bytes before copying it + * in the buffer. + */ +static +NFCSTATUS +phFriNfc_Tpz_H_CopyReadData ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function copies the stored read bytes. + * This function is used only for the offset " PH_FRINFC_NDEFMAP_SEEK_CUR ". + */ +static +NFCSTATUS +phFriNfc_Tpz_H_RemainingReadDataCopy ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function gives the exact byte address + * of the value field after the NDEF TYPE field + */ +static +uint16_t +phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function gives the exact byte address + * of the value field after the NDEF TYPE field + */ +static +uint16_t +phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite ( + phFriNfc_NdefMap_t *psNdefMap, + uint16_t size_to_write); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function gives the number of bytes to skip. + * This function checks the input byte address and checks if any lock or reserved bytes matches with the + * given address. if yes, then it will return number od bytes to skip. + */ +static +uint16_t +phFriNfc_Tpz_H_GetSkipSize ( + phFriNfc_NdefMap_t *psNdefMap, + uint16_t byte_adr_card); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function gives the actual data that can + * be read and written in the card. + * This function checks for the lock and reserved bytes and subtracts the remaining size to give the + * actual size. + */ +static +NFCSTATUS +phFriNfc_Tpz_H_ActualCardSize ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function processes the response for + * the write data + */ +static +NFCSTATUS +phFriNfc_Tpz_H_ProWrResp ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function processes the read 8 commands, + * that is required for writing the data + */ +static +NFCSTATUS +phFriNfc_Tpz_H_ProRdForWrResp ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function copies the user data to the + * write buffer and writes the data to the card. If the lock or memory blocks are in between the + * write data, then read the current block + */ +static +NFCSTATUS +phFriNfc_Tpz_H_CopySendWrData ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function compares the input block + * number with lock bytes block number and returns the p_skip_size which is the lock bytes + * size + */ +static +uint16_t +phFriNfc_Tpz_H_CompareLockBlocks ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t block_no, + uint16_t *p_skip_size); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function compares the input block + * number with reserved bytes block number and returns the p_skip_size which is the reserved bytes + * size + */ +static +uint16_t +phFriNfc_Tpz_H_CompareMemBlocks ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t block_no, + uint16_t *p_skip_size); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function copies the read data and update + * the user bytes by skipping lock or memory control areas. Also, used while updating the value field + * skips the initial bytes and to start at the proper value field byte offset of the block + */ +static +NFCSTATUS +phFriNfc_Tpz_H_CopyReadDataAndWrite ( + phFriNfc_NdefMap_t *psNdefMap); + + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function reads the required block for writing, + * as some of the bytes shall not be overwritten + */ +static +NFCSTATUS +phFriNfc_Tpz_H_RdForWrite ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function reads the length block for writing, + * updates the length bytes with 0 + */ +static +NFCSTATUS +phFriNfc_Tpz_H_UpdateLenFieldZeroAfterRead ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function reads the length block for writing, + * updates the length bytes with exact bytes that was written in the card + */ +static +NFCSTATUS +phFriNfc_Tpz_H_UpdateLenFieldValuesAfterRead ( + phFriNfc_NdefMap_t *psNdefMap); + +/*! + * \brief \copydoc page_ovr Helper function for Topaz. This function writes the NDEF TYPE of the + * NDEF TLV to the specific byte address. This function is called only if the previous write is + * failed or there is no NDEF TLV with correct CC bytes + */ +static +NFCSTATUS +phFriNfc_Tpz_H_UpdateNdefTypeField ( + phFriNfc_NdefMap_t *psNdefMap); + +#ifdef FRINFC_READONLY_NDEF + +static +NFCSTATUS +phFriNfc_Tpz_H_ProcessReadOnly ( + phFriNfc_NdefMap_t *psNdefMap); + +static +NFCSTATUS +phFriNfc_Tpz_H_UpdateAndWriteLockBits ( + phFriNfc_NdefMap_t *psNdefMap); + + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + + +/*! +* \brief Check whether a particular Remote Device is NDEF compliant. +* +* The function checks whether the peer device is NDEF compliant. +* +* \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t +* structure describing the component context. +* +* \retval NFCSTATUS_PENDING The action has been successfully triggered. +* \retval Others An error has occurred. +* +*/ +NFCSTATUS phFriNfc_TopazDynamicMap_ChkNdef( phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + if ( NdefMap != NULL) + { + /* Update the previous operation */ + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE; + /* Update the CR index to know from which operation completion + routine has to be called */ + NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_CHK_NDEF; + NdefMap->TopazContainer.Cur_RW_Index = PH_FRINFC_TOPAZ_VAL0; + NdefMap->TopazContainer.CurrentSeg = 0; + NdefMap->TopazContainer.NdefTLVByteAddress = 0; + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + + NdefMap->TopazContainer.CurrentBlock = 0; + NdefMap->TopazContainer.WriteSeq = 0; + NdefMap->TopazContainer.ExpectedSeq = 0; + + (void)memset ((void *)&(NdefMap->LockTlv), 0, + sizeof (phFriNfc_LockCntrlTLVCont_t)); + + (void)memset ((void *)&(NdefMap->MemTlv), 0, + sizeof (phFriNfc_ResMemCntrlTLVCont_t)); + + /* Set card state */ + NdefMap->CardType = PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD; + + /* Change the state to Read */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_READ; + + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_DYNAMIC_INIT_CHK_NDEF; +#ifdef TOPAZ_RAW_SUPPORT + + *NdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG; + +#else + +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead; +#endif + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + Result = phFriNfc_Tpz_H_NxpRead(NdefMap); + + } + return Result; +} + + +/*! +* \brief Initiates Reading of NDEF information from the Remote Device. +* +* The function initiates the reading of NDEF information from a Remote Device. +* It performs a reset of the state and starts the action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action +* has been triggered. +*/ + +NFCSTATUS phFriNfc_TopazDynamicMap_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Copy user buffer to the context */ + NdefMap->ApduBuffer = PacketData; + /* Copy user length to the context */ + NdefMap->ApduBufferSize = *PacketDataLength; + /* Update the user memory size to a context variable */ + NdefMap->NumOfBytesRead = PacketDataLength; + /* Number of bytes read from the card is zero. + This variable returns the number of bytes read + from the card. */ + *NdefMap->NumOfBytesRead = 0; + /* Index to know the length read */ + NdefMap->ApduBuffIndex = PH_FRINFC_TOPAZ_VAL0; + /* Store the offset in the context */ + NdefMap->Offset = Offset; + /* Update the CR index to know from which operation completion + routine has to be called */ + NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_RD_NDEF; + NdefMap->TopazContainer.SkipLockBlkFlag = 0; + + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + if ((PH_FRINFC_NDEFMAP_SEEK_CUR == Offset) && + (TRUE == NdefMap->TopazContainer.ReadWriteCompleteFlag)) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else if ((PH_NDEFMAP_CARD_STATE_INITIALIZED == + NdefMap->CardState) || + (0 == NdefMap->TopazContainer.ActualNDEFMsgSize)) + { + /* Length field of NDEF TLV is 0, so read cannot proceed */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_READ_FAILED); + } + else if ((PH_FRINFC_NDEFMAP_SEEK_BEGIN == Offset) || + (PH_FRINFC_NDEFMAP_READ_OPE != NdefMap->PrevOperation)) + { + /* If previous operation is not read then the read shall + start from BEGIN */ + NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN; + /* Initialise byte number */ + NdefMap->TopazContainer.Cur_RW_Index = PH_FRINFC_TOPAZ_VAL0; + + NdefMap->TopazContainer.RemainingReadSize = 0; + NdefMap->TopazContainer.ReadBufferSize = 0; + NdefMap->TopazContainer.ReadWriteCompleteFlag = FALSE; + NdefMap->TopazContainer.CurrentBlock = 0; + NdefMap->TopazContainer.WriteSeq = 0; + + NdefMap->TopazContainer.CurrentSeg = (uint8_t)TOPAZ_SEG_FROM_BYTE_ADR ( + phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (NdefMap)); + + /* Change the state to Read ID */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_READID; + /*Change the state to Read ID*/ + NdefMap->TopazContainer.ReadWriteCompleteFlag = 0; +#ifdef TOPAZ_RAW_SUPPORT + + NdefMap->SendRecvBuf[0] = PH_FRINFC_TOPAZ_CMD_READID; + +#else + +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_RID; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRid; +#endif + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + Result = phFriNfc_Tpz_H_NxpRead(NdefMap); + + } + else + { + /* Change the state to Read */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_READ; + Result = phFriNfc_Tpz_H_RemainingReadDataCopy (NdefMap); + } + + + return Result; +} + +#ifdef FRINFC_READONLY_NDEF + +NFCSTATUS +phFriNfc_TopazDynamicMap_ConvertToReadOnly ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t cc_read_only_byte = 0x0FU; + + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_READ_ONLY; + + psNdefMap->TopazContainer.read_only_seq = 0; + + + + psNdefMap->TopazContainer.CurrentBlock = 0x01U; + psNdefMap->TopazContainer.ByteNumber = 0x03U; + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_WRITE_1E; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, &cc_read_only_byte, + 1); + + if (NFCSTATUS_PENDING == result) + { + psNdefMap->TopazContainer.read_only_seq = (uint8_t)WR_READONLY_CC; + } + + + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/*! +* \brief Initiates Writing of NDEF information to the Remote Device. +* +* The function initiates the writing of NDEF information to a Remote Device. +* It performs a reset of the state and starts the action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action +* has been triggered. +*/ +NFCSTATUS phFriNfc_TopazDynamicMap_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Copy user buffer to the context */ + NdefMap->ApduBuffer = PacketData; + /* Copy user length to the context */ + NdefMap->ApduBufferSize = *PacketDataLength; + /* Index to know the length written */ + NdefMap->ApduBuffIndex = 0; + /* Update the user memory size to a context variable */ + NdefMap->WrNdefPacketLength = PacketDataLength; + /* Number of bytes written to the card is zero. + This variable returns the number of bytes written + to the card. */ + *NdefMap->WrNdefPacketLength = 0; + /* Update the CR index to know from which operation completion + routine has to be called */ + NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_WR_NDEF; + /* Store the offset in the context */ + NdefMap->Offset = Offset; + + /* Update the previous operation to write operation */ + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + + if (PH_NDEFMAP_CARD_STATE_READ_ONLY == NdefMap->CardState) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_WRITE_FAILED); + } + else if ((PH_FRINFC_NDEFMAP_SEEK_CUR == Offset) && + (TRUE == NdefMap->TopazContainer.ReadWriteCompleteFlag)) + { + /* Offset = Current, but the read has reached the End of Card */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else if (0 == NdefMap->TopazContainer.NdefTLVByteAddress) + { + /* No NDEF TLV found in the card, so write not possible */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else if ((PH_FRINFC_NDEFMAP_SEEK_BEGIN == Offset) || + (PH_FRINFC_NDEFMAP_WRITE_OPE != NdefMap->PrevOperation)) + { + NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN; + /* Initialise byte number */ + NdefMap->TopazContainer.Cur_RW_Index = PH_FRINFC_TOPAZ_VAL0; + /* State has to be changed */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_READ; + NdefMap->TopazContainer.ReadWriteCompleteFlag = FALSE; + + NdefMap->TopazContainer.CurrentSeg = 0; + NdefMap->TopazContainer.CurrentBlock = 1; + NdefMap->TopazContainer.WriteSeq = 0; + +#ifdef TOPAZ_RAW_SUPPORT + + *NdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8; + +#else + + /* Topaz command = Jewel Nxp Read */ +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_Read; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead; +#endif + + NdefMap->Cmd.JewelCmd = phHal_eJewel_Read8; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + /* Call read segment */ + Result = phFriNfc_Tpz_H_NxpRead (NdefMap); + } + else + { +#if 0 + /* This part is to handle the Current offset, + Current offset is not yet validated */ + Result = phFriNfc_Tpz_H_NxpWrite(NdefMap); +#endif /* #if 0 */ + } + + return Result; +} + + +/*! +* \brief Completion Routine, Processing function, needed to avoid long blocking. +* \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion +* Routine in order to be able to notify the component that an I/O has finished and data are +* ready to be processed. +* +*/ + +void phFriNfc_TopazDynamicMap_Process( void *Context, + NFCSTATUS Status) +{ + + phFriNfc_NdefMap_t *NdefMap; + + NdefMap = (phFriNfc_NdefMap_t *)Context; + + + if((NFCSTATUS_SUCCESS & PHNFCSTBLOWER) == (Status & PHNFCSTBLOWER)) + { + switch(NdefMap->State) + { + case PH_FRINFC_TOPAZ_STATE_READ: + { + Status = phFriNfc_Tpz_H_ProReadResp (NdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE: + { + Status = phFriNfc_Tpz_H_ProWrResp (NdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF: + { + Status = phFriNfc_Tpz_H_ProRdForWrResp (NdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_READID: + { + Status = phFriNfc_Tpz_H_ChkReadID(NdefMap); + break; + } + +#ifdef FRINFC_READONLY_NDEF + case PH_FRINFC_TOPAZ_STATE_READ_ONLY: + { + Status = phFriNfc_Tpz_H_ProcessReadOnly (NdefMap); + break; + } +#endif /* #ifdef FRINFC_READONLY_NDEF */ + + default: + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + } + + /* Call for the Completion Routine*/ + if(Status != NFCSTATUS_PENDING) + { + phFriNfc_Tpz_H_Complete(NdefMap, Status); + } +} + +#ifdef FRINFC_READONLY_NDEF + +static +NFCSTATUS +phFriNfc_Tpz_H_UpdateAndWriteLockBits ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL; + uint8_t remaining_lock_bits = 0; + uint8_t byte_index = 0; + uint8_t lock_bytes_value[TOPAZ_BYTES_PER_BLOCK] = {0}; + uint8_t lock_byte_index = 0; + uint8_t no_of_bits_left_in_block = 0; + + ps_tpz_info = &(psNdefMap->TopazContainer); + ps_locktlv_info = &(psNdefMap->LockTlv); + + (void)memcpy ((void *)lock_bytes_value, (void *)psNdefMap->SendRecvBuf, + TOPAZ_BYTES_PER_BLOCK); + + if (ps_tpz_info->CurrentBlock == ps_locktlv_info->BlkNum) + { + /* Get the lock bits that has to locked */ + remaining_lock_bits = ps_locktlv_info->LockTlvBuff[1]; + byte_index = (uint8_t)ps_locktlv_info->ByteNum; + } + else + { + /* This condition applies only for the lock bits not ending with + " ps_locktlv_info->BlkNum ". + Calculate the remaining lock bits */ + remaining_lock_bits = (uint8_t)(ps_locktlv_info->LockTlvBuff[1] - + ps_tpz_info->lock_bytes_written); + } + + no_of_bits_left_in_block = (uint8_t)((TOPAZ_BYTES_PER_BLOCK - byte_index) * + TOPAZ_BYTE_SIZE_IN_BITS); + + if (no_of_bits_left_in_block >= remaining_lock_bits) + { + /* Entire lock bits can be written */ + uint8_t mod_value = 0; + + mod_value = (uint8_t)(remaining_lock_bits % TOPAZ_BYTES_PER_BLOCK); + + if (mod_value) + { + /* The lock bits ends in between of a byte */ + /* lock bits to write is greater than 8 bits */ + if (mod_value > TOPAZ_BYTE_SIZE_IN_BITS) + { + while (lock_byte_index < + (TOPAZ_CONVERT_BITS_TO_BYTES(remaining_lock_bits) - 1)) + { + /* Set 1b to all bits left in the block */ + lock_bytes_value[byte_index] = 0xFF; + lock_byte_index = (uint8_t)(lock_byte_index + 1); + byte_index = (uint8_t)(byte_index + 1); + } + /* Last byte of the lock bits shall be filled partially, + Set only the remaining lock bits and dont change + the other bit value */ + lock_bytes_value[byte_index] = 0; + lock_bytes_value[byte_index] = (uint8_t) + SET_BITS8 (lock_bytes_value[byte_index], 0, + mod_value, 1); + } + else + { + /* lock bits to write is less than 8 bits, so + there is only one byte to write. + Set only the remaining lock bits and dont change + the other bit value */ + lock_bytes_value[0] = (uint8_t) + SET_BITS8 (lock_bytes_value[0], 0, + mod_value, 1); + } + } /* if (mod_value) */ + else + { + /* The lock bits exactly ends at a byte + MOD operation is 00, that means entire byte value shall be 0xFF, means + every bit shall be to 1 */ + + while (lock_byte_index < TOPAZ_CONVERT_BITS_TO_BYTES(remaining_lock_bits)) + { + /* Set 1b to all bits left in the block */ + lock_bytes_value[byte_index] = 0xFF; + lock_byte_index = (uint8_t)(lock_byte_index + 1); + byte_index = (uint8_t)(byte_index + 1); + } + } /* else of if (mod_value) */ + ps_tpz_info->lock_bytes_written = remaining_lock_bits; + } + else /* if (no_of_bits_left_in_block >= remaining_lock_bits) */ + { + /* Partial lock bits can be written. use next read to write + the remaining lock bits */ + while (lock_byte_index < (no_of_bits_left_in_block / + TOPAZ_BYTES_PER_BLOCK)) + { + /* Set 1b to all bits left in the block */ + lock_bytes_value[byte_index] = 0xFF; + lock_byte_index = (uint8_t)(lock_byte_index + 1); + byte_index = (uint8_t)(byte_index + 1); + } + ps_tpz_info->lock_bytes_written = (uint8_t)(no_of_bits_left_in_block / + TOPAZ_BYTES_PER_BLOCK); + } /* else of if (no_of_bits_left_in_block >= remaining_lock_bits) */ + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, lock_bytes_value, + sizeof (lock_bytes_value)); + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_ProcessReadOnly ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_Tpz_RO_Seq_t e_readonly_seq = RD_LOCK_BYTES; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL; + static uint8_t static_lock_bytes[2] = {0}; + + ps_tpz_info = &(psNdefMap->TopazContainer); + ps_locktlv_info = &(psNdefMap->LockTlv); + e_readonly_seq = (phFriNfc_Tpz_RO_Seq_t)psNdefMap->TopazContainer.read_only_seq; + + switch (e_readonly_seq) + { + case WR_READONLY_CC: + { + if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength) + { + psNdefMap->TopazContainer.CurrentBlock = (uint8_t) + psNdefMap->LockTlv.BlkNum; + + e_readonly_seq = RD_LOCK_BYTES; +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8; + +#else + + /* Topaz command = Jewel Nxp Read */ +#ifdef PH_HAL4_ENABLE + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead; +#endif + + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + /* Call read segment */ + result = phFriNfc_Tpz_H_NxpRead (psNdefMap); + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case RD_LOCK_BYTES: + { + if (TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength) + { + result = phFriNfc_Tpz_H_UpdateAndWriteLockBits (psNdefMap); + + if (NFCSTATUS_PENDING == result) + { + e_readonly_seq = WR_LOCK_BYTES; + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case WR_LOCK_BYTES: + { + if (TOPAZ_WRITE_8_RESPONSE == *psNdefMap->SendRecvLength) + { + ps_tpz_info->CurrentBlock = (uint8_t) + (ps_tpz_info->CurrentBlock + 1); + if (ps_locktlv_info->LockTlvBuff[1] - + ps_tpz_info->lock_bytes_written) + { +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8; + +#else + + /* Topaz command = Jewel Nxp Read */ +#ifdef PH_HAL4_ENABLE + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead; +#endif + + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + /* Call read segment */ + result = phFriNfc_Tpz_H_NxpRead (psNdefMap); + e_readonly_seq = RD_LOCK_BYTES; + } + else + { + ps_tpz_info->CurrentBlock = (uint8_t) + DYN_STATIC_LOCK_BLOCK_NUM; + ps_tpz_info->ByteNumber = (uint8_t) + DYN_STATIC_LOCK0_BYTE_NUM; +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_READ8; + +#else + + /* Topaz command = Jewel Nxp Read */ +#ifdef PH_HAL4_ENABLE + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead; +#endif + + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + /* Call read segment */ + result = phFriNfc_Tpz_H_NxpRead (psNdefMap); + e_readonly_seq = RD_STATIC_LOCK_BYTE0; + + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case RD_STATIC_LOCK_BYTE0: + { + if (TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength) + { + uint8_t lock_byte_value = 0; + + (void)memcpy ((void *)static_lock_bytes, + (void *)(psNdefMap->SendRecvBuf + + ps_tpz_info->ByteNumber), + sizeof (static_lock_bytes)); + + + lock_byte_value = (uint8_t)(static_lock_bytes[0] | + DYN_STATIC_LOCK0_BYTE_VALUE); + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_WRITE_1E; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, &lock_byte_value, + 1); + + if (NFCSTATUS_PENDING == result) + { + e_readonly_seq = (uint8_t)WR_STATIC_LOCK_BYTE0; + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case WR_STATIC_LOCK_BYTE0: + { + if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength) + { + uint8_t lock_byte_value = + (static_lock_bytes[1] | + DYN_STATIC_LOCK1_BYTE_VALUE); + + ps_tpz_info->CurrentBlock = (uint8_t) + DYN_STATIC_LOCK_BLOCK_NUM; + ps_tpz_info->ByteNumber = (uint8_t) + DYN_STATIC_LOCK1_BYTE_NUM; +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_WRITE_1E; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, &lock_byte_value, + 1); + + if (NFCSTATUS_PENDING == result) + { + e_readonly_seq = (uint8_t)WR_STATIC_LOCK_BYTE1; + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case WR_STATIC_LOCK_BYTE1: + { + if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength) + { + /* READ ONLY successful */ + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + break; + } + } + + psNdefMap->TopazContainer.read_only_seq = (uint8_t)e_readonly_seq; + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +static +NFCSTATUS +phFriNfc_Tpz_H_ProWrResp ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + phFriNfc_Tpz_WrSeq_t write_seq; + uint8_t write_buf[] = {0x00}; + uint8_t write_index = 0; + uint16_t write_len = 0; + uint16_t len_byte_addr = 0; + + ps_tpz_info = &(psNdefMap->TopazContainer); + write_seq = (phFriNfc_Tpz_WrSeq_t)(ps_tpz_info->WriteSeq); + write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ? + psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize); + + switch (write_seq) + { + case WR_NDEF_T_TLV: + { + /* TYPE field of the NDEF TLV write is complete */ + if (TOPAZ_WRITE_8_RESPONSE == *psNdefMap->SendRecvLength) + { + psNdefMap->State = (uint8_t) + PH_FRINFC_TOPAZ_STATE_WRITE; + + /* Now, Write 0 to the magic number byte */ + ps_tpz_info->WriteSeq = (uint8_t)WR_NMN_0; + write_seq = WR_NMN_0; + ps_tpz_info->CurrentBlock = 1; + ps_tpz_info->ByteNumber = 0; + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_1E; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf, + sizeof (write_buf)); + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case WR_NMN_0: + { + /* Magic number set to 0 write is complete */ + if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength) + { + ps_tpz_info->WriteSeq = (uint8_t)(write_seq + 1); + write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1); + /* Now the sequence = WR_LEN_1_0, so Length block is read, + and only length bytes are made 0, before writing data to 0 + */ + result = phFriNfc_Tpz_H_RdForWrite (psNdefMap); + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case WR_LEN_1_0: + { + /* Length field is updated with the value 0 */ + if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + else if (write_len >= 0xFF) + { + ps_tpz_info->ByteNumber = 0; + + ps_tpz_info->CurrentBlock = (uint8_t) + TOPAZ_INCREMENT_SKIP_STATIC_BLOCK ( + ps_tpz_info->CurrentBlock); + + ps_tpz_info->WriteSeq = (uint8_t)(write_seq + 1); + write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1); + /* Now the sequence = WR_LEN_1_1, so Length block is read, + and only length bytes are made 0, before writing data to 0 + */ + result = phFriNfc_Tpz_H_RdForWrite (psNdefMap); + } + else + { + /* NDEF data length < 0xFF */ + len_byte_addr = phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite + (psNdefMap, write_len); + ps_tpz_info->CurrentBlock = (uint8_t) + TOPAZ_BLK_FROM_BYTE_ADR (len_byte_addr); + ps_tpz_info->ByteNumber = (uint8_t) + TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR (len_byte_addr); + + + ps_tpz_info->WriteSeq = (uint8_t)WR_DATA; + write_seq = WR_DATA; + + if (0 != ps_tpz_info->ByteNumber) + { + /* If data starts in between the block then read + the data */ + result = phFriNfc_Tpz_H_RdForWrite (psNdefMap); + } + else + { + /* Data starts at the beginning of the block, so start + writing the user data */ + result = phFriNfc_Tpz_H_CopySendWrData (psNdefMap); + } + } + break; + } + + case WR_LEN_2_0: + case WR_LEN_2_VALUE: + { + /* 2nd length field is updated with the value 0 or the correct + written value */ + if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + else + { + ps_tpz_info->ByteNumber = 0; + ps_tpz_info->CurrentBlock = (uint8_t) + TOPAZ_INCREMENT_SKIP_STATIC_BLOCK ( + ps_tpz_info->CurrentBlock); + ps_tpz_info->WriteSeq = (uint8_t)(write_seq + 1); + write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1); + /* If length byte starts in between the block then read + the length block */ + result = phFriNfc_Tpz_H_RdForWrite (psNdefMap); + } + break; + } + + case WR_LEN_3_0: + { + /* 3rd length field is updated with the value 0 */ + if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + else + { + len_byte_addr = phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite + (psNdefMap, write_len); + ps_tpz_info->CurrentBlock = (uint8_t) + TOPAZ_BLK_FROM_BYTE_ADR (len_byte_addr); + ps_tpz_info->ByteNumber = (uint8_t) + TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR (len_byte_addr); + + ps_tpz_info->WriteSeq = (uint8_t)(write_seq + 1); + write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1); + + if (0 != ps_tpz_info->ByteNumber) + { + /* If data starts in between the block then read + the data */ + result = phFriNfc_Tpz_H_RdForWrite (psNdefMap); + } + else + { + /* Data starts at the beginning of the block, so start + writing the user data */ + result = phFriNfc_Tpz_H_CopySendWrData (psNdefMap); + } + } + break; + } + + case WR_DATA: + { + /* Data is written from the input buffer */ + if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + else if (write_len == psNdefMap->ApduBuffIndex) + { + /* Data to be written is completely written to the card */ + *psNdefMap->WrNdefPacketLength = psNdefMap->ApduBuffIndex; + ps_tpz_info->WriteSeq = (uint8_t)WR_LEN_1_VALUE; + write_seq = WR_LEN_1_VALUE; + /* To write the first length byte, it has to be read and then + the length has to be updated */ + result = phFriNfc_Tpz_H_RdForWrite (psNdefMap); + } + else + { + ps_tpz_info->ByteNumber = 0; + /* Go to the next block */ + ps_tpz_info->CurrentBlock = (uint8_t) + TOPAZ_INCREMENT_SKIP_STATIC_BLOCK ( + ps_tpz_info->CurrentBlock); + /* Copy and write the user data */ + result = phFriNfc_Tpz_H_CopySendWrData (psNdefMap); + } + break; + } + + case WR_DATA_READ_REQD: + { + /* This sequence is executed, if the first read has some + lock or reserved blocks bytes and the lock or reserved + blocks are extended to the next block */ + if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + else + { + ps_tpz_info->ByteNumber = 0; + /* Go to the next block */ + ps_tpz_info->CurrentBlock = (uint8_t) + TOPAZ_INCREMENT_SKIP_STATIC_BLOCK ( + ps_tpz_info->CurrentBlock); + /* Write is complete for one block, now because lock bytes are + shifted to next blocks, the next block is read and update + the written data by skipping the lock or reserved memory bytes */ + result = phFriNfc_Tpz_H_RdForWrite (psNdefMap); + } + break; + } + + case WR_LEN_3_VALUE: + { + /* 3rd LENGTH field byte is updated with correct written value */ + if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + else + { +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_1E; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + psNdefMap->State = (uint8_t)PH_FRINFC_TOPAZ_STATE_WRITE; + + write_buf[write_index] = PH_FRINFC_TOPAZ_CC_BYTE0; + write_index = (uint8_t)(write_index + 1); + + ps_tpz_info->ByteNumber = 0; + ps_tpz_info->CurrentBlock = 1; + + ps_tpz_info->WriteSeq = (uint8_t)WR_NMN_E1; + write_seq = WR_NMN_E1; + + /* Length byte write is complete, so now update the magic + number byte with value 0xE1 */ + result = phFriNfc_Tpz_H_NxpWrite(psNdefMap, write_buf, + write_index); + } + break; + } + + case WR_LEN_1_VALUE: + { + /* 1st LENGTH field byte is updated */ + if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + else if (write_len < 0xFF) + { + /* Total length to write is less than 0xFF, so LENGTH field has + only one byte, then update the magic number byte with + value 0xE1 */ +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_1E; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + psNdefMap->State = (uint8_t)PH_FRINFC_TOPAZ_STATE_WRITE; + + write_buf[write_index] = PH_FRINFC_TOPAZ_CC_BYTE0; + write_index = (uint8_t)(write_index + 1); + + ps_tpz_info->ByteNumber = 0; + ps_tpz_info->CurrentBlock = 1; + + ps_tpz_info->WriteSeq = (uint8_t)WR_NMN_E1; + write_seq = WR_NMN_E1; + result = phFriNfc_Tpz_H_NxpWrite(psNdefMap, write_buf, + write_index); + } + else + { + /* 2nd byte of the LENGTH field has to be updated so, + read the block, before updating it */ + ps_tpz_info->ByteNumber = 0; + ps_tpz_info->CurrentBlock = (uint8_t) + TOPAZ_INCREMENT_SKIP_STATIC_BLOCK ( + ps_tpz_info->CurrentBlock); + ps_tpz_info->WriteSeq = (uint8_t)WR_LEN_2_VALUE; + write_seq = WR_LEN_2_VALUE; + result = phFriNfc_Tpz_H_RdForWrite (psNdefMap); + } + break; + } + + case WR_NMN_E1: + { + /* Magic number is written, so update the actual ndef length. */ + if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength) + { + *psNdefMap->WrNdefPacketLength = (uint32_t) + psNdefMap->ApduBuffIndex; + ps_tpz_info->ActualNDEFMsgSize = (uint16_t) + psNdefMap->ApduBuffIndex; + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + default: + { + break; + } + } + + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_UpdateNdefTypeField ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + uint8_t write_buf[TOPAZ_WRITE_8_DATA_LENGTH]; + + ps_tpz_info = &(psNdefMap->TopazContainer); + + (void)memcpy ((void *)write_buf, (void *) + psNdefMap->SendRecvBuf, TOPAZ_WRITE_8_DATA_LENGTH); + + /* Update the TYPE field of the NDEF TLV */ + write_buf[ps_tpz_info->ByteNumber] = PH_FRINFC_TOPAZ_NDEF_T; + + psNdefMap->State = (uint8_t)PH_FRINFC_TOPAZ_STATE_WRITE; + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + result = phFriNfc_Tpz_H_NxpWrite(psNdefMap, write_buf, + sizeof (write_buf)); + + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_ProRdForWrResp ( + phFriNfc_NdefMap_t *psNdefMap) +{ + /* This function is used during the write operation */ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + + ps_tpz_info = &(psNdefMap->TopazContainer); + + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE; + + if (TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength) + { + switch ((phFriNfc_Tpz_WrSeq_t)ps_tpz_info->WriteSeq) + { + case WR_NDEF_T_TLV: + { + /* Read bytes are for updating the TYPE field of the NDEF TLV */ + result = phFriNfc_Tpz_H_UpdateNdefTypeField (psNdefMap); + break; + } + + case WR_LEN_1_0: + case WR_LEN_2_0: + case WR_LEN_3_0: + { + /* Read bytes are for updating the LENGTH field to 0 of the NDEF TLV and + also to update the data from the user buffer */ + result = phFriNfc_Tpz_H_UpdateLenFieldZeroAfterRead (psNdefMap); + break; + } + + case WR_DATA: + case WR_DATA_READ_REQD: + { + /* Read bytes are for skipping the lock and reserved bytes */ + result = phFriNfc_Tpz_H_CopyReadDataAndWrite (psNdefMap); + break; + } + + case WR_LEN_1_VALUE: + case WR_LEN_2_VALUE: + case WR_LEN_3_VALUE: + { + /* Read bytes are for updating the LENGTH field to the correct values + of the NDEF TLV */ + result = phFriNfc_Tpz_H_UpdateLenFieldValuesAfterRead (psNdefMap); + break; + } + + default: + { + /* Code must not come come here */ + break; + } + } + } + else + { + /* Error in the length, wither the HW has sent wrong response length or + the response length byte is corrupted */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + + + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_ChkReadID( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + int compare_result = 0; + uint8_t recv_index = 0; + + + if (PH_FRINFC_TOPAZ_VAL6 == *psNdefMap->SendRecvLength) + { + if (((psNdefMap->SendRecvBuf[recv_index] & + PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_DYNAMIC_HEADROM0_VAL)) + { + /* Copy UID to the context*/ + compare_result = phOsalNfc_MemCompare ( + psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid, + &psNdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2], + TOPAZ_UID_LENGTH_FOR_READ_WRITE); + if (0 == compare_result) + { + /* State has to be changed */ + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_READ; + + /* Topaz command = READSEG */ +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG; + +#else + +#ifdef PH_HAL4_ENABLE + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead; +#endif + psNdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + /* Read bytes from the card */ + result = phFriNfc_Tpz_H_NxpRead (psNdefMap); + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + + } + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + + return result; +} + +#define TOPAZ_READ_ID_ZERO_LENGTH (0x06U) +static +NFCSTATUS +phFriNfc_Tpz_H_NxpRead ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t send_index = 0; +#ifdef TOPAZ_RAW_SUPPORT + uint8_t read_append[] = { 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + /* set the data for additional data exchange*/ + psNdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0; + psNdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0; + psNdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0; + + psNdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazDynamicMap_Process; + psNdefMap->MapCompletionInfo.Context = psNdefMap; + + *psNdefMap->SendRecvLength = psNdefMap->TempReceiveLength; + + /* Depending on the jewel command, the send length is decided */ +#ifdef TOPAZ_RAW_SUPPORT + + psNdefMap->Cmd.JewelCmd = (phNfc_eJewelCmdList_t)phHal_eJewel_Raw; + /* " send_index " is incremented because already received buffer is filled with + TOPAZ command */ + send_index = (uint8_t)(send_index + 1); + + switch (*psNdefMap->SendRecvBuf) +#else + switch(psNdefMap->Cmd.JewelCmd) +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + { +#ifdef TOPAZ_RAW_SUPPORT + + case PH_FRINFC_TOPAZ_CMD_READID: + { + (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), + (void *)read_append, TOPAZ_READ_ID_ZERO_LENGTH); + send_index = (uint8_t)(send_index + TOPAZ_READ_ID_ZERO_LENGTH); + break; + } + + case PH_FRINFC_TOPAZ_CMD_READ8: + { + psNdefMap->SendRecvBuf[send_index] = + psNdefMap->TopazContainer.CurrentBlock; + send_index = (uint8_t)(send_index + 1); + break; + } + + case PH_FRINFC_TOPAZ_CMD_RSEG: + { + psNdefMap->SendRecvBuf[send_index] = (uint8_t) + (psNdefMap->TopazContainer.CurrentSeg + << NIBBLE_SIZE); + send_index = (uint8_t)(send_index + 1); + break; + } + +#else /* #ifdef TOPAZ_RAW_SUPPORT */ + +#ifdef PH_HAL4_ENABLE + case phHal_eJewel_RID: + case phHal_eJewel_ReadAll: +#else + case phHal_eJewelCmdListJewelRid: + case phHal_eJewelCmdListJewelReadAll: +#endif + { + /* For READ ID and READ ALL, send length is 0 */ + psNdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0; + break; + } + +#ifdef PH_HAL4_ENABLE + case phHal_eJewel_Read: +#else + case phHal_eJewelCmdListJewelRead: +#endif + { + /* Need to check the User data size request*/ + + psNdefMap->SendLength = PH_FRINFC_TOPAZ_VAL3; + break; + } + + case phHal_eJewel_ReadSeg: + { + psNdefMap->SendRecvBuf[send_index] = (uint8_t) + (psNdefMap->TopazContainer.CurrentSeg + << NIBBLE_SIZE); + send_index = (uint8_t)(send_index + 1); + psNdefMap->SendLength = send_index; + break; + } + + case phHal_eJewel_Read8: + { + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read4; + psNdefMap->SendRecvBuf[send_index] = psNdefMap->TopazContainer.CurrentBlock; + send_index = (uint8_t)(send_index + 1); + psNdefMap->SendLength = send_index; + break; + } + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + if(result == NFCSTATUS_SUCCESS) + { +#ifdef TOPAZ_RAW_SUPPORT + + if (PH_FRINFC_TOPAZ_CMD_READID != *psNdefMap->SendRecvBuf) + { + (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), + (void *)read_append, sizeof (read_append)); + send_index = (uint8_t)(send_index + sizeof (read_append)); + + (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), + (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid, + TOPAZ_UID_LENGTH_FOR_READ_WRITE); + send_index = (uint8_t)(send_index + + TOPAZ_UID_LENGTH_FOR_READ_WRITE); + } + + psNdefMap->SendLength = send_index; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + /* Call the Overlapped HAL Transceive function */ + result = phFriNfc_OvrHal_Transceive( psNdefMap->LowerDevice, + &psNdefMap->MapCompletionInfo, + psNdefMap->psRemoteDevInfo, + psNdefMap->Cmd, + &psNdefMap->psDepAdditionalInfo, + psNdefMap->SendRecvBuf, + psNdefMap->SendLength, + psNdefMap->SendRecvBuf, + psNdefMap->SendRecvLength); + } + return result; +} + + +static +NFCSTATUS +phFriNfc_Tpz_H_NxpWrite( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *p_write_data, + uint8_t wr_data_len) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + uint8_t send_index = 0; + + ps_tpz_info = &(psNdefMap->TopazContainer); + + /* set the data for additional data exchange*/ + psNdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0; + psNdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0; + psNdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0; + + psNdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazDynamicMap_Process; + psNdefMap->MapCompletionInfo.Context = psNdefMap; + + *psNdefMap->SendRecvLength = psNdefMap->TempReceiveLength; + +#ifdef TOPAZ_RAW_SUPPORT + /* " send_index " is incremented because already received buffer is filled with + TOPAZ command */ + send_index = (uint8_t)(send_index + 1); + psNdefMap->Cmd.JewelCmd = (phNfc_eJewelCmdList_t)phHal_eJewel_Raw; + + switch (*psNdefMap->SendRecvBuf) + +#else /* #ifdef TOPAZ_RAW_SUPPORT */ + + switch (psNdefMap->Cmd.JewelCmd) + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + { +#ifdef TOPAZ_RAW_SUPPORT + + case PH_FRINFC_TOPAZ_CMD_WRITE_1E: + { + psNdefMap->SendRecvBuf[send_index] = (uint8_t)((ps_tpz_info->CurrentBlock + << (NIBBLE_SIZE - 1)) | + ps_tpz_info->ByteNumber); + send_index = (uint8_t)(send_index + 1); + break; + } + + case PH_FRINFC_TOPAZ_CMD_WRITE_E8: + { + psNdefMap->SendRecvBuf[send_index] = ps_tpz_info->CurrentBlock; + send_index = (uint8_t)(send_index + 1); + break; + } + +#else /* #ifdef TOPAZ_RAW_SUPPORT */ + + case phHal_eJewel_Write1E: + { + psNdefMap->SendRecvBuf[send_index] = (uint8_t)((ps_tpz_info->CurrentBlock + << (NIBBLE_SIZE - 1)) | + ps_tpz_info->ByteNumber); + send_index = (uint8_t)(send_index + 1); + + + break; + } + + case phHal_eJewel_Write8E: + { + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write4E; + psNdefMap->SendRecvBuf[send_index] = ps_tpz_info->CurrentBlock; + send_index = (uint8_t)(send_index + 1); + break; + } + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + + + if (NFCSTATUS_SUCCESS == result) + { + (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), + (void *)p_write_data, wr_data_len); + + send_index = (uint8_t)(send_index + wr_data_len); + +#ifdef TOPAZ_RAW_SUPPORT + + (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), + (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid, + TOPAZ_UID_LENGTH_FOR_READ_WRITE); + send_index = (uint8_t)(send_index + TOPAZ_UID_LENGTH_FOR_READ_WRITE); + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + psNdefMap->SendLength = send_index; + + /* Call the Overlapped HAL Transceive function */ + result = phFriNfc_OvrHal_Transceive( psNdefMap->LowerDevice, + &psNdefMap->MapCompletionInfo, + psNdefMap->psRemoteDevInfo, + psNdefMap->Cmd, + &psNdefMap->psDepAdditionalInfo, + psNdefMap->SendRecvBuf, + psNdefMap->SendLength, + psNdefMap->SendRecvBuf, + psNdefMap->SendRecvLength); + } + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_ProReadResp( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + uint8_t write_buffer[] = {0x00}; + + ps_tpz_info = &(psNdefMap->TopazContainer); + + switch (psNdefMap->PrevOperation) + { + case PH_FRINFC_NDEFMAP_CHECK_OPE: + { + if (PH_FRINFC_TOPAZ_DYNAMIC_READSEG_RESP == + *psNdefMap->SendRecvLength) + { + if (0 == ps_tpz_info->CurrentSeg) + { + result = phFriNfc_Tpz_H_CheckCCBytes (psNdefMap); + } + + if (NFCSTATUS_SUCCESS == result) + { + result = phFriNfc_Tpz_H_ParseTLVs (psNdefMap); + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case PH_FRINFC_NDEFMAP_READ_OPE: + { + if (PH_FRINFC_TOPAZ_DYNAMIC_READSEG_RESP == + *psNdefMap->SendRecvLength) + { + /* call the data bytes to internal buffer*/ + result = phFriNfc_Tpz_H_CopyReadData (psNdefMap); + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case PH_FRINFC_NDEFMAP_WRITE_OPE: + { + /* read the bytes for cheking the CC bytes and lock bit status*/ + if(TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength) + { + (void)memcpy ((void *)ps_tpz_info->CCByteBuf, + (void *)(psNdefMap->SendRecvBuf), + TOPAZ_CC_BYTES_LENGTH); + + result = phFriNfc_Tpz_H_CheckCCBytesForWrite (psNdefMap); + if (NFCSTATUS_SUCCESS == result) + { + if ((0x00 == *ps_tpz_info->CCByteBuf) || + (NDEF_T_TLV == ps_tpz_info->ExpectedSeq)) + { + /* This statement is for getting the new + NDEF TLV byte address, because 1st CC byte is + corrupted or no NDEF TLV in the card + + If the 1st CC byte (NDEF magic number) in the + card is 0, means that previous write has failed, + so to write the exact file + OR + The NDEF TLV is not present in the entire card, and + the sequence is NDEF_T_TLV (this means, that lock and + memory control TLV is found in the card) + */ + psNdefMap->State = (uint8_t) + PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF; + ps_tpz_info->WriteSeq = (uint8_t)WR_NDEF_T_TLV; + + ps_tpz_info->CurrentBlock = (uint8_t) + TOPAZ_BLK_FROM_BYTE_ADR ( + ps_tpz_info->NdefTLVByteAddress); + + ps_tpz_info->ByteNumber = (uint8_t) + TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR ( + ps_tpz_info->NdefTLVByteAddress); + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + result = phFriNfc_Tpz_H_NxpRead (psNdefMap); + } + else + { + ps_tpz_info->WriteSeq = (uint8_t)WR_NMN_0; + ps_tpz_info->CurrentBlock = 1; + ps_tpz_info->ByteNumber = 0; + psNdefMap->State = (uint8_t) + PH_FRINFC_TOPAZ_STATE_WRITE; +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_1E; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + /* Call read 8 */ + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buffer, + sizeof (write_buffer)); + } + + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + + return result; +} + + + +static void phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Status) +{ + /* set the state back to the Reset_Init state*/ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; + + /* set the completion routine*/ + NdefMap->CompletionRoutine[NdefMap->TopazContainer.CRIndex]. + CompletionRoutine(NdefMap->CompletionRoutine->Context, Status); +} + +static +NFCSTATUS +phFriNfc_Tpz_H_ChkLockBits( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; +#ifdef ENABLE_LOCK_BITS_CHECK + uint8_t *p_recv_buf = psNdefMap->SendRecvBuf; +#endif /* #ifdef ENABLE_LOCK_BITS_CHECK */ + psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED; + +#ifdef ENABLE_LOCK_BITS_CHECK + + /* Set the card state */ + psNdefMap->CardState = (uint8_t) + (((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_0] == + PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_0) && + ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_1] == + PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_1)) && + ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_2] == + PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) && + ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_3] == + PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) && + ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_4] == + PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) && + ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_5] == + PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) && + ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_6] == + PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7))) && + ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_7] == + PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) ? + PH_NDEFMAP_CARD_STATE_INITIALIZED : + PH_NDEFMAP_CARD_STATE_READ_ONLY); + +#endif /* #ifdef ENABLE_LOCK_BITS_CHECK */ + + /* Set the card state from CC bytes */ + if (PH_NDEFMAP_CARD_STATE_INITIALIZED == psNdefMap->CardState) + { + switch ((psNdefMap->TopazContainer.CCByteBuf[3] & 0xFF)) + { + case PH_FRINFC_TOPAZ_CC_READWRITE: + { + psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED; + break; + } + + case PH_FRINFC_TOPAZ_CC_READONLY: + { + psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY; + break; + } + + default: + { + psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + } + + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_CheckCCBytes ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = &(psNdefMap->TopazContainer); + uint8_t *p_recv_buf = psNdefMap->SendRecvBuf; + uint16_t parse_index = 0; + + parse_index = (uint16_t)(parse_index + TOPAZ_UID_BYTES_LENGTH); + + (void)memcpy ((void *)ps_tpz_info->CCByteBuf, + (void *)(p_recv_buf + parse_index), + TOPAZ_CC_BYTES_LENGTH); + + p_recv_buf = ps_tpz_info->CCByteBuf; + parse_index = 0; + +#ifdef TOPAZ_MAGIC_NO_CHK_ENABLE + /* 1st CC byte value = 0 or 0xE1 */ + if ((PH_FRINFC_TOPAZ_CC_BYTE0 == p_recv_buf[parse_index]) +#ifdef TOPAZ_MAGIC_NO_0_CHK_ENABLE + || (0 == p_recv_buf[parse_index]) +#endif /* #if TOPAZ_MAGIC_NO_0_CHK_ENABLE */ + ) +#endif /* #ifdef TOPAZ_MAGIC_NO_CHK_ENABLE */ + { + parse_index = (uint16_t)(parse_index + 1); + /* 2nd CC byte value = 0x10 */ + result = phFriNfc_Tpz_H_ChkSpcVer (psNdefMap, p_recv_buf[parse_index]); + } +#ifdef TOPAZ_MAGIC_NO_CHK_ENABLE + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } +#endif /* #ifdef TOPAZ_MAGIC_NO_CHK_ENABLE */ + + if (NFCSTATUS_SUCCESS == result) + { + parse_index = (uint16_t)(parse_index + 1); + /* 3rd CC byte value = 0x3F for 512 card */ + if (PH_FRINFC_TOPAZ_DYNAMIC_CC_BYTE2_MMSIZE == p_recv_buf[parse_index]) + { + /* Card size calculated as ((3rd CC byte * 8) - 4 CC bytes) */ + psNdefMap->CardMemSize = (uint16_t)((p_recv_buf[parse_index] * + TOPAZ_BYTES_PER_BLOCK) - + TOPAZ_CC_BYTES_LENGTH); + ps_tpz_info->RemainingSize = (uint16_t)(psNdefMap->CardMemSize + + TOPAZ_UID_BYTES_LENGTH + + TOPAZ_CC_BYTES_LENGTH); + result = phFriNfc_Tpz_H_ChkLockBits (psNdefMap); + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + } + + if (NFCSTATUS_SUCCESS != result) + { + psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } + + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_CheckCCBytesForWrite ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + uint8_t check_cc_rw[] = {TOPAZ_SPEC_VERSION, + PH_FRINFC_TOPAZ_DYNAMIC_CC_BYTE2_MMSIZE, + PH_FRINFC_TOPAZ_CC_READWRITE}; + uint8_t check_index = 0; + + ps_tpz_info = &(psNdefMap->TopazContainer); + +#ifdef TOPAZ_MAGIC_NO_CHK_ENABLE + if ( + (PH_FRINFC_TOPAZ_CC_BYTE0 == ps_tpz_info->CCByteBuf[check_index]) +#if TOPAZ_MAGIC_NO_0_CHK_ENABLE + || (0 == ps_tpz_info->CCByteBuf[check_index]) +#endif /* #if TOPAZ_MAGIC_NO_0_CHK_ENABLE */ + ) +#endif /* #ifdef TOPAZ_MAGIC_NO_CHK_ENABLE */ + { + check_index = (uint8_t)(check_index + 1); + + if ((!TOPAZ_COMPARE_VERSION(check_cc_rw[0], ps_tpz_info->CCByteBuf[1])) || + (check_cc_rw[1] != ps_tpz_info->CCByteBuf[2]) || + (check_cc_rw[2] != ps_tpz_info->CCByteBuf[3])) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + } +#ifdef TOPAZ_MAGIC_NO_CHK_ENABLE + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } +#endif /* #ifdef TOPAZ_MAGIC_NO_CHK_ENABLE */ + return result; +} + +static +uint16_t +phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead ( + phFriNfc_NdefMap_t *psNdefMap) +{ + phFriNfc_TopazCont_t *ps_tpz_info = &(psNdefMap->TopazContainer); + uint16_t skip_size = 0; + uint16_t byte_addr = 0; + uint8_t exit_index = 0; + + byte_addr = ps_tpz_info->NdefTLVByteAddress; + + while (exit_index < ((ps_tpz_info->ActualNDEFMsgSize >= 0xFF) ? 3 : 1)) + { + byte_addr = (uint16_t)(byte_addr + 1); + if (TOPAZ_STATIC_LOCK_RES_START == byte_addr) + { + byte_addr = (uint16_t)(byte_addr + TOPAZ_STATIC_LOCK_RES_BYTES); + } + skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr); + + byte_addr = (uint16_t)(byte_addr + skip_size); + exit_index = (uint8_t)(exit_index + 1); + } + + byte_addr = (uint16_t)(byte_addr + 1); + if (TOPAZ_STATIC_LOCK_RES_START == byte_addr) + { + byte_addr = (uint16_t)(byte_addr + TOPAZ_STATIC_LOCK_RES_BYTES); + } + skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr); + + byte_addr = (uint16_t)(byte_addr + skip_size); + + return byte_addr; +} + +static +uint16_t +phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite ( + phFriNfc_NdefMap_t *psNdefMap, + uint16_t size_to_write) +{ + phFriNfc_TopazCont_t *ps_tpz_info = &(psNdefMap->TopazContainer); + uint16_t skip_size = 0; + uint16_t byte_addr = 0; + uint8_t exit_index = 0; + + byte_addr = ps_tpz_info->NdefTLVByteAddress; + + while (exit_index < ((size_to_write >= 0xFF) ? 3 : 1)) + { + byte_addr = (uint16_t)(byte_addr + 1); + if (TOPAZ_STATIC_LOCK_RES_START == byte_addr) + { + byte_addr = (uint16_t)(byte_addr + TOPAZ_STATIC_LOCK_RES_BYTES); + } + skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr); + + byte_addr = (uint16_t)(byte_addr + skip_size); + exit_index = (uint8_t)(exit_index + 1); + } + + byte_addr = (uint16_t)(byte_addr + 1); + if (TOPAZ_STATIC_LOCK_RES_START == byte_addr) + { + byte_addr = (uint16_t)(byte_addr + TOPAZ_STATIC_LOCK_RES_BYTES); + } + skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr); + + byte_addr = (uint16_t)(byte_addr + skip_size); + + return byte_addr; +} + + +static +NFCSTATUS +phFriNfc_Tpz_H_RemainingReadDataCopy ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = &(psNdefMap->TopazContainer); + uint8_t copy_temp_buf[PH_FRINFC_NDEFMAP_TOPAZ_MAX_SIZE]; + uint16_t copy_length = 0; + uint16_t read_copy_length = 0; + + + if (0 != ps_tpz_info->ReadBufferSize) + { + /* Data is already copied, so give it from the stored buffer */ + if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex) >= + ps_tpz_info->ReadBufferSize) + { + read_copy_length = ps_tpz_info->ReadBufferSize; + (void)memcpy ((void *)(psNdefMap->ApduBuffer + psNdefMap->ApduBuffIndex), + (void *)ps_tpz_info->ReadBuffer, ps_tpz_info->ReadBufferSize); + } + else + { + read_copy_length = (uint16_t)(psNdefMap->ApduBufferSize - + psNdefMap->ApduBuffIndex); + + copy_length = (uint16_t)(ps_tpz_info->ReadBufferSize - + read_copy_length); + + /* Copy data to user buffer */ + (void)memcpy ((void *)(psNdefMap->ApduBuffer + psNdefMap->ApduBuffIndex), + (void *)ps_tpz_info->ReadBuffer, read_copy_length); + + /* Copy data from " ReadBuffer " to temporary buffer */ + (void)memcpy ((void *)copy_temp_buf, + (void *)(ps_tpz_info->ReadBuffer + read_copy_length), + copy_length); + + /* Copy data from temporary buffer to " ReadBuffer " */ + (void)memcpy ((void *)ps_tpz_info->ReadBuffer, + (void *)copy_temp_buf, copy_length); + + } + + psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + + read_copy_length); + ps_tpz_info->ReadBufferSize = (uint8_t) + (ps_tpz_info->ReadBufferSize - + read_copy_length); + ps_tpz_info->RemainingReadSize = (uint16_t)( + ps_tpz_info->RemainingReadSize - read_copy_length); + } + + if (0 == ps_tpz_info->RemainingReadSize) + { + /* No data to read, so return */ + *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex; + ps_tpz_info->ReadBufferSize = 0; + ps_tpz_info->ReadWriteCompleteFlag = TRUE; + } + else if (psNdefMap->ApduBuffIndex == psNdefMap->ApduBufferSize) + { + /* User data length is read completely */ + *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex; + } + else + { + /* Stored data is not enough, so continue reading the next segment */ + ps_tpz_info->CurrentSeg = (uint8_t) + (ps_tpz_info->CurrentSeg + 1); +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG; + +#else + + psNdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + result = phFriNfc_Tpz_H_NxpRead (psNdefMap); + } + + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_CopyReadData ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = &(psNdefMap->TopazContainer); + phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL; + phFriNfc_ResMemCntrlTLVCont_t *ps_memtlv_info = NULL; + uint16_t copy_index = 0; + uint16_t copy_length = 0; + uint16_t recv_length = 0; + static uint16_t skip_size = 0; + /* byte address read */ + uint16_t copy_till_address = 0; + uint16_t exact_copy_length = 0; + uint16_t actual_ndef_length = 0; + + + recv_length = *(psNdefMap->SendRecvLength); + + actual_ndef_length = ps_tpz_info->ActualNDEFMsgSize; + if (PH_FRINFC_NDEFMAP_SEEK_CUR == psNdefMap->Offset) + { + actual_ndef_length = (uint16_t)( + ps_tpz_info->RemainingReadSize + + psNdefMap->ApduBuffIndex); + } + + exact_copy_length = (uint16_t)((psNdefMap->ApduBufferSize > + actual_ndef_length) ? actual_ndef_length : + psNdefMap->ApduBufferSize); + + if (0 == ps_tpz_info->CurrentSeg) + { + /* Skip copying the UID bytes, CC bytes, and lock and reserved memory bytes + */ + recv_length = (*(psNdefMap->SendRecvLength) - TOPAZ_STATIC_LOCK_RES_BYTES); + } + + if (TOPAZ_SEG_FROM_BYTE_ADR ( + phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (psNdefMap)) == + ps_tpz_info->CurrentSeg) + { + copy_index = (uint16_t)(copy_index + ( + phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead ( + psNdefMap) % TOPAZ_SEGMENT_READ_LENGTH)); + skip_size = 0; + } + + if (0 != skip_size) + { + copy_index = (copy_index + skip_size); + skip_size = 0; + } + + while (copy_index < recv_length) + { + copy_length = (uint16_t)(recv_length - copy_index); + copy_till_address = 0; + /* IF MORE THAN ONE TLV EXISTS THEN ADD A WHILE LOOP HERE, AND PLACE THE + IF STATEMENT INSIDE THE WHILE LOOP. ALSO, + ps_locktlv_info = &(psNdefMap->LockTlv) change this to + ps_locktlv_info = &(psNdefMap->LockTlv[index]) + */ + ps_locktlv_info = &(psNdefMap->LockTlv); + if ( + /* Check the lock bytes belong to this segment */ + (ps_tpz_info->CurrentSeg == + (ps_locktlv_info->ByteAddr / TOPAZ_SEGMENT_READ_LENGTH)) && + /* Now to check if the copy_index has surpassed the lock byte address */ + (TOPAZ_BYTE_ADR_FROM_SEG(ps_tpz_info->CurrentSeg, copy_index) + <= ps_locktlv_info->ByteAddr) + ) + { + if ((ps_locktlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_START) || + (ps_locktlv_info->ByteAddr >= (TOPAZ_STATIC_LOCK_RES_END + 8))) + { + copy_till_address = ps_locktlv_info->ByteAddr; + } + skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, + ps_locktlv_info->ByteAddr); + } + + /* IF MORE THAN ONE TLV EXISTS THEN ADD A WHILE LOOP HERE, AND PLACE THE + IF STATEMENT INSIDE THE WHILE LOOP. ALSO, + ps_memtlv_info = &(psNdefMap->MemTlv) change this to + ps_memtlv_info = &(psNdefMap->MemTlv[index]) + */ + ps_memtlv_info = &(psNdefMap->MemTlv); + if ( + /* Check the reserved bytes belong to this segment */ + (ps_tpz_info->CurrentSeg == + (ps_memtlv_info->ByteAddr / TOPAZ_SEGMENT_READ_LENGTH)) && + /* Now to check if the copy_index has surpassed the reserved byte address */ + (TOPAZ_BYTE_ADR_FROM_SEG(ps_tpz_info->CurrentSeg, copy_index) + <= ps_memtlv_info->ByteAddr) + ) + { + if ((ps_memtlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_START) || + (ps_memtlv_info->ByteAddr >= (TOPAZ_STATIC_LOCK_RES_END + 8))) + { + copy_till_address = (uint16_t) + (((ps_memtlv_info->ByteAddr < copy_till_address) || + (0 == copy_till_address))? + ps_memtlv_info->ByteAddr : copy_till_address); + } + + if (copy_till_address == ps_memtlv_info->ByteAddr) + { + skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, + ps_memtlv_info->ByteAddr); + } + } + + + copy_length = (uint16_t) ((copy_till_address == 0) ? copy_length : + ((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) - + copy_index)); + + /* After lock bytes, there are immediate reserved bytes, so " copy_length " + can be 0 */ + if (0 != copy_length) + { + /* If complete user buffer is not filled and the + read data is greater than the user data buffer, then get the + remaining size that should be copied. + The below " if " statement is used for the above scenario */ + if ((copy_length > (uint16_t) + (exact_copy_length - psNdefMap->ApduBuffIndex)) && + (exact_copy_length != psNdefMap->ApduBuffIndex)) + { + copy_length = (uint16_t)(exact_copy_length - + psNdefMap->ApduBuffIndex); + } + + if (exact_copy_length != psNdefMap->ApduBuffIndex) + { + (void)memcpy ((void *)(psNdefMap->ApduBuffer + + psNdefMap->ApduBuffIndex), + (void *)(psNdefMap->SendRecvBuf + copy_index), + copy_length); +#if 0 + if (((copy_till_address == 0) ? copy_length : + ((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) - + copy_index)) > (uint16_t) + (exact_copy_length - psNdefMap->ApduBuffIndex)) + { + /* Copy remaining buffer in the static memory */ + (void)memcpy ((void *)(ps_tpz_info->ReadBuffer + + ps_tpz_info->ReadBufferSize), + (void *)(psNdefMap->SendRecvBuf + copy_index), + (((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) - + copy_index) - copy_length)); + + ps_tpz_info->ReadBufferSize = (uint16_t)(((copy_till_address % + TOPAZ_SEGMENT_READ_LENGTH) - + copy_index) - copy_length); + + /* Copy the data in the user buffer */ + copy_index = (uint16_t)(copy_index + + ((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) - + copy_index)); + } + else +#endif /* #if 0 */ + { + /* Copy the data in the user buffer */ + copy_index = (uint16_t)(copy_index + copy_length); + } + + psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + + copy_length); + + + } + else + { + copy_length = (uint16_t) ((copy_till_address == 0) ? copy_length : + ((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) - + copy_index)); + + /* Actual NDEF message size is greater than the last index copied in + the user buffer */ + if (actual_ndef_length > (psNdefMap->ApduBuffIndex + + ps_tpz_info->ReadBufferSize)) + { + /* The statement is correct, check the remaining length */ + copy_length = ((copy_length > (actual_ndef_length - + psNdefMap->ApduBuffIndex)) ? + (actual_ndef_length - + psNdefMap->ApduBuffIndex) : + copy_length); + + /* Copy remaining buffer in the static memory */ + (void)memcpy ((void *)(ps_tpz_info->ReadBuffer + + ps_tpz_info->ReadBufferSize), + (void *)(psNdefMap->SendRecvBuf + copy_index), + copy_length); + + ps_tpz_info->ReadBufferSize = (uint8_t)( + ps_tpz_info->ReadBufferSize + + copy_length); + } + + /* Copy the data in the user buffer */ + copy_index = (uint16_t)(copy_index + copy_length); + } + } + + if (copy_index != copy_till_address) + { + skip_size = 0; + } + + if ((copy_index + skip_size) <= recv_length) + { + copy_index = (uint16_t)(copy_index + skip_size); + skip_size = 0; + } + else + { + skip_size = (uint16_t)((skip_size > 0) ? + (recv_length - copy_index) : 0); + copy_index = (uint16_t)recv_length; + } + } + + if (exact_copy_length != psNdefMap->ApduBuffIndex) + { + ps_tpz_info->CurrentSeg = (uint8_t) + (ps_tpz_info->CurrentSeg + 1); +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG; + +#else + + psNdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + result = phFriNfc_Tpz_H_NxpRead (psNdefMap); + } + else + { + *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex; + if (psNdefMap->ApduBuffIndex == actual_ndef_length) + { + ps_tpz_info->ReadBufferSize = 0; + ps_tpz_info->ReadWriteCompleteFlag = TRUE; + } + else + { + ps_tpz_info->RemainingReadSize = (actual_ndef_length - + psNdefMap->ApduBuffIndex); + } + } + return result; +} + + +static +NFCSTATUS +phFriNfc_Tpz_H_ParseTLVs ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = &(psNdefMap->TopazContainer); + uint8_t *p_recv_buf = NULL; + uint16_t recv_length = 0; + uint16_t parse_index = 0; + phFriNfc_Tpz_ParseSeq_t expected_seq = (phFriNfc_Tpz_ParseSeq_t) + ps_tpz_info->ExpectedSeq; + uint16_t byte_addr = 0; + /* This variable is kept static because if the size to skip LOCK or RESERVED + bytes extends to next read then it shall be stored and used to skip the next + read the bytes + */ + static uint16_t skip_size = 0; + /* This variable is kept static because if the bytes extends from the read segment, + then the index shall be stored + This is to store index copied from the + 1. lock memory VALUE field bytes in the LOCK and MEMORY CONTROL TLV. + 2. Also, LENGTH field of the NDEF TLV */ + static uint8_t lock_mem_ndef_index = 0; + /* This variable is kept static because if the bytes extends from the read segment, + then it has to stored + This is to store the + 1. lock memory VALUE field bytes in the LOCK and MEMORY CONTROL TLV. + 2. Also, LENGTH field of the NDEF TLV */ + static uint8_t lock_mem_buf[TOPAZ_MEM_LOCK_TLV_LENGTH] = {0}; + /* This is used in case if there is no MAGIC NUMBER found + OR + TYPE field is not found after reading entire card */ + static uint16_t ndef_tlv_byte_addr = 0; + + p_recv_buf = psNdefMap->SendRecvBuf; + recv_length = *psNdefMap->SendRecvLength; + + if (0 == ps_tpz_info->CurrentSeg) + { + /* First read, so reset all the static variables */ + lock_mem_ndef_index = 0; + skip_size = 0; + ndef_tlv_byte_addr = 0; + + /* Skip copying the UID bytes and CC bytes, which is first 12 bytes */ + parse_index = (uint16_t)(TOPAZ_UID_BYTES_LENGTH + + TOPAZ_CC_BYTES_LENGTH); + /* Delete the lock and reserved memory bytes + (which are the last 24 bytes in the card) */ + recv_length = (uint16_t)(*(psNdefMap->SendRecvLength) - + TOPAZ_STATIC_LOCK_RES_BYTES); + } + + while ((parse_index < recv_length) && (NFCSTATUS_SUCCESS == result) && + (NDEF_V_TLV != expected_seq)) + { + if (0 == skip_size) + { + /* Macro used to get the exact byte address of the card. + This is done by using the current segment and the parse index */ + byte_addr = TOPAZ_BYTE_ADR_FROM_SEG (ps_tpz_info->CurrentSeg, parse_index); + /* Skip size is to skip the lock or memory reserved bytes */ + skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr); + } + + if (0 != skip_size) + { + if ((recv_length - parse_index) >= skip_size) + { + parse_index = (uint16_t)(parse_index + skip_size); + skip_size = 0; + } + else + { + parse_index = (uint16_t)(parse_index + (recv_length - + parse_index)); + skip_size = (uint16_t)(skip_size - (recv_length - + parse_index)); + } + } + else + { + switch (expected_seq) + { + case LOCK_T_TLV: + { + /* Parse the bytes till TYPE field of LOCK TLV is found, Once the + TYPE field is found then change the sequence to LOCK_L_TLV */ + result = phFriNfc_Tpz_H_ParseLockTLVType (psNdefMap, p_recv_buf, + &parse_index, recv_length, &expected_seq); + + break; + } + + case LOCK_L_TLV: + { + /* Parse the length field of LOCK TLV. Length field value of the + LOCK TLV is always 3 */ + if (TOPAZ_MEM_LOCK_TLV_LENGTH != p_recv_buf[parse_index]) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + parse_index = (uint16_t)(parse_index + 1); + expected_seq = LOCK_V_TLV; + } + break; + } + + case LOCK_V_TLV: + { + /* Parse the VALUE field of the LOCK TLV */ + lock_mem_buf[lock_mem_ndef_index] = p_recv_buf[parse_index]; + parse_index = (uint16_t)(parse_index + 1); + lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1); + + + /* All the 3 bytes are copied in the local buffer */ + if (TOPAZ_MEM_LOCK_TLV_LENGTH == lock_mem_ndef_index) + { +#ifdef FRINFC_READONLY_NDEF + (void)memcpy ((void *)psNdefMap->LockTlv.LockTlvBuff, + (void *)lock_mem_buf, sizeof (lock_mem_buf)); +#endif /* #ifdef FRINFC_READONLY_NDEF */ + /* Calculate the byte address and size of the lock bytes */ + result = phFriNfc_Tpz_H_GetLockBytesInfo (psNdefMap, lock_mem_buf); + lock_mem_ndef_index = 0; + expected_seq = MEM_T_TLV; + } + break; + } + + case MEM_T_TLV: + { + /* Parse the bytes till TYPE field of MEMORY TLV is found, Once the + TYPE field is found then change the sequence to MEM_L_TLV */ + result = phFriNfc_Tpz_H_ParseMemTLVType (psNdefMap, p_recv_buf, + &parse_index, recv_length, &expected_seq); + break; + } + + case MEM_L_TLV: + { + /* Parse the length field of MEMORY TLV. Length field value of the + MEMORY TLV is always 3 */ + if (TOPAZ_MEM_LOCK_TLV_LENGTH != p_recv_buf[parse_index]) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + parse_index = (uint16_t)(parse_index + 1); + expected_seq = MEM_V_TLV; + } + + break; + } + + case MEM_V_TLV: + { + /* Parse the VALUE field of the MEMORY TLV */ + lock_mem_buf[lock_mem_ndef_index] = p_recv_buf[parse_index]; + parse_index = (uint16_t)(parse_index + 1); + lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1); + + /* All the 3 bytes are copied in the local buffer */ + if (TOPAZ_MEM_LOCK_TLV_LENGTH == lock_mem_ndef_index) + { + /* Calculate the byte address and size of the lock bytes */ + ndef_tlv_byte_addr = TOPAZ_BYTE_ADR_FROM_SEG ( + ps_tpz_info->CurrentSeg , parse_index); + result = phFriNfc_Tpz_H_GetMemBytesInfo (psNdefMap, lock_mem_buf); + lock_mem_ndef_index = 0; + expected_seq = NDEF_T_TLV; + } + + break; + } + + case NDEF_T_TLV: + { + /* Parse the bytes till TYPE field of NDEF TLV is found, Once the + TYPE field is found then change the sequence to NDEF_L_TLV */ + result = phFriNfc_Tpz_H_ParseNdefTLVType (psNdefMap, p_recv_buf, + &parse_index, recv_length, &expected_seq); + + break; + } + + case NDEF_L_TLV: + { + /* Length field of the NDEF TLV */ + if (0 == lock_mem_ndef_index) + { + /* This is the 1st time, the loop has entered this case, + means that the NDEF byte address has to be updated */ + ps_tpz_info->NdefTLVByteAddress = (uint16_t) + TOPAZ_BYTE_ADR_FROM_SEG (ps_tpz_info->CurrentSeg, + (parse_index - 1)); + } + + if (0 != lock_mem_ndef_index) + { + /* There is already index has been updated, update remaining + buffer */ + lock_mem_buf[lock_mem_ndef_index] = p_recv_buf[parse_index]; + parse_index = (uint16_t)(parse_index + 1); + lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1); + + if (TOPAZ_MEM_LOCK_TLV_LENGTH == lock_mem_ndef_index) + { + lock_mem_ndef_index = 0; + ps_tpz_info->ActualNDEFMsgSize = (uint16_t)((lock_mem_buf[1] << + TOPAZ_BYTE_SHIFT) | lock_mem_buf[2]); + expected_seq = NDEF_V_TLV; + } + } + /* Check for remaining size in the card and the actual ndef length */ + else if (p_recv_buf[parse_index] <= + (ps_tpz_info->RemainingSize - (parse_index + 1))) + { + /* This check is added to see that length field in the TLV is + greater than the 1 byte */ + if (0xFF == p_recv_buf[parse_index]) + { + lock_mem_buf[lock_mem_ndef_index] = + p_recv_buf[parse_index]; + lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1); + } + else + { + /* Length field of the TLV is ONE byte, so update the + actual ndef size */ + lock_mem_ndef_index = 0; + ps_tpz_info->ActualNDEFMsgSize = (uint16_t) + p_recv_buf[parse_index]; + + expected_seq = NDEF_V_TLV; + } + parse_index = (uint16_t)(parse_index + 1); + } + else + { + /* Wrong length, remaining size in the card is lesser than the actual + ndef message length */ + lock_mem_ndef_index = 0; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + break; + } + + default: + { + break; + } + }/* end of switch (expected_seq) */ + } /* end of if (0 != skip_size) */ + } /* while ((parse_index < recv_length) && (NFCSTATUS_SUCCESS != result) && + (NDEF_V_TLV != expected_seq)) */ + + ps_tpz_info->ExpectedSeq = (uint8_t)expected_seq; + + if (0 == ps_tpz_info->CurrentSeg) + { + /* First segment has the STATIC lock and reserved bytes, so delete it from + the remaining size */ + ps_tpz_info->RemainingSize = (uint16_t)(ps_tpz_info->RemainingSize - + (parse_index + TOPAZ_STATIC_LOCK_RES_BYTES)); + + } + else + { + ps_tpz_info->RemainingSize = (uint16_t)(ps_tpz_info->RemainingSize - + parse_index); + } + + if ((NDEF_V_TLV == expected_seq) && (NFCSTATUS_SUCCESS == result)) + { + /* NDEF TLV found */ + result = phFriNfc_Tpz_H_ActualCardSize (psNdefMap); + + if ((PH_NDEFMAP_CARD_STATE_READ_ONLY != psNdefMap->CardState) && + (0 != ps_tpz_info->ActualNDEFMsgSize)) + { + /* Check if the card state is READ ONLY or the actual NDEF size is 0 + if actual NDEF size is 0, then card state is INITIALISED + */ + psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE; + } + } + + if ((NFCSTATUS_SUCCESS == result) && (NDEF_V_TLV != expected_seq)) + { + ps_tpz_info->CurrentSeg = (uint8_t)(ps_tpz_info->CurrentSeg + 1); + if (TOPAZ_TOTAL_SEG_TO_READ == ps_tpz_info->CurrentSeg) + { + /* Max segment to read reached, so no more read can be done */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG; + +#else + + psNdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + result = phFriNfc_Tpz_H_NxpRead(psNdefMap); + } + } + + if ((NFCSTATUS_SUCCESS != result) && (NFCSTATUS_PENDING != result)) + { + /* Error scenario */ + ps_tpz_info->NdefTLVByteAddress = 0; + ps_tpz_info->ActualNDEFMsgSize = 0; + } + + if (NFCSTATUS_PENDING != result) + { + /* Exit scenario */ + if ((0x00 == *ps_tpz_info->CCByteBuf) || + ((NDEF_T_TLV == expected_seq) && + (TOPAZ_TOTAL_SEG_TO_READ == ps_tpz_info->CurrentSeg))) + { + /* This statement is for getting the new + NDEF TLV byte address, because 1st CC byte is corrupted or + no NDEF TLV in the card + + If the 1st CC byte (NDEF magic number) in the card is 0, means + that previous write has failed, so to write the exact TLV, + calculate the byte number + OR + The NDEF TLV is not present in the entire card, and the sequence is + NDEF_T_TLV (this means, that lock and memory control TLV is found + in the card) + */ + uint16_t size_to_skip = 0; + ps_tpz_info->ActualNDEFMsgSize = 0; + + if (0 != ndef_tlv_byte_addr) + { + /* ndef_tlv_byte_addr is updated, only after complete parsing the + memory control TLV so the value shall not be 0 */ + do + { + /* This loop is added to make sure the lock and reserved bytes are not + overwritten */ + size_to_skip = 0; + size_to_skip = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, + ndef_tlv_byte_addr); + + ndef_tlv_byte_addr = (uint16_t)(ndef_tlv_byte_addr + + size_to_skip); + }while (0 != size_to_skip); + + /* Update the TLV byte address */ + ps_tpz_info->NdefTLVByteAddress = ndef_tlv_byte_addr; + + /* Update the remaining size */ + ps_tpz_info->RemainingSize = (uint16_t)(psNdefMap->CardMemSize + + TOPAZ_UID_BYTES_LENGTH + + TOPAZ_CC_BYTES_LENGTH); + + ps_tpz_info->RemainingSize = (uint16_t) + (ps_tpz_info->RemainingSize - + (ndef_tlv_byte_addr + + TOPAZ_STATIC_LOCK_RES_BYTES)); + (void)phFriNfc_Tpz_H_ActualCardSize (psNdefMap); + + /* Length byte is subtracted here to get the actual NDEF + read and write size */ + ps_tpz_info->NDEFRWSize = (uint16_t) + (ps_tpz_info->NDEFRWSize - 2); + ndef_tlv_byte_addr = 0; + result = NFCSTATUS_SUCCESS; + } + } + } + + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_CopyReadDataAndWrite ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + uint8_t write_buf[TOPAZ_WRITE_8_DATA_LENGTH]; + uint16_t write_index = 0; + uint16_t write_len = 0; + uint16_t byte_addr = 0; + static uint16_t skip_size = 0; + + ps_tpz_info = &(psNdefMap->TopazContainer); + + write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ? + psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize); + + (void)memcpy ((void *)write_buf, (void *)psNdefMap->SendRecvBuf, + TOPAZ_WRITE_8_DATA_LENGTH); + + if (ps_tpz_info->CurrentBlock == TOPAZ_BLK_FROM_BYTE_ADR ( + phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite (psNdefMap, write_len))) + { + skip_size = 0; + } + + /* Byte Number != 0 menas that the VALUE field of the TLV is in between the + block, so the first few bytes shall be copied and then user data has to + be copied + */ + if (0 != ps_tpz_info->ByteNumber) + { + write_index = (uint16_t)(write_index + ps_tpz_info->ByteNumber); + } + + + if (0 != skip_size) + { + write_index = (uint16_t)(write_index + skip_size); + } + + while ((write_index < TOPAZ_WRITE_8_DATA_LENGTH) && + (write_len != psNdefMap->ApduBuffIndex)) + { + skip_size = 0; + byte_addr = TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock, + ps_tpz_info->ByteNumber); + skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr); + + if (0 == skip_size) + { + write_buf[write_index] = + psNdefMap->ApduBuffer[psNdefMap->ApduBuffIndex]; + + write_index = (uint16_t)(write_index + 1); + psNdefMap->ApduBuffIndex = (uint16_t) + (psNdefMap->ApduBuffIndex + 1); + ps_tpz_info->ByteNumber = (uint8_t) + (ps_tpz_info->ByteNumber + 1); + } + else + { + + if (skip_size >= (TOPAZ_WRITE_8_DATA_LENGTH - write_index)) + { + skip_size = (uint16_t)(skip_size - (TOPAZ_WRITE_8_DATA_LENGTH + - write_index)); + write_index = (uint16_t)TOPAZ_WRITE_8_DATA_LENGTH; + } + else + { + ps_tpz_info->ByteNumber = (uint8_t) + (ps_tpz_info->ByteNumber + skip_size); + write_index = (uint16_t)(write_index + skip_size); + skip_size = 0; + } + } + } + + if (psNdefMap->ApduBuffIndex == write_len) + { + ps_tpz_info->WriteSeq = (uint8_t)WR_DATA; + } + else + { + if (0 != skip_size) + { + ps_tpz_info->WriteSeq = (uint8_t)WR_DATA_READ_REQD; + + } + else + { + ps_tpz_info->WriteSeq = (uint8_t)WR_DATA; + } + } + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf, + sizeof (write_buf)); + + return result; + +} + +static +NFCSTATUS +phFriNfc_Tpz_H_UpdateLenFieldValuesAfterRead ( + phFriNfc_NdefMap_t *psNdefMap) +{ + /* This function is called, only when the LENGTH field has to be updated + with the correct value */ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + uint16_t write_len = 0; + uint16_t write_index = 0; + uint16_t byte_addr = 0; + phFriNfc_Tpz_WrSeq_t write_seq; + /* This variable is kept static because if the size to skip LOCK or RESERVED + bytes extends to next read then it shall be stored and used to skip the next + read the bytes + */ + static uint16_t skip_size = 0; + uint8_t write_buf[TOPAZ_WRITE_8_DATA_LENGTH]; + uint8_t exit_while = FALSE; + + ps_tpz_info = &(psNdefMap->TopazContainer); + write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ? + psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize); + + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE; + + (void)memcpy ((void *)write_buf, (void *)psNdefMap->SendRecvBuf, + TOPAZ_WRITE_8_DATA_LENGTH); + + write_seq = (phFriNfc_Tpz_WrSeq_t)ps_tpz_info->WriteSeq; + + if (WR_LEN_1_VALUE == write_seq) + { + /* First LENGTH field is geting updated, so the skip size + reset is done */ + skip_size = 0; + } + + if (0 != ps_tpz_info->ByteNumber) + { + /* Byte Number is not 0, means that some data shall not be overwriteen till + that position in the block */ + write_index = (uint16_t)(write_index + ps_tpz_info->ByteNumber); + } + + if (0 != skip_size) + { + /* This is possible after updating the FIRST length field + skip size is skipped because of the pending LOCK or + RESERVED bytes + */ + write_index = (uint16_t)(write_index + skip_size); + } + + while ((write_index < TOPAZ_WRITE_8_DATA_LENGTH) && + (FALSE == exit_while)) + { + skip_size = 0; + /* Get the exact byte address from the block number and + byte number */ + byte_addr = TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock, + ps_tpz_info->ByteNumber); + /* Get the skip size */ + skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr); + + if (0 == skip_size) + { + switch (write_seq) + { + case WR_LEN_1_VALUE: + { + /* First sequenc is always to update 1st LENGTH field of the TLV */ + if (write_len < 0xFF) + { + /* This means the LENGTH field is only one BYTE */ + write_buf[write_index] = (uint8_t) + psNdefMap->ApduBuffIndex; + /* Exit the loop */ + exit_while = TRUE; + } + else + { + /* Update the 1st LENGTH field */ + write_buf[write_index] = (uint8_t)0xFF; + } + break; + } + + case WR_LEN_2_VALUE: + { + /* Update the 2nd LENGTH field */ + write_buf[write_index] = (uint8_t) + (psNdefMap->ApduBuffIndex >> BYTE_SIZE); + break; + } + + case WR_LEN_3_VALUE: + { + /* Update the 3rd LENGTH field */ + write_buf[write_index] = (uint8_t) + (psNdefMap->ApduBuffIndex & + TOPAZ_BYTE_LENGTH_MASK); + /* Exit the loop */ + exit_while = TRUE; + break; + } + + default: + { + /* Invalid case */ + break; + } + } + write_index = (uint16_t)(write_index + 1); + if ( + /* As the write is done for 8 bytes, the write index cant + go for more than or equal to 8 bytes, if it reaches 8 bytes + then sequence shall not be incrmented */ + (TOPAZ_WRITE_8_DATA_LENGTH != write_index) && + /* If the last length field byte is updated then the + write sequence shall not be incremented */ + (WR_LEN_3_VALUE != write_seq) && + /* Check added if the write length is less than 0xFF. + If length is less than 0xFF, then write sequence + shall not be incremented */ + (write_len >= 0xFF) + ) + { + /* Sequence is incremented to the next level */ + write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1); + } + /* Byte number is incremented */ + ps_tpz_info->ByteNumber = (uint8_t) + (ps_tpz_info->ByteNumber + 1); + } + else + { + + if (skip_size >= (TOPAZ_WRITE_8_DATA_LENGTH - write_index)) + { + skip_size = (uint16_t)(skip_size - (TOPAZ_WRITE_8_DATA_LENGTH + - write_index)); + write_index = (uint16_t)TOPAZ_WRITE_8_DATA_LENGTH; + } + else + { + ps_tpz_info->ByteNumber = (uint8_t) + (ps_tpz_info->ByteNumber + skip_size); + write_index = (uint16_t)(write_index + skip_size); + skip_size = 0; + } + + } + } + + ps_tpz_info->WriteSeq = (uint8_t)write_seq; + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf, + sizeof (write_buf)); + return result; +} + + + +static +NFCSTATUS +phFriNfc_Tpz_H_UpdateLenFieldZeroAfterRead ( + phFriNfc_NdefMap_t *psNdefMap) +{ + /* This function is called, only when the LENGTH field has to be updated + with the 0 */ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + uint16_t write_len = 0; + uint16_t write_index = 0; + uint16_t prev_apdu_index = 0; + uint16_t byte_addr = 0; + phFriNfc_Tpz_WrSeq_t write_seq; + /* This variable is kept static because if the size to skip LOCK or RESERVED + bytes extends to next read then it shall be stored and used to skip the next + read bytes + */ + static uint16_t skip_size = 0; + uint8_t write_buf[TOPAZ_WRITE_8_DATA_LENGTH]; + + ps_tpz_info = &(psNdefMap->TopazContainer); + write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ? + psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize); + + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE; + + (void)memcpy ((void *)write_buf, (void *)psNdefMap->SendRecvBuf, + TOPAZ_WRITE_8_DATA_LENGTH); + + prev_apdu_index = psNdefMap->ApduBuffIndex; + write_seq = (phFriNfc_Tpz_WrSeq_t)ps_tpz_info->WriteSeq; + + if (WR_LEN_1_0 == write_seq) + { + /* First LENGTH field is geting updated, so the skip size + reset is done */ + skip_size = 0; + } + + if (0 != ps_tpz_info->ByteNumber) + { + /* Byte Number is not 0, means that some data shall not be overwriteen till + that position in the block */ + write_index = (uint16_t)(write_index + ps_tpz_info->ByteNumber); + ps_tpz_info->ByteNumber = 0; + } + + if (0 != skip_size) + { + /* This is possible after updating the FIRST length field + skip size is skipped because of the pending LOCK or + RESERVED bytes + */ + write_index = (uint16_t)(write_index + skip_size); + } + + while ((write_index < TOPAZ_WRITE_8_DATA_LENGTH) && + (write_len != psNdefMap->ApduBuffIndex)) + { + skip_size = 0; + byte_addr = TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock, + ps_tpz_info->ByteNumber); + skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr); + + if (0 == skip_size) + { + switch (write_seq) + { + case WR_LEN_1_0: + { + /* First sequence is always to update 1st LENGTH field + of the TLV */ + write_buf[write_index] = 0x00; + write_index = (uint16_t)(write_index + 1); + if (write_len < 0xFF) + { + /* LENGTH field is only 1 byte, so update change the sequence to + update user data */ + write_seq = WR_DATA; + } + else + { + /* Go to the next LENGTH field to update */ + write_seq = (phFriNfc_Tpz_WrSeq_t)((TOPAZ_WRITE_8_DATA_LENGTH != + write_index) ? + (write_seq + 1) : write_seq); + } + break; + } + + case WR_LEN_2_0: + case WR_LEN_3_0: + { + /* Update 2nd and 3rd LEGNTH field */ + write_buf[write_index] = 0x00; + write_index = (uint16_t)(write_index + 1); + write_seq = (phFriNfc_Tpz_WrSeq_t)((TOPAZ_WRITE_8_DATA_LENGTH != + write_index) ? + (write_seq + 1) : write_seq); + break; + } + + case WR_DATA: + default: + { + /* Update the buffer by the user data */ + write_buf[write_index] = + psNdefMap->ApduBuffer[psNdefMap->ApduBuffIndex]; + + write_index = (uint16_t)(write_index + 1); + psNdefMap->ApduBuffIndex = (uint16_t) + (psNdefMap->ApduBuffIndex + 1); + break; + } + + } + + ps_tpz_info->ByteNumber = (uint8_t) + (ps_tpz_info->ByteNumber + 1); + } + else + { + /* LOCK and MEMORY bytes are found */ + if (skip_size >= (TOPAZ_WRITE_8_DATA_LENGTH - write_index)) + { + /* skip size has exceeded the block number, so calculate the + remaining skip size */ + skip_size = (uint16_t)(skip_size - (TOPAZ_WRITE_8_DATA_LENGTH + - write_index)); + write_index = (uint16_t)TOPAZ_WRITE_8_DATA_LENGTH; + } + else + { + /* skip the LOCK and MEMORY bytes size */ + ps_tpz_info->ByteNumber = (uint8_t) + (ps_tpz_info->ByteNumber + skip_size); + write_index = (uint16_t)(write_index + skip_size); + skip_size = 0; + } + } + } + + if (psNdefMap->ApduBuffIndex == write_len) + { + /* User data has been completely copied and it is ready to write, so + change the sequence */ + ps_tpz_info->WriteSeq = (uint8_t)WR_DATA; + } + else if ((WR_DATA == write_seq) && (prev_apdu_index == + psNdefMap->ApduBuffIndex)) + { + /* The user data has not been written, only the LENGTH field is + updated */ + ps_tpz_info->WriteSeq = (uint8_t)((write_len < 0xFF) ? + WR_LEN_1_0 : WR_LEN_3_0); + } + else + { + /* Update the sequence in the context */ + ps_tpz_info->WriteSeq = (uint8_t)write_seq; + } + + ps_tpz_info->ByteNumber = 0; + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf, + sizeof (write_buf)); + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_RdForWrite ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + phFriNfc_Tpz_WrSeq_t write_seq; + uint16_t byte_addr = 0; + uint8_t exit_while = FALSE; + uint16_t skip_size = 0; + + ps_tpz_info = &(psNdefMap->TopazContainer); + write_seq = (phFriNfc_Tpz_WrSeq_t)(ps_tpz_info->WriteSeq); + +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8; + +#else + + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF; + + switch (write_seq) + { + case WR_LEN_1_0: + case WR_LEN_1_VALUE: + { + byte_addr = (ps_tpz_info->NdefTLVByteAddress + 1); + + /* This loop is to skip the lock amd reserved bytes */ + while (FALSE == exit_while) + { + if (TOPAZ_STATIC_LOCK_FIRST_BLOCK_NO == + TOPAZ_BLK_FROM_BYTE_ADR (byte_addr)) + { + byte_addr = (uint16_t)(byte_addr + + TOPAZ_STATIC_LOCK_RES_BYTES); + } + skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, + byte_addr); + if (0 != skip_size) + { + byte_addr = (uint16_t)(byte_addr + skip_size); + + + } + else + { + exit_while = TRUE; + } + } + break; + } + + case WR_LEN_2_0: + case WR_LEN_3_0: + case WR_LEN_2_VALUE: + case WR_LEN_3_VALUE: + { + byte_addr = (uint16_t)TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock, + ps_tpz_info->ByteNumber); + /* This loop is for to skip the lock amd reserved bytes */ + while (FALSE == exit_while) + { + skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, + byte_addr); + if (0 != skip_size) + { + byte_addr = (uint16_t)(byte_addr + skip_size); + } + else + { + exit_while = TRUE; + } + } + break; + } + + case WR_DATA_READ_REQD: + { + /* Lock or reserved bytes found bytes */ + byte_addr = (uint16_t)TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock, + ps_tpz_info->ByteNumber); + break; + } + + default: + { + break; + } + } + + ps_tpz_info->CurrentBlock = (uint8_t) + TOPAZ_BLK_FROM_BYTE_ADR (byte_addr); + ps_tpz_info->ByteNumber = (uint8_t) + TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR (byte_addr); + + result = phFriNfc_Tpz_H_NxpRead (psNdefMap); + + return result; +} + +static +uint16_t +phFriNfc_Tpz_H_CompareLockBlocks ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t block_no, + uint16_t *p_skip_size) +{ + uint16_t return_addr = 0; + phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL; + + ps_locktlv_info = &(psNdefMap->LockTlv); + + if (block_no == ps_locktlv_info->BlkNum) + { + /* ps_tpz_info->ByteNumber = (uint8_t)ps_locktlv_info->ByteNum; */ + *p_skip_size = ps_locktlv_info->Size; + return_addr = ps_locktlv_info->ByteAddr; + } + + return return_addr; +} + +static +uint16_t +phFriNfc_Tpz_H_CompareMemBlocks ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t block_no, + uint16_t *p_skip_size) +{ + uint16_t return_addr = 0; + phFriNfc_ResMemCntrlTLVCont_t *ps_memtlv_info = NULL; + + ps_memtlv_info = &(psNdefMap->MemTlv); + + if (block_no == ps_memtlv_info->BlkNum) + { + /* ps_tpz_info->ByteNumber = (uint8_t)ps_memtlv_info->ByteNum; */ + *p_skip_size = ps_memtlv_info->Size; + return_addr = ps_memtlv_info->ByteAddr; + } + + return return_addr; +} + + +static +NFCSTATUS +phFriNfc_Tpz_H_CopySendWrData ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + uint8_t write_buf[TOPAZ_WRITE_8_DATA_LENGTH]; + uint16_t write_len; + uint8_t copy_length; + uint16_t skip_size = 0; + + ps_tpz_info = &(psNdefMap->TopazContainer); + write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ? + psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize); + + if (0 != phFriNfc_Tpz_H_CompareLockBlocks (psNdefMap, + ps_tpz_info->CurrentBlock, &skip_size)) + { + ps_tpz_info->WriteSeq = (uint8_t)WR_DATA_READ_REQD; + ps_tpz_info->ByteNumber = 0; + result = phFriNfc_Tpz_H_RdForWrite (psNdefMap); + } + else if (0 != phFriNfc_Tpz_H_CompareMemBlocks (psNdefMap, + ps_tpz_info->CurrentBlock, &skip_size)) + { + ps_tpz_info->WriteSeq = (uint8_t)WR_DATA_READ_REQD; + ps_tpz_info->ByteNumber = 0; + result = phFriNfc_Tpz_H_RdForWrite (psNdefMap); + } + else + { +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + psNdefMap->State = (uint8_t)PH_FRINFC_TOPAZ_STATE_WRITE; + + if ((write_len - psNdefMap->ApduBuffIndex) >= (uint16_t)TOPAZ_WRITE_8_DATA_LENGTH) + { + copy_length = (uint8_t)TOPAZ_WRITE_8_DATA_LENGTH; + (void)memcpy ((void *)write_buf, + (void *)(psNdefMap->ApduBuffer + psNdefMap->ApduBuffIndex), + copy_length); + + psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + + copy_length); + } + else + { + copy_length = (uint8_t)(write_len - psNdefMap->ApduBuffIndex); + + (void)memcpy ((void *)write_buf, + (void *)(psNdefMap->ApduBuffer + psNdefMap->ApduBuffIndex), + TOPAZ_WRITE_8_DATA_LENGTH); + + psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + + copy_length); + + (void)memset ((void *)(write_buf + copy_length), 0x00, + (TOPAZ_WRITE_8_DATA_LENGTH - copy_length)); + } + +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf, + sizeof (write_buf)); + } + + + return result; +} + + +static +NFCSTATUS +phFriNfc_Tpz_H_ActualCardSize ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_TopazCont_t *ps_tpz_info = NULL; + phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL; + phFriNfc_ResMemCntrlTLVCont_t *ps_memtlv_info = NULL; + uint16_t ndef_value_byte_addr = 0; + uint16_t ndef_read_write_size = 0; + + ps_tpz_info = &(psNdefMap->TopazContainer); + if (ps_tpz_info->ActualNDEFMsgSize > ps_tpz_info->RemainingSize) + { + ps_tpz_info->ActualNDEFMsgSize = 0; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + ndef_read_write_size = ps_tpz_info->RemainingSize; + ndef_value_byte_addr = phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead + (psNdefMap); + + ps_locktlv_info = &(psNdefMap->LockTlv); + if (ps_locktlv_info->ByteAddr > ndef_value_byte_addr) + { + ndef_read_write_size = (ndef_read_write_size - + ps_locktlv_info->Size); + } + + ps_memtlv_info = &(psNdefMap->MemTlv); + if (ps_memtlv_info->ByteAddr > ndef_value_byte_addr) + { + ndef_read_write_size = (ndef_read_write_size - + ps_memtlv_info->Size); + } + + if (ps_tpz_info->ActualNDEFMsgSize > ndef_read_write_size) + { + ps_tpz_info->ActualNDEFMsgSize = 0; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + ps_tpz_info->NDEFRWSize = (uint16_t) + ((ps_tpz_info->ActualNDEFMsgSize < 0xFF) ? + (ndef_read_write_size - 2) : + ndef_read_write_size); + } + } + + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_ParseLockTLVType ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *p_parse_data, + uint16_t *p_parse_index, + uint16_t total_len_to_parse, + phFriNfc_Tpz_ParseSeq_t *seq_to_execute) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint16_t parse_index = *p_parse_index; + phFriNfc_Tpz_ParseSeq_t expected_seq = *seq_to_execute; + + PHNFC_UNUSED_VARIABLE(psNdefMap); + PHNFC_UNUSED_VARIABLE(total_len_to_parse); + + switch (p_parse_data[parse_index]) + { + case PH_FRINFC_TOPAZ_LOCK_CTRL_T: + { + expected_seq = LOCK_L_TLV; + parse_index = (parse_index + 1); + break; + } + + case PH_FRINFC_TOPAZ_NULL_T: + { + expected_seq = LOCK_T_TLV; + parse_index = (parse_index + 1); + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + + + *seq_to_execute = expected_seq; + *p_parse_index = parse_index; + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_ParseMemTLVType ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *p_parse_data, + uint16_t *p_parse_index, + uint16_t total_len_to_parse, + phFriNfc_Tpz_ParseSeq_t *seq_to_execute) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint16_t parse_index = *p_parse_index; + phFriNfc_Tpz_ParseSeq_t expected_seq = *seq_to_execute; + + PHNFC_UNUSED_VARIABLE(psNdefMap); + PHNFC_UNUSED_VARIABLE(total_len_to_parse); + + switch (p_parse_data[parse_index]) + { + case PH_FRINFC_TOPAZ_LOCK_CTRL_T: + { + expected_seq = LOCK_L_TLV; + parse_index = (parse_index + 1); + break; + } + + case PH_FRINFC_TOPAZ_NULL_T: + { + expected_seq = MEM_T_TLV; + parse_index = (parse_index + 1); + break; + } + + case PH_FRINFC_TOPAZ_MEM_CTRL_T: + { + expected_seq = MEM_L_TLV; + parse_index = (parse_index + 1); + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + + *seq_to_execute = expected_seq; + *p_parse_index = parse_index; + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_ParseNdefTLVType ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *p_parse_data, + uint16_t *p_parse_index, + uint16_t total_len_to_parse, + phFriNfc_Tpz_ParseSeq_t *seq_to_execute) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint16_t parse_index = *p_parse_index; + phFriNfc_Tpz_ParseSeq_t expected_seq = *seq_to_execute; + + PHNFC_UNUSED_VARIABLE(psNdefMap); + PHNFC_UNUSED_VARIABLE(total_len_to_parse); + + switch (p_parse_data[parse_index]) + { + case PH_FRINFC_TOPAZ_MEM_CTRL_T: + { + /* TYPE field of Memory control TLV is found. + This means that more than one memory control + TLV exists */ + expected_seq = MEM_L_TLV; + parse_index = (parse_index + 1); + break; + } + + case PH_FRINFC_TOPAZ_NULL_T: + { + /* Skip the NULL TLV */ + expected_seq = NDEF_T_TLV; + parse_index = (parse_index + 1); + break; + } + + case PH_FRINFC_TOPAZ_NDEF_T: + { + /* TYPE field of NDEF TLV found, so next expected + sequence is LENGTH field */ + expected_seq = NDEF_L_TLV; + parse_index = (parse_index + 1); + break; + } + + default: + { + /* Reset the sequence */ + expected_seq = LOCK_T_TLV; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + + *seq_to_execute = expected_seq; + *p_parse_index = parse_index; + return result; +} + +static +uint16_t +phFriNfc_Tpz_H_GetSkipSize ( + phFriNfc_NdefMap_t *psNdefMap, + uint16_t byte_adr_card) +{ + uint16_t return_size = 0; + phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL; + phFriNfc_ResMemCntrlTLVCont_t *ps_memtlv_info = NULL; + + ps_locktlv_info = &(psNdefMap->LockTlv); + ps_memtlv_info = &(psNdefMap->MemTlv); + + /* If there are more than one LOCK CONTROL TLV, then + ADD A LOOP HERE OF THE NUMBER OF TLVs FOUND */ + if (byte_adr_card == ps_locktlv_info->ByteAddr) + { + return_size = ps_locktlv_info->Size; + } + + /* If there are more than one MEMORY CONTROL TLV, then + ADD A LOOP HERE OF THE NUMBER OF TLVs FOUND */ + if (byte_adr_card == ps_memtlv_info->ByteAddr) + { + return_size = ps_memtlv_info->Size; + } + return return_size; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_GetLockBytesInfo ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *p_lock_info) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL; + uint8_t page_address = 0; + uint8_t bytes_offset = 0; + uint8_t lock_index = 0; + + ps_locktlv_info = &(psNdefMap->LockTlv); + + page_address = (uint8_t)(p_lock_info[lock_index] >> NIBBLE_SIZE); + bytes_offset = (uint8_t)(p_lock_info[lock_index] & TOPAZ_NIBBLE_MASK); + + lock_index = (lock_index + 1); + ps_locktlv_info->Size = (uint16_t) + (((p_lock_info[lock_index] % TOPAZ_BYTE_SIZE_IN_BITS) > 0)? + ((p_lock_info[lock_index] / TOPAZ_BYTE_SIZE_IN_BITS) + 1) : + (p_lock_info[lock_index] / TOPAZ_BYTE_SIZE_IN_BITS)); + + lock_index = (lock_index + 1); + ps_locktlv_info->BytesPerPage = + (p_lock_info[lock_index] & TOPAZ_NIBBLE_MASK); + ps_locktlv_info->BytesLockedPerLockBit = + (p_lock_info[lock_index] >> NIBBLE_SIZE); + + /* Apply the formula to calculate byte address + ByteAddr = PageAddr*2^BytesPerPage + ByteOffset + */ + ps_locktlv_info->ByteAddr = (uint16_t)((page_address + * (1 << ps_locktlv_info->BytesPerPage)) + + bytes_offset); + + + if ( + /* Out of bound memory check */ + ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size) > + (uint16_t)(psNdefMap->TopazContainer.CCByteBuf[2] * + TOPAZ_BYTES_PER_BLOCK)) || + + /* Check the static lock and reserved areas memory blocks */ + ((ps_locktlv_info->ByteAddr >= TOPAZ_STATIC_LOCK_RES_START) && + (ps_locktlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_END)) || + (((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1) >= + TOPAZ_STATIC_LOCK_RES_START) && + ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1) < + TOPAZ_STATIC_LOCK_RES_END)) + ) + { + ps_locktlv_info->ByteAddr = 0; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + ps_locktlv_info->BlkNum = (ps_locktlv_info->ByteAddr / + TOPAZ_BYTES_PER_BLOCK); + ps_locktlv_info->ByteNum = (ps_locktlv_info->ByteAddr % + TOPAZ_BYTES_PER_BLOCK); + } + + return result; +} + +static +NFCSTATUS +phFriNfc_Tpz_H_GetMemBytesInfo ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *p_mem_info) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ResMemCntrlTLVCont_t *ps_memtlv_info = NULL; + phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL; + uint8_t page_address = 0; + uint8_t bytes_offset = 0; + uint8_t mem_index = 0; + + ps_memtlv_info = &(psNdefMap->MemTlv); + ps_locktlv_info = &(psNdefMap->LockTlv); + page_address = (uint8_t)(p_mem_info[mem_index] >> NIBBLE_SIZE); + bytes_offset = (uint8_t)(p_mem_info[mem_index] & TOPAZ_NIBBLE_MASK); + + mem_index = (mem_index + 1); + ps_memtlv_info->Size = (uint16_t)p_mem_info[mem_index]; + + mem_index = (mem_index + 1); + ps_memtlv_info->BytesPerPage = + (p_mem_info[mem_index] & TOPAZ_NIBBLE_MASK); + + /* Apply the formula to calculate byte address + ByteAddr = PageAddr * 2^BytesPerPage + ByteOffset + */ + ps_memtlv_info->ByteAddr = (uint16_t)((page_address + * (1 << ps_memtlv_info->BytesPerPage)) + + bytes_offset); + + + if ( + /* Check if the lock and memory bytes are overlapped */ + ((ps_memtlv_info->ByteAddr >= ps_locktlv_info->ByteAddr) && + (ps_memtlv_info->ByteAddr <= + (ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1))) || + + (((ps_memtlv_info->ByteAddr + ps_memtlv_info->Size - 1) >= + ps_locktlv_info->ByteAddr) && + ((ps_memtlv_info->ByteAddr + ps_memtlv_info->Size - 1) <= + (ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1))) || + + /* Check the static lock and reserved areas memory blocks */ + ((ps_memtlv_info->ByteAddr >= TOPAZ_STATIC_LOCK_RES_START) && + (ps_memtlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_END)) || + (((ps_memtlv_info->ByteAddr + ps_memtlv_info->Size - 1) >= + TOPAZ_STATIC_LOCK_RES_START) && + ((ps_memtlv_info->ByteAddr + ps_memtlv_info->Size - 1) < + TOPAZ_STATIC_LOCK_RES_END)) || + + /* Check if the memory address is out bound */ + ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size) > + (uint16_t)(psNdefMap->TopazContainer.CCByteBuf[2] * + TOPAZ_BYTES_PER_BLOCK)) + ) + { + ps_memtlv_info->ByteAddr = 0; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + ps_memtlv_info->BlkNum = (ps_memtlv_info->ByteAddr / + TOPAZ_BYTES_PER_BLOCK); + ps_memtlv_info->ByteNum = (ps_memtlv_info->ByteAddr % + TOPAZ_BYTES_PER_BLOCK); + } + + return result; +} + +#ifdef UNIT_TEST +#include +#endif + +#endif /*#if !(defined(PH_FRINFC_MAP_TOPAZ_DISABLED ) || defined (PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED ))*/ + + + diff --git a/libnfc-nxp/phFriNfc_TopazMap.c b/libnfc-nxp/phFriNfc_TopazMap.c new file mode 100644 index 0000000..0ec7332 --- /dev/null +++ b/libnfc-nxp/phFriNfc_TopazMap.c @@ -0,0 +1,2016 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phFriNfc_TopazMap.c +* \brief NFC Ndef Mapping For Remote Devices. +* +* Project: NFC-FRI +* +* $Date: Mon Dec 13 14:14:14 2010 $ +* $Author: ing02260 $ +* $Revision: 1.23 $ +* $Aliases: $ +* +*/ + + + +#include +#include +#include +#include + +#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED +/*! \ingroup grp_file_attributes +* \name NDEF Mapping +* +* File: \ref phFriNfcNdefMap.c +* +*/ +/*@{*/ +#define PHFRINFCTOPAZMAP_FILEREVISION "$Revision: 1.23 $" +#define PHFRINFCTOPAZMAP_FILEALIASES "$Aliases: $" +/*@}*/ +/****************** Start of macros ********************/ +/* Below MACRO is used for the WRITE error scenario, + in case PN544 returns error for any WRITE, then + read the written block and byte number, to check the data + written to the card is correct or not +*/ +/* #define TOPAZ_RF_ERROR_WORKAROUND */ + +#ifdef FRINFC_READONLY_NDEF + + #define CC_BLOCK_NUMBER (0x01U) + #define LOCK_BLOCK_NUMBER (0x0EU) + + #define LOCK0_BYTE_NUMBER (0x00U) + #define LOCK0_BYTE_VALUE (0xFFU) + + #define LOCK1_BYTE_NUMBER (0x01U) + #define LOCK1_BYTE_VALUE (0x7FU) + + #define CC_RWA_BYTE_NUMBER (0x03U) + #define CC_READ_ONLY_VALUE (0x0FU) + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +#ifdef TOPAZ_RF_ERROR_WORKAROUND + + /* Below MACROs are added for the error returned from HAL, if the + below error has occured during the WRITE, then read the error + returned blocks to confirm */ + #define FRINFC_RF_TIMEOUT_89 (0x89U) + #define FRINFC_RF_TIMEOUT_90 (0x90U) + + /* State specific to read after the RF ERROR for the WRITE */ + #define PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ (0x0FU) + +#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ + +/****************** End of macros ********************/ + +/*! +* \name Topaz Mapping - Helper Functions +* +*/ +/*@{*/ + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall read 8 bytes +* from the card. +*/ +static NFCSTATUS phFriNfc_Tpz_H_RdBytes(phFriNfc_NdefMap_t *NdefMap, + uint16_t BlockNo, + uint16_t ByteNo); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall process +* read id command +*/ +static NFCSTATUS phFriNfc_Tpz_H_ProReadID(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall process +* read all command +*/ +static NFCSTATUS phFriNfc_Tpz_H_ProReadAll(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function depends on +* function called by the user +*/ +static NFCSTATUS phFriNfc_Tpz_H_CallNxtOp(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function checks the CC +* bytes +*/ +static NFCSTATUS phFriNfc_Tpz_H_ChkCCBytes(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function finds +* NDEF TLV +*/ +static NFCSTATUS phFriNfc_Tpz_H_findNDEFTLV(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function writes a +* byte into the card +*/ +static NFCSTATUS phFriNfc_Tpz_H_WrAByte(phFriNfc_NdefMap_t *NdefMap, + uint16_t BlockNo, + uint16_t ByteNo, + uint8_t ByteVal + ); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall process the +* NMN write +*/ +static NFCSTATUS phFriNfc_Tpz_H_ProWrNMN(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function writes the length field of +* the NDEF TLV +*/ +static NFCSTATUS phFriNfc_Tpz_H_ProWrTLV(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function updates length field +* of the NDEF TLV after complete write. +*/ +static NFCSTATUS phFriNfc_Tpz_H_WrLByte(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function copies the card data +* to the user buffer +*/ +static NFCSTATUS phFriNfc_Tpz_H_CpDataToUsrBuf( phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall process the +* written data +*/ +static NFCSTATUS phFriNfc_Tpz_H_ProWrUsrData( phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function checks the block +* number is correct or not +*/ +static void phFriNfc_Tpz_H_BlkChk(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function writes the 0th +* byte of block 1 has Zero +*/ +static NFCSTATUS phFriNfc_Tpz_H_WrByte0ValE1(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function calls the +* completion routine +*/ +static void phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Status); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz check ndef. This function checks +* the CC byte in check ndef function +*/ +static NFCSTATUS phFriNfc_Tpz_H_ChkCCinChkNdef(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz check ndef. This function checks +* the lock bits and set a card state +*/ +static void phFriNfc_Tpz_H_ChkLockBits(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function writes CC bytes or +* type of the TLV +*/ +static NFCSTATUS phFriNfc_Tpz_H_WrCCorTLV(phFriNfc_NdefMap_t *NdefMap); + +#ifdef TOPAZ_RF_ERROR_WORKAROUND + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function checks the written +* value after the +*/ +static +NFCSTATUS +phFriNfc_Tpz_H_CheckWrittenData ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t state_rf_error); + +#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function checks the written +* CC bytes are correct +*/ +static NFCSTATUS phFriNfc_Tpz_H_ProCCTLV(phFriNfc_NdefMap_t *NdefMap); +/*@}*/ +void phFriNfc_TopazMap_H_Reset(phFriNfc_NdefMap_t *NdefMap) +{ + /* Initialising the Topaz structure variable */ + NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_INVALID_OPE; + NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1; + NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0; + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_VAL0; + (void)memset(NdefMap->TopazContainer.ReadBuffer, PH_FRINFC_TOPAZ_VAL0, + sizeof(NdefMap->TopazContainer.ReadBuffer)); + NdefMap->TopazContainer.ReadWriteCompleteFlag = PH_FRINFC_TOPAZ_FLAG0; + NdefMap->TopazContainer.RemainingSize = PH_FRINFC_TOPAZ_VAL0; + (void)memset(NdefMap->TopazContainer.UID, PH_FRINFC_TOPAZ_VAL0, + sizeof(NdefMap->TopazContainer.UID)); + NdefMap->TopazContainer.Cur_RW_Index=0; + NdefMap->TopazContainer.ByteRWFrmCard =0; +} + +/*! +* \brief Check whether a particular Remote Device is NDEF compliant. +* +* The function checks whether the peer device is NDEF compliant. +* +* \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t +* structure describing the component context. +* +* \retval NFCSTATUS_PENDING The action has been successfully triggered. +* \retval Others An error has occurred. +* +*/ + +NFCSTATUS phFriNfc_TopazMap_ChkNdef( phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + if ( NdefMap != NULL) + { + /* Update the previous operation */ + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE; + /* Update the CR index to know from which operation completion + routine has to be called */ + NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_CHK_NDEF; + NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1; + NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0; + + /* Set card state */ + NdefMap->CardType = PH_FRINFC_NDEFMAP_TOPAZ_CARD; + + /* Change the state to Check Ndef Compliant */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_READID; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE; + +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = (phNfc_eJewelCmdList_t)phHal_eJewel_Raw; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READID; +#else +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_RID; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRid; +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + Result = phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber); + } + return Result; +} + +#ifdef FRINFC_READONLY_NDEF + +NFCSTATUS +phFriNfc_TopazMap_ConvertToReadOnly ( + phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + + result = phFriNfc_Tpz_H_WrAByte (NdefMap, CC_BLOCK_NUMBER, + CC_RWA_BYTE_NUMBER, CC_READ_ONLY_VALUE); + + if (NFCSTATUS_PENDING == PHNFCSTATUS(result)) + { + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WR_CC_BYTE; + } + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/*! +* \brief Initiates Reading of NDEF information from the Remote Device. +* +* The function initiates the reading of NDEF information from a Remote Device. +* It performs a reset of the state and starts the action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action +* has been triggered. +*/ +NFCSTATUS phFriNfc_TopazMap_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Copy user buffer to the context */ + NdefMap->ApduBuffer = PacketData; + /* Copy user length to the context */ + NdefMap->ApduBufferSize = *PacketDataLength; + /* Update the user memory size to a context variable */ + NdefMap->NumOfBytesRead = PacketDataLength; + /* Number of bytes read from the card is zero. + This variable returns the number of bytes read + from the card. */ + *NdefMap->NumOfBytesRead = PH_FRINFC_TOPAZ_VAL0; + /* Index to know the length read */ + NdefMap->ApduBuffIndex = PH_FRINFC_TOPAZ_VAL0; + /* Store the offset in the context */ + NdefMap->Offset = Offset; + /* Update the CR index to know from which operation completion + routine has to be called */ + NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_RD_NDEF; + + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || ( NdefMap->PrevOperation == + PH_FRINFC_NDEFMAP_WRITE_OPE)) + { + /* If previous operation is not read then the read shall + start from BEGIN */ + NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN; + /* Initialise current block and byte number */ + NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1; + NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0; + /* State has to be changed */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL; + NdefMap->TopazContainer.ReadWriteCompleteFlag = + PH_FRINFC_TOPAZ_FLAG0; + /* Topaz command = READALL */ +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = (phNfc_eJewelCmdList_t)phHal_eJewel_Raw; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL; +#else + +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll; +#endif + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + } + + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + /* Offset = Current, but the read has reached the End of Card */ + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (NdefMap->TopazContainer.ReadWriteCompleteFlag == + PH_FRINFC_TOPAZ_FLAG1)) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + /* if the offset is begin then call READALL else copy the data + from the user buffer */ + Result = ((Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + phFriNfc_Tpz_H_RdBytes(NdefMap, + NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber): + phFriNfc_Tpz_H_CpDataToUsrBuf(NdefMap)); + } + + return Result; +} + +/*! +* \brief Initiates Writing of NDEF information to the Remote Device. +* +* The function initiates the writing of NDEF information to a Remote Device. +* It performs a reset of the state and starts the action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action +* has been triggered. +*/ +NFCSTATUS phFriNfc_TopazMap_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t TempByteVal = 0; + /* Copy user buffer to the context */ + NdefMap->ApduBuffer = PacketData; + /* Copy user length to the context */ + NdefMap->ApduBufferSize = *PacketDataLength; + /* Index to know the length written */ + NdefMap->ApduBuffIndex = PH_FRINFC_TOPAZ_VAL0; + /* Update the user memory size to a context variable */ + NdefMap->WrNdefPacketLength = PacketDataLength; + /* Number of bytes written to the card is zero. + This variable returns the number of bytes written + to the card. */ + *NdefMap->WrNdefPacketLength = PH_FRINFC_TOPAZ_VAL0; + /* Update the CR index to know from which operation completion + routine has to be called */ + NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_WR_NDEF; + /* Store the offset in the context */ + NdefMap->Offset = Offset; + + + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || + (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE)) + { + NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN; + /* Initialise current block and byte number */ + NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1; + NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0; + /* State has to be changed */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL; + /* Topaz command = READALL */ + +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = (phNfc_eJewelCmdList_t)phHal_eJewel_Raw; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL; +#else +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll; +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + NdefMap->TopazContainer.ReadWriteCompleteFlag = + PH_FRINFC_TOPAZ_FLAG0; + NdefMap->TopazContainer.RemainingSize = NdefMap->CardMemSize; + TempByteVal = NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1]; + } + else + { + /* State has to be changed */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE; + /* copy the user data to write into the card */ + TempByteVal = NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]; + } + + /* Update the previous operation to write operation */ + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + if((Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (NdefMap->TopazContainer.ReadWriteCompleteFlag == + PH_FRINFC_TOPAZ_FLAG1)) + { + /* Offset = Current, but the read has reached the End of Card */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + /* Check the block */ + phFriNfc_Tpz_H_BlkChk(NdefMap); + /* if offset is begin then call READALL else start writing */ + Result = ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber): + phFriNfc_Tpz_H_WrAByte(NdefMap, NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber,TempByteVal)); + } + + return Result; +} + + +/*! +* \brief Completion Routine, Processing function, needed to avoid long blocking. +* \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion +* Routine in order to be able to notify the component that an I/O has finished and data are +* ready to be processed. +* +*/ + +void phFriNfc_TopazMap_Process( void *Context, + NFCSTATUS Status) +{ + + phFriNfc_NdefMap_t *psNdefMap = NULL; + +#ifdef TOPAZ_RF_ERROR_WORKAROUND + + static uint8_t rf_error_state = 0; + +#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ +#ifdef FRINFC_READONLY_NDEF + static uint8_t written_lock_byte = 0; +#endif /* #ifdef FRINFC_READONLY_NDEF */ + + psNdefMap = (phFriNfc_NdefMap_t *)Context; + + if ((Status & PHNFCSTBLOWER) == (NFCSTATUS_SUCCESS & PHNFCSTBLOWER)) + { + switch (psNdefMap->State) + { +#ifdef FRINFC_READONLY_NDEF + case PH_FRINFC_TOPAZ_STATE_WR_CC_BYTE: + { + if((CC_READ_ONLY_VALUE == *psNdefMap->SendRecvBuf) + && (PH_FRINFC_TOPAZ_VAL1 == *psNdefMap->SendRecvLength)) + { + written_lock_byte = 0; +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ; +#else +#ifdef PH_HAL4_ENABLE + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read1; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead1; +#endif /* #ifdef PH_HAL4_ENABLE */ +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + Status = phFriNfc_Tpz_H_RdBytes (psNdefMap, LOCK_BLOCK_NUMBER, + LOCK0_BYTE_NUMBER); + + if (NFCSTATUS_PENDING == PHNFCSTATUS(Status)) + { + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_RD_LOCK0_BYTE; + } + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case PH_FRINFC_TOPAZ_STATE_RD_LOCK0_BYTE: + { + if (PH_FRINFC_TOPAZ_VAL1 == *psNdefMap->SendRecvLength) + { + Status = phFriNfc_Tpz_H_WrAByte (psNdefMap, LOCK_BLOCK_NUMBER, + LOCK0_BYTE_NUMBER, + LOCK0_BYTE_VALUE); + + if (NFCSTATUS_PENDING == PHNFCSTATUS(Status)) + { + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WR_LOCK0_BYTE; + } + } + break; + } + + case PH_FRINFC_TOPAZ_STATE_WR_LOCK0_BYTE: + { + if((LOCK0_BYTE_VALUE == *psNdefMap->SendRecvBuf) + && (PH_FRINFC_TOPAZ_VAL1 == *psNdefMap->SendRecvLength)) + { +#ifdef TOPAZ_RAW_SUPPORT + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ; +#else +#ifdef PH_HAL4_ENABLE + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read1; +#else + psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead1; +#endif /* #ifdef PH_HAL4_ENABLE */ +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + Status = phFriNfc_Tpz_H_RdBytes (psNdefMap, LOCK_BLOCK_NUMBER, + LOCK1_BYTE_NUMBER); + + if (NFCSTATUS_PENDING == PHNFCSTATUS(Status)) + { + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_RD_LOCK1_BYTE; + } + } + else + { + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + } + + case PH_FRINFC_TOPAZ_STATE_RD_LOCK1_BYTE: + { + if (PH_FRINFC_TOPAZ_VAL1 == *psNdefMap->SendRecvLength) + { + written_lock_byte = (uint8_t)(*psNdefMap->SendRecvBuf | LOCK1_BYTE_VALUE); + Status = phFriNfc_Tpz_H_WrAByte (psNdefMap, LOCK_BLOCK_NUMBER, + LOCK1_BYTE_NUMBER, + written_lock_byte); + + if (NFCSTATUS_PENDING == PHNFCSTATUS(Status)) + { + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WR_LOCK1_BYTE; + } + } + break; + } + + case PH_FRINFC_TOPAZ_STATE_WR_LOCK1_BYTE: + { + if((written_lock_byte == *psNdefMap->SendRecvBuf) + && (PH_FRINFC_TOPAZ_VAL1 == *psNdefMap->SendRecvLength)) + { + written_lock_byte = 0; + /* Do nothing */ + } + else + { + written_lock_byte = 0; + Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + } +#endif /* #ifdef FRINFC_READONLY_NDEF */ + case PH_FRINFC_TOPAZ_STATE_WRITE: + { + Status = phFriNfc_Tpz_H_ProWrUsrData (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_READID: + { + Status = phFriNfc_Tpz_H_ProReadID (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_READALL: + { + Status = phFriNfc_Tpz_H_ProReadAll (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE_NMN: + { + Status = phFriNfc_Tpz_H_ProWrNMN (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV: + { + Status = phFriNfc_Tpz_H_ProWrTLV (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV: + { + Status = phFriNfc_Tpz_H_ProCCTLV (psNdefMap); + break; + } + +#ifdef TOPAZ_RF_ERROR_WORKAROUND + + case PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ: + { + Status = phFriNfc_Tpz_H_CheckWrittenData (psNdefMap, + rf_error_state); + break; + } + +#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ + + default: + { + Status = PHNFCSTVAL (CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + } + else + { +#ifdef TOPAZ_RF_ERROR_WORKAROUND + + if ((FRINFC_RF_TIMEOUT_89 == PHNFCSTATUS (Status)) || + (FRINFC_RF_TIMEOUT_90 == PHNFCSTATUS (Status)) || + (NFCSTATUS_RF_TIMEOUT == PHNFCSTATUS (Status))) + { + uint8_t byte_number = 0; + uint8_t block_number = 0; + + rf_error_state = psNdefMap->State; + +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ; + +#else + +#ifdef PH_HAL4_ENABLE + + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read1; + +#else + + psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead1; + +#endif /* #ifdef PH_HAL4_ENABLE */ + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + /* Update the state variable to the new work around state*/ + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ; + + /* Switch is used to know, if the error occured during WRITE or READ */ + switch (rf_error_state) + { + case PH_FRINFC_TOPAZ_STATE_WRITE_NMN: + { + /* Block and byte number is updated for NMN */ + byte_number = PH_FRINFC_TOPAZ_VAL0; + block_number = PH_FRINFC_TOPAZ_VAL1; + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV: + { + /* Get the L field of the TLV block */ + block_number = (uint8_t)(((psNdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_TOPAZ_VAL1) > + PH_FRINFC_TOPAZ_VAL7)? + (psNdefMap->TLVStruct.NdefTLVBlock + + PH_FRINFC_TOPAZ_VAL1): + psNdefMap->TLVStruct.NdefTLVBlock); + /* Get the L byte */ + byte_number = (uint8_t)((psNdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_TOPAZ_VAL1) % + PH_FRINFC_TOPAZ_VAL8); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV: + { + switch (psNdefMap->TopazContainer.InternalState) + { + case PH_FRINFC_TOPAZ_WR_CC_BYTE0: + { + /* Block and byte number is updated for the CC byte 0 */ + block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; + byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL0; + break; + } + + case PH_FRINFC_TOPAZ_WR_CC_BYTE1: + { + /* Block and byte number is updated for the CC byte 1 */ + block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; + byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; + break; + } + + case PH_FRINFC_TOPAZ_WR_CC_BYTE2: + { + /* Block and byte number is updated for the CC byte 2 */ + block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; + byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL2; + break; + } + + case PH_FRINFC_TOPAZ_WR_CC_BYTE3: + { + /* Block and byte number is updated for the CC byte 3 */ + block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; + byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL3; + break; + } + + case PH_FRINFC_TOPAZ_WR_T_OF_TLV: + { + /* Block and byte number is updated for the Type field of the TLV */ + block_number = psNdefMap->TLVStruct.NdefTLVBlock; + byte_number = (uint8_t)psNdefMap->TLVStruct.NdefTLVByte; + break; + } + + default: + { + /* Do nothing */ + break; + } + } /* switch (psNdefMap->TopazContainer.InternalState) */ + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE: + { + /* Block and byte number is updated for the written error data */ + block_number = psNdefMap->TopazContainer.CurrentBlock; + byte_number = psNdefMap->TopazContainer.ByteNumber; + break; + } + + default: + { + /* Error occured is not during WRITE, so update + state variable to the previous state */ + psNdefMap->State = rf_error_state; + break; + } + } /* switch (rf_error_state) */ + + /* The below check is added, to know if the error is for + the WRITE or READ scenario, + If the error is for READ, then state variable is not updated + If the error is for WRITE, then state variable is updated with + PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ value */ + if (PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ == psNdefMap->State) + { + /* Read the data with the updated block and byte number */ + Status = phFriNfc_Tpz_H_RdBytes (psNdefMap, block_number, + byte_number); + } + } + +#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ + } + + /* Call Completion Routine, if Status != PENDING */ + if (NFCSTATUS_PENDING != Status) + { + phFriNfc_Tpz_H_Complete(psNdefMap, Status); + } +} + + +#ifdef TOPAZ_RF_ERROR_WORKAROUND + +static +NFCSTATUS +phFriNfc_Tpz_H_CheckWrittenData ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t state_rf_error) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + + switch (state_rf_error) + { + case PH_FRINFC_TOPAZ_STATE_WRITE: + { + result = phFriNfc_Tpz_H_ProWrUsrData (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE_NMN: + { + result = phFriNfc_Tpz_H_ProWrNMN (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV: + { + result = phFriNfc_Tpz_H_ProWrTLV (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV: + { + result = phFriNfc_Tpz_H_ProCCTLV (psNdefMap); + break; + } + + default: + { + break; + } + } + + return result; +} + + +#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ + +static NFCSTATUS phFriNfc_Tpz_H_RdBytes(phFriNfc_NdefMap_t *NdefMap, + uint16_t BlockNo, + uint16_t ByteNo) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; +#ifdef TOPAZ_RAW_SUPPORT + uint8_t index = 0; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + /* set the data for additional data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0; + NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0; + + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + + /* Depending on the jewel command, the send length is decided */ +#ifdef TOPAZ_RAW_SUPPORT + switch(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0]) +#else + switch(NdefMap->Cmd.JewelCmd) +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + { + +#ifdef TOPAZ_RAW_SUPPORT + case PH_FRINFC_TOPAZ_CMD_READID: +#else +#ifdef PH_HAL4_ENABLE + case phHal_eJewel_RID: +#else + case phHal_eJewelCmdListJewelRid: +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = (phNfc_eJewelCmdList_t)phHal_eJewel_Raw; + /*Copy command to Send Buffer*/ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READID; + index ++; + + /*Copy UID of the tag to Send Buffer*/ + (void)memset(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1]), + 0x00,(0x06)); + index = index + 0x06; + + /* Update the length of the command buffer*/ + NdefMap->SendLength = index; +#else + /* For READ ID and READ ALL, send length is 0 */ + NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + break; + +#ifdef TOPAZ_RAW_SUPPORT + case PH_FRINFC_TOPAZ_CMD_READALL: +#else +#ifdef PH_HAL4_ENABLE + case phHal_eJewel_ReadAll: +#else + case phHal_eJewelCmdListJewelReadAll: +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = (phNfc_eJewelCmdList_t)phHal_eJewel_Raw; + /*Copy command to Send Buffer*/ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL; + index ++; + + /*Copy 0x00 to Send Buffer*/ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = 0x00; + index ++; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 0x00; + index ++; + + /*Copy UID of the tag to Send Buffer*/ + (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]), + &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid), + TOPAZ_UID_LENGTH_FOR_READ_WRITE); + + index = (uint8_t)(index + TOPAZ_UID_LENGTH_FOR_READ_WRITE); + + /* Update the length of the command buffer*/ + NdefMap->SendLength = index; +#else + /* For READ ID and READ ALL, send length is 0 */ + NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + break; + +#ifdef TOPAZ_RAW_SUPPORT + case PH_FRINFC_TOPAZ_CMD_READ: +#else +#ifdef PH_HAL4_ENABLE + case phHal_eJewel_Read1: +#else + case phHal_eJewelCmdListJewelRead1: +#endif + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = (phNfc_eJewelCmdList_t)phHal_eJewel_Raw; + /*Copy command to Send Buffer*/ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READ; + index ++; + + /*Copy Address to Send Buffer*/ + /* Calculate send length + 7 | 6 5 4 3 | 2 1 0 | + | block no | byte no | + */ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = + (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) + + ByteNo); + index ++; + /*Copy 0x00 to Send Buffer*/ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 0x00; + index ++; + + /*Copy UID of the tag to Send Buffer*/ + (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]), + &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid), + TOPAZ_UID_LENGTH_FOR_READ_WRITE); + index = (uint8_t)(index + TOPAZ_UID_LENGTH_FOR_READ_WRITE); + + /* Update the length of the command buffer*/ + NdefMap->SendLength = index; +#else + /* Calculate send length + 7 | 6 5 4 3 | 2 1 0 | + | block no | byte no | + */ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = + (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) + + ByteNo); + NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL1; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + break; +#ifdef TOPAZ_RAW_SUPPORT +#else +#ifdef PH_HAL4_ENABLE + case phHal_eJewel_Read: + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = 0x00; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = 0x00; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 104; + NdefMap->SendLength = 3; + break; +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + default: + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + } + + if(Result == NFCSTATUS_SUCCESS) + { + /* Call the Overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_WrAByte(phFriNfc_NdefMap_t *NdefMap, + uint16_t BlockNo, + uint16_t ByteNo, + uint8_t ByteVal + ) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t index = 0; + + + PHNFC_UNUSED_VARIABLE(ByteVal); + /* set the data for additional data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0; + NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0; + + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + /* Command used to write 1 byte */ +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = (phNfc_eJewelCmdList_t)phHal_eJewel_Raw; +#else +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelWriteErase1; +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + +#ifdef TOPAZ_RAW_SUPPORT + /*Copy command to Send Buffer*/ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_WRITE_1E; + index ++; + + /*Copy Address to Send Buffer*/ + /* Calculate send length + 7 | 6 5 4 3 | 2 1 0 | + | block no | byte no | + */ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = + (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) + + ByteNo); + index ++; + /*Copy Data byte to Send Buffer*/ + NdefMap->SendRecvBuf[index] = ByteVal; + index ++; + + /*Copy UID of the tag to Send Buffer*/ + (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]), + &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid), + TOPAZ_UID_LENGTH_FOR_READ_WRITE); + index = (uint8_t)(index + TOPAZ_UID_LENGTH_FOR_READ_WRITE); + + /* Update the length of the command buffer*/ + NdefMap->SendLength = index; + +#else + /* Depending on the jewel command, the send length is decided */ + /* Calculate send length + 7 | 6 5 4 3 | 2 1 0 | + | block no | byte no | + */ + NdefMap->SendRecvBuf[index] = + (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) + + ByteNo); + index ++; + NdefMap->SendRecvBuf[index] = ByteVal; + index ++; + NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL2; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + /* Call the Overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ProReadID(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + + if(((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] & + PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_HEADROM0_VAL) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL6)) + { + /* Copy UID to the context, Used when the READ ALL command is used */ + (void)memcpy(NdefMap->TopazContainer.UID, + &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2], + PH_FRINFC_TOPAZ_VAL4); + + /* State has to be changed */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL; + /* Topaz command = READALL */ +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = (phNfc_eJewelCmdList_t)phHal_eJewel_Raw; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL; +#else +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll; +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + /* Read all bytes from the card */ + Result = phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber); + } + + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ProReadAll(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + int32_t memcompare = PH_FRINFC_TOPAZ_VAL0; + + /* Compare the UID of READ ALL command with the stored UID */ +#ifdef PH_HAL4_ENABLE + if ((NdefMap->TopazContainer.UID[0] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2]) && + (NdefMap->TopazContainer.UID[1] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 1]) && + (NdefMap->TopazContainer.UID[2] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 2]) && + (NdefMap->TopazContainer.UID[3] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 3])) + { + memcompare = PH_FRINFC_TOPAZ_VAL0; + } + else + { + memcompare = PH_FRINFC_TOPAZ_VAL1; + } +#else + memcompare = memcmp(NdefMap->TopazContainer.UID, + &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2], + PH_FRINFC_TOPAZ_VAL4); +#endif /* #ifdef PH_HAL4_ENABLE */ + + if(((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] & + PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_HEADROM0_VAL) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_READALL_RESP) && + (memcompare == PH_FRINFC_TOPAZ_VAL0)) + { + /* Copy 96 bytes from the read/write memory space */ + (void)memcpy(NdefMap->TopazContainer.ReadBuffer, + &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL10], + PH_FRINFC_TOPAZ_TOTAL_RWBYTES); + + /* Check the lock bits and set the card state */ + phFriNfc_Tpz_H_ChkLockBits(NdefMap); + + Result = phFriNfc_Tpz_H_CallNxtOp(NdefMap); + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_CallNxtOp(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + /* Depending on the operation (check, read or write ndef), process the + read data */ + switch(NdefMap->PrevOperation) + { + case PH_FRINFC_NDEFMAP_CHECK_OPE: + /* Check the capabilty container values, according + to the spec */ + Result = phFriNfc_Tpz_H_ChkCCinChkNdef(NdefMap); + + if (NdefMap->CardState != PH_NDEFMAP_CARD_STATE_INVALID) + { + /* Check the spec version */ + Result = phFriNfc_Tpz_H_ChkSpcVer( NdefMap, + NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL1]); + /* Check the CC header size: Only valid ones are + 0x0C for 96 bytes. */ + if ((Result == NFCSTATUS_SUCCESS) && + ( NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL2] <= + PH_FRINFC_TOPAZ_CC_BYTE2_MAX)) + { + Result = phFriNfc_Tpz_H_findNDEFTLV(NdefMap); + /* As there is possibility of either having or not having TLV in + Topaz, no need to send the Actual status to the context*/ + Result = NFCSTATUS_SUCCESS; + } + } + else + { + Result = NFCSTATUS_SUCCESS; + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED; + NdefMap->CardMemSize = + NdefMap->TopazContainer.RemainingSize = (uint16_t) + /* + 4 is decremented from the max size because of the 4 CC bytes + 2 is decremented because of the NDEF TLV T and L byte + to get the actual data size + */ + (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4 - + PH_FRINFC_TOPAZ_VAL2); + } + break; + + case PH_FRINFC_NDEFMAP_READ_OPE: + /* Check the capabilty container values, according + to the spec */ + Result = phFriNfc_Tpz_H_ChkCCBytes(NdefMap); + + /* If success, find the ndef TLV */ + Result = ((Result != NFCSTATUS_SUCCESS)? + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT)): + phFriNfc_Tpz_H_findNDEFTLV(NdefMap)); + + if(Result == NFCSTATUS_SUCCESS) + { + NdefMap->TopazContainer.ByteNumber += PH_FRINFC_TOPAZ_VAL2; + /* If success, copy the read bytes to the user buffer */ + Result = phFriNfc_Tpz_H_CpDataToUsrBuf(NdefMap); + } + break; + + case PH_FRINFC_NDEFMAP_WRITE_OPE: + default: + if((NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_WRITE) || + (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INITIALIZED)) + { + /* Check the capabilty container values, according + to the spec */ + Result = phFriNfc_Tpz_H_ChkCCBytes(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + /* Find the NDEF TLV */ + Result = phFriNfc_Tpz_H_findNDEFTLV(NdefMap); + + /* Write the TLV */ + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_T_OF_TLV; + } + else + { + NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_TOPAZ_VAL4; + NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_TOPAZ_VAL1; + NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL4; + /* Write the TLV */ + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE0; + } + /* Write CC bytes */ + Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); + } + break; + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ChkCCBytes(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + + if(NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE0) + { + /* Check the spec version */ + Result = phFriNfc_Tpz_H_ChkSpcVer( NdefMap, + NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL1]); + /* Check the CC header size: Only valid ones are + 0x0C for 96 bytes. */ + Result = ((( NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL2] > + PH_FRINFC_TOPAZ_CC_BYTE2_MAX) || (Result != + NFCSTATUS_SUCCESS))? + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED)): + Result); + + /* Get the read/write card memory size */ + NdefMap->TopazContainer.RemainingSize = + NdefMap->CardMemSize = ((Result == NFCSTATUS_SUCCESS)? + (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4): + NdefMap->CardMemSize); + + /* if the call is from write ndef then check for read write access */ + if(((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE) && + (NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] != + PH_FRINFC_TOPAZ_CC_BYTE3_RW) && (Result == NFCSTATUS_SUCCESS))) + { + Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT)); + } + + /* if the call is from read ndef then check for read only or read write access */ + if(((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE) && + ((NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] != + PH_FRINFC_TOPAZ_CC_BYTE3_RW) && + (NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] != + PH_FRINFC_TOPAZ_CC_BYTE3_RO))&& (Result == NFCSTATUS_SUCCESS))) + { + Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT)); + } + } + return Result; +} + +extern NFCSTATUS phFriNfc_Tpz_H_ChkSpcVer( phFriNfc_NdefMap_t *NdefMap, + uint8_t VersionNo) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t TagVerNo = VersionNo; + + /* To remove "warning (VS C4100) : unreferenced formal parameter" */ + PHNFC_UNUSED_VARIABLE(NdefMap); + + if ( TagVerNo == 0 ) + { + /*Return Status Error “ Invalid Format”*/ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT); + } + else + { + /* calculate the major and minor version number of T3VerNo */ + if( (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM == + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&& + ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM >= + PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo))) || + (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM == + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&& + ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM < + PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo) ))) + { + Result = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS); + } + else + { + if (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM < + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo) ) || + ( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM > + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo))) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT); + } + } + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_findNDEFTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + uint8_t index = PH_FRINFC_TOPAZ_VAL4; + + /* If remaining size is less than 3 then, there cant be any + TLV present in the card */ + while((index < PH_FRINFC_TOPAZ_TOTAL_RWBYTES) && + (NdefMap->TopazContainer.RemainingSize >= PH_FRINFC_TOPAZ_VAL3)) + { + switch(NdefMap->TopazContainer.ReadBuffer[index]) + { + case PH_FRINFC_TOPAZ_NDEF_T: + /* To get the length field of the TLV */ + index++; + /* Type and length are not data bytes, so to know the exact + remaining size in the card, the below operation is done */ + NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL2; + /* Set the card state depending on the L value */ + Result = phFriNfc_MapTool_SetCardState(NdefMap, + (uint32_t)NdefMap->TopazContainer.ReadBuffer[index]); + /* Check the TLV is correct */ + if((NdefMap->TopazContainer.ReadBuffer[index] > + NdefMap->TopazContainer.RemainingSize) || + ((NdefMap->TopazContainer.ReadBuffer[index] == + PH_FRINFC_TOPAZ_VAL0) && (NdefMap->PrevOperation == + PH_FRINFC_NDEFMAP_READ_OPE)) || (Result != NFCSTATUS_SUCCESS)) + { + /* L field value cant be greater than the remaining size, so error */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + /* To break out of the loop */ + index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES; + } + else + { + /* So remaining size also changes, according to the position of NDEF TLV */ + NdefMap->TLVStruct.BytesRemainLinTLV = + NdefMap->TopazContainer.ReadBuffer[index]; + + /* Get the byte number */ + NdefMap->TLVStruct.NdefTLVByte = (uint16_t)((index - PH_FRINFC_TOPAZ_VAL1) % + PH_FRINFC_TOPAZ_VAL8); + /* Get the block number */ + NdefMap->TLVStruct.NdefTLVBlock = (uint8_t)(((index - PH_FRINFC_TOPAZ_VAL1) / + PH_FRINFC_TOPAZ_VAL8) + + PH_FRINFC_TOPAZ_VAL1); + /* TLV found flag is set */ + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_TOPAZ_FLAG1; + /* To know the position of V field in the TLV */ + NdefMap->TopazContainer.ByteNumber = (uint8_t)(((NdefMap->TLVStruct.NdefTLVBlock - 1) * 8) + + NdefMap->TLVStruct.NdefTLVByte); + /* To break out of the loop */ + index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES; + Result = NFCSTATUS_SUCCESS; + } + break; + + case PH_FRINFC_TOPAZ_NULL_T: + /* Null TLV, Skip the TLV */ + NdefMap->TopazContainer.RemainingSize--; + index++; + break; + + case PH_FRINFC_TOPAZ_TERM_T: + /* No more TLV present in the card, so error */ + index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES; + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + + default: + /* Go till the length field of the TLV */ + index++; + /* Type and length is not the data, so to know the exact + remaining size in the card, the below operation is done */ + NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL2; + if(NdefMap->TopazContainer.ReadBuffer[index] > + NdefMap->TopazContainer.RemainingSize) + { + /* L field value cant be greater than the remaining size, so error */ + index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES; + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + /* Remaining size of the free space available in the card changes, + according to the position of NDEF TLV */ + NdefMap->TopazContainer.RemainingSize = + NdefMap->TopazContainer.RemainingSize - + NdefMap->TopazContainer.ReadBuffer[index]; + + /* Get the position of the next TLV */ + index = (uint8_t)(index + + (NdefMap->TopazContainer.ReadBuffer[index] + + PH_FRINFC_TOPAZ_VAL1)); + } + break; + } + } + + /* If no Ndef TLV found and operation done is read */ + if((NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_TOPAZ_FLAG0) && + (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE)) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + if((NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_TOPAZ_FLAG0) && + ((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE) || + (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_CHECK_OPE))) + { + NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_TOPAZ_VAL4; + NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_TOPAZ_VAL1; + NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL4; + NdefMap->TopazContainer.RemainingSize = PH_FRINFC_TOPAZ_TOTAL_RWBYTES1; + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_CpDataToUsrBuf(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Check the the TLV size and the user size */ + if(NdefMap->ApduBufferSize >= + NdefMap->TLVStruct.BytesRemainLinTLV) + { + /* Copy the read bytes to user buffer till the value (V) + of TLV ends */ + (void)memcpy(NdefMap->ApduBuffer, + &(NdefMap->TopazContainer.ReadBuffer[ + NdefMap->TopazContainer.ByteNumber]), + NdefMap->TLVStruct.BytesRemainLinTLV); + + /* Update the number of read bytes to the user */ + *(NdefMap->NumOfBytesRead) = + NdefMap->TLVStruct.BytesRemainLinTLV; + /* There is no byte to read */ + NdefMap->TopazContainer.ByteNumber = + PH_FRINFC_TOPAZ_VAL0; + /* No further read is possible */ + NdefMap->TopazContainer.ReadWriteCompleteFlag = + PH_FRINFC_TOPAZ_FLAG1; + /* Remaining size in the card can be greater than length field in + the TLV */ + NdefMap->TopazContainer.RemainingSize = + NdefMap->TopazContainer.RemainingSize - + NdefMap->TLVStruct.BytesRemainLinTLV; + /* TLV has been completely read, no more bytes to read */ + NdefMap->TLVStruct.BytesRemainLinTLV = + PH_FRINFC_TOPAZ_VAL0; + } + else + { + /* Copy read bytes till the user buffer size */ + (void)memcpy(NdefMap->ApduBuffer, + &(NdefMap->TopazContainer.ReadBuffer[ + NdefMap->TopazContainer.ByteNumber]), + NdefMap->ApduBufferSize); + + /* Update the number of read bytes to the user */ + *(NdefMap->NumOfBytesRead) = + NdefMap->ApduBufferSize; + /* Get the next byte number to read */ + NdefMap->TopazContainer.ByteNumber = + (uint8_t)(NdefMap->TopazContainer.ByteNumber + + NdefMap->ApduBufferSize); + /* Free space left in the card */ + NdefMap->TopazContainer.RemainingSize + = NdefMap->TopazContainer.RemainingSize + - (uint16_t)NdefMap->ApduBufferSize; + /* Bytes left in the TLV */ + NdefMap->TLVStruct.BytesRemainLinTLV = + NdefMap->TLVStruct.BytesRemainLinTLV - + (uint16_t)NdefMap->ApduBufferSize; + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ProWrNMN(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + uint8_t BlockNo = PH_FRINFC_TOPAZ_VAL0, + ByteNo = PH_FRINFC_TOPAZ_VAL0; + + if((NdefMap->TopazContainer.InternalState == + PH_FRINFC_TOPAZ_WR_NMN_0) && + (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_VAL0) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV; + /* Get the L field of the TLV block */ + BlockNo = (uint8_t)(((NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_TOPAZ_VAL1) > + PH_FRINFC_TOPAZ_VAL7)? + (NdefMap->TLVStruct.NdefTLVBlock + PH_FRINFC_TOPAZ_VAL1): + NdefMap->TLVStruct.NdefTLVBlock); + /* Get the L byte */ + ByteNo = (uint8_t)((NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_TOPAZ_VAL1) % + PH_FRINFC_TOPAZ_VAL8); + + + /* Here the NMN is written 0, so internal state is used */ + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_L_TLV_0; + /* Write the length value = 0x00 , Write L field of TLV = 0 inside this*/ + Result = phFriNfc_Tpz_H_WrAByte( NdefMap, BlockNo, ByteNo, + PH_FRINFC_TOPAZ_VAL0); + } + else + { + if((NdefMap->TopazContainer.InternalState == + PH_FRINFC_TOPAZ_WR_NMN_E1) && + (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE0) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + /* Card state is initialised or invalid */ + NdefMap->CardState = (uint8_t)((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INITIALIZED)? + PH_NDEFMAP_CARD_STATE_READ_WRITE: + NdefMap->CardState); + /* update the length to the user */ + *NdefMap->WrNdefPacketLength = NdefMap->ApduBuffIndex; + Result = NFCSTATUS_SUCCESS; + } + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ProWrTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + if((NdefMap->TopazContainer.InternalState == + PH_FRINFC_TOPAZ_WR_L_TLV_0) && + (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_VAL0) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + /* state is writing user data to the card */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE; + + NdefMap->TopazContainer.ByteNumber++; + /* Check the byte number */ + phFriNfc_Tpz_H_BlkChk(NdefMap); + + /* Write data to the specified location */ + /* Write the data to the card from the user buffer */ + Result = phFriNfc_Tpz_H_WrAByte( NdefMap, + NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber, + NdefMap->ApduBuffer[NdefMap->ApduBuffIndex] + ); + } + else + { + if((NdefMap->TopazContainer.InternalState == + PH_FRINFC_TOPAZ_WR_L_TLV) && + (((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) && + (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + NdefMap->ApduBuffIndex)) || + ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + (NdefMap->ApduBuffIndex + NdefMap->TLVStruct.BytesRemainLinTLV)))) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + /* Update the L value in the context */ + NdefMap->TLVStruct.BytesRemainLinTLV = + ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + NdefMap->ApduBuffIndex: + (NdefMap->TLVStruct.BytesRemainLinTLV + NdefMap->ApduBuffIndex)); + + /* Write 0xE1 in block number = 1 and byte number = 0 */ + Result = phFriNfc_Tpz_H_WrByte0ValE1(NdefMap); + } + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ProWrUsrData(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + /* send buffer should be equal to receive buffer */ + if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + /* Increment the index */ + NdefMap->ApduBuffIndex += PH_FRINFC_TOPAZ_VAL1; + + /* Remaining space left in the card is less by one */ + NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL1; + + /* Increment the byte number */ + NdefMap->TopazContainer.ByteNumber++; + + /* Check the block number */ + phFriNfc_Tpz_H_BlkChk(NdefMap); + + /* check for the user space or the card size */ + if((NdefMap->ApduBufferSize == NdefMap->ApduBuffIndex) || + (NdefMap->TopazContainer.RemainingSize == PH_FRINFC_TOPAZ_VAL0)) + { + /* Set write complete, if the end of card is reached */ + NdefMap->TopazContainer.ReadWriteCompleteFlag = (uint8_t) + ((NdefMap->TopazContainer.RemainingSize == PH_FRINFC_TOPAZ_VAL0)? + PH_FRINFC_TOPAZ_FLAG1:PH_FRINFC_TOPAZ_FLAG0); + + Result = phFriNfc_Tpz_H_WrLByte(NdefMap); + } + else + { + /* State is continued to be in write */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE; + + /* Write the byte to the specified location , and Byte to write */ + Result = phFriNfc_Tpz_H_WrAByte(NdefMap, NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber, + NdefMap->ApduBuffer[NdefMap->ApduBuffIndex] + ); + } + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_WrLByte(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t BlockNo = PH_FRINFC_TOPAZ_VAL0, + ByteNo = PH_FRINFC_TOPAZ_VAL0; + uint8_t TempByteVal = 0; + BlockNo = (uint8_t)(((NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_TOPAZ_VAL1) > + PH_FRINFC_TOPAZ_VAL7)? + (NdefMap->TLVStruct.NdefTLVBlock + + PH_FRINFC_TOPAZ_VAL1): + NdefMap->TLVStruct.NdefTLVBlock); + + ByteNo = (uint8_t)((NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_TOPAZ_VAL1) % PH_FRINFC_TOPAZ_VAL8); + /* Update L field */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV; + /* Internal state for write */ + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_L_TLV; + /* Update the length field depending on the offset */ + TempByteVal = (uint8_t) + ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + NdefMap->ApduBuffIndex: + (NdefMap->ApduBuffIndex + + NdefMap->TLVStruct.BytesRemainLinTLV)); + /* Write the L field */ + Result = phFriNfc_Tpz_H_WrAByte(NdefMap, BlockNo, ByteNo,TempByteVal); + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_WrByte0ValE1(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Update L field */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_NMN; + /* Internal state for writing 0xE1 */ + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_NMN_E1; + /* Update the length field depending on the offset */ + /* Write the L field */ + Result = phFriNfc_Tpz_H_WrAByte(NdefMap, PH_FRINFC_TOPAZ_VAL1, + PH_FRINFC_TOPAZ_VAL0,PH_FRINFC_TOPAZ_CC_BYTE0); + return Result; +} + +static void phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Status) +{ + /* set the state back to the Reset_Init state*/ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; + + /* set the completion routine*/ + NdefMap->CompletionRoutine[NdefMap->TopazContainer.CRIndex]. + CompletionRoutine(NdefMap->CompletionRoutine->Context, Status); +} + +static void phFriNfc_Tpz_H_BlkChk(phFriNfc_NdefMap_t *NdefMap) +{ + NdefMap->TopazContainer.CurrentBlock = + (uint8_t)((NdefMap->TopazContainer.ByteNumber > + PH_FRINFC_TOPAZ_VAL7)? + (NdefMap->TopazContainer.CurrentBlock + + PH_FRINFC_TOPAZ_VAL1): + NdefMap->TopazContainer.CurrentBlock); + + NdefMap->TopazContainer.ByteNumber = (uint8_t)(NdefMap->TopazContainer.ByteNumber % + PH_FRINFC_TOPAZ_VAL8); +} + +static NFCSTATUS phFriNfc_Tpz_H_ChkCCinChkNdef(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + + if(NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE0) + { + /* Check the most significant nibble of byte 3 (RWA) = 0 */ + Result = (((NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] & + PH_FRINFC_TOPAZ_BYTE3_MSB)== PH_FRINFC_TOPAZ_VAL0)? + NFCSTATUS_SUCCESS: + Result); + + /* Card size is initialised */ + NdefMap->CardMemSize = NdefMap->TopazContainer.RemainingSize = + ((Result == NFCSTATUS_SUCCESS)? + (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4): + NdefMap->CardMemSize); + } + + if (NdefMap->CardState != PH_NDEFMAP_CARD_STATE_READ_ONLY) + { + NdefMap->CardState = (uint8_t)((Result == NFCSTATUS_SUCCESS)? + PH_NDEFMAP_CARD_STATE_INITIALIZED: + PH_NDEFMAP_CARD_STATE_INVALID); + } + + return Result; +} + +static void phFriNfc_Tpz_H_ChkLockBits(phFriNfc_NdefMap_t *NdefMap) +{ + /* Set the card state */ + NdefMap->CardState = (uint8_t) + (((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_0] == + PH_FRINFC_TOPAZ_LOCKBIT_BYTE114) && + ((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_1] == + PH_FRINFC_TOPAZ_LOCKBIT_BYTE115_1) || + (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_1] == + PH_FRINFC_TOPAZ_LOCKBIT_BYTE115_2)))? + PH_NDEFMAP_CARD_STATE_READ_WRITE: + PH_NDEFMAP_CARD_STATE_READ_ONLY); + + /* Set the card state from CC bytes */ + if (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_WRITE) + { + if (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_CC_BYTENO_3] == PH_FRINFC_TOPAZ_CC_READWRITE) + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE; + } + else if (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_CC_BYTENO_3] == PH_FRINFC_TOPAZ_CC_READONLY) + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY; + } + else + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } + } +} + +static NFCSTATUS phFriNfc_Tpz_H_WrCCorTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t ByteNo = PH_FRINFC_TOPAZ_VAL0, + BlockNo = PH_FRINFC_TOPAZ_VAL0; + uint8_t TempByteVal = 0; + switch(NdefMap->TopazContainer.InternalState) + { + case PH_FRINFC_TOPAZ_WR_CC_BYTE0: + /* To write the CC bytes */ + TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE0; + ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL0; + BlockNo = PH_FRINFC_TOPAZ_VAL1; + break; + + case PH_FRINFC_TOPAZ_WR_CC_BYTE1: + /* To write the CC bytes */ + TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE1; + ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL1; + BlockNo = PH_FRINFC_TOPAZ_VAL1; + break; + + case PH_FRINFC_TOPAZ_WR_CC_BYTE2: + /* To write the CC bytes */ + TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE2_MAX; + ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL2; + BlockNo = PH_FRINFC_TOPAZ_VAL1; + break; + + case PH_FRINFC_TOPAZ_WR_CC_BYTE3: + /* To write the CC bytes */ + TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE3_RW; + ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL3; + BlockNo = PH_FRINFC_TOPAZ_VAL1; + break; + + case PH_FRINFC_TOPAZ_WR_T_OF_TLV: + default: + /* To write the NDEF TLV (if not present) */ + TempByteVal = PH_FRINFC_TOPAZ_NDEF_T; + ByteNo = (uint8_t)NdefMap->TLVStruct.NdefTLVByte; + BlockNo = NdefMap->TLVStruct.NdefTLVBlock; + break; + } + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV; + Result = phFriNfc_Tpz_H_WrAByte( NdefMap, BlockNo, ByteNo,TempByteVal); + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ProCCTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + switch(NdefMap->TopazContainer.InternalState) + { + case PH_FRINFC_TOPAZ_WR_CC_BYTE0: + /* Process the CC byte */ + /* Check the response */ + if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE0) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE1; + Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); + } + break; + + case PH_FRINFC_TOPAZ_WR_CC_BYTE1: + /* Process the CC byte */ + /* Check the response */ + if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE1) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE2; + Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); + } + break; + + case PH_FRINFC_TOPAZ_WR_CC_BYTE2: + /* Process the CC byte */ + /* Check the response */ + if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE2_MAX) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE3; + Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); + } + break; + + case PH_FRINFC_TOPAZ_WR_CC_BYTE3: + /* Process the CC byte */ + /* Check the response */ + if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE3_RW) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_T_OF_TLV; + Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); + } + break; + + case PH_FRINFC_TOPAZ_WR_T_OF_TLV: + default: + /* Check the response */ + if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_NDEF_T) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + /* Increment the Byte Number */ + NdefMap->TopazContainer.ByteNumber++; + /* Check the block and byte number */ + phFriNfc_Tpz_H_BlkChk(NdefMap); + /* Process the T of NDEF TLV */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_NMN; + + /* Here the NMN is written 0, so internal state is used */ + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_NMN_0; + + /*Inside this call Write NMN (block number 1 and byte number 0) = 0 */ + Result = phFriNfc_Tpz_H_WrAByte( NdefMap, PH_FRINFC_TOPAZ_VAL1, + PH_FRINFC_TOPAZ_VAL0,PH_FRINFC_TOPAZ_VAL0); + } + break; + } + return Result; +} + +#ifdef UNIT_TEST +#include +#endif + +#endif /* PH_FRINFC_MAP_TOPAZ_DISABLED */ diff --git a/libnfc-nxp/phFriNfc_TopazMap.h b/libnfc-nxp/phFriNfc_TopazMap.h new file mode 100644 index 0000000..eb503f8 --- /dev/null +++ b/libnfc-nxp/phFriNfc_TopazMap.h @@ -0,0 +1,636 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* + * \file phFriNfc_TopazMap.h + * \brief NFC Ndef Mapping For Mifare UL Card. + * + * Project: NFC-FRI + * + * $Date: Mon Dec 13 14:14:14 2010 $ + * $Author: ing02260 $ + * $Revision: 1.26 $ + * $Aliases: $ + * + */ + +#ifndef PHFRINFC_TOPAZMAP_H +#define PHFRINFC_TOPAZMAP_H + +#include +#ifdef PH_HAL4_ENABLE +#include +#else +#include +#endif +#include +#include +#include + + +#define PH_FRINFC_NDEFMAP_TOPAZMAP_FILEREVISION "$Revision: 1.26 $" +#define PH_FRINFC_NDEFMAP_TOPAZMAP_FILEALIASES "$Aliases: $" + +#if !defined (ES_HW_VER) + + #define ES_HW_VER (32U) + +#endif /* #if !defined (ES_HW_VER) */ + +#if (ES_HW_VER >= 32) + + /* This macro is used for the new 3.2 chip,as the JEWEL_READ and + JEWEL_WRITE for this chip is removed from the firmware. And for the + new FW, only JEWEL_RAW shall be used */ + #define TOPAZ_RAW_SUPPORT + +#endif /* #if (ES_HW_VER == 32) */ + +#define TOPAZ_UID_LENGTH_FOR_READ_WRITE 0x04U + +/*! + * \name Topaz - states of the Finite State machine + * + */ +/*@{*/ +#define PH_FRINFC_TOPAZ_STATE_READ 1 /*!< Read State */ +#define PH_FRINFC_TOPAZ_STATE_WRITE 2 /*!< Write is going on*/ +#define PH_FRINFC_TOPAZ_STATE_CHK_NDEF 3 /*!< Check Ndef is going on */ +#define PH_FRINFC_TOPAZ_STATE_READID 4 /*!< Read Id under progress */ +#define PH_FRINFC_TOPAZ_STATE_READALL 5 /*!< Read all under progress */ +#define PH_FRINFC_TOPAZ_STATE_WRITE_NMN 6 /*!< Write ndef magic number */ +#define PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV 7 /*!< Write length field of TLV */ +#define PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV 8 /*!< Write CC or NDEF TLV */ + +#ifdef FRINFC_READONLY_NDEF + + #define PH_FRINFC_TOPAZ_STATE_WR_CC_BYTE 9 /*!< READ ONLY state */ + #define PH_FRINFC_TOPAZ_STATE_RD_LOCK0_BYTE 10 /*!< read Lock byte 0 state */ + #define PH_FRINFC_TOPAZ_STATE_WR_LOCK0_BYTE 11 /*!< write Lock byte 0 state */ + #define PH_FRINFC_TOPAZ_STATE_RD_LOCK1_BYTE 12 /*!< read Lock byte 1 state */ + #define PH_FRINFC_TOPAZ_STATE_WR_LOCK1_BYTE 13 /*!< write Lock byte 1 state */ + +#endif /* #ifdef FRINFC_READONLY_NDEF */ +/*@}*/ + +/*! + * \name Topaz - constants for the capability container + * + */ +/*@{*/ +#define PH_FRINFC_TOPAZ_CC_BYTE0 0xE1 /*!< Capability container byte 0 = 0xE1 (NMN) */ +#define PH_FRINFC_TOPAZ_CC_BYTE1 0x10 /*!< Capability container byte 1 = 0x10 (version number) */ +#define PH_FRINFC_TOPAZ_CC_BYTE2_MAX 0x0E /*!< Capability container byte 2 = 0x0E (Total free space + in the card) */ +#define PH_FRINFC_TOPAZ_CC_BYTE3_RW 0x00 /*!< Capability container byte 3 = 0x00 for + READ WRITE/INITIALISED card state */ +#define PH_FRINFC_TOPAZ_CC_BYTE3_RO 0x0F /*!< Capability container byte 3 = 0x0F for + READ only card state */ + +/*@}*/ + +/*! + * \name Topaz - constants for Flags + * + */ +/*@{*/ +#define PH_FRINFC_TOPAZ_FLAG0 0 /*!< Flag value = 0 */ +#define PH_FRINFC_TOPAZ_FLAG1 1 /*!< Flag value = 1 */ +/*@}*/ + +/*! + * \name Topaz - constants for left shift + * + */ +/*@{*/ +#define PH_FRINFC_TOPAZ_SHIFT3 3 /*!< Shift by 3 bits */ +/*@}*/ + +/*! + * \name Topaz - internal state for write + * + */ +/*@{*/ +enum +{ + PH_FRINFC_TOPAZ_WR_CC_BYTE0, /*!< CC Byte 0 = 0xE1 ndef magic number */ + PH_FRINFC_TOPAZ_WR_CC_BYTE1, /*!< CC Byte 1 = 0x10 version number */ + PH_FRINFC_TOPAZ_WR_CC_BYTE2, /*!< CC Byte 2 = 0x0C space in the data area */ + PH_FRINFC_TOPAZ_WR_CC_BYTE3, /*!< CC Byte 3 = 0x00 read write access */ + PH_FRINFC_TOPAZ_WR_T_OF_TLV, /*!< CC Byte 3 = 0x00 read write access */ + PH_FRINFC_TOPAZ_WR_NMN_0, /*!< NMN = 0x00 */ + PH_FRINFC_TOPAZ_WR_NMN_E1, /*!< NMN = 0xE1 */ + PH_FRINFC_TOPAZ_WR_L_TLV_0, /*!< L field of TLV = 0 */ + PH_FRINFC_TOPAZ_WR_L_TLV, /*!< To update the L field */ + PH_FRINFC_TOPAZ_DYNAMIC_INIT_CHK_NDEF, /*!< Internal state to represent the parsing of card to locate Ndef TLV*/ + PH_FRINFC_TOPAZ_DYNAMIC_INIT_FIND_NDEF_TLV + + +}; +/*@}*/ + +/*! + * \name Topaz - TLV related constants + * + */ +/*@{*/ +#define PH_FRINFC_TOPAZ_NULL_T 0x00 /*!< Null TLV value = 0x00 */ +#define PH_FRINFC_TOPAZ_LOCK_CTRL_T 0x01 /*!< Lock TLV = 0x01 */ +#define PH_FRINFC_TOPAZ_MEM_CTRL_T 0x02 /*!< Memory TLV = 0x02 */ +#define PH_FRINFC_TOPAZ_NDEF_T 0x03 /*!< NDEF TLV = 0x03 */ +#define PH_FRINFC_TOPAZ_PROP_T 0xFD /*!< NDEF TLV = 0xFD */ +#define PH_FRINFC_TOPAZ_TERM_T 0xFE /*!< Terminator TLV value = 0xFE */ + +#define PH_FRINFC_TOPAZ_NDEFTLV_L 0x00 /*!< Length value of TLV = 0x00 */ +#define PH_FRINFC_TOPAZ_NDEFTLV_LFF 0xFF /*!< Length value of TLV = 0xFF */ +#define PH_FRINFC_TOPAZ_MAX_CARD_SZ 0x60 /*!< Send Length for Read Ndef */ +/*@}*/ + + +/*! + * \name Topaz - Standard constants + * + */ +/*@{*/ +#define PH_FRINFC_TOPAZ_WR_A_BYTE 0x02 /*!< Send Length for Write Ndef */ +#define PH_FRINFC_TOPAZ_SEND_BUF_READ 0x01 /*!< Send Length for Read Ndef */ +#define PH_FRINFC_TOPAZ_HEADROM0_CHK 0xFF /*!< To check the header rom byte 0 */ +#define PH_FRINFC_TOPAZ_HEADROM0_VAL 0x11 /*!< Header rom byte 0 value of static card */ +#define PH_FRINFC_TOPAZ_READALL_RESP 0x7A /*!< Response of the read all command 122 bytes */ +#define PH_FRINFC_TOPAZ_TOTAL_RWBYTES 0x60 /*!< Total number of raw Bytes that can + be read or written to the card 96 bytes */ +#define PH_FRINFC_TOPAZ_TOTAL_RWBYTES1 0x5A /*!< Total number of bytes that can be read + or written 90 bytes */ +#define PH_FRINFC_TOPAZ_BYTE3_MSB 0xF0 /*!< most significant nibble of byte 3(RWA) shall be + 0 */ +#define PH_FRINFC_TOPAZ_LOCKBIT_BYTE114 0x01 /*!< lock bits value of byte 104 */ +#define PH_FRINFC_TOPAZ_LOCKBIT_BYTE115_1 0x60 /*!< lock bits value of byte 105 */ +#define PH_FRINFC_TOPAZ_LOCKBIT_BYTE115_2 0xE0 /*!< lock bits value of byte 105 */ +#define PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_0 114 /*!< lock bits byte number 104 */ +#define PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_1 115 /*!< lock bits byte number 105 */ +#define PH_FRINFC_TOPAZ_CC_BYTENO_3 13 /*! Lock status according to CC bytes */ +#define PH_FRINFC_TOPAZ_CC_READWRITE 0x00 /*! Lock status according to CC bytes */ +#define PH_FRINFC_TOPAZ_CC_READONLY 0x0F /*! Lock status according to CC bytes */ + +/**Topaz static commands*/ +#define PH_FRINFC_TOPAZ_CMD_READID 0x78U +#define PH_FRINFC_TOPAZ_CMD_READALL 0x00U +#define PH_FRINFC_TOPAZ_CMD_READ 0x01U +#define PH_FRINFC_TOPAZ_CMD_WRITE_1E 0x53U +#define PH_FRINFC_TOPAZ_CMD_WRITE_1NE 0x1AU + +/**Topaz Dynamic commands*/ +#define PH_FRINFC_TOPAZ_CMD_RSEG 0x10U +#define PH_FRINFC_TOPAZ_CMD_READ8 0x02U +#define PH_FRINFC_TOPAZ_CMD_WRITE_E8 0x54U +#define PH_FRINFC_TOPAZ_CMD_WRITE_NE8 0x1BU + +enum +{ + PH_FRINFC_TOPAZ_VAL0, + PH_FRINFC_TOPAZ_VAL1, + PH_FRINFC_TOPAZ_VAL2, + PH_FRINFC_TOPAZ_VAL3, + PH_FRINFC_TOPAZ_VAL4, + PH_FRINFC_TOPAZ_VAL5, + PH_FRINFC_TOPAZ_VAL6, + PH_FRINFC_TOPAZ_VAL7, + PH_FRINFC_TOPAZ_VAL8, + PH_FRINFC_TOPAZ_VAL9, + PH_FRINFC_TOPAZ_VAL10, + PH_FRINFC_TOPAZ_VAL11, + PH_FRINFC_TOPAZ_VAL12, + PH_FRINFC_TOPAZ_VAL13, + PH_FRINFC_TOPAZ_VAL14, + PH_FRINFC_TOPAZ_VAL15, + PH_FRINFC_TOPAZ_VAL16, + PH_FRINFC_TOPAZ_VAL17, + PH_FRINFC_TOPAZ_VAL18 +}; + + +/*@}*/ + +/*! + * \brief \copydoc page_reg Resets the component instance to the initial state and lets the component forget about + * the list of registered items. Moreover, the lower device is set. + * + * \param[in] NdefMap Pointer to a valid or uninitialised instance of \ref phFriNfc_NdefMap_t . + * + * \note This function has to be called at the beginning, after creating an instance of + * \ref phFriNfc_NdefMap_t . Use this function to reset the instance and/or switch + * to a different underlying device (different NFC device or device mode, or different + * Remote Device). + */ +void phFriNfc_TopazMap_H_Reset( phFriNfc_NdefMap_t *NdefMap); + +#ifdef FRINFC_READONLY_NDEF + +/*! + * \ingroup grp_fri_smart_card_formatting + * + * \brief Initiates the conversion of the already NDEF formatted tag to READ ONLY. + * + * \copydoc page_ovr The function initiates the conversion of the already NDEF formatted + * tag to READ ONLY.After this formation, remote card would be properly Ndef Compliant and READ ONLY. + * Depending upon the different card type, this function handles formatting procedure. + * This function supports only for the TOPAZ tags. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval Other values An error has occurred. + * + */ +NFCSTATUS +phFriNfc_TopazMap_ConvertToReadOnly ( + phFriNfc_NdefMap_t *NdefMap); + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/*! + * \brief \copydoc page_ovr Initiates Reading of NDEF information from the Remote Device. + * + * The function initiates the reading of NDEF information from a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that receives the NDEF Packet. + * + * \param[in,out] PacketDataLength Pointer to a variable receiving the length of the NDEF packet. + * + * \param[in] Offset Indicates whether the read operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start reading from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start reading + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED No Space in the File to read. + * \retval NFCSTATUS_MORE_INFORMATION There are more bytes to read in the card. + * \retval NFCSTATUS_SUCCESS Last Byte of the card read. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_TopazMap_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + + + +/*! + * \brief \copydoc page_ovr Initiates Writing of NDEF information to the Remote Device. + * + * The function initiates the writing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that holds the prepared NDEF Packet. + * + * \param[in,out] PacketDataLength Variable specifying the length of the prepared NDEF packet. + * + * \param[in] Offset Indicates whether the write operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start writing from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start writing + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED Last byte is written to the card after this + * no further writing is possible. + * \retval NFCSTATUS_SUCCESS Buffer provided by the user is completely written + * into the card. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_TopazMap_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + +/*! + * \brief \copydoc page_ovr Check whether a particulat Remote Device is NDEF compliant. + * + * The function checks whether the peer device is NDEF compliant. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_TopazMap_ChkNdef( phFriNfc_NdefMap_t *NdefMap); + +extern NFCSTATUS phFriNfc_Tpz_H_ChkSpcVer( phFriNfc_NdefMap_t *NdefMap, + uint8_t VersionNo); + + +/*! + * \brief \copydoc page_cb Completion Routine, Processing function, needed to avoid long blocking. + * + * The function call scheme is according to \ref grp_interact. No State reset is performed during operation. + * + * \copydoc pphFriNfc_Cr_t + * + * \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion + * Routine in order to be able to notify the component that an I/O has finished and data are + * ready to be processed. + * + */ + +void phFriNfc_TopazMap_Process( void *Context, + NFCSTATUS Status); + + +/*! + * \name TopazDynamicMap - Following section describes constans, functions, variables used in + * Topaz Dyanmic card mapping. Ex : Topaz-512 + * + */ +/*@{*/ +/*! + * \brief \copydoc Dynamic Card supported definitions. + * \note State Mechine Delcations. + */ + +#define PH_FRINFC_TOPAZ_DYNAMIC_STATE_WRITE_COMPLETE 11 /*!< Write Operation Complete */ +#define PH_FRINFC_TOPAZ_DYNAMIC_STATE_NXP_READ 12 +#define PH_FRINFC_TOPAZ_DYNAMIC_STATE_RD_CCBLK 13 +#define PH_FRINFC_TOPAZ_DYNAMIC_STATE_INIT_RD_CCBLK 14 +#define PH_FRINFC_TOPAZ_DYNAMIC_STATE_INIT_WR 15 +#define PH_FRINFC_TOPAZ_DYNAMIC_STATE_WRITE_LEN 16 +#define PH_FRINFC_TOPAZ_DYNAMIC_STATE_FIND_NDEF_TLV 17 +#define PH_FRINFC_TOPAZ_DYNAMI_FOUND_RESERV_AREA 18 +#define PH_FRINFC_TOPAZ_DYNAMIC_NOT_FOUND_RESERV_AREA 19 +#define PH_FRINFC_TOPAZ_DYNAMIC_PROCESS_CHK_NDEF 20 +#define PH_FRINFC_TOPAZ_DYNAMIC_FIND_NDEF_TLV 21 +#define PH_FRINFC_TOPAZ_DYNAMIC_INIT_RD_NDEF 22 +#define PH_FRINFC_TOPAZ_DYNAMIC_STATE_WR_MEM_TLV 23 +#define PH_FRINFC_TOPAZ_DYNAMIC_STATE_WR_LOCK_TLV 24 + +/*! + * \brief \copydoc Dynamic Card : Capability Container bytes. + * \note State Mechine Delcations. + */ + +#define PH_FRINFC_TOPAZ_DYNAMIC_CC_BYTE2_MMSIZE 0x3F /*!< Capability container byte 2 = 0x3F (Total free space + in the card) */ +#define PH_FRINFC_TOPAZ_DYNAMIC_HEADROM0_VAL 0x12 /*!< Header rom byte 0 value of dynamic card */ + +#define PH_FRINFC_TOPAZ_DYNAMIC_TOTAL_RWBYTES 0x1CC /*!< Total number of raw Bytes that can + be read or written to the card 460 bytes + 460 = 512 - 6 bloks * 8(48)( this includes 2 bytes of null byte in 02 block) + - 4 bytes ( NDEF TLV )*/ +#define PH_FRINFC_TOPAZ_DYNAMIC_MAX_CARD_SZ 0x1E0 /*!< Card size */ +#define PH_FRINFC_TOPAZ_DYNAMIC_MX_ONEBYTE_TLV_SIZE 0xFF /*!< MAX size supported in one byte length TLV*/ +#define PH_FRINFC_TOPAZ_DYNAMIC_MAX_DATA_SIZE_TO_WRITE 0xE6 /*!< MAX size supported by HAL if the data size > 255*/ + +#define PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_0 0x00 /*!< lock bits value of byte 104 */ +#define PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_1 0x00 /*!< lock bits value of byte 105 */ +#define PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7 0x00 /*!< lock bits value of byte 105 */ + +#define PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_0 112 /*!< lock bits byte number 104:Blk0-7 */ +#define PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_1 113 /*!< lock bits byte number 105:Blk08-F */ +#define PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_2 122 /*!< lock bits byte number 124:Blk10-17 */ +#define PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_3 123 /*!< lock bits byte number 125:Blk18-1F */ +#define PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_4 124 /*!< lock bits byte number 126:Blk20-27*/ +#define PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_5 125 /*!< lock bits byte number 127:Blk28-2F*/ +#define PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_6 126 /*!< lock bits byte number 128:Blk30-37*/ +#define PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_7 127 /*!< lock bits byte number 128:Blk30-37*/ +#define PH_FRINFC_TOPAZ_DYNAMIC_CC_BYTENO_3 11 /*! Lock status according to CC bytes */ + +#define PH_FRINFC_TOPAZ_DYNAMIC_SEGMENT0 0x00 /*!< 00000000 : 0th segment */ +#define PH_FRINFC_TOPAZ_DYNAMIC_READSEG_RESP 0x80 + +#define PH_FRINFC_TOPAZ_DYNAMIC_MAX_BYTES_TO_READ_IN_ONEB_LTLV_FSEG 78 +#define PH_FRINFC_TOPAZ_DYNAMIC_MAX_BYTES_TO_READ_IN_THREEB_LTLV_FSEG 76 + +#define PH_FRINFC_TOPAZ_DYNAMIC_MAX_DATA_SIZE PHHAL_MAX_DATASIZE +#define PH_FRINFC_TOPAZ_DYNAMIC_FSEG_BYTE_COUNT 104 +#define PH_FRINFC_TOPAZ_DYNAMIC_SEG_BYTE_COUNT 128 +#define PH_FRINFC_TOPAZ_DYNAMIC_CC_BLK_SIZE 18 +#define PH_FRINFC_TOPAZ_DYNAMIC_CC_BLK_ADDRESS 8 +#define PH_FRINFC_TOPAZ_DYNAMIC_UID_BLK_ADDRESS 0 +#define PH_FRINFC_TOPAZ_DYNAMIC_LOCK_BYTE_SIZE 24 +#define PH_FRINFC_TOPAZ_DYNAMIC_FSEG_TOT_DATA_BYTES 120 + +#define PH_FRINFC_TOPAZ_DYNAMIC_DATA_BYTE_COUNT_OF_FSEG_IN_ONEB_LTLV_FSEG 26 +#define PH_FRINFC_TOPAZ_DYNAMIC_DATA_BYTE_COUNT_OF_FSEG_IN_THREEB_LTLV_FSEG 28 + + +enum +{ + + NULL_TLV, + LOCK_TLV, + MEM_TLV, + NDEF_TLV, + PROP_TLV, + TERM_TLV, + INVALID_TLV, + VALID_TLV, + TLV_NOT_FOUND + +}; + +/*! + * \brief \copydoc page_ovr Initiates Reading of NDEF information from the Remote Device. + * + * The function initiates the reading of NDEF information from a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that receives the NDEF Packet. + * + * \param[in,out] PacketDataLength Pointer to a variable receiving the length of the NDEF packet. + * + * \param[in] Offset Indicates whether the read operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start reading from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start reading + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED No Space in the File to read. + * \retval NFCSTATUS_MORE_INFORMATION There are more bytes to read in the card. + * \retval NFCSTATUS_SUCCESS Last Byte of the card read. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ + +NFCSTATUS phFriNfc_TopazDynamicMap_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + +/*! + * \brief \copydoc page_ovr Initiates Writing of NDEF information to the Remote Device. + * + * The function initiates the writing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \param[in] PacketData Pointer to a location that holds the prepared NDEF Packet. + * + * \param[in,out] PacketDataLength Variable specifying the length of the prepared NDEF packet. + * + * \param[in] Offset Indicates whether the write operation shall start from the begining of the + * file/card storage \b or continue from the last offset. The last Offset set is stored + * within a context variable (must not be modified by the integration). + * If the caller sets the value to \ref PH_FRINFC_NDEFMAP_SEEK_CUR, the component shall + * start writing from the last offset set (continue where it has stopped before). + * If set to \ref PH_FRINFC_NDEFMAP_SEEK_BEGIN, the component shall start writing + * from the begining of the card (restarted) + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED Last byte is written to the card after this + * no further writing is possible. + * \retval NFCSTATUS_SUCCESS Buffer provided by the user is completely written + * into the card. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ +NFCSTATUS phFriNfc_TopazDynamicMap_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset); + +/*! + * \brief \copydoc page_ovr Check whether a particulat Remote Device is NDEF compliant. + * + * The function checks whether the peer device is NDEF compliant. + * + * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ +NFCSTATUS phFriNfc_TopazDynamicMap_ChkNdef( phFriNfc_NdefMap_t *NdefMap); + +/*! + * \brief \copydoc page_cb Completion Routine, Processing function, needed to avoid long blocking. + * + * The function call scheme is according to \ref grp_interact. No State reset is performed during operation. + * + * \copydoc pphFriNfc_Cr_t + * + * \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion + * Routine in order to be able to notify the component that an I/O has finished and data are + * ready to be processed. + * + */ +void phFriNfc_TopazDynamicMap_Process( void *Context, + NFCSTATUS Status); + +#ifdef FRINFC_READONLY_NDEF +/*! + * \brief \copydoc page_ovr Initiates Writing of NDEF information to the Remote Device. + * + * The function initiates the writing of NDEF information to a Remote Device. + * It performs a reset of the state and starts the action (state machine). + * A periodic call of the \ref phFriNfc_NdefMap_Process has to be done once the action + * has been triggered. + * + * \param[in] psNdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t structure describing + * the component context. + * + * + * \retval NFCSTATUS_PENDING The action has been successfully triggered. + * \retval NFCSTATUS_INVALID_DEVICE_REQUEST If Previous Operation is Write Ndef and Offset + * is Current then this error is displayed. + * \retval NFCSTATUS_EOF_NDEF_CONTAINER_REACHED Last byte is written to the card after this + * no further writing is possible. + * \retval NFCSTATUS_SUCCESS Buffer provided by the user is completely written + * into the card. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has been disconnected + * meanwhile. + * \retval NFCSTATUS_CMD_ABORTED The caller/driver has aborted the request. + * \retval NFCSTATUS_BUFFER_TOO_SMALL The buffer provided by the caller is too small. + * \retval NFCSTATUS_RF_TIMEOUT No data has been received within the TIMEOUT period. + * + */ +NFCSTATUS +phFriNfc_TopazDynamicMap_ConvertToReadOnly ( + phFriNfc_NdefMap_t *psNdefMap); +#endif /* #ifdef FRINFC_READONLY_NDEF */ + + + +#endif /* PHFRINFC_TOPAZMAP_H */ + diff --git a/libnfc-nxp/phHal4Nfc.c b/libnfc-nxp/phHal4Nfc.c new file mode 100644 index 0000000..df72bd8 --- /dev/null +++ b/libnfc-nxp/phHal4Nfc.c @@ -0,0 +1,1478 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ +/*! + * \file phHal4Nfc.c + * \brief Hal4Nfc source. + * + * Project: NFC-FRI 1.1 + * + * $Date: Fri Jun 11 09:32:23 2010 $ + * $Author: ing07385 $ + * $Revision: 1.192 $ + * $Aliases: NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +/* ---------------------------Include files ---------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* ------------------------------- Macros -----------------------------------*/ +#ifndef HAL_UNIT_TEST +#define STATIC static +#else +#define STATIC +#endif/*#ifndef UNIT_TEST*/ +#define HAL4_LAYERS 3 +#define LAYER_HCI 2 +#define LAYER_LLC 1 +#define LAYER_DAL 0 + +/* --------------------Structures and enumerations --------------------------*/ + +phHal_sHwReference_t *gpphHal4Nfc_Hwref; + +static void phHal4Nfc_IoctlComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ); + +static void phHal4Nfc_LowerNotificationHandler( + void *pContext, + void *pHwRef, + uint8_t type, + void *pInfo + ); +static void phHal4Nfc_HandleEvent( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ); + +static void phHal4Nfc_OpenComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ); + +static void phHal4Nfc_CloseComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ); + +static void phHal4Nfc_DownloadComplete( + void *pContext, + void *pHwRef, + uint8_t type, + void *pInfo + ); + +static NFCSTATUS phHal4Nfc_Configure_Layers( + phNfcLayer_sCfg_t **pphLayer + ); + + +/*Callback for Self tests*/ +static void phHal4Nfc_SelfTestComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ); + +/** + * The open callback function to be called by the HCI when open (initializaion) + * sequence is completed or if there is an error in initialization. + * It is passed as a parameter to HCI when calling HCI Init. + */ + +static void phHal4Nfc_OpenComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + NFCSTATUS status = ((phNfc_sCompletionInfo_t *)pInfo)->status; + pphHal4Nfc_GenCallback_t pUpper_OpenCb + = Hal4Ctxt->sUpperLayerInfo.pUpperOpenCb; + void *pUpper_Context + = Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt; + if(status == NFCSTATUS_SUCCESS) + { + PHDBG_INFO("Hal4:Open Successful"); +#ifdef MERGE_SAK_SW1 /*Software Workaround*/ + if(eHal4StateOpenAndReady == Hal4Ctxt->Hal4NextState) + { + status = phHciNfc_System_Configure ( + Hal4Ctxt->psHciHandle, + (void *)gpphHal4Nfc_Hwref, + PH_HAL4NFC_TGT_MERGE_ADDRESS, + PH_HAL4NFC_TGT_MERGE_SAK /*config value*/ + ); + } + if(NFCSTATUS_PENDING != status) +#endif/*#ifdef MERGE_SAK_SW1*/ + { + /*Update State*/ + Hal4Ctxt->Hal4CurrentState = Hal4Ctxt->Hal4NextState; + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + Hal4Ctxt->sUpperLayerInfo.pUpperOpenCb = NULL; + if(NULL != pUpper_OpenCb) + { + /*Upper layer's Open Cb*/ + (*pUpper_OpenCb)(Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + NFCSTATUS_SUCCESS + ); + } + } + } + else/*Open did not succeed.Go back to reset state*/ + { + Hal4Ctxt->Hal4CurrentState = eHal4StateClosed; + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + Hal4Ctxt->psHciHandle = NULL; + phOsalNfc_FreeMemory((void *)Hal4Ctxt->pHal4Nfc_LayerCfg); + Hal4Ctxt->pHal4Nfc_LayerCfg = NULL; + phOsalNfc_FreeMemory((void *)Hal4Ctxt); + gpphHal4Nfc_Hwref->hal_context = NULL; + gpphHal4Nfc_Hwref = NULL; + PHDBG_INFO("Hal4:Open Failed"); + /*Call upper layer's Open Cb with error status*/ + if(NULL != pUpper_OpenCb) + { + /*Upper layer's Open Cb*/ + (*pUpper_OpenCb)(pUpper_Context,status); + } + } + return; +} + +/** + * The close callback function called by the HCI when close sequence is + * completed or if there is an error in closing. + * It is passed as a parameter to HCI when calling HCI Release. + */ +static void phHal4Nfc_CloseComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + NFCSTATUS status= ((phNfc_sCompletionInfo_t *)pInfo)->status; + pphHal4Nfc_GenCallback_t pUpper_CloseCb; + void *pUpper_Context; + uint8_t RemoteDevNumber = 0; + pUpper_CloseCb = Hal4Ctxt->sUpperLayerInfo.pUpperCloseCb; + pUpper_Context = Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt; + /*Update state*/ + Hal4Ctxt->Hal4CurrentState = Hal4Ctxt->Hal4NextState; + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + /*If Closed successfully*/ + if(NFCSTATUS_SUCCESS == status) + { + Hal4Ctxt->psHciHandle = NULL; + /*Free all heap allocations*/ + phOsalNfc_FreeMemory((void *)Hal4Ctxt->pHal4Nfc_LayerCfg); + Hal4Ctxt->pHal4Nfc_LayerCfg = NULL; + /*Free ADD context info*/ + if(NULL != Hal4Ctxt->psADDCtxtInfo) + { + while(RemoteDevNumber < MAX_REMOTE_DEVICES) + { + if(NULL != Hal4Ctxt->rem_dev_list[RemoteDevNumber]) + { + phOsalNfc_FreeMemory((void *) + (Hal4Ctxt->rem_dev_list[RemoteDevNumber])); + Hal4Ctxt->rem_dev_list[RemoteDevNumber] = NULL; + } + RemoteDevNumber++; + } + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices = 0; + phOsalNfc_FreeMemory(Hal4Ctxt->psADDCtxtInfo); + }/*if(NULL != Hal4Ctxt->psADDCtxtInfo)*/ + /*Free Trcv context info*/ + if(NULL != Hal4Ctxt->psTrcvCtxtInfo) + { + if(NULL != Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer) + { + phOsalNfc_FreeMemory( + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer + ); + } + if((NULL == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice) + && (NULL != Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData)) + { + phOsalNfc_FreeMemory(Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData); + } + phOsalNfc_FreeMemory(Hal4Ctxt->psTrcvCtxtInfo); + }/*if(NULL != Hal4Ctxt->psTrcvCtxtInfo)*/ + /*Free Hal context and Hardware reference*/ + gpphHal4Nfc_Hwref->hal_context = NULL; + gpphHal4Nfc_Hwref = NULL; + phOsalNfc_FreeMemory((void *)Hal4Ctxt); + }/* if(NFCSTATUS_SUCCESS == status)*/ + /*Call Upper layer's Close Cb with status*/ + (*pUpper_CloseCb)(pUpper_Context,status); + return; +} + + +/* +* For configuring the various layers during the Initialization call +* +* +*/ +static +NFCSTATUS +phHal4Nfc_Configure_Layers( + phNfcLayer_sCfg_t **pphLayer + ) +{ + uint8_t index = HAL4_LAYERS - 1; + uint8_t i = 0; + NFCSTATUS status = NFCSTATUS_SUCCESS ; + PHDBG_INFO("Hal4:Configuring layers"); + *pphLayer = (phNfcLayer_sCfg_t *) phOsalNfc_GetMemory( + sizeof(phNfcLayer_sCfg_t) * HAL4_LAYERS); + + if( NULL == *pphLayer) + { + status = PHNFCSTVAL(CID_NFC_HAL, + NFCSTATUS_INSUFFICIENT_RESOURCES);/*Memory allocation error*/ + } + else + { + + (void)memset((void *)*pphLayer,0,( + sizeof(phNfcLayer_sCfg_t) * HAL4_LAYERS)); + + for(i=0 ; i < HAL4_LAYERS ;i++, index-- ) + { + (*pphLayer + i)->layer_index = index; + switch(index) + { + case LAYER_HCI: /*Configure Hci*/ + { + (*pphLayer+i)->layer_name =(uint8_t *) "Hci"; + (*pphLayer+i)->layer_registry = NULL; + (*pphLayer+i)->layer_next = + (((phNfcLayer_sCfg_t *)*pphLayer) + i + 1); + break; + } + case LAYER_LLC:/*Configure LLC*/ + { + (*pphLayer+i)->layer_registry = phLlcNfc_Register; + (*pphLayer+i)->layer_name = (uint8_t *)"Llc"; + (*pphLayer+i)->layer_next = + (((phNfcLayer_sCfg_t *)*pphLayer) + i + 1); + break; + } + case LAYER_DAL: /*Configure the DAL*/ + { + (*pphLayer+i)->layer_registry = phDal4Nfc_Register; + (*pphLayer+i)->layer_name = (uint8_t *)"Dal"; + (*pphLayer+i)->layer_next = NULL ; + break; + } + default: + break; + } /* End of Switch */ + } /* End of For Loop */ + } /* End of NULL Check */ + + return status ; +} + + + +#ifdef ANDROID + +#define LOG_TAG "NFC-HCI" + +#include +#include + +#define FW_PATH "/vendor/firmware/libpn544_fw.so" + +const unsigned char *nxp_nfc_full_version = NULL; +const unsigned char *nxp_nfc_fw = NULL; + +int dlopen_firmware() { + void *p; + + void *handle = dlopen(FW_PATH, RTLD_NOW); + if (handle == NULL) { + ALOGE("Could not open %s", FW_PATH); + return -1; + } + + p = dlsym(handle, "nxp_nfc_full_version"); + if (p == NULL) { + ALOGE("Could not link nxp_nfc_full_version"); + return -1; + } + nxp_nfc_full_version = (unsigned char *)p; + + p = dlsym(handle, "nxp_nfc_fw"); + if (p == NULL) { + ALOGE("Could not link nxp_nfc_fw"); + return -1; + } + nxp_nfc_fw = (unsigned char *)p; + + return 0; +} +#endif + +/** + * The open function called by the upper HAL when HAL4 is to be opened + * (initialized). + * + */ +NFCSTATUS phHal4Nfc_Open( + phHal_sHwReference_t *psHwReference, + phHal4Nfc_InitType_t InitType, + pphHal4Nfc_GenCallback_t pOpenCallback, + void *pContext + ) +{ + NFCSTATUS openRetVal = NFCSTATUS_SUCCESS; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + phHciNfc_Init_t eHciInitType = (phHciNfc_Init_t)InitType; + /*Set Default Clock settings once*/ + static phHal_sHwConfig_t sHwConfig = { + {0}, + NXP_DEFAULT_CLK_REQUEST, + NXP_DEFAULT_INPUT_CLK + }; + /*NULL checks*/ + if(NULL == psHwReference || NULL == pOpenCallback) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + openRetVal = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL != gpphHal4Nfc_Hwref) + { + /*Hal4 context is open or open in progress ,return Ctxt already open*/ + openRetVal = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_ALREADY_INITIALISED); + } + else/*Do an initialization*/ + { +#ifdef ANDROID + dlopen_firmware(); +#endif + + /*If hal4 ctxt in Hwreference is NULL create a new context*/ + if(NULL == ((phHal_sHwReference_t *)psHwReference)->hal_context) + { + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *) + phOsalNfc_GetMemory((uint32_t)sizeof( + phHal4Nfc_Hal4Ctxt_t) + ); + ((phHal_sHwReference_t *)psHwReference)->hal_context = Hal4Ctxt; + } + else/*Take context from Hw reference*/ + { + Hal4Ctxt = ((phHal_sHwReference_t *)psHwReference)->hal_context; + } + if(NULL == Hal4Ctxt) + { + openRetVal = PHNFCSTVAL(CID_NFC_HAL, + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + (void)memset((void *)Hal4Ctxt, + 0, + ((uint32_t)sizeof(phHal4Nfc_Hal4Ctxt_t))); + /* Configure layers if not configured */ + if( NULL == Hal4Ctxt->pHal4Nfc_LayerCfg ) + { + openRetVal = phHal4Nfc_Configure_Layers( + &(Hal4Ctxt->pHal4Nfc_LayerCfg) + ); + } + + if( openRetVal == NFCSTATUS_SUCCESS ) + { + /*update Next state*/ + Hal4Ctxt->Hal4NextState = (HCI_NFC_DEVICE_TEST == eHciInitType? + eHal4StateSelfTestMode:eHal4StateOpenAndReady); + /*Store callback and context ,and set Default settings in Context*/ + Hal4Ctxt->sUpperLayerInfo.pUpperOpenCb = pOpenCallback; + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext; + Hal4Ctxt->sTgtConnectInfo.EmulationState = NFC_EVT_DEACTIVATED; + gpphHal4Nfc_Hwref = psHwReference; + PHDBG_INFO("Hal4:Calling Hci-Init"); + openRetVal = phHciNfc_Initialise ( + (void *)&Hal4Ctxt->psHciHandle, + psHwReference, + eHciInitType, + &sHwConfig, + (pphNfcIF_Notification_CB_t) + phHal4Nfc_LowerNotificationHandler, + (void *)Hal4Ctxt, + Hal4Ctxt->pHal4Nfc_LayerCfg + ); + /*Hci Init did not succeed.free Resources and return*/ + if( (openRetVal != NFCSTATUS_SUCCESS) + && (PHNFCSTATUS (openRetVal) != NFCSTATUS_PENDING) ) + { + phOsalNfc_FreeMemory(Hal4Ctxt->pHal4Nfc_LayerCfg); + phOsalNfc_FreeMemory(Hal4Ctxt); + Hal4Ctxt = NULL; + } + }/*if( openRetVal == NFCSTATUS_SUCCESS )*/ + else/*Free the context*/ + { + phOsalNfc_FreeMemory(Hal4Ctxt); + }/*else*/ + } + } + return openRetVal; +} + +/** The I/O Control function allows the caller to use (vendor-) specific +* functionality provided by the lower layer or by the hardware. */ +NFCSTATUS phHal4Nfc_Ioctl( + phHal_sHwReference_t *psHwReference, + uint32_t IoctlCode, + phNfc_sData_t *pInParam, + phNfc_sData_t *pOutParam, + pphHal4Nfc_IoctlCallback_t pIoctlCallback, + void *pContext + ) +{ + NFCSTATUS RetStatus = NFCSTATUS_FAILED; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + uint32_t config_type = 0; + uint8_t ind = 0; + /*NULL checks*/ + if((NULL == psHwReference) + || (NULL == pIoctlCallback) + ) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_INVALID_PARAMETER); + } + /*Only the Ioctls NFC_FW_DOWNLOAD_CHECK and NFC_FW_DOWNLOAD are allowed in + the uninitialized state of HAL*/ + else if(NULL == psHwReference->hal_context) + { +#ifdef FW_DOWNLOAD + +#if !defined (NXP_FW_INTEGRITY_VERIFY) + if(NFC_FW_DOWNLOAD_CHECK == IoctlCode) + { + RetStatus = phDnldNfc_Run_Check( + psHwReference + ); + } + else +#endif /* !defined (NXP_FW_INTEGRITY_VERIFY) */ + if((NFC_FW_DOWNLOAD == IoctlCode) + &&(NULL == gpphHal4Nfc_Hwref))/*Indicates current state is shutdown*/ + { + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *) + phOsalNfc_GetMemory((uint32_t)sizeof( + phHal4Nfc_Hal4Ctxt_t) + ); + if(NULL == Hal4Ctxt) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL, + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + ((phHal_sHwReference_t *)psHwReference)->hal_context + = Hal4Ctxt; + (void)memset((void *)Hal4Ctxt, + 0, + ((uint32_t)sizeof(phHal4Nfc_Hal4Ctxt_t))); + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext; + Hal4Ctxt->sUpperLayerInfo.pUpperIoctlCb + = pIoctlCallback;/*Register upper layer callback*/ + Hal4Ctxt->sUpperLayerInfo.pIoctlOutParam = pOutParam; + /*Upgrade the firmware*/ + RetStatus = phDnldNfc_Upgrade ( + psHwReference, + phHal4Nfc_DownloadComplete, + Hal4Ctxt + ); + if((NFCSTATUS_SUCCESS == RetStatus) + || (NFCSTATUS_PENDING != PHNFCSTATUS(RetStatus)) + ) + { + phOsalNfc_FreeMemory(Hal4Ctxt); + ((phHal_sHwReference_t *)psHwReference)->hal_context = NULL; + } + } + } + else +#endif/*NFC_FW_DOWNLOAD*/ + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_INITIALISED); + } + } + else/*Status is Initialised*/ + { + /*Register upper layer context*/ + Hal4Ctxt = psHwReference->hal_context; + Hal4Ctxt->sUpperLayerInfo.pIoctlOutParam = pOutParam; + switch(IoctlCode) + { + /*Self test Ioctls*/ + case DEVMGMT_ANTENNA_TEST: + case DEVMGMT_SWP_TEST: + case DEVMGMT_NFCWI_TEST: + if(eHal4StateSelfTestMode ==Hal4Ctxt->Hal4CurrentState) + { + RetStatus = phHciNfc_System_Test( + Hal4Ctxt->psHciHandle, + (void *)psHwReference, + IoctlCode , + pInParam + ); + } + break; + /*PRBS Test*/ + case DEVMGMT_PRBS_TEST: + RetStatus = phHciNfc_PRBS_Test( + Hal4Ctxt->psHciHandle, + (void *)psHwReference, + IoctlCode , + pInParam + ); + break; + /*To Set Antenna Power Level*/ + case NFC_ANTENNA_CWG: + if(eHal4StateSelfTestMode ==Hal4Ctxt->Hal4CurrentState) + { + RetStatus = phHciNfc_System_Configure ( + Hal4Ctxt->psHciHandle, + (void *)psHwReference, + NFC_ANTENNA_CWG, + pInParam->buffer[0] /**Set Power Level*/ + ); + + } + break; + /*Not allowed when Init is complete*/ + case NFC_FW_DOWNLOAD_CHECK: + case NFC_FW_DOWNLOAD: + RetStatus = PHNFCSTVAL(CID_NFC_HAL, + NFCSTATUS_BUSY); + break; + /*Gpio read*/ + case NFC_GPIO_READ: + /* if(eHal4StateSelfTestMode == Hal4Ctxt->Hal4CurrentState) */ + { + RetStatus = phHciNfc_System_Get_Info( + Hal4Ctxt->psHciHandle, + (void *)psHwReference, + IoctlCode , + pOutParam->buffer + ); + } + break; + /*Used to Read Memory/Registers .3 bytes of Array passed form the + address to read from in MSB first format.*/ + case NFC_MEM_READ: + { + if((NULL != pInParam) + && (pInParam->length == 3)) + { + for( ind = 0; ind < 3; ind++ ) + { + config_type = ((config_type << BYTE_SIZE ) + | (pInParam->buffer[ind] )); + } + RetStatus = phHciNfc_System_Get_Info( + Hal4Ctxt->psHciHandle, + (void *)psHwReference, + config_type , + pOutParam->buffer + ); + } + else + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL, + NFCSTATUS_INVALID_PARAMETER); + } + } + break; + /*Used to Write Memory/Registers .First 3 bytes of Array passed in MSB + first format form the address to write to.The 4th Byte is the 8 bit + value to be written to the address*/ + case NFC_MEM_WRITE: + { + if((NULL != pInParam) + && (pInParam->length == 4)) + { + for( ind = 0; ind < 3; ind++ ) + { + config_type = ((config_type << BYTE_SIZE ) + | (pInParam->buffer[ind] )); + } + RetStatus = phHciNfc_System_Configure ( + Hal4Ctxt->psHciHandle, + (void *)psHwReference, + config_type, + pInParam->buffer[3] /*config value*/ + ); + } + else + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INVALID_PARAMETER); + } + } + break; + default: + break; + } + if(NFCSTATUS_PENDING == RetStatus)/*Callback Pending*/ + { + /*Register upper layer callback and context*/ + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext; + Hal4Ctxt->sUpperLayerInfo.pUpperIoctlCb= pIoctlCallback; + /*Store the Ioctl code*/ + Hal4Ctxt->Ioctl_Type = IoctlCode; + } + } + return RetStatus; +} + + +/** + * The close function called by the upper layer when HAL4 is to be closed + * (shutdown). + */ +NFCSTATUS phHal4Nfc_Close( + phHal_sHwReference_t *psHwReference, + pphHal4Nfc_GenCallback_t pCloseCallback, + void *pContext + ) +{ + NFCSTATUS closeRetVal = NFCSTATUS_SUCCESS; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + /*NULL checks*/ + if(NULL == psHwReference || NULL == pCloseCallback) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + closeRetVal = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateSelfTestMode) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + /*return already closed*/ + closeRetVal= PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_NOT_INITIALISED); + } + else /*Close the HAL*/ + { + /*Get Hal4 context from Hw reference*/ + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)((phHal_sHwReference_t *) + psHwReference)->hal_context; + /*Unregister Tag Listener*/ + if(NULL != Hal4Ctxt->psADDCtxtInfo) + { + Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification = NULL; + } + /*store Callback and Context*/ + Hal4Ctxt->sUpperLayerInfo.pUpperCloseCb = pCloseCallback; + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext; + /*Call Hci Release*/ + PHDBG_INFO("Hal4:Calling Hci Release"); + closeRetVal =(NFCSTATUS)phHciNfc_Release( + (void *)Hal4Ctxt->psHciHandle, + psHwReference, + (pphNfcIF_Notification_CB_t) + phHal4Nfc_LowerNotificationHandler, + (void *)Hal4Ctxt + ); + /*Update Next state and exit*/ + if( PHNFCSTATUS (closeRetVal) == NFCSTATUS_PENDING ) + { + Hal4Ctxt->Hal4NextState = eHal4StateClosed; + Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification = NULL; + } + else + { + + } + } + return closeRetVal; +} + +/*Forcibly shutdown the HAl4.Frees all Resources in use by Hal4 before shutting + down*/ +void phHal4Nfc_Hal4Reset( + phHal_sHwReference_t *pHwRef, + void *pContext + ) +{ + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + NFCSTATUS closeRetVal = NFCSTATUS_SUCCESS; + uint8_t RemoteDevNumber = 0; + if(pHwRef ==NULL) + { + closeRetVal = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_INVALID_PARAMETER); + } + else if(pHwRef->hal_context != NULL) + { + /*Get the Hal context*/ + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)pHwRef->hal_context; + /*store the upper layer context*/ + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext; + Hal4Ctxt->Hal4NextState = eHal4StateClosed; + Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification = NULL; + /*Call Hci Release*/ + PHDBG_INFO("Hal4:Calling Hci Release"); + closeRetVal =(NFCSTATUS)phHciNfc_Release( + (void *)Hal4Ctxt->psHciHandle, + pHwRef, + (pphNfcIF_Notification_CB_t)NULL, + (void *)Hal4Ctxt + );/*Clean up Hci*/ + Hal4Ctxt->Hal4CurrentState = eHal4StateClosed; + phOsalNfc_FreeMemory((void *)Hal4Ctxt->pHal4Nfc_LayerCfg); + Hal4Ctxt->pHal4Nfc_LayerCfg = NULL; + /*Free ADD context*/ + if(NULL != Hal4Ctxt->psADDCtxtInfo) + { + Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification = NULL; + while(RemoteDevNumber < MAX_REMOTE_DEVICES) + { + if(NULL != Hal4Ctxt->rem_dev_list[RemoteDevNumber]) + { + phOsalNfc_FreeMemory((void *) + (Hal4Ctxt->rem_dev_list[RemoteDevNumber])); + Hal4Ctxt->rem_dev_list[RemoteDevNumber] = NULL; + } + RemoteDevNumber++; + } + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices = 0; + phOsalNfc_FreeMemory(Hal4Ctxt->psADDCtxtInfo); + } + /*Free Trcv context*/ + if(NULL != Hal4Ctxt->psTrcvCtxtInfo) + { + if(NULL != Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer) + { + phOsalNfc_FreeMemory(Hal4Ctxt->psTrcvCtxtInfo + ->sLowerRecvData.buffer); + } + if((NULL == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice) + && (NULL != Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData)) + { + phOsalNfc_FreeMemory(Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData); + } + phOsalNfc_FreeMemory(Hal4Ctxt->psTrcvCtxtInfo); + } + phOsalNfc_FreeMemory(Hal4Ctxt);/*Free the context*/ + pHwRef->hal_context = NULL; + gpphHal4Nfc_Hwref = NULL; + } + else + { + /*Hal4 Context is already closed.Return Success*/ + } + /*Reset Should always return Success*/ + if(closeRetVal != NFCSTATUS_SUCCESS) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + } + return; +} + +/** + * \if hal + * \ingroup grp_hal_common + * \else + * \ingroup grp_mw_external_hal_funcs + * \endif + * + * Retrieves the capabilities of the device represented by the Hardware + * Reference parameter. + * The HW, SW versions, the MTU and other mandatory information are located + * inside the pDevCapabilities parameter. + */ +NFCSTATUS phHal4Nfc_GetDeviceCapabilities( + phHal_sHwReference_t *psHwReference, + phHal_sDeviceCapabilities_t *psDevCapabilities, + void *pContext + ) +{ + NFCSTATUS retstatus = NFCSTATUS_SUCCESS; + /*NULL checks*/ + if(psDevCapabilities == NULL || psHwReference == NULL || pContext == NULL) + { + retstatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_INVALID_PARAMETER); + } + /*Check for Initialized state*/ + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + retstatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_INITIALISED); + } + else/*Provide Device capabilities and Version Info to the caller*/ + { + (void)memcpy((void *)psDevCapabilities, + (void *)&(psHwReference->device_info), + sizeof(phHal_sDeviceCapabilities_t)); + psDevCapabilities->ReaderSupProtocol.Felica = TRUE; + psDevCapabilities->ReaderSupProtocol.ISO14443_4A = TRUE; + psDevCapabilities->ReaderSupProtocol.ISO14443_4B = TRUE; + psDevCapabilities->ReaderSupProtocol.ISO15693 = TRUE; + psDevCapabilities->ReaderSupProtocol.Jewel = TRUE; + psDevCapabilities->ReaderSupProtocol.MifareStd = TRUE; + psDevCapabilities->ReaderSupProtocol.MifareUL = TRUE; + psDevCapabilities->ReaderSupProtocol.NFC = TRUE; + psDevCapabilities->EmulationSupProtocol.Felica = FALSE; + psDevCapabilities->EmulationSupProtocol.ISO14443_4A = FALSE; + psDevCapabilities->EmulationSupProtocol.ISO14443_4B = FALSE; + psDevCapabilities->EmulationSupProtocol.ISO15693 = FALSE; + psDevCapabilities->EmulationSupProtocol.Jewel = FALSE; + psDevCapabilities->EmulationSupProtocol.MifareStd = FALSE; + psDevCapabilities->EmulationSupProtocol.MifareUL = FALSE; + psDevCapabilities->EmulationSupProtocol.NFC = TRUE; + psDevCapabilities->hal_version = ( + (((PH_HAL4NFC_INTERFACE_VERSION << BYTE_SIZE) + |(PH_HAL4NFC_INTERFACE_REVISION)<hal_context; + if(NFC_INVALID_RELEASE_TYPE == Hal4Ctxt->sTgtConnectInfo.ReleaseType) + { + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)pContext; + gpphHal4Nfc_Hwref = (phHal_sHwReference_t *)pHwRef; + } + } + else/*No Copy of Hw ref in HAL.Copy both Hwref and Hal context passed + by Hci*/ + { + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)pContext; + gpphHal4Nfc_Hwref = (phHal_sHwReference_t *)pHwRef; + } + /*Check the type of notification received from Hci and handle it + accordingly*/ + switch(type) + { + case NFC_NOTIFY_INIT_COMPLETED: + case NFC_NOTIFY_INIT_FAILED: + phHal4Nfc_OpenComplete(Hal4Ctxt,pInfo); + break; + case NFC_IO_SUCCESS: + case NFC_IO_ERROR: + phHal4Nfc_IoctlComplete(Hal4Ctxt,pInfo); + break; + case NFC_NOTIFY_RESULT: + phHal4Nfc_SelfTestComplete(Hal4Ctxt,pInfo); + break; + case NFC_NOTIFY_DEINIT_COMPLETED: + case NFC_NOTIFY_DEINIT_FAILED: + phHal4Nfc_CloseComplete(Hal4Ctxt,pInfo); + break; + case NFC_NOTIFY_POLL_ENABLED: + case NFC_NOTIFY_POLL_DISABLED: + case NFC_NOTIFY_POLL_RESTARTED: + case NFC_NOTIFY_CONFIG_ERROR: + case NFC_NOTIFY_CONFIG_SUCCESS: + phHal4Nfc_ConfigureComplete(Hal4Ctxt,pInfo,type); + break; + case NFC_NOTIFY_TARGET_DISCOVERED: + case NFC_NOTIFY_DISCOVERY_ERROR: + phHal4Nfc_TargetDiscoveryComplete(Hal4Ctxt,pInfo); + break; + case NFC_NOTIFY_TARGET_REACTIVATED: + phHal4Nfc_ReactivationComplete(Hal4Ctxt,pInfo); + break; + case NFC_NOTIFY_EVENT: + PHDBG_INFO("Hal4:Calling Event callback"); + phHal4Nfc_HandleEvent(Hal4Ctxt,pInfo); + break; + case NFC_NOTIFY_TARGET_CONNECTED: + PHDBG_INFO("Hal4:Calling Hal4 Connect complete"); + phHal4Nfc_ConnectComplete(Hal4Ctxt,pInfo); + break; + + case NFC_NOTIFY_TARGET_DISCONNECTED: + { + PHDBG_INFO("Hal4:Target Disconnected"); + if(Hal4Ctxt->Hal4NextState == eHal4StatePresenceCheck) + { + phHal4Nfc_PresenceChkComplete(Hal4Ctxt,pInfo); + } + else + { + phHal4Nfc_DisconnectComplete(Hal4Ctxt,pInfo); + } + break; + } + case NFC_NOTIFY_TRANSCEIVE_COMPLETED: + case NFC_NOTIFY_TRANSCEIVE_ERROR : + PHDBG_INFO("Hal4:Transceive Callback"); + if(NULL != Hal4Ctxt->psTrcvCtxtInfo) + { +#ifdef TRANSACTION_TIMER + if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + != PH_OSALNFC_INVALID_TIMER_ID) + { + phOsalNfc_Timer_Stop( + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + ); + phOsalNfc_Timer_Delete( + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + ); + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + = PH_OSALNFC_INVALID_TIMER_ID; + } +#endif /*TRANSACTION_TIMER*/ + phHal4Nfc_TransceiveComplete(Hal4Ctxt,pInfo); + } + break; + case NFC_NOTIFY_SEND_COMPLETED : + PHDBG_INFO("Hal4:NfcIp1 Send Callback"); + if(NULL != Hal4Ctxt->psTrcvCtxtInfo) + { + phHal4Nfc_SendCompleteHandler(Hal4Ctxt,pInfo); + } + break; + case NFC_NOTIFY_TRANSACTION : + phHal4Nfc_HandleEmulationEvent(Hal4Ctxt,pInfo); + break; + case NFC_NOTIFY_RECV_ERROR : + case NFC_NOTIFY_RECV_EVENT : + PHDBG_INFO("Hal4:Receive Event"); + if(NULL != Hal4Ctxt->psTrcvCtxtInfo) + { + if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + != PH_OSALNFC_INVALID_TIMER_ID) + { + phOsalNfc_Timer_Stop( + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + ); + phOsalNfc_Timer_Delete( + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + ); + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + = PH_OSALNFC_INVALID_TIMER_ID; + } + } + phHal4Nfc_RecvCompleteHandler(Hal4Ctxt,pInfo); + break; + case NFC_NOTIFY_TARGET_PRESENT: + phHal4Nfc_PresenceChkComplete(Hal4Ctxt,pInfo); + break; + case NFC_NOTIFY_DEVICE_ERROR: + { + NFCSTATUS status = NFCSTATUS_BOARD_COMMUNICATION_ERROR; + pphHal4Nfc_GenCallback_t pUpper_OpenCb + = Hal4Ctxt->sUpperLayerInfo.pUpperOpenCb; + void *pUpper_Context + = Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt; + static phHal4Nfc_NotificationInfo_t uNotificationInfo; + if(NULL != Hal4Ctxt->sUpperLayerInfo.pDefaultEventHandler) + { + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + Hal4Ctxt->sUpperLayerInfo.pDefaultEventHandler( + Hal4Ctxt->sUpperLayerInfo.DefaultListenerCtxt, + NFC_EVENT_NOTIFICATION, + uNotificationInfo, + NFCSTATUS_BOARD_COMMUNICATION_ERROR + ); + } + else if (( eHal4StateSelfTestMode == Hal4Ctxt->Hal4NextState ) + || ( eHal4StateOpenAndReady == Hal4Ctxt->Hal4NextState ) ) + { + Hal4Ctxt->Hal4CurrentState = eHal4StateClosed; + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + (void)phHciNfc_Release((void *)Hal4Ctxt->psHciHandle, + pHwRef, (pphNfcIF_Notification_CB_t)NULL, + (void *)Hal4Ctxt);/*Clean up Hci*/ + Hal4Ctxt->psHciHandle = NULL; + phOsalNfc_FreeMemory((void *)Hal4Ctxt->pHal4Nfc_LayerCfg); + Hal4Ctxt->pHal4Nfc_LayerCfg = NULL; + phOsalNfc_FreeMemory((void *)Hal4Ctxt); + gpphHal4Nfc_Hwref->hal_context = NULL; + gpphHal4Nfc_Hwref = NULL; + PHDBG_INFO("Hal4:Open Failed"); + /*Call upper layer's Open Cb with error status*/ + if(NULL != pUpper_OpenCb) + { + /*Upper layer's Open Cb*/ + (*pUpper_OpenCb)(pUpper_Context,status); + } + } + else + { + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); + } + break; + } + case NFC_NOTIFY_CONNECT_FAILED: + case NFC_NOTIFY_DISCONNECT_FAILED: + /*Generic Error type received from Hci.Handle the error based on + Hal4 next state and which past callback was Pending*/ + case NFC_NOTIFY_ERROR: + { + PHDBG_WARNING("Hal4:Error Notification from HCI"); + switch(Hal4Ctxt->Hal4NextState) + { + case eHal4StateClosed: + phHal4Nfc_CloseComplete(Hal4Ctxt,pInfo); + break; + case eHal4StateSelfTestMode: + phHal4Nfc_SelfTestComplete(Hal4Ctxt,pInfo); + break; + case eHal4StateConfiguring: + phHal4Nfc_ConfigureComplete(Hal4Ctxt,pInfo,type); + break; + case eHal4StateTargetDiscovered: + case eHal4StateTargetActivate: + { + if(NULL != Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb) + { + if(NULL == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice) + { + phHal4Nfc_ConfigureComplete(Hal4Ctxt,pInfo,type); + } + else + { + phHal4Nfc_ConnectComplete(Hal4Ctxt,pInfo); + } + } + else + { + phHal4Nfc_TargetDiscoveryComplete(Hal4Ctxt,pInfo); + } + break; + } + case eHal4StateTargetConnected: + phHal4Nfc_ConnectComplete(Hal4Ctxt,pInfo); + break; + case eHal4StateOpenAndReady: + phHal4Nfc_DisconnectComplete(Hal4Ctxt,pInfo); + break; + case eHal4StatePresenceCheck: + phHal4Nfc_PresenceChkComplete(Hal4Ctxt,pInfo); + break; + default: + PHDBG_WARNING("Unknown Error notification"); + break; + } + break; + }/*End of switch(Hal4Ctxt->Hal4State)*/ + default: + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + break; + }/*End of switch(type)*/ + } + return; +} + + +/*Event handler for HAL-HCI interface*/ +static void phHal4Nfc_HandleEvent( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + phHal_sEventInfo_t *psEventInfo = (phHal_sEventInfo_t *)pInfo; + static phNfc_sNotificationInfo_t sNotificationInfo; + phHal4Nfc_NotificationInfo_t uNotificationInfo = {NULL}; + NFCSTATUS RetStatus = NFCSTATUS_FAILED; + /*Check if Hal4 Close has already been called*/ + if(eHal4StateClosed != Hal4Ctxt->Hal4NextState) + { + switch(psEventInfo->eventType) + { + case NFC_EVT_ACTIVATED:/*Target Activated*/ + { + if(psEventInfo->eventHost == phHal_eHostController) + { + switch(psEventInfo->eventSource) + { + case phHal_eNfcIP1_Target: + phHal4Nfc_P2PActivateComplete(Hal4Ctxt,pInfo); + break; + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_B_PICC: + sNotificationInfo.info = psEventInfo; + sNotificationInfo.status = NFCSTATUS_SUCCESS; + sNotificationInfo.type = NFC_EVENT_NOTIFICATION; + pInfo = &sNotificationInfo; + phHal4Nfc_HandleEmulationEvent(Hal4Ctxt,pInfo); + break; + default: + break; + } + } + } + break; + case NFC_EVT_DEACTIVATED:/*Target Deactivated*/ + { + if(psEventInfo->eventHost == phHal_eHostController) + { + switch(psEventInfo->eventSource) + { + case phHal_eNfcIP1_Target: + phHal4Nfc_HandleP2PDeActivate(Hal4Ctxt,pInfo); + break; + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_B_PICC: + sNotificationInfo.info = psEventInfo; + sNotificationInfo.status = NFCSTATUS_SUCCESS; + sNotificationInfo.type = NFC_EVENT_NOTIFICATION; + pInfo = &sNotificationInfo; + phHal4Nfc_HandleEmulationEvent(Hal4Ctxt,pInfo); + break; + default: + break; + } + } + } + break; + /*Set Protection Event*/ + case NFC_EVT_PROTECTED: + { +#ifdef IGNORE_EVT_PROTECTED + /*Ignore_Event_Protected is set to false during Field Off event and + Set protection Configuration.After a NFC_EVT_PROTECTED is received + once all subsequent NFC_EVT_PROTECTED events are ignored*/ + if(FALSE == Hal4Ctxt->Ignore_Event_Protected) + { + Hal4Ctxt->Ignore_Event_Protected = TRUE; +#endif/*#ifdef IGNORE_EVT_PROTECTED*/ + sNotificationInfo.info = psEventInfo; + sNotificationInfo.status = NFCSTATUS_SUCCESS; + sNotificationInfo.type = NFC_EVENT_NOTIFICATION; + pInfo = &sNotificationInfo; + phHal4Nfc_HandleEmulationEvent(Hal4Ctxt,pInfo); +#ifdef IGNORE_EVT_PROTECTED + } +#endif/*#ifdef IGNORE_EVT_PROTECTED*/ + break; + } + /*NFC_UICC_RDPHASES_DEACTIVATE_REQ*/ + case NFC_UICC_RDPHASES_DEACTIVATE_REQ: + { + if(NULL != gpphHal4Nfc_Hwref) + { + gpphHal4Nfc_Hwref->uicc_rdr_active = FALSE; + } + break; + } + case NFC_UICC_RDPHASES_ACTIVATE_REQ: + { + if(NULL != gpphHal4Nfc_Hwref) + { + gpphHal4Nfc_Hwref->uicc_rdr_active = TRUE; + } + /*If a NFC_UICC_RDPHASES_ACTIVATE_REQ is received before a configure + discovery,then create a ADD context info*/ + if (NULL == Hal4Ctxt->psADDCtxtInfo) + { + Hal4Ctxt->psADDCtxtInfo= (pphHal4Nfc_ADDCtxtInfo_t) + phOsalNfc_GetMemory((uint32_t) + (sizeof(phHal4Nfc_ADDCtxtInfo_t))); + if(NULL != Hal4Ctxt->psADDCtxtInfo) + { + (void)memset(Hal4Ctxt->psADDCtxtInfo,0, + sizeof(phHal4Nfc_ADDCtxtInfo_t) + ); + } + } + if(NULL != Hal4Ctxt->psADDCtxtInfo) + { + Hal4Ctxt->psADDCtxtInfo->sADDCfg.PollDevInfo.PollEnabled + |= psEventInfo->eventInfo.rd_phases; + /*Configure HCI Discovery*/ + RetStatus = phHciNfc_Config_Discovery( + (void *)Hal4Ctxt->psHciHandle, + gpphHal4Nfc_Hwref, + &(Hal4Ctxt->psADDCtxtInfo->sADDCfg) + ); + Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == RetStatus? + eHal4StateConfiguring: + Hal4Ctxt->Hal4NextState); + } + break; + } + /*Call Default Event handler for these Events*/ + case NFC_INFO_TXLDO_OVERCUR: + case NFC_INFO_MEM_VIOLATION: + case NFC_INFO_TEMP_OVERHEAT: + case NFC_INFO_LLC_ERROR: + { + sNotificationInfo.info = psEventInfo; + sNotificationInfo.status = NFCSTATUS_SUCCESS; + sNotificationInfo.type = NFC_EVENT_NOTIFICATION; + pInfo = &sNotificationInfo; + PHDBG_INFO("Hal4:Exception events"); + if(NULL != Hal4Ctxt->sUpperLayerInfo.pDefaultEventHandler) + { + /*Pass on Event notification info from Hci to Upper layer*/ + uNotificationInfo.psEventInfo = psEventInfo; + Hal4Ctxt->sUpperLayerInfo.pDefaultEventHandler( + Hal4Ctxt->sUpperLayerInfo.DefaultListenerCtxt, + sNotificationInfo.type, + uNotificationInfo, + NFCSTATUS_SUCCESS + ); + } + break; + } + /*Call emulation Event handler fto handle these Events*/ + case NFC_EVT_TRANSACTION: + case NFC_EVT_START_OF_TRANSACTION: + case NFC_EVT_END_OF_TRANSACTION: + case NFC_EVT_CONNECTIVITY: + case NFC_EVT_OPERATION_ENDED: + case NFC_EVT_MIFARE_ACCESS: + case NFC_EVT_APDU_RECEIVED: + case NFC_EVT_EMV_CARD_REMOVAL: + sNotificationInfo.info = psEventInfo; + sNotificationInfo.status = NFCSTATUS_SUCCESS; + sNotificationInfo.type = NFC_EVENT_NOTIFICATION; + pInfo = &sNotificationInfo; + PHDBG_INFO("Hal4:Event transaction\n"); + phHal4Nfc_HandleEmulationEvent(Hal4Ctxt,pInfo); + break; + case NFC_EVT_FIELD_ON: + Hal4Ctxt->psEventInfo = sNotificationInfo.info = psEventInfo; + sNotificationInfo.status = NFCSTATUS_SUCCESS; + sNotificationInfo.type = NFC_EVENT_NOTIFICATION; + pInfo = &sNotificationInfo; + PHDBG_INFO("Hal4:Event Field ON\n"); + phHal4Nfc_HandleEmulationEvent(Hal4Ctxt,pInfo); + break; + case NFC_EVT_FIELD_OFF: + #ifdef IGNORE_EVT_PROTECTED + Hal4Ctxt->Ignore_Event_Protected = FALSE; + #endif/*#ifdef IGNORE_EVT_PROTECTED*/ + Hal4Ctxt->psEventInfo = sNotificationInfo.info = psEventInfo; + sNotificationInfo.status = NFCSTATUS_SUCCESS; + sNotificationInfo.type = NFC_EVENT_NOTIFICATION; + pInfo = &sNotificationInfo; + PHDBG_INFO("Hal4:Event Field OFF\n"); + phHal4Nfc_HandleEmulationEvent(Hal4Ctxt,pInfo); + break; + default: + PHDBG_WARNING("Hal4:Unhandled Event type received"); + break; + }/*End of switch*/ + }/*if(eHal4StateClosed != Hal4Ctxt->Hal4NextState)*/ + return; +} + + +/*Callback handler for Self Test Ioctl completion*/ +static void phHal4Nfc_SelfTestComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + NFCSTATUS status = NFCSTATUS_FAILED; + phNfc_sData_t *SelfTestResults + = (phNfc_sData_t *)(((phNfc_sCompletionInfo_t *)pInfo)->info); + pphHal4Nfc_IoctlCallback_t pUpper_IoctlCb + = Hal4Ctxt->sUpperLayerInfo.pUpperIoctlCb; + void *pUpper_Context = Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt; + /*check for Success*/ + if(( DEVMGMT_SWP_TEST == Hal4Ctxt->Ioctl_Type ) + || ( DEVMGMT_ANTENNA_TEST == Hal4Ctxt->Ioctl_Type )) + { + status = NFCSTATUS_SUCCESS; + } + else if((SelfTestResults->length > 0) && (0 == SelfTestResults->buffer[0])) + { + status = NFCSTATUS_SUCCESS; + } + else + { + if (NULL != pInfo) + { + status = ((phNfc_sCompletionInfo_t *)pInfo)->status; + } + } + + /*Copy response buffer and length*/ + (void)memcpy(Hal4Ctxt->sUpperLayerInfo.pIoctlOutParam->buffer, + SelfTestResults->buffer, + SelfTestResults->length); + Hal4Ctxt->sUpperLayerInfo.pIoctlOutParam->length + = SelfTestResults->length; + /*Call registered Ioctl callback*/ + (*pUpper_IoctlCb)( + pUpper_Context, + Hal4Ctxt->sUpperLayerInfo.pIoctlOutParam, + status + ); + return; +} + + +static void phHal4Nfc_IoctlComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + /*Copy status*/ + NFCSTATUS status = (((phNfc_sCompletionInfo_t *)pInfo)->status); + pphHal4Nfc_IoctlCallback_t pUpper_IoctlCb + = Hal4Ctxt->sUpperLayerInfo.pUpperIoctlCb; +#ifdef MERGE_SAK_SW2 + pphHal4Nfc_GenCallback_t pConfigCallback = + Hal4Ctxt->sUpperLayerInfo.pConfigCallback; +#endif/*#ifdef MERGE_SAK_SW2*/ + void *pUpper_Context = Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt; + Hal4Ctxt->sUpperLayerInfo.pUpperIoctlCb = NULL; +#ifdef MERGE_SAK_SW1 /*Software workaround 1*/ + if(eHal4StateOpenAndReady == Hal4Ctxt->Hal4NextState) + { + Hal4Ctxt->Hal4CurrentState = Hal4Ctxt->Hal4NextState; + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + /*Upper layer's Open Cb*/ + (*Hal4Ctxt->sUpperLayerInfo.pUpperOpenCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + NFCSTATUS_SUCCESS + ); + } +#endif/*#ifdef MERGE_SAK_SW1*/ +#ifdef MERGE_SAK_SW2 /*Software workaround 2*/ + else if((eHal4StateConfiguring == Hal4Ctxt->Hal4NextState) + &&(NULL != pConfigCallback)) + { + Hal4Ctxt->sUpperLayerInfo.pConfigCallback = NULL; + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + (*pConfigCallback)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt,status + ); + } + else +#endif/*#ifdef MERGE_SAK_SW2*/ + { + /*for NFC_MEM_READ and NFC_GPIO_READ ,provide one Byte Response*/ + if ((NFC_MEM_READ == Hal4Ctxt->Ioctl_Type) + || (NFC_GPIO_READ == Hal4Ctxt->Ioctl_Type) + ) + { + Hal4Ctxt->sUpperLayerInfo.pIoctlOutParam->length + = sizeof (uint8_t); + } + /*Call registered Ioctl callback*/ + if(NULL != pUpper_IoctlCb) + { + (*pUpper_IoctlCb)( + pUpper_Context, + Hal4Ctxt->sUpperLayerInfo.pIoctlOutParam, + status + ); + } + } + return; +} + +#ifdef FW_DOWNLOAD +/**Callback handler for Download completion*/ +STATIC void phHal4Nfc_DownloadComplete( + void *pContext, + void *pHwRef, + uint8_t type, + void *pInfo + ) +{ + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + NFCSTATUS status = NFCSTATUS_FAILED; + pphHal4Nfc_IoctlCallback_t pUpper_DnldCb = NULL; + phNfc_sData_t *pIoctlOutParam = NULL; + phHal_sHwReference_t *psHwRef = NULL; + void *pUpper_Context = NULL; + /*NULL checks*/ + if((NULL == pInfo) || (NULL == pHwRef) || (NULL == pContext)) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + } + else + { + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)pContext; + /*Copy back stored context/callback for the upper layer*/ + pUpper_Context = Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt; + pIoctlOutParam = Hal4Ctxt->sUpperLayerInfo.pIoctlOutParam; + pUpper_DnldCb = Hal4Ctxt->sUpperLayerInfo.pUpperIoctlCb; + Hal4Ctxt->sUpperLayerInfo.pUpperIoctlCb = NULL; + /*Copy download status*/ + status = (((phNfc_sCompletionInfo_t *)pInfo)->status); + /*copy hw reference*/ + psHwRef = (phHal_sHwReference_t *)pHwRef; + /*Free the temporary hal context used only for the sake of download*/ + phOsalNfc_FreeMemory(psHwRef->hal_context); + psHwRef->hal_context = NULL; + /*Call upper layer callback*/ + if(NULL != pUpper_DnldCb) + { + (*pUpper_DnldCb)( + pUpper_Context, + pIoctlOutParam, + status + ); + } + } + return; +} +#endif /*FW_DOWNLOAD*/ + diff --git a/libnfc-nxp/phHal4Nfc.h b/libnfc-nxp/phHal4Nfc.h new file mode 100644 index 0000000..47e3136 --- /dev/null +++ b/libnfc-nxp/phHal4Nfc.h @@ -0,0 +1,1169 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/** + * \file phHal4Nfc.h + * \brief HAL Function Prototypes + * The HAL4.0 API provides the user to have a interface for PN544(PN54x)/PN65N + * NFC device.The API is a non-blocking API, asynchronous API. This means that + * when ever an API function call results in waiting for a response from the + * NFC device, the API function will return immediately with status 'PENDING' + * and the actual result will be returned through specific callback functions + * on receiving the response from the NFC device + * + * \note This is the representative header file of the HAL 4.0. The release + * TAG or label is representing the release TAG (alias) of the entire + * library.A mechanism (see documentation \ref hal_release_label near + * the include guards of this file) is used to propagate the alias to + * the main documentation page. + * + * Project: NFC-FRI-1.1 / HAL4.0 + * + * $Date: Mon Jun 14 11:36:12 2010 $ + * $Author: ing07385 $ + * $Revision: 1.171 $ + * $Aliases: NFC_FRI1.1_WK1023_R35_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +/** page hal_release_label HAL 4.0 Release Label + * SDK_HAL_4.0 v 0.1 Draft + * \note This is the TAG (label, alias) of the HAL. If the string is empty,the + * current documentation has not been generated from an official release. + */ +/*@{*/ +#ifndef PHHAL4NFC_H +#define PHHAL4NFC_H +/*@}*/ + + +/** + * \name HAL4 + * + * File: \ref phHal4Nfc.h + *\def hal + */ + +/*@{*/ +#define PH_HAL4NFC_FILEREVISION "$Revision: 1.171 $" /**< \ingroup grp_file_attributes */ +#define PH_HAL4NFC_FILEALIASES "$Aliases: NFC_FRI1.1_WK1023_R35_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* -----------------Include files ---------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#ifdef ANDROID +#include +#endif + +/*************************** Includes *******************************/ +/** \defgroup grp_mw_external_hal_funcs NFC HAL4.0 +* +* +* +*/ +/* ---------------- Macros ----------------------------------------------*/ + +/** HAL Implementation Version Macros : Updated for every feature release of + HAL functionality */ +#define PH_HAL4NFC_VERSION 8 +#define PH_HAL4NFC_REVISION 21 +#define PH_HAL4NFC_PATCH 1 +#define PH_HAL4NFC_BUILD 0 + +/** HAL Interface Version Macros : Updated for every external release of + HAL Interface */ +#define PH_HAL4NFC_INTERFACE_VERSION 0 +#define PH_HAL4NFC_INTERFACE_REVISION 6 +#define PH_HAL4NFC_INTERFACE_PATCH 0 +#define PH_HAL4NFC_INTERAFECE_BUILD 0 + +/**Maximum length of receive buffer maintained by HAL*/ +#define PH_HAL4NFC_MAX_RECEIVE_BUFFER 4096U + +/**Send length used for Transceive*/ +#define PH_HAL4NFC_MAX_SEND_LEN PHHAL_MAX_DATASIZE + +/* -----------------Structures and Enumerations -------------------------*/ + +/** + * \ingroup grp_mw_external_hal_funcs + * + * Structure containing information about discovered remote device, like + * the number of remote devices found, device specific information + * like type of device (eg: ISO14443-4A/4B, NFCIP1 target etc) and + * the type sepcific information (eg: UID, SAK etc). This structure is + * returned as part of the disocvery notification. For more info refer + * \ref phHal4Nfc_ConfigureDiscovery, + * \ref phHal4Nfc_RegisterNotification, + * \ref pphHal4Nfc_Notification_t, + * phHal4Nfc_NotificationInfo_t + * + * + */ +typedef struct phHal4Nfc_DiscoveryInfo +{ + uint32_t NumberOfDevices;/**< Number of devices found */ + phHal_sRemoteDevInformation_t **ppRemoteDevInfo;/**< Pointer to Remote + device info list*/ +}phHal4Nfc_DiscoveryInfo_t; + +/** + * \ingroup grp_mw_external_hal_funcs + * + * This is a union returned as part of the \ref pphHal4Nfc_Notification_t + * callback. It contains either discovery information or other event + * information for which the client has registered using the + * \ref phHal4Nfc_RegisterNotification. + */ +typedef union +{ + phHal4Nfc_DiscoveryInfo_t *psDiscoveryInfo; + phHal_sEventInfo_t *psEventInfo; +}phHal4Nfc_NotificationInfo_t; + + + +/** +* \ingroup grp_mw_external_hal_funcs +* +* Prototype for Generic callback type provided by upper layer. This is used +* to return the success or failure status an asynchronous API function which +* does not have any other additional information to be returned. Refer +* specific function for applicable status codes. +*/ +typedef void (*pphHal4Nfc_GenCallback_t)( + void *context, + NFCSTATUS status + ); + +/** +* \ingroup grp_mw_external_hal_funcs +* +* Disconnect callback type provided by upper layer to called on completion +* of disconnect call \ref phHal4Nfc_Disconnect. +* +*/ +typedef void (*pphHal4Nfc_DiscntCallback_t)( + void *context, + phHal_sRemoteDevInformation_t *psDisconnectDevInfo, + NFCSTATUS status + ); + +/** +* \ingroup grp_mw_external_hal_funcs +* +* Notification callback type used by HAL to provide a Discovery or +* Event notification to the upper layer. +* +*/ +typedef void (*pphHal4Nfc_Notification_t) ( + void *context, + phHal_eNotificationType_t type, + phHal4Nfc_NotificationInfo_t info, + NFCSTATUS status + ); + + +/** +* \ingroup grp_mw_external_hal_funcs +* +* Callback type used to provide a Connect Success or Failure indication to +* the upper layer as a result of \ref phHal4Nfc_Connect call used to connect +* to discovered remote device. +* +*/ +typedef void (*pphHal4Nfc_ConnectCallback_t)( + void *context, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + NFCSTATUS status + ); + +/** +* \ingroup grp_mw_external_hal_funcs +* +* This callback type is used to provide received data and it's size to the +* upper layer in \ref phNfc_sData_t format ,when the upper layer has performed +* a Transceive operation on a tag or when the Device acts as an Initiator in a +* P2P transaction. +* +* +*/ +typedef void (*pphHal4Nfc_TransceiveCallback_t) ( + void *context, + phHal_sRemoteDevInformation_t *ConnectedDevice, + phNfc_sData_t *pRecvdata, + NFCSTATUS status + ); + +/** +* \ingroup grp_mw_external_hal_funcs +* +* This callback type is used to provide received data and it's size to the +* upper layer in \ref phNfc_sData_t structure, when the upper layer when the +* Device acts as a Target in a P2P transaction. +* +* +*/ +typedef void (*pphHal4Nfc_ReceiveCallback_t) ( + void *context, + phNfc_sData_t *pDataInfo, + NFCSTATUS status + ); + +/** +* \ingroup grp_mw_external_hal_funcs +* +* Callback type to inform success or failure of the Ioctl calls +* made by upper layer. It may optionally contain response data +* depending on the Ioctl command issued. +* +*/ +typedef void (*pphHal4Nfc_IoctlCallback_t) (void *context, + phNfc_sData_t *pOutData, + NFCSTATUS status ); + +/** +* \ingroup grp_mw_external_hal_funcs +*\if hal +* \sa \ref pphHal4Nfc_GenCallback_t +* \endif +* +*/ + +/** Same as general callback type, used to inform the completion of +* \ref phHal4Nfc_Send call done by when in NFCIP1 Target mode +*/ +typedef pphHal4Nfc_GenCallback_t pphHal4Nfc_SendCallback_t; + +/** +* \ingroup grp_mw_external_hal_funcs +* +* Enum type to distinguish between normal init and test mode init +* to be done as part of phHal4Nfc_Open +* In test mode init only minimal initialization of the NFC Device +* sufficient to run the self test is performed. +* +* \note Note: No functional features can be accessed when +* phHal4Nfc_Open is called with TestModeOn +* \ref phHal4Nfc_Open +* +*/ +typedef enum{ + eInitDefault = 0x00, /** + * pOpenCallback is called. It uses a Hardware Reference + * \ref phHal_sHwReference, allocated by the upper layer and the p_board_driver + * member initialized with the dal_instance (handle to the communication driver) + * and other members initialized to zero or NULL. + * + * \note + * - The device is in initialized state after the command has completed + * successfully. + * + * + * \param[in,out] psHwReference Hardware Reference, pre-initialized by upper + * layer. Members of this structure are made valid if + * this function is successful. \n + * + * \param[in] InitType Initialization type, used to differentiate between + * test mode limited initialization and normal init. + * + * \param[in] pOpenCallback The open callback function called by the HAL + * when open (initialization) sequence is completed or if there + * is an error in initialization. \n + * + * \param[in] pContext Upper layer context which will be included in the + * call back when request is completed. \n + * + * \retval NFCSTATUS_PENDING Open sequence has been successfully + * started and result will be conveyed + * via the pOpenCallback function. + * \retval NFCSTATUS_ALREADY_INITIALISED Device initialization already in + * progress. + * \retval NFCSTATUS_INVALID_PARAMETER The parameter could not be properly + * interpreted (structure uninitialized?). + * \retval NFCSTATUS_INSUFFICIENT_RESOURCES Insufficient resources for + * completing the request. + * \retval Others Errors related to the lower layers. + * + * \if hal + * \sa \ref phHal4Nfc_Close, + * \endif + */ +extern NFCSTATUS phHal4Nfc_Open( + phHal_sHwReference_t *psHwReference, + phHal4Nfc_InitType_t InitType, + pphHal4Nfc_GenCallback_t pOpenCallback, + void *pContext + ); + + + +/** + * \if hal + * \ingroup grp_hal_common + * \else + * \ingroup grp_mw_external_hal_funcs + * \endif + * + * Retrieves the capabilities of the device represented by the Hardware + * Reference parameter.The HW, FW versions,model-id and other capability + * information are located inside the pDevCapabilities parameter. + * + * \param[in] psHwReference Hardware Reference, pre-initialized + * by upper layer. \n + * \param[out] psDevCapabilities Pointer to the device capabilities structure + * where all relevant capabilities of the + * peripheral are stored. \n + * \param[in] pContext Upper layer context which will be included in + * the call back when request is completed. \n + * + * \retval NFCSTATUS_SUCCESS Success and the psDevCapabilities is + * updated with info. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be properly interpreted. + * \retval NFCSTATUS_NOT_INITIALISED Hal is not yet initialized. + * \retval Others Errors related to the lower layers. + * + */ +extern NFCSTATUS phHal4Nfc_GetDeviceCapabilities( + phHal_sHwReference_t *psHwReference, + phHal_sDeviceCapabilities_t *psDevCapabilities, + void *pContext + ); + + +/** +* \if hal +* \ingroup grp_hal_common +* \else +* \ingroup grp_mw_external_hal_funcs +* \endif +* +* This function is used to Configure discovery wheel (and start if +* required) based on the discovery configuration passed. +* This includes enabling/disabling of the Reader phases (A, B, F), +* NFCIP1 Initiator Speed and duration of the Emulation phase. +* Additional optional parameters for each of the features i.e. Reader, +* Emulation and Peer2Peer can be set using the +* \ref phHal4Nfc_ConfigParameters function +* +* \param[in] psHwReference Hardware Reference, pre-initialized by +* upper layer. \n +* +* \param[in] discoveryMode Discovery Mode allows to choose between: +* discovery configuration and start, stop +* discovery and start discovery (with last +* set configuration). +* \ref phHal_eDiscoveryConfigMode_t +* \note Note: Presently only NFC_DISCOVERY_CONFIG is supported, other values +* are for future use. When in Reader/Initiator mode it mandatory +* to call phHal4Nfc_Connect before any transaction can be performed +* with the discovered device. +* +* \param[in] discoveryCfg Discovery configuration parameters. +* Reader A/Reader B, Felica 212, Felica 424, +* NFCIP1 Speed, Emulation Enable and Duration. +* +* +* \param[in] pConfigCallback This callback has to be called once Hal +* completes the Configuration. +* +* \param[in] pContext Upper layer context to be returned in the +* callback. +* +* \retval NFCSTATUS_INVALID_PARAMETER Wrong Parameter values. +* +* \retval NFCSTATUS_NOT_INITIALISED Hal is not initialized. +* +* \retval NFCSTATUS_BUSY Cannot Configure Hal in +* Current state. +* +* \retval NFCSTATUS_INSUFFICIENT_RESOURCES System Resources insufficient. +* +* \retval NFCSTATUS_PENDING Configuration request accepted +* and Configuration is in progress. +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied +* parameters could not be properly +* interpreted. +* \retval Others Errors related to the lower layers +* +* \note Note: When in Reader/Initiator mode it mandatory +* to call phHal4Nfc_Connect before any transaction can be performed +* with the discovered device. Even if the HAL client is not +* interested in using any of the discovered phHal4Nfc_Connect and +* phHal4Nfc_Disconnect should be called to restart the Discovery +* wheel +* +* \ref phHal4Nfc_Connect, phHal4Nfc_Disconnect +* +*/ +extern NFCSTATUS phHal4Nfc_ConfigureDiscovery( + phHal_sHwReference_t *psHwReference, + phHal_eDiscoveryConfigMode_t discoveryMode, + phHal_sADD_Cfg_t *discoveryCfg, + pphHal4Nfc_GenCallback_t pConfigCallback, + void *pContext + ); +/** +* \if hal +* \ingroup grp_hal_common +* \else +* \ingroup grp_mw_external_hal_funcs +* \endif +* +* This function is used to set parameters of various features of the Hal, +* based on the CfgType parameter. Presently following configuration +* types are supported :- +* \n 1. NFC_RF_READER_CONFIG (optional)-> Configure parameters for Reader A +* or Reader B based on the configuration passed +* \n 2. NFC_P2P_CONFIG (optional)-> Congfigure P2P parameters like +* 'General bytes', 'PSL Request' etc. +* \n 3. NFC_EMULATION_CONFIG -> Enable and configure the emulation mode +* parameters for either NFC Target, SmartMX, UICC and +* \n Card Emulation from Host (A, B, F) +* All the configuration modes can be called independent of each other. The +* setting will typically take effect for the next cycle of the relevant +* phase of discovery. For optional configuration internal defaults will be +* used in case the configuration is not set. +* \note Card emulation from Host and Card Emulation from UICC are mutually +* exclusive modes, i.e: only one can be enabled at a time. Using +* this function to enable one of the emulation modes implicitly disables the +* the other. eg. Setting Type A (or Type B) Emulation from Host disables +* card emulation from UICC and vice versa. +* +* \param[in] psHwReference Hardware Reference, pre-initialized by +* upper layer. \n +* +* \param[in] eCfgType Configuration type which can take one of the +* enum values of \ref phHal_eConfigType_t. Each +* config type is associated with its corresponding +* information which is passed using the uCfg structure. +* +* +* \param[in] uCfg Union containing configuration information, +* which will be interpreted based on eCfgType +* parameter. +* +* +* \param[in] pConfigCallback This callback has to be called once Hal +* completes the Configuration. +* +* \param[in] pContext Upper layer context to be returned in the +* callback. +* +* \retval NFCSTATUS_INVALID_PARAMETER Wrong Parameter values. +* +* \retval NFCSTATUS_NOT_INITIALISED Hal is not initialized. +* +* \retval NFCSTATUS_BUSY Cannot Configure Hal in +* Current state. +* +* \retval NFCSTATUS_INSUFFICIENT_RESOURCES System Resources insufficient. +* +* \retval NFCSTATUS_PENDING Configuration request accepted +* and Configuration is in progress. +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied +* parameters could not be properly +* interpreted. +* \retval Others Errors related to the lower layers +*/ + +extern NFCSTATUS phHal4Nfc_ConfigParameters( + phHal_sHwReference_t *psHwReference, + phHal_eConfigType_t eCfgType, + phHal_uConfig_t *uCfg, + pphHal4Nfc_GenCallback_t pConfigCallback, + void *pContext + ); + +/** + * \if hal + * \ingroup grp_hal_nfci + * \else + * \ingroup grp_mw_external_hal_funcs + * \endif + * + * This function is called to connect to a one (out of many if multiple + * devices are discovered) already discovered Remote Device notified + * through register notification. The Remote Device Information structure is + * already pre-initialized with data (e.g. from Discovery Notificaiton + * Callback) A new session is started after the connect function returns + * successfully. The session ends with a successful disconnect + * (see \ref phHal4Nfc_Disconnect). + * + * \param[in] psHwReference Hardware Reference, pre-initialized by + * upper layer. \n + * + * \param[in,out] psRemoteDevInfo Points to the Remote Device Information + * structure. The members of it can be + * re-used from a previous session. + * + * \param[in] pNotifyConnectCb Upper layer callback to be called for + * notifying Connect Success/Failure + * + * \param[in] pContext Upper layer context to be returned in + * pNotifyConnectCb. + * + * \retval NFCSTATUS_PENDING Request initiated, result will + * be informed through the callback. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied + * parameters could not be + * properly interpreted. + * \retval NFCSTATUS_FAILED More than one phHal4Nfc_Connect + * is not allowed during a session + * on the same remote device. The + * session has to be closed before + * (see\ref phHal4Nfc_Disconnect). + * \retval NFCSTATUS_NOT_INITIALIZED Hal is not initialized. + * \retval NFCSTATUS_FEATURE_NOT_SUPPORTED Reactivation is not supported for + * NfcIp target and Jewel/Topaz + * remote device types. + * \retval NFCSTATUS_INVALID_REMOTE_DEVICE The Remote Device Identifier is + * not valid. + * \retval Others Errors related to the lower layers. + * + * \if hal + * \sa \ref phHal4Nfc_Disconnect + * \endif + */ +extern NFCSTATUS phHal4Nfc_Connect( + phHal_sHwReference_t *psHwReference, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + pphHal4Nfc_ConnectCallback_t pNotifyConnectCb, + void *pContext + ); + + +/** + * \if hal + * \ingroup grp_hal_nfci + * \else + * \ingroup grp_mw_external_hal_funcs + * \endif + * + * The phHal4Nfc_Transceive function allows to send data to and receive data + * from the Remote Device selected by the caller.It is also used by the + * NFCIP1 Initiator while performing a transaction with the NFCIP1 target. + * The caller has to provide the Remote Device Information structure and the + * command in order to communicate with the selected remote device.For P2P + * transactions the command type will not be used. + * + * + * \note the RecvData should be valid until the pTrcvCallback has been called. + * + * + * \param[in] psHwReference Hardware Reference, pre-initialized by + * upper layer. \n + * + * \param[in,out] psTransceiveInfo Information required by transceive is + * concealed in this structure.It contains + * the send,receive buffers and their + * lengths. + * + * \param[in] psRemoteDevInfo Points to the Remote Device Information + * structure which identifies the selected + * Remote Device. + * + * \param[in] pTrcvCallback Callback function for returning the + * received response or error. + * + * \param[in] pContext Upper layer context to be returned in + * the callback. + * + * \retval NFCSTATUS_PENDING Transceive initiated.pTrcvCallback + * will return the response or error. + * \retval NFCSTATUS_NOT_INITIALIZED Hal is not initialized. + * \retval NFCSTATUS_SUCCESS This status is used when send data + * length is zero and HAL contains + * previously more bytes from previous + * receive. \n + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied + * parameters could not be properly + * interpreted or are invalid. + * \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or + * has been disconnected meanwhile. + * \retval NFCSTATUS_FEATURE_NOT_SUPPORTED Transaction on this Device type is + * not supported. + * \retval NFCSTATUS_BUSY Previous transaction is not + * completed. + * \retval NFCSTATUS_INSUFFICIENT_RESOURCES System resources are insufficient + * to complete the request at that + * point in time. + * \retval NFCSTATUS_MORE_INFORMATION Received number of bytes is greater + * than receive buffer provided by the + * upper layer.Extra bytes will be + * retained by Hal and returned on next + * call to transceive. + * \retval Others Errors related to the lower layers. + * + */ +extern NFCSTATUS phHal4Nfc_Transceive( + phHal_sHwReference_t *psHwReference, + phHal_sTransceiveInfo_t *psTransceiveInfo, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + pphHal4Nfc_TransceiveCallback_t pTrcvCallback, + void *pContext + ); + + + + +/** + * \if hal + * \ingroup grp_hal_nfci + * \else + * \ingroup grp_mw_external_hal_funcs + * \endif + * + * The function allows to disconnect from a specific Remote Device. This + * function closes the session opened with \ref phHal4Nfc_Connect "Connect".It + * is also used to switch from wired to virtual mode in case the discovered + * device is SmartMX in wired mode. The status of discovery wheel after + * disconnection is determined by the ReleaseType parameter. + * + * + * + * \param[in] psHwReference Hardware Reference, pre-initialized by + * upper layer. \n + * \param[in,out] psRemoteDevInfo Points to the valid (connected) Remote + * Device Information structure. + * + * \param[in] ReleaseType Defines various modes of releasing an acquired + * target or tag + * + * \param[in] pDscntCallback Callback function to notify + * disconnect success/error. + * + * \param[in] pContext Upper layer context to be returned in + * the callback. + * + * + * \retval NFCSTATUS_PENDING Disconnect initiated.pDscntCallback + * will return the response or error. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied + * parameters could not be properly + * interpreted. + * \retval NFCSTATUS_INVALID_REMOTE_DEVICE The device has not been opened + * before or has already been closed. + * \retval NFCSTATUS_NOT_INITIALIZED Hal is not initialized. + * \retval Others Errors related to the lower layers. + * + * \if hal + * \sa \ref phHal4Nfc_Connect + * \endif + */ +extern NFCSTATUS phHal4Nfc_Disconnect( + phHal_sHwReference_t *psHwReference, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phHal_eReleaseType_t ReleaseType, + pphHal4Nfc_DiscntCallback_t pDscntCallback, + void *pContext + ); + +/** +* \if hal +* \ingroup grp_hal_common +* \else +* \ingroup grp_mw_external_hal_funcs +* \endif +* +* The function allows to do a one time check on whether the connected target +* is still present in the field of the Reader. The call back returns the +* result of the presence check sequence indicating whether it is still present +* or moved out of the reader field. +* +* \param[in] psHwReference Hardware Reference, pre-initialized by +* upper layer. \n +* +* \param[in] pPresenceChkCb Callback function called on completion of the +* presence check sequence or in case an error +* has occurred.. +* +* \param[in] context Upper layer context to be returned in the +* callback. +* +* \retval NFCSTATUS_PENDING Call successfully issued to lower layer. +* Status will be returned in pPresenceChkCb. +* +* \retval NFCSTATUS_NOT_INITIALISED The device has not been opened or has +* been disconnected meanwhile. +* +* \retval NFCSTATUS_BUSY Previous presence check callback has not +* been received +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* +* \retval NFCSTATUS_RELEASED P2P target has been released by Initiator. +* \retval Others Errors related to the lower layers +* +*/ +extern NFCSTATUS phHal4Nfc_PresenceCheck( + phHal_sHwReference_t *psHwReference, + pphHal4Nfc_GenCallback_t pPresenceChkCb, + void *context + ); + + +/** + * \if hal + * \ingroup grp_hal_common + * \else + * \ingroup grp_mw_external_hal_funcs + * \endif + * + * The I/O Control function allows the caller to use (vendor-) specific + * functionality provided by the lower layer or by the hardware. Each feature + * is accessible via a specific IOCTL Code and has to be documented by the + * provider of the driver and the hardware. + * See "IOCTL Codes" for the definition of a standard command set.\n + * + * + * \param[in] psHwReference Hardware Reference, pre-initialized by + * upper layer. \n + * \param[in] IoctlCode Control code for the operation. + * This value identifies the specific + * operation to be performed and are defined + * in \ref phNfcIoctlCode.h + * + * \param[in] pInParam Pointer to any input data structure + * containing data which is interpreted + * based on Ioctl code and the length of + * the data. + * + * \param[in] pOutParam Pointer to output data structure + * containing data which is returned as a + * result of the Ioctl operation and the + * length of the data. + * + * \param[in] pIoctlCallback callback function called in case an + * error has occurred while performing + * requested operation,or on successful + * completion of the request + * + * \param[in] pContext Upper layer context to be returned in + * the callback. + * + * \retval NFCSTATUS_SUCCESS Success. + * \retval NFCSTATUS_PENDING Call issued to lower layer.Status will + * be notified in pIoctlCallback. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be properly interpreted. + * \retval NFCSTATUS_NOT_INITIALIZED Hal is not initialized. + * \retval Others Errors related to the lower layers. + * + */ +extern NFCSTATUS phHal4Nfc_Ioctl( + phHal_sHwReference_t *psHwReference, + uint32_t IoctlCode, + phNfc_sData_t *pInParam, + phNfc_sData_t *pOutParam, + pphHal4Nfc_IoctlCallback_t pIoctlCallback, + void *pContext + ); + + + +/** + * \if hal + * \ingroup grp_hal_common + * \else + * \ingroup grp_mw_external_hal_funcs + * \endif + * + * Closes the link to the NFC device. All configurations/setups + * done until now are invalidated.To restart communication, phHal4Nfc_Open + * needs to be called. The pClosecallback is called when all steps + * in the close sequence are completed. + * + * + * \param[in] psHwReference Hardware Reference, pre-initialized by + * upper layer. \n + * + * \param[in] pCloseCallback Callback function called on completion of + * the close sequence or in case an error + * has occurred.. + * + * \param[in] pContext Upper layer context to be returned + * in the callback. + * + * \retval NFCSTATUS_SUCCESS Closing successful. + * \retval NFCSTATUS_NOT_INITIALIZED The device has not been opened or has + * been disconnected meanwhile. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be properly interpreted. + * \retval NFCSTATUS_BUSY Configuration is in progress.Shutdown + * is not allowed until configure complete. + * \retval Others Errors related to the lower layers. + * + * \if hal + * \sa \ref phHal4Nfc_Open + * \endif + */ +extern NFCSTATUS phHal4Nfc_Close( + phHal_sHwReference_t *psHwReference, + pphHal4Nfc_GenCallback_t pCloseCallback, + void *pContext + ); + + +/** + * \if hal + * \ingroup grp_hal_common + * \else + * \ingroup grp_mw_external_hal_funcs + * \endif + * + * Forcibly shutdown the HAl.This API makes a call to forcibly shutdown the + * lower layer and frees all resources in use by Hal before shutting down.The + * API always succeeds.It does not however reset the target. + * + * \param[in] psHwReference Hardware Reference, pre-initialized by + * upper layer. \n + * + * \param[in] pConfig Reserved for future use. + * + * + */ +extern void phHal4Nfc_Hal4Reset( + phHal_sHwReference_t *psHwReference, + void *pConfig + ); + + +/** +* \if hal +* \ingroup grp_hal_common +* \else +* \ingroup grp_mw_external_hal_funcs +* \endif +* +* The function is used by the NFCIP1 Target to respond to packect received +* from NFCIP1 initiator. pSendCallback() +* is called , when all steps in the send sequence are completed. +* +* \param[in] psHwReference Hardware Reference, pre-initialized by +* upper layer. \n +* +* \param[in] psTransactInfo information required for transferring +* the data +* +* \param[in] sTransferData Data and the length of the data to be +* transferred +* +* \param[in] pSendCallback Callback function called on completion +* of the NfcIP sequence or in case an +* error has occurred. +* +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_PENDING Send is in progress. +* \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has +* been disconnected meanwhile. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALIZED Hal is not initialized. +* \retval Others Errors related to the lower layers. +* +* +*/ +extern +NFCSTATUS +phHal4Nfc_Send( + phHal_sHwReference_t *psHwReference, + phHal4Nfc_TransactInfo_t *psTransactInfo, + phNfc_sData_t sTransferData, + pphHal4Nfc_SendCallback_t pSendCallback, + void *pContext + ); + +/** +* \if hal +* \ingroup grp_hal_common +* \else +* \ingroup grp_mw_external_hal_funcs +* \endif +* +* This function is called by the NfcIP Peer to wait for receiving data from +* the other peer.It is used only by the NfcIP Target. +* \note NOTE: After this function is called, its mandatory to wait for the +* pphHal4Nfc_ReceiveCallback_t callback, before calling any other function. +* Only functions allowed are phHal4Nfc_Close() and phHal4Nfc_Hal4Reset(). +* +* +* \param[in] psHwReference Hardware Reference, pre-initialized by +* upper layer. \n +* +* \param[in] psTransactInfo information required for transferring the +* data +* +* \param[in] pReceiveCallback Callback function called after receiving +* the data or in case an error has +* has occurred. +* +* \param[in] pContext Upper layer context to be returned +* in the callback. +* +* \retval NFCSTATUS_PENDING Receive is in progress. +* \retval NFCSTATUS_INVALID_DEVICE The device has not been opened or has +* been disconnected meanwhile. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALIZED Hal is not initialized. +* \retval Others Errors related to the lower layers +* +*/ +extern +NFCSTATUS +phHal4Nfc_Receive( + phHal_sHwReference_t *psHwReference, + phHal4Nfc_TransactInfo_t *psTransactInfo, + pphHal4Nfc_ReceiveCallback_t pReceiveCallback, + void *pContext + ); + + +/** +* \if hal +* \ingroup grp_hal_common +* \else +* \ingroup grp_mw_external_hal_funcs +* \endif +* +* This API is a synchronous call used to register a listener for either tag +* discovery, Secure element notification or P2P Notification or a general +* notification handler for all the three. +* +* +* \param[in] psHwRef Hardware Reference, pre-initialized by +* upper layer. \n +* +* \param[in] eRegisterType Type of Notification registered.Informs +* whether upper layer is interested in Tag +* Discovery,secure element or P2P notification. +* +* \param[in] pNotificationHandler Notification callback.If this parameter is +* NULL,any notification from Hci will be +* ignored and upper layer will not be notified +* of the event. +* +* \param[in] Context Upper layer context. +* +* \retval NFCSTATUS_SUCCESS Notification unregister successful. +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALIZED Hal is not initialized. +* +*/ +extern NFCSTATUS phHal4Nfc_RegisterNotification( + phHal_sHwReference_t *psHwRef, + phHal4Nfc_RegisterType_t eRegisterType, + pphHal4Nfc_Notification_t pNotificationHandler, + void *Context + ); + +/** +* \if hal +* \ingroup grp_hal_common +* \else +* \ingroup grp_mw_external_hal_funcs +* \endif +* +* This API is a synchronous call used to unregister a listener for either tag +* discovery, Secure element notification or P2P Notification, previously +* registered using \ref phHal4Nfc_RegisterNotification. +* +* \param[in] psHwReference Hardware Reference, pre-initialized by +* upper layer. \n +* +* \param[in] eRegisterType Type of registration ,tells whether upper +* layer is interested in unregistering for +* Tag Discovery,Secure element or P2P. \n +* +* \param[in] Context Upper layer context. +* +* \retval NFCSTATUS_SUCCESS Notification unregister successful. +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* +* \retval NFCSTATUS_NOT_INITIALIZED Hal is not initialized. +* +* +*/ +extern NFCSTATUS phHal4Nfc_UnregisterNotification( + phHal_sHwReference_t *psHwReference, + phHal4Nfc_RegisterType_t eRegisterType, + void *Context + ); + + +/** +* \if hal +* \ingroup grp_hal_common +* \else +* \ingroup grp_mw_external_hal_funcs +* \endif +* +* This function is called to switch the SmartMX to Wired Mode. After switching +* to Wired mode the SmartMX can be discovered through Tag Discovery like a normal +* tag and used in the same manner as a tag. SmartMx returns to previous mode +* (Virtual or Off) when the tag is relased by phHal4Nfc_Disconnect +* +* +* \param[in] psHwReference Hardware Reference, pre-initialized by +* upper layer. \n +* +* \param[in] smx_mode Mode to which the switch should be made. +* +* \param[in] pSwitchModecb Callback for Switch mode complete +* with success/error notification. +* +* \param[in] pContext Upper layer context. +* +* \retval NFCSTATUS_PENDING Switch in progress.Status will be +* returned in pSwitchModecb. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied +* parameters could not be properly +* interpreted. +* \retval NFCSTATUS_NOT_INITIALIZED Hal is not initialized. +* \retval NFCSTATUS_BUSY Configuration in Progress or +* remote device is connected. +* \retval NFCSTATUS_INSUFFICIENT_RESOURCES System resources are insufficient +* to complete the request at that +* point in time. +* \retval NFCSTATUS_FAILED No listener has been registered +* by the upper layer for Emulation +* before making this call. +* \retval Others Errors related to the lower +* layers. +*/ +extern NFCSTATUS phHal4Nfc_Switch_SMX_Mode( + phHal_sHwReference_t *psHwReference, + phHal_eSmartMX_Mode_t smx_mode, + pphHal4Nfc_GenCallback_t pSwitchModecb, + void *pContext + ); + + +/** +* \if hal +* \ingroup grp_hal_common +* \else +* \ingroup grp_mw_external_hal_funcs +* \endif +* +* This function is called to switch the UICC on or Off. +* +* +* \param[in] psHwReference Hardware Reference, pre-initialized by +* upper layer. \n +* +* \param[in] smx_mode Mode to which the switch should be made. +* +* \param[in] pSwitchModecb Callback for Switch mode complete +* with success/error notification. +* +* \param[in] pContext Upper layer context. +* +* \retval NFCSTATUS_PENDING Switch in progress.Status will be +* returned in pSwitchModecb. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied +* parameters could not be properly +* interpreted. +* \retval NFCSTATUS_NOT_INITIALIZED Hal is not initialized. +* \retval NFCSTATUS_BUSY Configuration in Progress or +* remote device is connected. +* \retval NFCSTATUS_INSUFFICIENT_RESOURCES System resources are insufficient +* to complete the request at that +* point in time. +* \retval NFCSTATUS_FAILED No listener has been registered +* by the upper layer for Emulation +* before making this call. +* \retval Others Errors related to the lower +* layers. +*/ +extern NFCSTATUS phHal4Nfc_Switch_Swp_Mode( + phHal_sHwReference_t *psHwReference, + phHal_eSWP_Mode_t swp_mode, + pphHal4Nfc_GenCallback_t pSwitchModecb, + void *pContext + ); + +#endif /* end of PHHAL4NFC_H */ + + diff --git a/libnfc-nxp/phHal4Nfc_ADD.c b/libnfc-nxp/phHal4Nfc_ADD.c new file mode 100644 index 0000000..d2040ea --- /dev/null +++ b/libnfc-nxp/phHal4Nfc_ADD.c @@ -0,0 +1,1014 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ +/*! + * \file phHal4Nfc_ADD.c + * \brief Hal4Nfc_ADD source. + * + * Project: NFC-FRI 1.1 + * + * $Date: Mon May 31 11:43:42 2010 $ + * $Author: ing07385 $ + * $Revision: 1.151 $ + * $Aliases: NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +/* ---------------------------Include files ----------------------------------*/ +#include +#include +#include +#include + +/* ------------------------------- Macros ------------------------------------*/ +#define NFCIP_ACTIVE_SHIFT 0x03U +#define NXP_UID 0x04U +#define NXP_MIN_UID_LEN 0x07U +/* --------------------Structures and enumerations --------------------------*/ + +NFCSTATUS phHal4Nfc_ConfigParameters( + phHal_sHwReference_t *psHwReference, + phHal_eConfigType_t CfgType, + phHal_uConfig_t *puConfig, + pphHal4Nfc_GenCallback_t pConfigCallback, + void *pContext + ) +{ + NFCSTATUS CfgStatus = NFCSTATUS_SUCCESS; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + /*NULL checks*/ + if(NULL == psHwReference + || NULL == pConfigCallback + || NULL == puConfig + ) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + CfgStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_INVALID_PARAMETER); + } + /*Check if initialised*/ + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + CfgStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_NOT_INITIALISED); + } + else + { + Hal4Ctxt = psHwReference->hal_context; + /*If previous Configuration request has not completed,do not allow new + configuration*/ + if(Hal4Ctxt->Hal4NextState == eHal4StateConfiguring) + { + PHDBG_INFO("Hal4:PollCfg in progress.Returning status Busy"); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_BUSY); + } + else if(Hal4Ctxt->Hal4CurrentState >= eHal4StateOpenAndReady) + { + /*Allocate ADD context*/ + if (NULL == Hal4Ctxt->psADDCtxtInfo) + { + Hal4Ctxt->psADDCtxtInfo= (pphHal4Nfc_ADDCtxtInfo_t) + phOsalNfc_GetMemory((uint32_t) + (sizeof(phHal4Nfc_ADDCtxtInfo_t))); + if(NULL != Hal4Ctxt->psADDCtxtInfo) + { + (void)memset(Hal4Ctxt->psADDCtxtInfo,0, + sizeof(phHal4Nfc_ADDCtxtInfo_t) + ); + } + } + if(NULL == Hal4Ctxt->psADDCtxtInfo) + { + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + /*Register Upper layer context*/ +#ifdef LLCP_DISCON_CHANGES + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCfgDiscCtxt = pContext; +#else /* #ifdef LLCP_DISCON_CHANGES */ + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext; +#endif /* #ifdef LLCP_DISCON_CHANGES */ + switch(CfgType) + { + /*NFC_EMULATION_CONFIG*/ + case NFC_EMULATION_CONFIG: + { + (void)memcpy((void *)&Hal4Ctxt->uConfig, + (void *)puConfig, + sizeof(phHal_uConfig_t) + ); + break; + } + /*P2P Configuration*/ + case NFC_P2P_CONFIG: + { + /*If general bytes are not provided by above layer copy zeros + in general bytes*/ + if(puConfig->nfcIPConfig.generalBytesLength == 0) + { + Hal4Ctxt->uConfig.nfcIPConfig.generalBytesLength = 0x00; + (void)memset(Hal4Ctxt->uConfig.nfcIPConfig.generalBytes, + 0,Hal4Ctxt->uConfig.nfcIPConfig.generalBytesLength + ); + } + else + { + (void)memcpy((void *)&Hal4Ctxt->uConfig, + (void *)puConfig, + sizeof(phHal_uConfig_t) + ); + } + break; + } + /*Protection config*/ + case NFC_SE_PROTECTION_CONFIG: + { +#ifdef IGNORE_EVT_PROTECTED + Hal4Ctxt->Ignore_Event_Protected = FALSE; +#endif/*#ifdef IGNORE_EVT_PROTECTED*/ + (void)memcpy((void *)&Hal4Ctxt->uConfig, + (void *)puConfig, + sizeof(phHal_uConfig_t) + ); + break; + } + default: + CfgStatus = NFCSTATUS_FAILED; + break; + } + if ( NFCSTATUS_SUCCESS == CfgStatus ) + { + /*Issue configure with given configuration*/ + CfgStatus = phHciNfc_Configure( + (void *)Hal4Ctxt->psHciHandle, + (void *)psHwReference, + CfgType, + &Hal4Ctxt->uConfig + ); + /* Change the State of the HAL only if status is Pending */ + if ( NFCSTATUS_PENDING == CfgStatus ) + { + Hal4Ctxt->Hal4NextState = eHal4StateConfiguring; + Hal4Ctxt->sUpperLayerInfo.pConfigCallback + = pConfigCallback; + } + } + } + } + else + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_NOT_INITIALISED); + } + } + return CfgStatus; +} + + +/**Configure the discovery*/ +NFCSTATUS phHal4Nfc_ConfigureDiscovery( + phHal_sHwReference_t *psHwReference, + phHal_eDiscoveryConfigMode_t discoveryMode, + phHal_sADD_Cfg_t *discoveryCfg, + pphHal4Nfc_GenCallback_t pConfigCallback, + void *pContext + ) +{ + NFCSTATUS CfgStatus = NFCSTATUS_SUCCESS; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + if(NULL == psHwReference + || NULL == pConfigCallback + || NULL == discoveryCfg + ) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + CfgStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + CfgStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_NOT_INITIALISED); + } + else + { + Hal4Ctxt = psHwReference->hal_context; + /*If previous Configuration request has not completed ,do not allow + new configuration*/ + if(Hal4Ctxt->Hal4NextState == eHal4StateConfiguring) + { + PHDBG_INFO("Hal4:PollCfg in progress.Returning status Busy"); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_BUSY); + } + else if(Hal4Ctxt->Hal4CurrentState >= eHal4StateOpenAndReady) + { + if (NULL == Hal4Ctxt->psADDCtxtInfo) + { + Hal4Ctxt->psADDCtxtInfo= (pphHal4Nfc_ADDCtxtInfo_t) + phOsalNfc_GetMemory((uint32_t) + (sizeof(phHal4Nfc_ADDCtxtInfo_t))); + if(NULL != Hal4Ctxt->psADDCtxtInfo) + { + (void)memset(Hal4Ctxt->psADDCtxtInfo,0, + sizeof(phHal4Nfc_ADDCtxtInfo_t) + ); + } + } + if(NULL == Hal4Ctxt->psADDCtxtInfo) + { + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + /*Register Upper layer context*/ +#ifdef LLCP_DISCON_CHANGES + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCfgDiscCtxt = pContext; +#else /* #ifdef LLCP_DISCON_CHANGES */ + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext; +#endif /* #ifdef LLCP_DISCON_CHANGES */ + switch(discoveryMode) + { + case NFC_DISCOVERY_START: + PHDBG_INFO("Hal4:Call to NFC_DISCOVERY_START"); + break; + case NFC_DISCOVERY_CONFIG: + PHDBG_INFO("Hal4:Call to NFC_DISCOVERY_CONFIG"); + /*Since sADDCfg is allocated in stack ,copy the ADD + configuration structure to HAL4 context*/ + (void)memcpy((void *) + &(Hal4Ctxt->psADDCtxtInfo->sADDCfg), + (void *)discoveryCfg, + sizeof(phHal_sADD_Cfg_t) + ); + PHDBG_INFO("Hal4:Finished copying sADDCfg"); + Hal4Ctxt->psADDCtxtInfo->smx_discovery = FALSE; +#ifdef UPDATE_NFC_ACTIVE + Hal4Ctxt->psADDCtxtInfo->sADDCfg.PollDevInfo.PollCfgInfo.EnableNfcActive + = ( 0 == Hal4Ctxt->psADDCtxtInfo->sADDCfg.NfcIP_Mode? + Hal4Ctxt->psADDCtxtInfo->sADDCfg.NfcIP_Mode: + NXP_NFCIP_ACTIVE_DEFAULT); + Hal4Ctxt->psADDCtxtInfo->sADDCfg.NfcIP_Mode = (( + Hal4Ctxt->psADDCtxtInfo->sADDCfg.NfcIP_Mode << + (NXP_NFCIP_ACTIVE_DEFAULT * NFCIP_ACTIVE_SHIFT)) + | Hal4Ctxt->psADDCtxtInfo->sADDCfg.NfcIP_Mode); +#endif/*#ifdef UPDATE_NFC_ACTIVE*/ + /* information system_code(Felica) and + AFI(ReaderB) to be populated later */ + + CfgStatus = phHciNfc_Config_Discovery( + (void *)Hal4Ctxt->psHciHandle, + (void *)psHwReference, + &(Hal4Ctxt->psADDCtxtInfo->sADDCfg) + );/*Configure HCI Discovery*/ + break; + case NFC_DISCOVERY_STOP: + break; + /*Restart Discovery wheel*/ + case NFC_DISCOVERY_RESUME: + PHDBG_INFO("Hal4:Call to NFC_DISCOVERY_RESUME"); + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices = 0; + CfgStatus = phHciNfc_Restart_Discovery ( + (void *)Hal4Ctxt->psHciHandle, + (void *)psHwReference, + FALSE + ); + break; + default: + break; + } + /* Change the State of the HAL only if HCI Configure + Returns status as Pending */ + if ( NFCSTATUS_PENDING == CfgStatus ) + { + (void)memcpy((void *) + &(Hal4Ctxt->psADDCtxtInfo->sCurrentPollConfig), + (void *)&(discoveryCfg->PollDevInfo.PollCfgInfo), + sizeof(phHal_sPollDevInfo_t) + ); + PHDBG_INFO("Hal4:Finished copying PollCfgInfo"); + PHDBG_INFO("Hal4:Configure returned NFCSTATUS_PENDING"); + Hal4Ctxt->Hal4NextState = eHal4StateConfiguring; + Hal4Ctxt->sUpperLayerInfo.pConfigCallback + = pConfigCallback; + } + else/*Configure failed.Restore old poll dev info*/ + { + (void)memcpy((void *) + &(Hal4Ctxt->psADDCtxtInfo->sADDCfg.PollDevInfo.PollCfgInfo), + (void *)&(Hal4Ctxt->psADDCtxtInfo->sCurrentPollConfig), + sizeof(phHal_sPollDevInfo_t) + ); + } + } + } + else + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_NOT_INITIALISED); + } + } + return CfgStatus; +} + + +/*Configuration completion handler*/ +void phHal4Nfc_ConfigureComplete(phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo, + uint8_t type + ) +{ + pphHal4Nfc_GenCallback_t pConfigCallback + = Hal4Ctxt->sUpperLayerInfo.pConfigCallback; + pphHal4Nfc_ConnectCallback_t pUpperConnectCb + = Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb; + NFCSTATUS Status = ((phNfc_sCompletionInfo_t *)pInfo)->status; + if((type == NFC_NOTIFY_POLL_ENABLED) ||(type == NFC_NOTIFY_POLL_RESTARTED)) + { + Hal4Ctxt->psADDCtxtInfo->IsPollConfigured = TRUE; + PHDBG_INFO("Hal4:Poll Config Complete"); + } + else + { + Hal4Ctxt->psADDCtxtInfo->IsPollConfigured = FALSE; + PHDBG_WARNING("Hal4:Poll disabled,config success or config error"); + } + if(NULL != Hal4Ctxt->sUpperLayerInfo.pConfigCallback) + { +#ifdef MERGE_SAK_SW2 + if((NFC_UICC_EMULATION == Hal4Ctxt->uConfig.emuConfig.emuType)&& + (FALSE == + Hal4Ctxt->uConfig.emuConfig.config.uiccEmuCfg.enableUicc)) + { + Status = phHciNfc_System_Configure ( + Hal4Ctxt->psHciHandle, + (void *)gpphHal4Nfc_Hwref, + PH_HAL4NFC_TGT_MERGE_ADDRESS, + PH_HAL4NFC_TGT_MERGE_SAK /*config value*/ + ); + } + if(NFCSTATUS_PENDING != Status) + { +#endif/*#ifdef MERGE_SAK_SW2*/ + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + Hal4Ctxt->sUpperLayerInfo.pConfigCallback = NULL; + (*pConfigCallback)( +#ifdef LLCP_DISCON_CHANGES + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCfgDiscCtxt, +#else /* #ifdef LLCP_DISCON_CHANGES */ + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, +#endif /* #ifdef LLCP_DISCON_CHANGES */ + Status + ); +#ifdef MERGE_SAK_SW2 + } +#endif/*#ifdef MERGE_SAK_SW2*/ + } + /**if connect failed and discovery wheel was restarted*/ + else if(Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb) + { + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = NULL; + /*Notify to the upper layer*/ + (*pUpperConnectCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + NFCSTATUS_FAILED + ); + } + else + { + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + /**if disconnect failed and discovery wheel was restarted*/ + if ( NULL != Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb) + { + ((phNfc_sCompletionInfo_t *)pInfo)->status = NFCSTATUS_SUCCESS; + phHal4Nfc_DisconnectComplete(Hal4Ctxt,pInfo); + } + } +} + + +/**Handler for Target discovery completion for all remote device types*/ +void phHal4Nfc_TargetDiscoveryComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + static phHal4Nfc_DiscoveryInfo_t sDiscoveryInfo; + NFCSTATUS status = NFCSTATUS_SUCCESS; + /**SAK byte*/ + uint8_t Sak = 0; + /*Union type to encapsulate and return the discovery info*/ + phHal4Nfc_NotificationInfo_t uNotificationInfo; + /*All the following types will be discovered as type A ,and differentiation + will have to be done within this module based on SAK byte and UID info*/ + phHal_eRemDevType_t aRemoteDevTypes[3] = { + phHal_eISO14443_A_PICC, + phHal_eNfcIP1_Target, + phHal_eMifare_PICC + }; + /*Count is used to add multiple info into remote dvice list for devices that + support multiple protocols*/ + uint8_t Count = 0, + NfcIpDeviceCount = 0;/**status; + /*Update Hal4 state*/ + Hal4Ctxt->Hal4CurrentState = eHal4StateTargetDiscovered; + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + PHDBG_INFO("Hal4:Remotedevice Discovered"); + if(NULL != ((phNfc_sCompletionInfo_t *)pInfo)->info) + { + /*Extract Remote device Info*/ + psRemoteDevInfo = (phHal_sRemoteDevInformation_t *) + ((phNfc_sCompletionInfo_t *)pInfo)->info; + + switch(psRemoteDevInfo->RemDevType) + { + case phHal_eISO14443_A_PICC:/*for TYPE A*/ + { + Sak = psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak; + if((Hal4Ctxt->psADDCtxtInfo->sCurrentPollConfig.EnableIso14443A) + || (TRUE == Hal4Ctxt->psADDCtxtInfo->smx_discovery)) + { + /*Check if Iso is Supported*/ + if(Sak & ISO_14443_BITMASK) + { + Count++; + } + /*Check for Mifare Supported*/ + switch( Sak ) + { + case 0x01: // 1K Classic + case 0x09: // Mini + case 0x08: // 1K + case 0x18: // 4K + case 0x88: // Infineon 1K + case 0x98: // Pro 4K + case 0xB8: // Pro 4K + case 0x28: // 1K emulation + case 0x38: // 4K emulation + aRemoteDevTypes[Count] = phHal_eMifare_PICC; + Count++; + break; + } + if((0 == Sak)&& (0 == Count)) + { + /*Mifare check*/ + if((NXP_UID == + psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Uid[0]) + &&(NXP_MIN_UID_LEN <= + psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.UidLength)) + { + aRemoteDevTypes[Count] = phHal_eMifare_PICC; + Count++; + } + } + // Always add a separate 3A target on a separate + // handle, so the upper layers can connect to it. + aRemoteDevTypes[Count] = phHal_eISO14443_3A_PICC; + Count++; + } + /*Check for P2P target passive*/ + if((Sak & NFCIP_BITMASK) && + (NULL != Hal4Ctxt->sUpperLayerInfo.pP2PNotification)&& + (Hal4Ctxt->psADDCtxtInfo->sADDCfg.NfcIP_Mode + & phHal_ePassive106)) + { + if( Sak == 0x53 // Fudan card incompatible to ISO18092 + && psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA[0] == 0x04 + && psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA[1] == 0x00 + ) + { + aRemoteDevTypes[Count] = phHal_eISO14443_3A_PICC; + Count++; + } + else + { + aRemoteDevTypes[Count] = phHal_eNfcIP1_Target; + Count++; + } + } + }/*case phHal_eISO14443_A_PICC:*/ + break; + case phHal_eNfcIP1_Target:/*P2P target detected*/ + aRemoteDevTypes[Count] = phHal_eNfcIP1_Target; + Count++; + break; + case phHal_eISO14443_B_PICC: /*TYPE_B*/ +#ifdef TYPE_B + aRemoteDevTypes[Count] = phHal_eISO14443_B_PICC; + Count++; + break; +#endif + case phHal_eFelica_PICC: /*Felica*/ +#ifdef TYPE_FELICA + { + /*nfc_id is used to differentiate between Felica and NfcIp target + discovered in Type F*/ + nfc_id = (((uint16_t)psRemoteDevInfo->RemoteDevInfo.Felica_Info.IDm[0]) + << BYTE_SIZE) | + psRemoteDevInfo->RemoteDevInfo.Felica_Info.IDm[1]; + /*check for NfcIp target*/ + if(NXP_NFCIP_NFCID2_ID == nfc_id) + { + if((NULL != Hal4Ctxt->sUpperLayerInfo.pP2PNotification) + &&((Hal4Ctxt->psADDCtxtInfo->sADDCfg.NfcIP_Mode + & phHal_ePassive212) || + (Hal4Ctxt->psADDCtxtInfo->sADDCfg.NfcIP_Mode + & phHal_ePassive424))) + { + aRemoteDevTypes[Count] = phHal_eNfcIP1_Target; + Count++; + } + } + else/*Felica*/ + { + if(Hal4Ctxt->psADDCtxtInfo->sCurrentPollConfig.EnableFelica212 + || Hal4Ctxt->psADDCtxtInfo->sCurrentPollConfig.EnableFelica424) + { + aRemoteDevTypes[Count] = phHal_eFelica_PICC; + Count++; + } + } + break; + } +#endif + case phHal_eJewel_PICC: /*Jewel*/ +#ifdef TYPE_JEWEL + { + /*Report Jewel tags only if TYPE A is enabled*/ + if(Hal4Ctxt->psADDCtxtInfo->sCurrentPollConfig.EnableIso14443A) + { + aRemoteDevTypes[Count] = phHal_eJewel_PICC; + Count++; + } + break; + } +#endif +#ifdef TYPE_ISO15693 + case phHal_eISO15693_PICC: /*ISO15693*/ + { + if(Hal4Ctxt->psADDCtxtInfo->sCurrentPollConfig.EnableIso15693) + { + aRemoteDevTypes[Count] = phHal_eISO15693_PICC; + Count++; + } + break; + } +#endif /* #ifdef TYPE_ISO15693 */ + /*Types currently not supported*/ + case phHal_eISO14443_BPrime_PICC: + default: + PHDBG_WARNING("Hal4:Notification for Not supported types"); + break; + }/*End of switch*/ + /*Update status code to success if atleast one device info is available*/ + status = (((NFCSTATUS_SUCCESS != status) + && (NFCSTATUS_MULTIPLE_TAGS != status)) + &&(Hal4Ctxt->psADDCtxtInfo->nbr_of_devices != 0))? + NFCSTATUS_SUCCESS:status; + + /*Update status to NFCSTATUS_MULTIPLE_PROTOCOLS if count > 1 ,and this + is first discovery notification from Hci*/ + status = ((NFCSTATUS_SUCCESS == status) + &&(Hal4Ctxt->psADDCtxtInfo->nbr_of_devices == 0) + &&(Count > 1)?NFCSTATUS_MULTIPLE_PROTOCOLS:status); + /*If multiple protocols are supported ,allocate separate remote device + information for each protocol supported*/ + /*Allocate and copy Remote device info into Hal4 Context*/ + while(Count) + { + PHDBG_INFO("Hal4:Count is not zero"); + --Count; + /*Allocate memory for each of Count number of + devices*/ + if(NULL == Hal4Ctxt->rem_dev_list[ + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices]) + { + Hal4Ctxt->rem_dev_list[ + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices] + = (phHal_sRemoteDevInformation_t *) + phOsalNfc_GetMemory( + (uint32_t)( + sizeof(phHal_sRemoteDevInformation_t)) + ); + } + if(NULL == Hal4Ctxt->rem_dev_list[ + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices]) + { + status = PHNFCSTVAL(CID_NFC_HAL, + NFCSTATUS_INSUFFICIENT_RESOURCES); + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0); + break; + } + else + { + (void)memcpy( + (void *)Hal4Ctxt->rem_dev_list[ + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices], + (void *)psRemoteDevInfo, + sizeof(phHal_sRemoteDevInformation_t) + ); + /*Now copy appropriate device type from aRemoteDevTypes array*/ + Hal4Ctxt->rem_dev_list[ + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices]->RemDevType + = aRemoteDevTypes[Count]; + /*Increment number of devices*/ + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices++; + }/*End of else*/ + }/*End of while*/ + + /*If Upper layer is interested only in P2P notifications*/ + if((NULL != Hal4Ctxt->sUpperLayerInfo.pP2PNotification) + &&(((Hal4Ctxt->psADDCtxtInfo->nbr_of_devices == 1) + &&(phHal_eNfcIP1_Target == Hal4Ctxt->rem_dev_list[0]->RemDevType)) + ||(NULL == Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification)) + ) + { + PHDBG_INFO("Hal4:Trying to notify P2P Listener"); + /*NFCSTATUS_SUCCESS or NFCSTATUS_MULTIPLE_PROTOCOLS*/ + if((NFCSTATUS_SUCCESS == status) + ||(NFCSTATUS_MULTIPLE_PROTOCOLS == status)) + { + /*Pick only the P2P target device info from the list*/ + for(Count = Hal4Ctxt->psADDCtxtInfo->nbr_of_devices; + Count > 0;--Count) + { + /*Only one P2P target can be detected in one discovery*/ + if(phHal_eNfcIP1_Target == + Hal4Ctxt->rem_dev_list[Count-1]->RemDevType) + { + if (Count != 1) + { + (void)memcpy( + (void *)Hal4Ctxt->rem_dev_list[0], + (void *)Hal4Ctxt->rem_dev_list[Count-1], + sizeof(phHal_sRemoteDevInformation_t) + ); + } + NfcIpDeviceCount = 1; + break; + } + } + /*If any P2p devices are discovered free other device info*/ + while(Hal4Ctxt->psADDCtxtInfo->nbr_of_devices > NfcIpDeviceCount) + { + phOsalNfc_FreeMemory(Hal4Ctxt->rem_dev_list[ + --Hal4Ctxt->psADDCtxtInfo->nbr_of_devices]); + Hal4Ctxt->rem_dev_list[ + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices] = NULL; + } + /*Issue P2P notification*/ + if(NfcIpDeviceCount == 1) + { + sDiscoveryInfo.NumberOfDevices + = Hal4Ctxt->psADDCtxtInfo->nbr_of_devices; + sDiscoveryInfo.ppRemoteDevInfo = Hal4Ctxt->rem_dev_list; + uNotificationInfo.psDiscoveryInfo = &sDiscoveryInfo; + PHDBG_INFO("Hal4:Calling P2P listener"); + (*Hal4Ctxt->sUpperLayerInfo.pP2PNotification)( + (void *)(Hal4Ctxt->sUpperLayerInfo.P2PDiscoveryCtxt), + NFC_DISCOVERY_NOTIFICATION, + uNotificationInfo, + NFCSTATUS_SUCCESS + ); + } + else/*Restart Discovery wheel*/ + { + PHDBG_INFO("Hal4:No P2P device in list"); + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices = 0; + PHDBG_INFO("Hal4:Restart discovery1"); + status = phHciNfc_Restart_Discovery ( + (void *)Hal4Ctxt->psHciHandle, + (void *)gpphHal4Nfc_Hwref, + FALSE + ); + Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == status? + eHal4StateConfiguring: + Hal4Ctxt->Hal4NextState); + } + } + /*More discovery info available ,get next info from HCI*/ + else if((NFCSTATUS_MULTIPLE_TAGS == status) + &&(Hal4Ctxt->psADDCtxtInfo->nbr_of_devices + < MAX_REMOTE_DEVICES)) + { + status = phHciNfc_Select_Next_Target ( + Hal4Ctxt->psHciHandle, + (void *)gpphHal4Nfc_Hwref + ); + } + else/*Failed discovery ,restart discovery*/ + { + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices = 0; + PHDBG_INFO("Hal4:Restart discovery2"); + status = phHciNfc_Restart_Discovery ( + (void *)Hal4Ctxt->psHciHandle, + (void *)gpphHal4Nfc_Hwref, + FALSE + );/*Restart Discovery wheel*/ + Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == status? + eHal4StateConfiguring: + Hal4Ctxt->Hal4NextState); + } + }/*if((NULL != Hal4Ctxt->sUpperLayerInfo.pP2PNotification)...*/ + /*Notify if Upper layer is interested in tag notifications,also notify + P2p if its in the list with other tags*/ + else if(NULL != Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification) + { + PHDBG_INFO("Hal4:Trying to notify Tag notification"); + /*Multiple tags in field, get discovery info a second time for the + other devices*/ + if((NFCSTATUS_MULTIPLE_TAGS == status) + &&(Hal4Ctxt->psADDCtxtInfo->nbr_of_devices < MAX_REMOTE_DEVICES)) + { + PHDBG_INFO("Hal4:select next target1"); + status = phHciNfc_Select_Next_Target ( + Hal4Ctxt->psHciHandle, + (void *)gpphHal4Nfc_Hwref + ); + } + /*Single tag multiple protocols scenario,Notify Multiple Protocols + status to upper layer*/ + else if(status == NFCSTATUS_MULTIPLE_PROTOCOLS) + { + PHDBG_INFO("Hal4:Multiple Tags or protocols"); + sDiscoveryInfo.NumberOfDevices + = Hal4Ctxt->psADDCtxtInfo->nbr_of_devices; + sDiscoveryInfo.ppRemoteDevInfo = Hal4Ctxt->rem_dev_list; + uNotificationInfo.psDiscoveryInfo = &sDiscoveryInfo; + (*Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification)( + (void *)(Hal4Ctxt->sUpperLayerInfo.DiscoveryCtxt), + NFC_DISCOVERY_NOTIFICATION, + uNotificationInfo, + status + ); + } + else /*NFCSTATUS_SUCCESS*/ + { + if(((Hal4Ctxt->psADDCtxtInfo->nbr_of_devices == 1) + &&(phHal_eNfcIP1_Target + == Hal4Ctxt->rem_dev_list[0]->RemDevType)) + ||(NFCSTATUS_SUCCESS != status) + || (Hal4Ctxt->psADDCtxtInfo->nbr_of_devices == 0) + )/*device detected but upper layer is not interested + in the type(P2P) or activate next failed*/ + { + while(Hal4Ctxt->psADDCtxtInfo->nbr_of_devices > 0) + { + phOsalNfc_FreeMemory(Hal4Ctxt->rem_dev_list[ + --Hal4Ctxt->psADDCtxtInfo->nbr_of_devices]); + Hal4Ctxt->rem_dev_list[ + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices] = NULL; + } + PHDBG_INFO("Hal4:Restart discovery3"); + status = phHciNfc_Restart_Discovery ( + (void *)Hal4Ctxt->psHciHandle, + (void *)gpphHal4Nfc_Hwref, + FALSE + );/*Restart Discovery wheel*/ + Hal4Ctxt->Hal4NextState = ( + NFCSTATUS_PENDING == status?eHal4StateConfiguring + :Hal4Ctxt->Hal4NextState + ); + } + else/*All remote device info available.Notify to upper layer*/ + { + /*Update status for MULTIPLE_TAGS here*/ + status = (Hal4Ctxt->psADDCtxtInfo->nbr_of_devices > 1? + NFCSTATUS_MULTIPLE_TAGS:status); + /*If listener is registered ,call it*/ + sDiscoveryInfo.NumberOfDevices + = Hal4Ctxt->psADDCtxtInfo->nbr_of_devices; + sDiscoveryInfo.ppRemoteDevInfo + = Hal4Ctxt->rem_dev_list; + uNotificationInfo.psDiscoveryInfo = &sDiscoveryInfo; + PHDBG_INFO("Hal4:Calling Discovery Handler1"); + (*Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification)( + (void *)(Hal4Ctxt->sUpperLayerInfo.DiscoveryCtxt), + NFC_DISCOVERY_NOTIFICATION, + uNotificationInfo, + status + ); + } + } + } /*else if(NULL != Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification)*/ + else/*listener not registered ,Restart Discovery wheel*/ + { + PHDBG_INFO("Hal4:No listener registered.Ignoring Discovery \ + Notification"); + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices = 0; + PHDBG_INFO("Hal4:Restart discovery4"); + status = phHciNfc_Restart_Discovery ( + (void *)Hal4Ctxt->psHciHandle, + (void *)gpphHal4Nfc_Hwref, + FALSE + ); + Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == status? + eHal4StateConfiguring: + Hal4Ctxt->Hal4NextState); + } + }/*if(NULL != ((phNfc_sCompletionInfo_t *)pInfo)->info)*/ + else/*NULL info received*/ + { + sDiscoveryInfo.NumberOfDevices + = Hal4Ctxt->psADDCtxtInfo->nbr_of_devices; + sDiscoveryInfo.ppRemoteDevInfo = Hal4Ctxt->rem_dev_list; + uNotificationInfo.psDiscoveryInfo = &sDiscoveryInfo; + /*If Discovery info is available from previous notifications try to + notify that to the upper layer*/ + if((NULL != Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification) +#ifdef NFC_RF_NOISE_SW + &&((NFCSTATUS_SUCCESS == status) + || (NFCSTATUS_MULTIPLE_TAGS == status)) +#endif /* #ifdef NFC_RF_NOISE_SW */ + ) + { +#ifndef NFC_RF_NOISE_SW + status = (((NFCSTATUS_SUCCESS != status) + && (NFCSTATUS_MULTIPLE_TAGS != status)) + &&(Hal4Ctxt->psADDCtxtInfo->nbr_of_devices != 0))? + NFCSTATUS_SUCCESS:status; +#endif/*#ifndef NFC_RF_NOISE_SW*/ + PHDBG_INFO("Hal4:Calling Discovery Handler2"); + (*Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification)( + (void *)(Hal4Ctxt->sUpperLayerInfo.DiscoveryCtxt), + NFC_DISCOVERY_NOTIFICATION, + uNotificationInfo, + status + ); + } + else/*Restart Discovery wheel*/ + { + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices = 0; + PHDBG_INFO("Hal4:Restart discovery5"); + status = phHciNfc_Restart_Discovery ( + (void *)Hal4Ctxt->psHciHandle, + (void *)gpphHal4Nfc_Hwref, + FALSE + ); + Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == status? + eHal4StateConfiguring:Hal4Ctxt->Hal4NextState); + } + }/*else*/ + return; +} + + +/**Register Notification handlers*/ +NFCSTATUS phHal4Nfc_RegisterNotification( + phHal_sHwReference_t *psHwReference, + phHal4Nfc_RegisterType_t eRegisterType, + pphHal4Nfc_Notification_t pNotificationHandler, + void *Context + ) +{ + NFCSTATUS RetStatus = NFCSTATUS_SUCCESS; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + if(NULL == pNotificationHandler || NULL == psHwReference) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + RetStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + RetStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_NOT_INITIALISED); + } + else + { + /*Extract context from hardware reference*/ + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context; + switch(eRegisterType) + { + case eRegisterTagDiscovery: + Hal4Ctxt->sUpperLayerInfo.DiscoveryCtxt = Context; + Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification + = pNotificationHandler; /*Register the tag Notification*/ + break; + case eRegisterP2PDiscovery: + Hal4Ctxt->sUpperLayerInfo.P2PDiscoveryCtxt = Context; + Hal4Ctxt->sUpperLayerInfo.pP2PNotification + = pNotificationHandler; /*Register the P2P Notification*/ + break; + case eRegisterHostCardEmulation: + RetStatus = NFCSTATUS_FEATURE_NOT_SUPPORTED; + break; + case eRegisterSecureElement: + Hal4Ctxt->sUpperLayerInfo.EventNotificationCtxt = Context; + Hal4Ctxt->sUpperLayerInfo.pEventNotification + = pNotificationHandler; /*Register the Se Notification*/ + break; + default: + Hal4Ctxt->sUpperLayerInfo.DefaultListenerCtxt = Context; + Hal4Ctxt->sUpperLayerInfo.pDefaultEventHandler + = pNotificationHandler; /*Register the default Notification*/ + break; + } + PHDBG_INFO("Hal4:listener registered"); + } + return RetStatus; +} + + +/**Unregister Notification handlers*/ +NFCSTATUS phHal4Nfc_UnregisterNotification( + phHal_sHwReference_t *psHwReference, + phHal4Nfc_RegisterType_t eRegisterType, + void *Context + ) +{ + NFCSTATUS RetStatus = NFCSTATUS_SUCCESS; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + if(psHwReference == NULL) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + RetStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + RetStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_NOT_INITIALISED); + } + else + { + /*Extract context from hardware reference*/ + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context; + switch(eRegisterType) + { + case eRegisterTagDiscovery: + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = Context; + Hal4Ctxt->sUpperLayerInfo.DiscoveryCtxt = NULL; + /*UnRegister the tag Notification*/ + Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification = NULL; + PHDBG_INFO("Hal4:Tag Discovery Listener Unregistered"); + break; + case eRegisterP2PDiscovery: + Hal4Ctxt->sUpperLayerInfo.P2PDiscoveryCtxt = NULL; + /*UnRegister the p2p Notification*/ + Hal4Ctxt->sUpperLayerInfo.pP2PNotification = NULL; + PHDBG_INFO("Hal4:P2P Discovery Listener Unregistered"); + break; + case eRegisterHostCardEmulation:/*RFU*/ + RetStatus = NFCSTATUS_FEATURE_NOT_SUPPORTED; + break; + /*UnRegister the Se Notification*/ + case eRegisterSecureElement: + Hal4Ctxt->sUpperLayerInfo.EventNotificationCtxt = NULL; + Hal4Ctxt->sUpperLayerInfo.pEventNotification = NULL; + PHDBG_INFO("Hal4:SE Listener Unregistered"); + break; + default: + Hal4Ctxt->sUpperLayerInfo.DefaultListenerCtxt = NULL; + /*UnRegister the default Notification*/ + Hal4Ctxt->sUpperLayerInfo.pDefaultEventHandler = NULL; + PHDBG_INFO("Hal4:Default Listener Unregistered"); + break; + } + } + return RetStatus; +} + + diff --git a/libnfc-nxp/phHal4Nfc_Emulation.c b/libnfc-nxp/phHal4Nfc_Emulation.c new file mode 100644 index 0000000..6bb60e2 --- /dev/null +++ b/libnfc-nxp/phHal4Nfc_Emulation.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ +/*! +* \file phHal4Nfc_Emulation.c +* \brief Hal4 Emulation source. +* +* Project: NFC-FRI 1.1 +* +* $Date: Wed May 26 18:03:59 2010 $ +* $Author: ing07385 $ +* $Revision: 1.35 $ +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +/* ---------------------------Include files ------------------------------------*/ +#include +#include +#include +#include + +/* ------------------------------- Macros ------------------------------------*/ + +/* Note : Macros required and used only in this module to be declared here*/ + + +/* --------------------Structures and enumerations --------------------------*/ + + +/*Event Notification handler for emulation*/ +void phHal4Nfc_HandleEmulationEvent( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + phNfc_sNotificationInfo_t *psNotificationInfo = (phNfc_sNotificationInfo_t *) + pInfo; + phHal4Nfc_NotificationInfo_t uNotificationInfo = {NULL}; + /*Pass on Event notification info from Hci to Upper layer*/ + uNotificationInfo.psEventInfo = psNotificationInfo->info; + if(NULL != Hal4Ctxt->sUpperLayerInfo.pEventNotification) + { + Hal4Ctxt->sUpperLayerInfo.pEventNotification( + Hal4Ctxt->sUpperLayerInfo.EventNotificationCtxt, + psNotificationInfo->type, + uNotificationInfo, + NFCSTATUS_SUCCESS + ); + } + else/*No Event notification handler registered*/ + { + /*Use default handler to notify to the upper layer*/ + if(NULL != Hal4Ctxt->sUpperLayerInfo.pDefaultEventHandler) + { + Hal4Ctxt->sUpperLayerInfo.pDefaultEventHandler( + Hal4Ctxt->sUpperLayerInfo.DefaultListenerCtxt, + psNotificationInfo->type, + uNotificationInfo, + NFCSTATUS_SUCCESS + ); + } + } + return; +} + +/* Switch mode from Virtual to Wired or Vice Versa for SMX. +*/ +NFCSTATUS phHal4Nfc_Switch_SMX_Mode( + phHal_sHwReference_t *psHwReference, + phHal_eSmartMX_Mode_t smx_mode, + pphHal4Nfc_GenCallback_t pSwitchModecb, + void *pContext + ) +{ + NFCSTATUS CfgStatus = NFCSTATUS_PENDING; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + static phHal_sADD_Cfg_t sSmxCfg; + + /*NULL checks*/ + if((NULL == psHwReference) || (NULL == pSwitchModecb)) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + CfgStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_INVALID_PARAMETER); + } + /*Check Initialised state*/ + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + CfgStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_NOT_INITIALISED); + } + else + { + Hal4Ctxt = psHwReference->hal_context; + /*Previous POLL Config has not completed or device is connected, + do not allow poll*/ + if(Hal4Ctxt->Hal4NextState == eHal4StateConfiguring) + { + PHDBG_INFO("Hal4:Configuration in progress.Returning status Busy"); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_BUSY); + } + else if(Hal4Ctxt->Hal4CurrentState >= eHal4StateOpenAndReady) + { + /**If config discovery has not been called prior to this ,allocate + ADD Context here*/ + if (NULL == Hal4Ctxt->psADDCtxtInfo) + { + Hal4Ctxt->psADDCtxtInfo= (pphHal4Nfc_ADDCtxtInfo_t) + phOsalNfc_GetMemory((uint32_t) + (sizeof(phHal4Nfc_ADDCtxtInfo_t))); + if(NULL != Hal4Ctxt->psADDCtxtInfo) + { + (void)memset(Hal4Ctxt->psADDCtxtInfo, + 0,sizeof(phHal4Nfc_ADDCtxtInfo_t)); + } + } + if(NULL == Hal4Ctxt->psADDCtxtInfo) + { + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + /* Switch request to Wired mode */ + if(eSmartMx_Wired == smx_mode) + { + if(Hal4Ctxt->Hal4CurrentState + == eHal4StateTargetConnected) + { + PHDBG_INFO("Hal4:In Connected state.Returning Busy"); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_BUSY); + } + /*It is Mandatory to register a listener before switching + to wired mode*/ + else if(NULL == + Hal4Ctxt->sUpperLayerInfo.pTagDiscoveryNotification) + { + CfgStatus = PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_FAILED); + } + else + { + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices = 0; + Hal4Ctxt->psADDCtxtInfo->smx_discovery = TRUE; + sSmxCfg.PollDevInfo.PollCfgInfo.EnableIso14443A = TRUE; + sSmxCfg.PollDevInfo.PollCfgInfo.DisableCardEmulation = TRUE; + /*Switch mode to wired*/ + CfgStatus = phHciNfc_Switch_SmxMode ( + Hal4Ctxt->psHciHandle, + psHwReference, + smx_mode, + &sSmxCfg + ); + } + } + else + { + Hal4Ctxt->psADDCtxtInfo->smx_discovery = FALSE; + /*Switch mode to virtual or off*/ + CfgStatus = phHciNfc_Switch_SmxMode ( + Hal4Ctxt->psHciHandle, + psHwReference, + smx_mode, + &(Hal4Ctxt->psADDCtxtInfo->sADDCfg) + ); + } + + /* Change the State of the HAL only if Switch mode Returns + Success*/ + if ( NFCSTATUS_PENDING == CfgStatus ) + { + Hal4Ctxt->Hal4NextState = eHal4StateConfiguring; + Hal4Ctxt->sUpperLayerInfo.pConfigCallback + = pSwitchModecb; + } + } + } + else/*Return Status not initialised*/ + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_NOT_INITIALISED); + } + } + return CfgStatus; +} + + + +/* Switch mode for Swp.*/ +NFCSTATUS phHal4Nfc_Switch_Swp_Mode( + phHal_sHwReference_t *psHwReference, + phHal_eSWP_Mode_t swp_mode, + pphHal4Nfc_GenCallback_t pSwitchModecb, + void *pContext + ) +{ + NFCSTATUS CfgStatus = NFCSTATUS_PENDING; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + /*NULL checks*/ + if(NULL == psHwReference + || NULL == pSwitchModecb + ) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + CfgStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_INVALID_PARAMETER); + } + /*Check Initialised state*/ + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + CfgStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_NOT_INITIALISED); + } + else + { + Hal4Ctxt = psHwReference->hal_context; + /*Previous POLL CFG has not completed or device is connected, + do not allow poll*/ + if(Hal4Ctxt->Hal4NextState == eHal4StateConfiguring) + { + PHDBG_INFO("Hal4:Configuration in progress.Returning status Busy"); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_BUSY); + } + else if(Hal4Ctxt->Hal4CurrentState >= eHal4StateOpenAndReady) + { + /**If config discovery has not been called prior to this ,allocate + ADD Context here*/ + if (NULL == Hal4Ctxt->psADDCtxtInfo) + { + Hal4Ctxt->psADDCtxtInfo= (pphHal4Nfc_ADDCtxtInfo_t) + phOsalNfc_GetMemory((uint32_t) + (sizeof(phHal4Nfc_ADDCtxtInfo_t))); + if(NULL != Hal4Ctxt->psADDCtxtInfo) + { + (void)memset(Hal4Ctxt->psADDCtxtInfo, + 0,sizeof(phHal4Nfc_ADDCtxtInfo_t)); + } + } + if(NULL == Hal4Ctxt->psADDCtxtInfo) + { + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + /*Switch mode to On or off*/ + CfgStatus = phHciNfc_Switch_SwpMode( + Hal4Ctxt->psHciHandle, + psHwReference, + swp_mode + ); + + /* Change the State of the HAL only if Switch mode Returns + Success*/ + if ( NFCSTATUS_PENDING == CfgStatus ) + { + Hal4Ctxt->Hal4NextState = eHal4StateConfiguring; + Hal4Ctxt->sUpperLayerInfo.pConfigCallback + = pSwitchModecb; + } + } + } + else/*Return Status not initialised*/ + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + CfgStatus= PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_NOT_INITIALISED); + } + } + return CfgStatus; +} + +#ifdef FULL_HAL4_EMULATION_ENABLE +/* Switch Emulation mode ON or OFF.*/ +NFCSTATUS phHal4Nfc_Host_Emulation_Mode( + phHal_sHwReference_t *psHwReference, + phNfc_eModeType_t eModeType, + pphHal4Nfc_GenCallback_t pEmulationModecb, + void *pContext + ) +{ + NFCSTATUS RetStatus = NFCSTATUS_PENDING; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + /*NULL checks*/ + if(NULL == psHwReference + || NULL == pEmulationModecb + ) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + RetStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_INVALID_PARAMETER); + } + /*Check Initialised state*/ + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + RetStatus = PHNFCSTVAL(CID_NFC_HAL , NFCSTATUS_NOT_INITIALISED); + } + else + { + + } + return NFCSTATUS_PENDING; +} +#endif /*FULL_HAL4_EMULATION_ENABLE*/ diff --git a/libnfc-nxp/phHal4Nfc_Internal.h b/libnfc-nxp/phHal4Nfc_Internal.h new file mode 100644 index 0000000..50f4ea1 --- /dev/null +++ b/libnfc-nxp/phHal4Nfc_Internal.h @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/** +* \file phHal4Nfc_Internal.h +* \brief HAL callback Function Prototypes +* +* The HAL4.0 Internal header file +* +* Project: NFC-FRI-1.1 / HAL4.0 +* +* $Date: Mon May 31 11:43:42 2010 $ +* $Author: ing07385 $ +* $Revision: 1.40 $ +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +/*@{*/ +#ifndef PHHAL4NFC_INTERNAL_H +#define PHHAL4NFC_INTERNAL_H +/*@}*/ + +#include + +/** +* \name HAL4 +* +* File: \ref phHal4Nfc_Internal.h +* +*/ + +/*@{*/ +#define PH_HAL4NFC_INTERNAL_FILEREVISION "$Revision: 1.40 $" /**< \ingroup grp_file_attributes */ +#define PH_HAL4NFC_INTERNAL_FILEALIASES "$Aliases: NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* -----------------Include files ---------------------------------------*/ + +/* ---------------- Macros ----------------------------------------------*/ +#define LLCP_DISCON_CHANGES +#define PH_HAL4NFC_TRANSCEIVE_TIMEOUT 30000 /** +#include +#include +#include +#include +#include + +/* ------------------------------- Macros ------------------------------------*/ + +#ifdef _WIN32 +/*Timeout value for recv data timer for P2P.This timer is used for creating + Asynchronous behavior in the scenario where the data is received even before + the upper layer calls the phHal4Nfc_receive().*/ +#define PH_HAL4NFC_RECV_CB_TIMEOUT 100U +#else +#define PH_HAL4NFC_RECV_CB_TIMEOUT 0x00U +#endif/*#ifdef _WIN32*/ + + +/* --------------------Structures and enumerations --------------------------*/ + +/*timer callback to send already buffered receive data to upper layer*/ +static void phHal4Nfc_P2PRecvTimerCb(uint32_t P2PRecvTimerId, void *pContext); + +/* ---------------------- Function definitions ------------------------------*/ + +/* Transfer the user data to another NfcIP device from the host. + * pTransferCallback is called, when all steps in the transfer sequence are + * completed.*/ +NFCSTATUS +phHal4Nfc_Send( + phHal_sHwReference_t *psHwReference, + phHal4Nfc_TransactInfo_t *psTransferInfo, + phNfc_sData_t sTransferData, + pphHal4Nfc_SendCallback_t pSendCallback, + void *pContext + ) +{ + NFCSTATUS RetStatus = NFCSTATUS_PENDING; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + + /*NULL checks*/ + if((NULL == psHwReference) + ||( NULL == pSendCallback ) + || (NULL == psTransferInfo) + ) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_INVALID_PARAMETER); + } + /*Check initialised state*/ + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_INITIALISED); + } + /*Only NfcIp1 Target can call this API*/ + else if(phHal_eNfcIP1_Initiator != psTransferInfo->remotePCDType) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_INVALID_DEVICE); + } + else + { + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context; + if(NULL == Hal4Ctxt->psTrcvCtxtInfo) + { + RetStatus= PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_FAILED); + } + /*Check Activated*/ + else if(NFC_EVT_ACTIVATED == Hal4Ctxt->sTgtConnectInfo.EmulationState) + { + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext; + /*Register upper layer callback*/ + Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb = pSendCallback; + PHDBG_INFO("NfcIP1 Send"); + /*allocate buffer to store senddata received from upper layer*/ + if (NULL == Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData) + { + Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData = (phNfc_sData_t *) + phOsalNfc_GetMemory(sizeof(phNfc_sData_t)); + if(NULL != Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData) + { + (void)memset(Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData, 0, + sizeof(phNfc_sData_t)); + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + = PH_OSALNFC_INVALID_TIMER_ID; + } + } + + Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->buffer + = sTransferData.buffer; + Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length + = sTransferData.length; + + /* If data size is less than Peer's Max frame length, then no chaining is required */ + if(Hal4Ctxt->rem_dev_list[0]->RemoteDevInfo.NfcIP_Info.MaxFrameLength >= sTransferData.length) + { + Hal4Ctxt->psTrcvCtxtInfo-> + XchangeInfo.params.nfc_info.more_info = FALSE; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length + = (uint8_t)sTransferData.length; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_buffer + = sTransferData.buffer; + } + else/*set more_info to true,to indicate more data pending to be sent*/ + { + Hal4Ctxt->psTrcvCtxtInfo-> + XchangeInfo.params.nfc_info.more_info = TRUE; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length + = Hal4Ctxt->rem_dev_list[0]->RemoteDevInfo.NfcIP_Info.MaxFrameLength; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_buffer + = sTransferData.buffer; + Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent + += Hal4Ctxt->rem_dev_list[0]->RemoteDevInfo.NfcIP_Info.MaxFrameLength; + } + PHDBG_INFO("HAL4:Calling Hci_Send_data()"); + RetStatus = phHciNfc_Send_Data ( + Hal4Ctxt->psHciHandle, + psHwReference, + NULL, + &(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo) + ); + /*check return status*/ + if (NFCSTATUS_PENDING == RetStatus) + { + /*Set P2P_Send_In_Progress to defer any disconnect call until + Send complete occurs*/ + Hal4Ctxt->psTrcvCtxtInfo->P2P_Send_In_Progress = TRUE; + Hal4Ctxt->Hal4NextState = eHal4StateTransaction; + /*No of bytes remaining for next send*/ + Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length + -= Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length; + } + } + else/*Deactivated*/ + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_DESELECTED); + } + } + return RetStatus; +} + + +/* Transfer the user data to the another NfcIP device from the host. + * pTransferCallback is called, when all steps in the transfer sequence are + * completed.*/ + +NFCSTATUS +phHal4Nfc_Receive( + phHal_sHwReference_t *psHwReference, + phHal4Nfc_TransactInfo_t *psRecvInfo, + pphHal4Nfc_ReceiveCallback_t pReceiveCallback, + void *pContext + ) +{ + NFCSTATUS RetStatus = NFCSTATUS_PENDING; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + /*NULL checks*/ + if((NULL == psHwReference) + ||( NULL == pReceiveCallback) + ||( NULL == psRecvInfo)) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_INVALID_PARAMETER); + } + /*Check initialised state*/ + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_INITIALISED); + } + else + { + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context; + if(NFC_EVT_ACTIVATED == Hal4Ctxt->sTgtConnectInfo.EmulationState) + { + /*Following condition gets satisfied only on target side,if receive + is not already called*/ + if(NULL == Hal4Ctxt->psTrcvCtxtInfo) + { + Hal4Ctxt->psTrcvCtxtInfo= (pphHal4Nfc_TrcvCtxtInfo_t) + phOsalNfc_GetMemory((uint32_t) + (sizeof(phHal4Nfc_TrcvCtxtInfo_t))); + if(NULL != Hal4Ctxt->psTrcvCtxtInfo) + { + (void)memset(Hal4Ctxt->psTrcvCtxtInfo,0, + sizeof(phHal4Nfc_TrcvCtxtInfo_t)); + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + = PH_OSALNFC_INVALID_TIMER_ID; + Hal4Ctxt->psTrcvCtxtInfo->RecvDataBufferStatus = NFCSTATUS_PENDING; + } + } + if(NULL == Hal4Ctxt->psTrcvCtxtInfo) + { + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0); + RetStatus= PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else /*Store callback & Return status pending*/ + { + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext; + /*Register upper layer callback*/ + Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb = NULL; + Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb = pReceiveCallback; + if(NFCSTATUS_PENDING != + Hal4Ctxt->psTrcvCtxtInfo->RecvDataBufferStatus) + { + /**Create a timer to send received data in the callback*/ + if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + == PH_OSALNFC_INVALID_TIMER_ID) + { + PHDBG_INFO("HAL4: Transaction Timer Create for Receive"); + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + = phOsalNfc_Timer_Create(); + } + if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + == PH_OSALNFC_INVALID_TIMER_ID) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else/*start the timer*/ + { + phOsalNfc_Timer_Start( + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId, + PH_HAL4NFC_RECV_CB_TIMEOUT, + phHal4Nfc_P2PRecvTimerCb, + NULL + ); + } + } + } + } + else/*deactivated*/ + { + RetStatus= PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_DESELECTED); + } + } + return RetStatus; +} + +/*Timer callback for recv data timer for P2P.This timer is used for creating + Asynchronous behavior in the scenario where the data is received even before + the upper layer calls the phHal4Nfc_receive().*/ +static void phHal4Nfc_P2PRecvTimerCb(uint32_t P2PRecvTimerId, void *pContext) +{ + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)( + gpphHal4Nfc_Hwref->hal_context); + pphHal4Nfc_ReceiveCallback_t pUpperRecvCb = NULL; + NFCSTATUS RecvDataBufferStatus = NFCSTATUS_PENDING; + PHNFC_UNUSED_VARIABLE(pContext); + + phOsalNfc_Timer_Stop(P2PRecvTimerId); + phOsalNfc_Timer_Delete(P2PRecvTimerId); + if(NULL != Hal4Ctxt->psTrcvCtxtInfo) + { + RecvDataBufferStatus = Hal4Ctxt->psTrcvCtxtInfo->RecvDataBufferStatus; + Hal4Ctxt->psTrcvCtxtInfo->RecvDataBufferStatus = NFCSTATUS_PENDING; + + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + = PH_OSALNFC_INVALID_TIMER_ID; + /*Update state*/ + Hal4Ctxt->Hal4NextState = (eHal4StateTransaction + == Hal4Ctxt->Hal4NextState?eHal4StateInvalid:Hal4Ctxt->Hal4NextState); + /*Provide address of received data to upper layer data pointer*/ + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData + = &(Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData); + /*Chk NULL and call recv callback*/ + if(Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb != NULL) + { + pUpperRecvCb = Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb; + Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb = NULL; + (*pUpperRecvCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData, + RecvDataBufferStatus + ); + } + } + return; +} + +/**Send complete handler*/ +void phHal4Nfc_SendCompleteHandler(phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt,void *pInfo) +{ + pphHal4Nfc_SendCallback_t pUpperSendCb = NULL; + pphHal4Nfc_TransceiveCallback_t pUpperTrcvCb = NULL; + NFCSTATUS SendStatus = ((phNfc_sCompletionInfo_t *)pInfo)->status; + pphHal4Nfc_DiscntCallback_t pUpperDisconnectCb = NULL; + Hal4Ctxt->psTrcvCtxtInfo->P2P_Send_In_Progress = FALSE; + /*Send status Success or Pending disconnect in HAl4*/ + if((SendStatus != NFCSTATUS_SUCCESS) + ||(NFC_INVALID_RELEASE_TYPE != Hal4Ctxt->sTgtConnectInfo.ReleaseType)) + { + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + /*Update Status*/ + SendStatus = (NFCSTATUS)(NFC_INVALID_RELEASE_TYPE != + Hal4Ctxt->sTgtConnectInfo.ReleaseType?NFCSTATUS_RELEASED:SendStatus); + /*Callback For Target Send*/ + if(NULL != Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb) + { + pUpperSendCb = Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb; + Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb = NULL; + (*pUpperSendCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + SendStatus + ); + } + else/*Callback For Initiator Send*/ + { + if(NULL != Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb) + { + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length = 0; + pUpperTrcvCb = Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb; + Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb = NULL; + (*pUpperTrcvCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData, + SendStatus + ); + } + } + /*Issue Pending disconnect from HAl4*/ + if(NFC_INVALID_RELEASE_TYPE != Hal4Ctxt->sTgtConnectInfo.ReleaseType) + { + SendStatus = phHal4Nfc_Disconnect_Execute(gpphHal4Nfc_Hwref); + if((NFCSTATUS_PENDING != SendStatus) && + (NULL != Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb)) + { + pUpperDisconnectCb = + Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb; + Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb = NULL; + (*pUpperDisconnectCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerDisconnectCtxt, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + SendStatus + );/*Notify disconnect failed to upper layer*/ + } + } + } + else + { + /*More info remaining in send buffer.continue with sending remaining + bytes*/ + if(Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length + > Hal4Ctxt->rem_dev_list[0]->RemoteDevInfo.NfcIP_Info.MaxFrameLength) + { + /*Set more info*/ + Hal4Ctxt->psTrcvCtxtInfo-> + XchangeInfo.params.nfc_info.more_info = TRUE; + /*copy to tx_buffer ,remaining bytes.NumberOfBytesSent is the + number of bytes already sent from current send buffer.*/ + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_buffer + = (Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->buffer + + Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent); + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length + = Hal4Ctxt->rem_dev_list[0]->RemoteDevInfo.NfcIP_Info.MaxFrameLength; + Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent + += Hal4Ctxt->rem_dev_list[0]->RemoteDevInfo.NfcIP_Info.MaxFrameLength; + Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length + -= Hal4Ctxt->rem_dev_list[0]->RemoteDevInfo.NfcIP_Info.MaxFrameLength; + PHDBG_INFO("Hal4:Calling Hci_senddata() from sendcompletehandler1"); + SendStatus = phHciNfc_Send_Data ( + Hal4Ctxt->psHciHandle, + gpphHal4Nfc_Hwref, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + &(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo) + ); + if(NFCSTATUS_PENDING == SendStatus) + { + Hal4Ctxt->psTrcvCtxtInfo->P2P_Send_In_Progress = TRUE; + } + } + /*Remaining bytes is less than PH_HAL4NFC_MAX_SEND_LEN*/ + else if(Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length > 0) + { + Hal4Ctxt->psTrcvCtxtInfo-> + XchangeInfo.params.nfc_info.more_info = FALSE; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length + = (uint8_t)Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_buffer + = (Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->buffer + + Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent); + Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent = 0; + /*No of bytes remaining for next send*/ + Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length = 0; + PHDBG_INFO("Hal4:Calling Hci_senddata() from sendcompletehandler2"); + SendStatus = phHciNfc_Send_Data ( + Hal4Ctxt->psHciHandle, + gpphHal4Nfc_Hwref, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + &(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo) + ); + } + else/*No more Bytes left.Send complete*/ + { + Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent = 0; + /*Callback For Target Send*/ + if(NULL != Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb) + { + pUpperSendCb = Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb; + Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb = NULL; + (*pUpperSendCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + SendStatus + ); + } + else + { + /**Start timer to keep track of transceive timeout*/ +#ifdef TRANSACTION_TIMER + phOsalNfc_Timer_Start( + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId, + PH_HAL4NFC_TRANSCEIVE_TIMEOUT, + phHal4Nfc_TrcvTimeoutHandler + ); +#endif /*TRANSACTION_TIMER*/ + } + } + } + return; +} + +/**Receive complete handler*/ +void phHal4Nfc_RecvCompleteHandler(phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt,void *pInfo) +{ + pphHal4Nfc_ReceiveCallback_t pUpperRecvCb = NULL; + pphHal4Nfc_TransceiveCallback_t pUpperTrcvCb = NULL; + NFCSTATUS RecvStatus = ((phNfc_sTransactionInfo_t *)pInfo)->status; + /*allocate TrcvContext if not already allocated.Required since + Receive complete can occur before any other send /receive calls.*/ + if(NULL == Hal4Ctxt->psTrcvCtxtInfo) + { + Hal4Ctxt->psTrcvCtxtInfo= (pphHal4Nfc_TrcvCtxtInfo_t) + phOsalNfc_GetMemory((uint32_t) + (sizeof(phHal4Nfc_TrcvCtxtInfo_t))); + if(NULL != Hal4Ctxt->psTrcvCtxtInfo) + { + (void)memset(Hal4Ctxt->psTrcvCtxtInfo,0, + sizeof(phHal4Nfc_TrcvCtxtInfo_t)); + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + = PH_OSALNFC_INVALID_TIMER_ID; + Hal4Ctxt->psTrcvCtxtInfo->RecvDataBufferStatus + = NFCSTATUS_PENDING; + } + } + if(NULL == Hal4Ctxt->psTrcvCtxtInfo) + { + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0); + RecvStatus = PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + /*Allocate 4K buffer to copy the received data into*/ + if(NULL == Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer) + { + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer + = (uint8_t *)phOsalNfc_GetMemory( + PH_HAL4NFC_MAX_RECEIVE_BUFFER + ); + if(NULL == Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer) + { + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, + 0); + RecvStatus = NFCSTATUS_INSUFFICIENT_RESOURCES; + } + else/*memset*/ + { + (void)memset( + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer, + 0, + PH_HAL4NFC_MAX_RECEIVE_BUFFER + ); + } + } + + if(RecvStatus != NFCSTATUS_INSUFFICIENT_RESOURCES) + { + /*Copy the data*/ + (void)memcpy( + (Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer + + Hal4Ctxt->psTrcvCtxtInfo->P2PRecvLength), + ((phNfc_sTransactionInfo_t *)pInfo)->buffer, + ((phNfc_sTransactionInfo_t *)pInfo)->length + ); + /*Update P2PRecvLength,this also acts as the offset to append more + received bytes*/ + Hal4Ctxt->psTrcvCtxtInfo->P2PRecvLength + += ((phNfc_sTransactionInfo_t *)pInfo)->length; + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length + = Hal4Ctxt->psTrcvCtxtInfo->P2PRecvLength; + } + + if(RecvStatus != NFCSTATUS_MORE_INFORMATION) + { + Hal4Ctxt->psTrcvCtxtInfo->P2PRecvLength = 0; + Hal4Ctxt->Hal4NextState = (eHal4StateTransaction + == Hal4Ctxt->Hal4NextState?eHal4StateInvalid:Hal4Ctxt->Hal4NextState); + if(NFCSTATUS_PENDING == Hal4Ctxt->psTrcvCtxtInfo->RecvDataBufferStatus) + { + /*Initiator case*/ + if(NULL != Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb) + { + RecvStatus =(NFCSTATUS_RF_TIMEOUT == RecvStatus? + NFCSTATUS_DESELECTED:RecvStatus); + pUpperTrcvCb = Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb; + Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb = NULL; + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData + = &(Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData); + (*pUpperTrcvCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData, + RecvStatus + ); + } + /*P2P target*/ + else if(NULL != Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb) + { + pUpperRecvCb = Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb; + Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb = NULL; + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData + = &(Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData); + (*pUpperRecvCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData, + RecvStatus + ); + } + else + { + /*Receive data buffer is complete with data & P2P receive has + not yet been called*/ + Hal4Ctxt->psTrcvCtxtInfo->RecvDataBufferStatus + = NFCSTATUS_SUCCESS; + } + } + } + } + return; +} + +/*Activation complete handler*/ +void phHal4Nfc_P2PActivateComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + phHal_sEventInfo_t *psEventInfo = (phHal_sEventInfo_t *)pInfo; + NFCSTATUS Status = NFCSTATUS_SUCCESS; + static phHal4Nfc_DiscoveryInfo_t sDiscoveryInfo; + /*Copy notification info to provide to upper layer*/ + phHal4Nfc_NotificationInfo_t uNotificationInfo = {&sDiscoveryInfo}; + Hal4Ctxt->sTgtConnectInfo.EmulationState = NFC_EVT_ACTIVATED; + /*if P2p notification is registered*/ + if( NULL != Hal4Ctxt->sUpperLayerInfo.pP2PNotification) + { + /*Allocate remote device Info for P2P target*/ + uNotificationInfo.psDiscoveryInfo->NumberOfDevices = 1; + if(NULL == Hal4Ctxt->rem_dev_list[0]) + { + Hal4Ctxt->rem_dev_list[0] + = (phHal_sRemoteDevInformation_t *) + phOsalNfc_GetMemory( + sizeof(phHal_sRemoteDevInformation_t) + ); + } + if(NULL == Hal4Ctxt->rem_dev_list[0]) + { + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0); + Status = PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + (void)memset((void *)Hal4Ctxt->rem_dev_list[0], + 0,sizeof(phHal_sRemoteDevInformation_t)); + /*Copy device info*/ + (void)memcpy(Hal4Ctxt->rem_dev_list[0], + psEventInfo->eventInfo.pRemoteDevInfo, + sizeof(phHal_sRemoteDevInformation_t) + ); + /*Allocate Trcv context info*/ + if(NULL == Hal4Ctxt->psTrcvCtxtInfo) + { + Hal4Ctxt->psTrcvCtxtInfo= (pphHal4Nfc_TrcvCtxtInfo_t) + phOsalNfc_GetMemory((uint32_t) + (sizeof(phHal4Nfc_TrcvCtxtInfo_t))); + if(NULL != Hal4Ctxt->psTrcvCtxtInfo) + { + (void)memset(Hal4Ctxt->psTrcvCtxtInfo,0, + sizeof(phHal4Nfc_TrcvCtxtInfo_t)); + Hal4Ctxt->psTrcvCtxtInfo->RecvDataBufferStatus + = NFCSTATUS_PENDING; + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + = PH_OSALNFC_INVALID_TIMER_ID; + } + } + if(NULL == Hal4Ctxt->psTrcvCtxtInfo) + { + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0); + Status= PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + /*Update state*/ + Hal4Ctxt->Hal4CurrentState = eHal4StateEmulation; + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + uNotificationInfo.psDiscoveryInfo->ppRemoteDevInfo + = Hal4Ctxt->rem_dev_list; + /*set session Opened ,this will keep track of whether the session + is alive.will be reset if a Event DEACTIVATED is received*/ + Hal4Ctxt->rem_dev_list[0]->SessionOpened = TRUE; + (*Hal4Ctxt->sUpperLayerInfo.pP2PNotification)( + Hal4Ctxt->sUpperLayerInfo.P2PDiscoveryCtxt, + NFC_DISCOVERY_NOTIFICATION, + uNotificationInfo, + Status + ); + } + } + } + return; +} + +/*Deactivation complete handler*/ +void phHal4Nfc_HandleP2PDeActivate( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + pphHal4Nfc_ReceiveCallback_t pUpperRecvCb = NULL; + pphHal4Nfc_SendCallback_t pUpperSendCb = NULL; + phHal4Nfc_NotificationInfo_t uNotificationInfo; + uNotificationInfo.psEventInfo = (phHal_sEventInfo_t *)pInfo; + /*session is closed*/ + if(NULL != Hal4Ctxt->rem_dev_list[0]) + { + Hal4Ctxt->rem_dev_list[0]->SessionOpened = FALSE; + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices = 0; + } + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice = NULL; + /*Update state*/ + Hal4Ctxt->Hal4CurrentState = eHal4StateOpenAndReady; + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + Hal4Ctxt->sTgtConnectInfo.EmulationState = NFC_EVT_DEACTIVATED; + /*If Trcv ctxt info is allocated ,free it here*/ + if(NULL != Hal4Ctxt->psTrcvCtxtInfo) + { + if(PH_OSALNFC_INVALID_TIMER_ID != + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId) + { + phOsalNfc_Timer_Stop(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId); + phOsalNfc_Timer_Delete(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId); + } + pUpperRecvCb = Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb; + pUpperSendCb = Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb; + /*Free Hal4 resources used by Target*/ + if (NULL != Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer) + { + phOsalNfc_FreeMemory(Hal4Ctxt->psTrcvCtxtInfo-> + sLowerRecvData.buffer); + } + if((NULL == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice) + && (NULL != Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData)) + { + phOsalNfc_FreeMemory(Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData); + } + phOsalNfc_FreeMemory(Hal4Ctxt->psTrcvCtxtInfo); + Hal4Ctxt->psTrcvCtxtInfo = NULL; + } + /*if recv callback is pending*/ + if(NULL != pUpperRecvCb) + { + (*pUpperRecvCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + NULL, + NFCSTATUS_DESELECTED + ); + } + /*if send callback is pending*/ + else if(NULL != pUpperSendCb) + { + (*pUpperSendCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + NFCSTATUS_DESELECTED + ); + } + /*if pP2PNotification is registered*/ + else if(NULL != Hal4Ctxt->sUpperLayerInfo.pP2PNotification) + { + (*Hal4Ctxt->sUpperLayerInfo.pP2PNotification)( + Hal4Ctxt->sUpperLayerInfo.P2PDiscoveryCtxt, + NFC_EVENT_NOTIFICATION, + uNotificationInfo, + NFCSTATUS_DESELECTED + ); + } + else/*Call Default event handler*/ + { + if(NULL != Hal4Ctxt->sUpperLayerInfo.pDefaultEventHandler) + { + Hal4Ctxt->sUpperLayerInfo.pDefaultEventHandler( + Hal4Ctxt->sUpperLayerInfo.DefaultListenerCtxt, + NFC_EVENT_NOTIFICATION, + uNotificationInfo, + NFCSTATUS_DESELECTED + ); + } + } +} diff --git a/libnfc-nxp/phHal4Nfc_Reader.c b/libnfc-nxp/phHal4Nfc_Reader.c new file mode 100644 index 0000000..526d0fc --- /dev/null +++ b/libnfc-nxp/phHal4Nfc_Reader.c @@ -0,0 +1,1411 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ +/*! +* \file phHal4Nfc_Reader.c +* \brief Hal4Nfc Reader source. +* +* Project: NFC-FRI 1.1 +* +* $Date: Mon May 31 11:43:43 2010 $ +* $Author: ing07385 $ +* $Revision: 1.120 $ +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +/* ---------------------------Include files ------------------------------------*/ +#include +#include +#include +#include +#include +#include + + +/* ------------------------------- Macros ------------------------------------*/ +#define PH_HAL4NFC_CMD_LENGTH PHHAL_MAX_DATASIZE+12/**< Cmd length used + for Transceive*/ +#define PH_HAL4NFC_MAX_TRCV_LEN 4096 /**hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_INITIALISED); + } + else if ((psRemoteDevInfo == + ((phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context)-> + sTgtConnectInfo.psConnectedDevice) + &&((phHal_eNfcIP1_Target == psRemoteDevInfo->RemDevType) + ||(phHal_eJewel_PICC == psRemoteDevInfo->RemDevType))) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + /*Get Hal ctxt from hardware reference*/ + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context; + /*Register upper layer context*/ + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext; + /*Register upper layer callback*/ + Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = pNotifyConnectCb; + /*Allow Connect only if no other remote device is connected*/ + if((eHal4StateTargetDiscovered == Hal4Ctxt->Hal4CurrentState) + && (NULL == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice)) + { + RemoteDevCount = Hal4Ctxt->psADDCtxtInfo->nbr_of_devices; + while(0 != RemoteDevCount) + { + RemoteDevCount--; + /*Check if handle provided by upper layer matches with any + remote device in the list*/ + if(psRemoteDevInfo + == (Hal4Ctxt->rem_dev_list[RemoteDevCount])) + { + + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice + = Hal4Ctxt->rem_dev_list[RemoteDevCount]; + break; + } + }/*End of while*/ + + if(NULL == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice) + { + /*No matching device handle in list*/ + RetStatus = PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INVALID_REMOTE_DEVICE); + } + else + { + MemCmpRet = phOsalNfc_MemCompare( + (void *)&(psRemoteDevInfo->RemoteDevInfo), + (void *)&(Hal4Ctxt->rem_dev_list[Hal4Ctxt + ->psADDCtxtInfo->nbr_of_devices - 1]->RemoteDevInfo), + sizeof(phHal_uRemoteDevInfo_t)); + + /*If device is already selected issue connect from here*/ + if(0 == MemCmpRet) + { + RetStatus = phHciNfc_Connect(Hal4Ctxt->psHciHandle, + (void *)psHwReference, + Hal4Ctxt->rem_dev_list[RemoteDevCount]); + if(NFCSTATUS_PENDING == RetStatus) + { + Hal4Ctxt->Hal4NextState = eHal4StateTargetConnected; + } + + } + else/*Select the matching device to connect to*/ + { + RetStatus = phHciNfc_Reactivate ( + Hal4Ctxt->psHciHandle, + (void *)psHwReference, + Hal4Ctxt->rem_dev_list[RemoteDevCount] + ); + Hal4Ctxt->Hal4NextState = eHal4StateTargetActivate; + } + if(NFCSTATUS_PENDING != RetStatus) + { + /*Rollback state*/ + Hal4Ctxt->Hal4CurrentState = eHal4StateOpenAndReady; + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice = NULL; + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = NULL; + Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = NULL; + } + } + } + /*Issue Reconnect*/ + else if(psRemoteDevInfo == + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice) + { + RetStatus = phHciNfc_Reactivate ( + Hal4Ctxt->psHciHandle, + (void *)psHwReference, + psRemoteDevInfo + ); + Hal4Ctxt->Hal4NextState = eHal4StateTargetActivate; + } +#ifdef RECONNECT_SUPPORT + else if (psRemoteDevInfo != + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice) + { + phHal_sRemoteDevInformation_t *ps_store_connected_device = + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice; + + RemoteDevCount = Hal4Ctxt->psADDCtxtInfo->nbr_of_devices; + + while (0 != RemoteDevCount) + { + RemoteDevCount--; + /*Check if handle provided by upper layer matches with any + remote device in the list*/ + if(psRemoteDevInfo == (Hal4Ctxt->rem_dev_list[RemoteDevCount])) + { + break; + } + }/*End of while*/ + + if (ps_store_connected_device == + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice) + { + RetStatus = phHciNfc_Reactivate (Hal4Ctxt->psHciHandle, + (void *)psHwReference, + psRemoteDevInfo); + + if (NFCSTATUS_PENDING == RetStatus) + { + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice = + Hal4Ctxt->rem_dev_list[RemoteDevCount]; + Hal4Ctxt->Hal4NextState = eHal4StateTargetActivate; + } + } + } +#endif /* #ifdef RECONNECT_SUPPORT */ + else if(NULL == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice) + { + /*Wrong state to issue connect*/ + RetStatus = PHNFCSTVAL(CID_NFC_HAL, + NFCSTATUS_INVALID_REMOTE_DEVICE); + } + else/*No Target or already connected to device*/ + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_FAILED); + } + + } + if(NFCSTATUS_PENDING != RetStatus) + { + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = NULL; + Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = NULL; + } + return RetStatus; +} + +/*For Ordering Transceive Info for ISO_3A type tags*/ +static void phHal4Nfc_Iso_3A_Transceive( + phHal_sTransceiveInfo_t *psTransceiveInfo, + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt + ) +{ + uint16_t i; + uint16_t counter= 0; + /* Mifare UL, Keep MIFARE RAW command as it is */ + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.cmd_type + = (uint8_t)psTransceiveInfo->cmd.MfCmd; + /* Set flags for Select Sector */ + if (psTransceiveInfo->sSendData.buffer[0] != phHal_eMifareWrite4) + { + if (Hal4Ctxt->SelectSectorFlag == PH_HAL4NFC_FLAG_0) + { + /* First Select Sector command */ + if ((psTransceiveInfo->sSendData.buffer[1] == PH_HAL4NFC_SEL_SECTOR1_BYTE0) && + (psTransceiveInfo->sSendData.buffer[2] == PH_HAL4NFC_SEL_SECTOR1_BYTE1)) + { + Hal4Ctxt->SelectSectorFlag++; + PHDBG_INFO("Inside 3ATrancv,first cmd, SelectSectorFlag is 1"); + for (i = 1; i < psTransceiveInfo->sSendData.length; i++) + { + psTransceiveInfo->sSendData.buffer[i - 1] = + psTransceiveInfo->sSendData.buffer[i]; + } + + psTransceiveInfo->sSendData.length--; + } + else + { + PHDBG_INFO("Inside 3ATrancv,first cmd,setting SelectSectorFlag 0"); + Hal4Ctxt->SelectSectorFlag = 0; + } + } + else if (Hal4Ctxt->SelectSectorFlag == PH_HAL4NFC_FLAG_1) + { + if ((psTransceiveInfo->sSendData.buffer[1] < PH_HAL4NFC_SEL_SECTOR2_BYTE0) && + (psTransceiveInfo->sSendData.buffer[2] == PH_HAL4NFC_SEL_SECTOR2_BYTE_RESERVED) && + (psTransceiveInfo->sSendData.buffer[3] == PH_HAL4NFC_SEL_SECTOR2_BYTE_RESERVED) && + (psTransceiveInfo->sSendData.buffer[4] == PH_HAL4NFC_SEL_SECTOR2_BYTE_RESERVED)) + { + Hal4Ctxt->SelectSectorFlag++; + PHDBG_INFO("Inside 3ATrancv,2nd cmd, SelectSectorFlag set to 2"); + for (i = 1; i < psTransceiveInfo->sSendData.length; i++) + { + psTransceiveInfo->sSendData.buffer[i - 1] = + psTransceiveInfo->sSendData.buffer[i]; + } + + psTransceiveInfo->sSendData.length--; + } + else + { + PHDBG_INFO("Inside 3ATrancv,2nd cmd, SelectSectorFlag set to 0"); + Hal4Ctxt->SelectSectorFlag = 0; + } + } + else + { + Hal4Ctxt->SelectSectorFlag = 0; + } + } + else + { + PHDBG_INFO("Inside 3ATrancv,Mifarewrite4"); + /* Convert MIFARE RAW to MIFARE CMD */ + if (psTransceiveInfo->cmd.MfCmd == phHal_eMifareRaw) + { + psTransceiveInfo->cmd.MfCmd = + (phHal_eMifareCmdList_t)psTransceiveInfo->sSendData.buffer[0]; + + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.cmd_type = + (uint8_t)psTransceiveInfo->cmd.MfCmd; + + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.addr = + psTransceiveInfo->addr = + psTransceiveInfo->sSendData.buffer[1]; + + for (counter = 2; counter < psTransceiveInfo->sSendData.length; + counter++) + { + psTransceiveInfo->sSendData.buffer[counter - 2] = + psTransceiveInfo->sSendData.buffer[counter]; + } + PHDBG_INFO("Hal4:Inside 3A_Trcv() ,minus length by 4"); + psTransceiveInfo->sSendData.length = + psTransceiveInfo->sSendData.length - 4; + } + else + { + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.cmd_type + = (uint8_t)psTransceiveInfo->cmd.MfCmd; + } + } + return; +} + +/*For Ordering Transceive Info for Mifare tags*/ +static void phHal4Nfc_MifareTransceive( + phHal_sTransceiveInfo_t *psTransceiveInfo, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt + ) +{ + uint16_t counter; + if ( +#ifndef DISABLE_MIFARE_UL_WRITE_WORKAROUND + phHal_eMifareWrite4 != psTransceiveInfo->sSendData.buffer[0] +#else + 1 +#endif/*#ifndef DISABLE_MIFARE_UL_WRITE_WORKAROUND*/ + ) + + { + /* Mifare UL, Keep MIFARE RAW command as it is */ + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.cmd_type + = (uint8_t)psTransceiveInfo->cmd.MfCmd; + + } + else + { + /* Convert MIFARE RAW to MIFARE CMD */ + if (psTransceiveInfo->cmd.MfCmd == phHal_eMifareRaw) + { + psTransceiveInfo->cmd.MfCmd = + (phHal_eMifareCmdList_t)psTransceiveInfo->sSendData.buffer[0]; + + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.cmd_type = + (uint8_t)psTransceiveInfo->cmd.MfCmd; + + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.addr = + psTransceiveInfo->addr = + psTransceiveInfo->sSendData.buffer[1]; + + for (counter = 2; counter < psTransceiveInfo->sSendData.length; + counter++) + { + psTransceiveInfo->sSendData.buffer[counter - 2] = + psTransceiveInfo->sSendData.buffer[counter]; + } + PHDBG_INFO("Hal4:Inside MifareTrcv() ,minus length by 4"); + psTransceiveInfo->sSendData.length = + psTransceiveInfo->sSendData.length - 4; + + } + else + { + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.cmd_type + = (uint8_t)psTransceiveInfo->cmd.MfCmd; + } + } + return; +} + +/* The phHal4Nfc_Transceive function allows the Initiator to send and receive + * data to and from the Remote Device selected by the caller.*/ +NFCSTATUS phHal4Nfc_Transceive( + phHal_sHwReference_t *psHwReference, + phHal_sTransceiveInfo_t *psTransceiveInfo, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + pphHal4Nfc_TransceiveCallback_t pTrcvCallback, + void *pContext + ) +{ + NFCSTATUS RetStatus = NFCSTATUS_PENDING; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)pContext; + + /*NULL checks*/ + if((NULL == psHwReference) + ||( NULL == pTrcvCallback ) + || (NULL == psRemoteDevInfo) + || (NULL == psTransceiveInfo) + || (NULL == psTransceiveInfo->sRecvData.buffer) + || (NULL == psTransceiveInfo->sSendData.buffer) + ) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_INVALID_PARAMETER); + } +#ifdef HAL_TRCV_LIMIT + else if(PH_HAL4NFC_MAX_TRCV_LEN < psTransceiveInfo->sSendData.length) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_ALLOWED); + } +#endif/*#ifdef HAL_TRCV_LIMIT*/ + /*Check initialised state*/ + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_INITIALISED); + } + else + { + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context; + gpphHal4Nfc_Hwref = (phHal_sHwReference_t *)psHwReference; + if((eHal4StateTargetConnected != Hal4Ctxt->Hal4CurrentState) + ||(eHal4StateInvalid != Hal4Ctxt->Hal4NextState)) + { + /*Hal4 state Busy*/ + RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_BUSY); + PHDBG_INFO("HAL4:Trcv Failed.Returning Busy"); + } + else if(psRemoteDevInfo != Hal4Ctxt->sTgtConnectInfo.psConnectedDevice) + { + /*No such Target connected*/ + RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_INVALID_REMOTE_DEVICE); + } + else + { + /*allocate Trcv context*/ + if(NULL == Hal4Ctxt->psTrcvCtxtInfo) + { + Hal4Ctxt->psTrcvCtxtInfo= (pphHal4Nfc_TrcvCtxtInfo_t) + phOsalNfc_GetMemory((uint32_t)(sizeof(phHal4Nfc_TrcvCtxtInfo_t))); + if(NULL != Hal4Ctxt->psTrcvCtxtInfo) + { + (void)memset(Hal4Ctxt->psTrcvCtxtInfo,0, + sizeof(phHal4Nfc_TrcvCtxtInfo_t)); + Hal4Ctxt->psTrcvCtxtInfo->RecvDataBufferStatus + = NFCSTATUS_PENDING; + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + = PH_OSALNFC_INVALID_TIMER_ID; + } + } + if(NULL == Hal4Ctxt->psTrcvCtxtInfo) + { + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0); + RetStatus= PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + /*Process transceive based on Remote device type*/ + switch(Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemDevType) + { + case phHal_eISO14443_3A_PICC: + phHal4Nfc_Iso_3A_Transceive( + psTransceiveInfo, + Hal4Ctxt + ); + break; + case phHal_eMifare_PICC: + PHDBG_INFO("Mifare Cmd received"); + phHal4Nfc_MifareTransceive( + psTransceiveInfo, + psRemoteDevInfo, + Hal4Ctxt + ); + +#if 0 + Hal4Ctxt->psTrcvCtxtInfo-> + XchangeInfo.params.tag_info.cmd_type + = (uint8_t)psTransceiveInfo->cmd.MfCmd; +#endif + break; + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_B_PICC: + PHDBG_INFO("ISO14443 Cmd received"); + Hal4Ctxt->psTrcvCtxtInfo-> + XchangeInfo.params.tag_info.cmd_type + = (uint8_t)psTransceiveInfo->cmd.Iso144434Cmd; + break; + case phHal_eISO15693_PICC: + PHDBG_INFO("ISO15693 Cmd received"); + Hal4Ctxt->psTrcvCtxtInfo-> + XchangeInfo.params.tag_info.cmd_type + = (uint8_t)psTransceiveInfo->cmd.Iso15693Cmd; + break; + case phHal_eNfcIP1_Target: + { + PHDBG_INFO("NfcIP1 Transceive"); + Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData + = &(psTransceiveInfo->sSendData); + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData = + &(psTransceiveInfo->sRecvData); + } + break; + case phHal_eFelica_PICC: + PHDBG_INFO("Felica Cmd received"); + Hal4Ctxt->psTrcvCtxtInfo-> + XchangeInfo.params.tag_info.cmd_type + = (uint8_t)psTransceiveInfo->cmd.FelCmd; + break; + case phHal_eJewel_PICC: + PHDBG_INFO("Jewel Cmd received"); + Hal4Ctxt->psTrcvCtxtInfo-> + XchangeInfo.params.tag_info.cmd_type + = (uint8_t)psTransceiveInfo->cmd.JewelCmd; + break; + case phHal_eISO14443_BPrime_PICC: + RetStatus = PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + default: + PHDBG_WARNING("Invalid Device type received"); + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_FAILED); + break; + + } + } + } + /*If status is anything other than NFCSTATUS_PENDING ,an error has + already occured, so dont process any further and return*/ + if(RetStatus == NFCSTATUS_PENDING) + { + if(phHal_eNfcIP1_Target == + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemDevType) + { + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext; + /*Register upper layer callback*/ + Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb = pTrcvCallback; + if(psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.MaxFrameLength + >= psTransceiveInfo->sSendData.length) + { + Hal4Ctxt->psTrcvCtxtInfo-> + XchangeInfo.params.nfc_info.more_info = FALSE; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length + = (uint8_t)psTransceiveInfo->sSendData.length; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_buffer + = psTransceiveInfo->sSendData.buffer; + /*Number of bytes remaining for next send*/ + Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length = 0; + } + else + { + Hal4Ctxt->psTrcvCtxtInfo-> + XchangeInfo.params.nfc_info.more_info = TRUE; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_buffer + = Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->buffer; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length + = psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.MaxFrameLength; +#if 0 + Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->buffer + += psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.MaxFrameLength; +#else + Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent + += psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.MaxFrameLength; +#endif + /*Number of bytes remaining for next send*/ + Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length + -= psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.MaxFrameLength; + } + Hal4Ctxt->Hal4NextState = eHal4StateTransaction; +#ifdef TRANSACTION_TIMER + /**Create a timer to keep track of transceive timeout*/ + if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + == PH_OSALNFC_INVALID_TIMER_ID) + { + PHDBG_INFO("HAL4: Transaction Timer Create for transceive"); + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + = phOsalNfc_Timer_Create(); + } + if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + == PH_OSALNFC_INVALID_TIMER_ID) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else +#endif/*TRANSACTION_TIMER*/ + { + PHDBG_INFO("Hal4:Calling phHciNfc_Send_Data from Hal4_Transceive()"); + RetStatus = phHciNfc_Send_Data ( + Hal4Ctxt->psHciHandle, + psHwReference, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + &(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo) + ); + if(NFCSTATUS_PENDING == RetStatus) + { + Hal4Ctxt->psTrcvCtxtInfo->P2P_Send_In_Progress = TRUE; + } + } + } + else if(psTransceiveInfo->sSendData.length > PH_HAL4NFC_CMD_LENGTH) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_INVALID_PARAMETER); + } + else if((psTransceiveInfo->sSendData.length == 0) + && (Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length != 0)) + { + PHDBG_INFO("Hal4:Read remaining bytes"); + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData + = &(psTransceiveInfo->sRecvData); + /*Number of read bytes left is greater than bytes requested + by upper layer*/ + if(Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length + < Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length) + { + (void)memcpy(Hal4Ctxt->psTrcvCtxtInfo + ->psUpperRecvData->buffer, + (Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer + + Hal4Ctxt->psTrcvCtxtInfo->LowerRecvBufferOffset) + ,Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length); + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length -= + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length; + Hal4Ctxt->psTrcvCtxtInfo->LowerRecvBufferOffset + += Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length; + RetStatus = PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_MORE_INFORMATION); + } + else/*Number of read bytes left is smaller.Copy all bytes + and free Hal's buffer*/ + { + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length + = Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length; + (void)memcpy(Hal4Ctxt->psTrcvCtxtInfo + ->psUpperRecvData + ->buffer, + (Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer + + Hal4Ctxt->psTrcvCtxtInfo->LowerRecvBufferOffset) + ,Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length); + phOsalNfc_FreeMemory(Hal4Ctxt->psTrcvCtxtInfo + ->sLowerRecvData.buffer); + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer = NULL; + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length = 0; + Hal4Ctxt->psTrcvCtxtInfo->LowerRecvBufferOffset = 0; + RetStatus = NFCSTATUS_SUCCESS; + } + } + else/*No more bytes remaining in Hal.Read from device*/ + { + /*Register upper layer context*/ + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext; + /*Register upper layer callback*/ + Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb = pTrcvCallback; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params.tag_info.addr + = psTransceiveInfo->addr; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length + = (uint16_t)psTransceiveInfo->sSendData.length; + Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_buffer + = psTransceiveInfo->sSendData.buffer; + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData + = &(psTransceiveInfo->sRecvData); +#ifdef TRANSACTION_TIMER + /**Create a timer to keep track of transceive timeout*/ + if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + == PH_OSALNFC_INVALID_TIMER_ID) + { + PHDBG_INFO("HAL4: Transaction Timer Create for transceive"); + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + = phOsalNfc_Timer_Create(); + } + if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId + == PH_OSALNFC_INVALID_TIMER_ID) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL , + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else +#endif /*TRANSACTION_TIMER*/ + { + PHDBG_INFO("Calling phHciNfc_Exchange_Data"); + RetStatus = phHciNfc_Exchange_Data( + Hal4Ctxt->psHciHandle, + psHwReference, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + &(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo) + ); + + if(NFCSTATUS_PENDING == RetStatus) + { + Hal4Ctxt->Hal4NextState = eHal4StateTransaction; +#ifdef TRANSACTION_TIMER + /**Start timer to keep track of transceive timeout*/ + phOsalNfc_Timer_Start( + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId, + PH_HAL4NFC_TRANSCEIVE_TIMEOUT, + phHal4Nfc_TrcvTimeoutHandler + ); +#endif/*#ifdef TRANSACTION_TIMER*/ + } + else + { + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + } + } + } + } + } + return RetStatus; +} + +#ifdef TRANSACTION_TIMER +/**Handle transceive timeout*/ +void phHal4Nfc_TrcvTimeoutHandler(uint32_t TrcvTimerId) +{ + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = gpphHal4Nfc_Hwref->hal_context; + pphHal4Nfc_ReceiveCallback_t pUpperRecvCb = NULL; + pphHal4Nfc_TransceiveCallback_t pUpperTrcvCb = NULL; + phOsalNfc_Timer_Stop(TrcvTimerId); + phOsalNfc_Timer_Delete(TrcvTimerId); + Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId = PH_OSALNFC_INVALID_TIMER_ID; + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + /*For a P2P target*/ + if(Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb != NULL) + { + pUpperRecvCb = Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb; + Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb = NULL; + (*pUpperRecvCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + NULL, + NFCSTATUS_RF_TIMEOUT + ); + } + else + { + /*For a P2P Initiator and tags*/ + if(Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb != NULL) + { + pUpperTrcvCb = Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb; + Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb = NULL; + (*pUpperTrcvCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + NULL, + NFCSTATUS_RF_TIMEOUT + ); + } + } +} +#endif /*TRANSACTION_TIMER*/ + + +/**The function allows to disconnect from a specific Remote Device.*/ +NFCSTATUS phHal4Nfc_Disconnect( + phHal_sHwReference_t *psHwReference, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phHal_eReleaseType_t ReleaseType, + pphHal4Nfc_DiscntCallback_t pDscntCallback, + void *pContext + ) +{ + NFCSTATUS RetStatus = NFCSTATUS_PENDING; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + PHDBG_INFO("Hal4:Inside Hal4 disconnect"); + /*NULL checks*/ + if(NULL == psHwReference || NULL == pDscntCallback + || NULL == psRemoteDevInfo) + { + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_INVALID_PARAMETER); + } + /*Check Initialised state*/ + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_INITIALISED); + } + else if(((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + != eHal4StateTargetConnected) + { + PHDBG_INFO("Hal4:Current sate is not connect.Release returning failed"); + RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_FAILED); + } + else + { + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context; + if((Hal4Ctxt->sTgtConnectInfo.psConnectedDevice == NULL) + || (psRemoteDevInfo != Hal4Ctxt->sTgtConnectInfo.psConnectedDevice)) + { + PHDBG_INFO("Hal4:disconnect returning INVALID_REMOTE_DEVICE"); + RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_INVALID_REMOTE_DEVICE); + } + else + { + /*Register upper layer context*/ + Hal4Ctxt->sUpperLayerInfo.psUpperLayerDisconnectCtxt = pContext; + /*Register upper layer callback*/ + Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb = pDscntCallback; + /*Register Release Type*/ + Hal4Ctxt->sTgtConnectInfo.ReleaseType = ReleaseType; + if((eHal4StateTransaction == Hal4Ctxt->Hal4NextState) + &&((phHal_eNfcIP1_Target != psRemoteDevInfo->RemDevType) + ||((NFC_DISCOVERY_CONTINUE != ReleaseType) + &&(NFC_DISCOVERY_RESTART != ReleaseType)))) + { + Hal4Ctxt->sTgtConnectInfo.ReleaseType + = NFC_INVALID_RELEASE_TYPE; + PHDBG_INFO("Hal4:disconnect returning NFCSTATUS_NOT_ALLOWED"); + RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_NOT_ALLOWED); + } + else if((eHal4StateTransaction == Hal4Ctxt->Hal4NextState) + &&(NULL != Hal4Ctxt->psTrcvCtxtInfo) + &&(TRUE == Hal4Ctxt->psTrcvCtxtInfo->P2P_Send_In_Progress)) + { + /*store the hardware reference for executing disconnect later*/ + gpphHal4Nfc_Hwref = psHwReference; + PHDBG_INFO("Hal4:disconnect deferred"); + } + else/*execute disconnect*/ + { + RetStatus = phHal4Nfc_Disconnect_Execute(psHwReference); + } + } + } + return RetStatus; +} + +/**Execute Hal4 Disconnect*/ +NFCSTATUS phHal4Nfc_Disconnect_Execute( + phHal_sHwReference_t *psHwReference + ) +{ + NFCSTATUS RetStatus = NFCSTATUS_PENDING; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = + (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context; + phHal_eSmartMX_Mode_t SmxMode = eSmartMx_Default; + PHDBG_INFO("Hal4:Inside Hal4 disconnect execute"); + switch(Hal4Ctxt->sTgtConnectInfo.ReleaseType) + { + /*Switch mode to Default*/ + case NFC_SMARTMX_RELEASE: + SmxMode = eSmartMx_Default; + RetStatus = phHciNfc_Switch_SmxMode ( + Hal4Ctxt->psHciHandle, + psHwReference, + SmxMode, + &(Hal4Ctxt->psADDCtxtInfo->sADDCfg) + ); + break; + /*Disconnect and continue polling wheel*/ + case NFC_DISCOVERY_CONTINUE: + { + RetStatus = phHciNfc_Disconnect ( + Hal4Ctxt->psHciHandle, + psHwReference, + FALSE + ); + if(NFCSTATUS_PENDING != RetStatus) + { + PHDBG_INFO("Hal4:Hci disconnect failed.Restarting discovery"); + RetStatus = phHciNfc_Restart_Discovery ( + (void *)Hal4Ctxt->psHciHandle, + (void *)gpphHal4Nfc_Hwref, + FALSE + ); + if(NFCSTATUS_PENDING != RetStatus) + { + PHDBG_INFO("Hal4:Hci Restart discovery also failed"); + } + } + break; + } + /*Disconnect and restart polling wheel*/ + case NFC_DISCOVERY_RESTART: + RetStatus = phHciNfc_Disconnect ( + Hal4Ctxt->psHciHandle, + psHwReference, + TRUE + ); + break; + default: + RetStatus = PHNFCSTVAL(CID_NFC_HAL, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + Hal4Ctxt->sTgtConnectInfo.ReleaseType = NFC_INVALID_RELEASE_TYPE; + /*Update or rollback next state*/ + Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == RetStatus? + eHal4StateOpenAndReady:Hal4Ctxt->Hal4NextState); + return RetStatus; +} + +/*The function allows to check for presence in vicinity of connected remote + device.*/ +NFCSTATUS phHal4Nfc_PresenceCheck( + phHal_sHwReference_t *psHwReference, + pphHal4Nfc_GenCallback_t pPresenceChkCb, + void *context + ) +{ + NFCSTATUS RetStatus = NFCSTATUS_FAILED; + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL; + /*NULL checks*/ + if((NULL == pPresenceChkCb) || (NULL == psHwReference)) + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_INVALID_PARAMETER); + } + /*Check Initialised state*/ + else if((NULL == psHwReference->hal_context) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateOpenAndReady) + || (((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4NextState + == eHal4StateClosed)) + { + PHDBG_INFO("HAL4:Context not Open"); + RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_NOT_INITIALISED); + } + /*check connected state and session alive*/ + else if((((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->Hal4CurrentState + < eHal4StateTargetConnected)|| + (NULL == ((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->sTgtConnectInfo.psConnectedDevice)|| + (FALSE == ((phHal4Nfc_Hal4Ctxt_t *) + psHwReference->hal_context)->sTgtConnectInfo. + psConnectedDevice->SessionOpened)) + { + PHDBG_INFO("HAL4:No target connected"); + RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_RELEASED); + } + else + { + Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context; + /*allow only one Presence chk command at any point in time*/ + if (eHal4StatePresenceCheck != Hal4Ctxt->Hal4NextState) + { + /* Check if remote device is felica */ + if (Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemDevType == + phHal_eFelica_PICC) + { + /* If felica PICC then copy existing IDm to compare later, + If IDm will be same then same PICC is present after presence check + else PICC is changed */ + (void) memcpy(Hal4Ctxt->FelicaIDm, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDm, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDmLength); + } + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = context; + Hal4Ctxt->sTgtConnectInfo.pPresenceChkCb = pPresenceChkCb; + RetStatus = phHciNfc_Presence_Check(Hal4Ctxt->psHciHandle, + psHwReference + ); + Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == RetStatus? + eHal4StatePresenceCheck:Hal4Ctxt->Hal4NextState); + } + else/*Ongoing presence chk*/ + { + RetStatus = PHNFCSTVAL(CID_NFC_HAL,NFCSTATUS_BUSY); + } + } + return RetStatus; +} + +void phHal4Nfc_PresenceChkComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + NFCSTATUS RetStatus = ((phNfc_sCompletionInfo_t *)pInfo)->status; + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + /*Notify to upper layer*/ + if(NULL != Hal4Ctxt->sTgtConnectInfo.pPresenceChkCb) + { + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->SessionOpened + =(uint8_t)(NFCSTATUS_SUCCESS == RetStatus?TRUE:FALSE); + /* Check if remote device is felica */ + if (Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemDevType == + phHal_eFelica_PICC) + { + /* Check if IDm received is same as saved */ + if (0 != phOsalNfc_MemCompare(Hal4Ctxt->FelicaIDm, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDm, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDmLength)) + { + RetStatus = NFCSTATUS_FAILED; + + /* Presence check failed so reset remote device information */ + (void) memset(Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDm, + 0, PHHAL_FEL_ID_LEN + 2); + (void) memset(Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.PMm, + 0, PHHAL_FEL_PM_LEN); + } + + /* Cleanup for stored IDm value for using it next time */ + (void) memset(Hal4Ctxt->FelicaIDm, 0, PHHAL_FEL_ID_LEN + 2); + } + + (*Hal4Ctxt->sTgtConnectInfo.pPresenceChkCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + RetStatus + ); + } + return; +} + +/*Callback for reactivate target and to select appropriate target incase + of multiple targets*/ +void phHal4Nfc_ReactivationComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + NFCSTATUS Status = ((phNfc_sCompletionInfo_t *)pInfo)->status; + /*A NFCSTATUS_SUCCESS status returned here means that the correct device + to connect to has now been selected.So issue connect from here to complete + activation*/ + if(NFCSTATUS_SUCCESS == Status) + { + Hal4Ctxt->Hal4NextState = eHal4StateTargetConnected; + Status = phHciNfc_Connect( + Hal4Ctxt->psHciHandle, + gpphHal4Nfc_Hwref, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice + ); + Status = (NFCSTATUS_PENDING == Status)? + NFCSTATUS_PENDING:NFCSTATUS_FAILED; + } + else/*Device unavailable, return error in connect Callback*/ + { + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + if(NULL != Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb) + { + (*Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + Status + ); + } + } + return; +} + +void phHal4Nfc_Felica_RePoll(void *context, + NFCSTATUS status) +{ + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = gpHal4Ctxt; + pphHal4Nfc_ConnectCallback_t pUpperConnectCb + = Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb; + + Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = NULL; + PHDBG_INFO("Hal4:Calling Connect callback"); + + if (pUpperConnectCb != NULL) + { + /*Notify to the upper layer*/ + (*pUpperConnectCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + status + ); + } + + return; +} +void phHal4Nfc_ConnectComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + NFCSTATUS ConnectStatus = ((phNfc_sCompletionInfo_t *)pInfo)->status; + pphHal4Nfc_ConnectCallback_t pUpperConnectCb + = Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb; + /*Flag to decide whether or not upper layer callback has to be called*/ + uint8_t CallConnectCb = TRUE; + uint8_t felicaRePoll = FALSE; + + /*Remote device Connect successful*/ + if((NFCSTATUS_SUCCESS == ConnectStatus) + ||(eHal4StateTargetConnected == Hal4Ctxt->Hal4CurrentState)) + { + phHal_sRemoteDevInformation_t *psRmtTgtConnected = + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice; + PHDBG_INFO("Hal4:Connect status Success"); + Hal4Ctxt->Hal4CurrentState = eHal4StateTargetConnected; + Hal4Ctxt->Hal4NextState = eHal4StateInvalid; + /* Open the Session */ + psRmtTgtConnected->SessionOpened = + (uint8_t)(NFCSTATUS_SUCCESS == ConnectStatus?TRUE:FALSE); + Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = NULL; + if (psRmtTgtConnected->RemDevType == phHal_eFelica_PICC) + { + felicaRePoll = TRUE; + } + } + else/*Remote device Connect failed*/ + { + Hal4Ctxt->Hal4CurrentState = eHal4StateOpenAndReady; + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->SessionOpened = FALSE; + /*For a NfcIp1 target and case where it is not a internal reconnect + from Hal4 ,notify callback to upper layer*/ + if((phHal_eNfcIP1_Target + == Hal4Ctxt->rem_dev_list[0]->RemDevType) + || (NULL != Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb)) + { + Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = NULL; + } + else/*do not notify callback*/ + { + CallConnectCb = FALSE; + } + /*Free the remote device list*/ + do + { + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices--; + if(NULL != Hal4Ctxt->rem_dev_list[ + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices]) + { + phOsalNfc_FreeMemory((void *) + (Hal4Ctxt->rem_dev_list[ + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices])); + Hal4Ctxt->rem_dev_list[ + Hal4Ctxt->psADDCtxtInfo->nbr_of_devices] = NULL; + } + }while(0 < Hal4Ctxt->psADDCtxtInfo->nbr_of_devices); + + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice = NULL; + } + if(TRUE == CallConnectCb) + { + if (felicaRePoll == TRUE) + { + /* Felica repoll through presence check */ + + /* If felica PICC then copy existing IDm to compare later, + If IDm will be same then same PICC is present after presence check + else PICC is changed */ + (void) memcpy(Hal4Ctxt->FelicaIDm, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDm, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemoteDevInfo.Felica_Info.IDmLength); + + gpHal4Ctxt = Hal4Ctxt; + Hal4Ctxt->sTgtConnectInfo.pPresenceChkCb = phHal4Nfc_Felica_RePoll; + ConnectStatus = phHciNfc_Presence_Check(Hal4Ctxt->psHciHandle, + gpphHal4Nfc_Hwref + ); + Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == ConnectStatus? + eHal4StatePresenceCheck:Hal4Ctxt->Hal4NextState); + felicaRePoll = FALSE; + Hal4Ctxt->sTgtConnectInfo.pUpperConnectCb = pUpperConnectCb; + } + else + { + PHDBG_INFO("Hal4:Calling Connect callback"); + /*Notify to the upper layer*/ + (*pUpperConnectCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + ConnectStatus + ); + } + } + else + { + PHDBG_INFO("Hal4:Connect failed ,Restarting discovery"); + /*Restart the Discovery wheel*/ + ConnectStatus = phHciNfc_Restart_Discovery ( + (void *)Hal4Ctxt->psHciHandle, + (void *)gpphHal4Nfc_Hwref, + FALSE + ); + Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == ConnectStatus? + eHal4StateConfiguring:eHal4StateInvalid); + } + return; +} + + + + +void phHal4Nfc_DisconnectComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + NFCSTATUS ConnectStatus = ((phNfc_sCompletionInfo_t *)pInfo)->status; + phHal_sRemoteDevInformation_t *psConnectedDevice = NULL; + pphHal4Nfc_DiscntCallback_t pUpperDisconnectCb = NULL; + pphHal4Nfc_TransceiveCallback_t pUpperTrcvCb = NULL; + PHDBG_INFO("Hal4:Inside Hal4 disconnect callback"); + if(NULL == Hal4Ctxt) + { + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else if(NFCSTATUS_SUCCESS != ConnectStatus)/*Restart the Discovery wheel*/ + { + ConnectStatus = phHciNfc_Restart_Discovery ( + (void *)Hal4Ctxt->psHciHandle, + (void *)gpphHal4Nfc_Hwref, + FALSE + ); + Hal4Ctxt->Hal4NextState = (NFCSTATUS_PENDING == ConnectStatus? + eHal4StateConfiguring:eHal4StateInvalid); + } + else/*Remote device Disconnect successful*/ + { + psConnectedDevice = Hal4Ctxt->sTgtConnectInfo.psConnectedDevice; + pUpperDisconnectCb = Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb; + /*Deallocate psTrcvCtxtInfo*/ + if(NULL != Hal4Ctxt->psTrcvCtxtInfo) + { + if(NULL == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice) + { + if(NULL != Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData) + { + phOsalNfc_FreeMemory( + Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData); + } + } + else + { + if(phHal_eNfcIP1_Target + == Hal4Ctxt->sTgtConnectInfo.psConnectedDevice->RemDevType) + { + pUpperTrcvCb = Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb; + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length = 0; + pUpperTrcvCb = Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb; + Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb = NULL; + } + } + if(NULL != Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer) + { + phOsalNfc_FreeMemory( + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer); + } + + phOsalNfc_FreeMemory(Hal4Ctxt->psTrcvCtxtInfo); + Hal4Ctxt->psTrcvCtxtInfo = NULL; + } + /*Free the remote device list*/ + do + { + if(NULL != Hal4Ctxt->rem_dev_list[Hal4Ctxt-> + psADDCtxtInfo->nbr_of_devices-1]) + { + phOsalNfc_FreeMemory((void *) + (Hal4Ctxt->rem_dev_list[Hal4Ctxt-> + psADDCtxtInfo->nbr_of_devices-1])); + Hal4Ctxt->rem_dev_list[Hal4Ctxt-> + psADDCtxtInfo->nbr_of_devices-1] = NULL; + } + }while(--(Hal4Ctxt->psADDCtxtInfo->nbr_of_devices)); + + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice = NULL; + /*Disconnect successful.Go to Ready state*/ + Hal4Ctxt->Hal4CurrentState = Hal4Ctxt->Hal4NextState; + Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb = NULL; + Hal4Ctxt->Hal4NextState = ( + eHal4StateOpenAndReady == Hal4Ctxt->Hal4NextState? + eHal4StateInvalid:Hal4Ctxt->Hal4NextState); + /*Issue any pending Trcv callback*/ + if(NULL != pUpperTrcvCb) + { + (*pUpperTrcvCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + psConnectedDevice, + NULL, + NFCSTATUS_FAILED + ); + } + /*Notify upper layer*/ + if(NULL != pUpperDisconnectCb) + { + PHDBG_INFO("Hal4:Calling Upper layer disconnect callback"); + (*pUpperDisconnectCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerDisconnectCtxt, + psConnectedDevice, + ConnectStatus + ); + } + } + return; +} + + +/*Transceive complete handler function*/ +void phHal4Nfc_TransceiveComplete( + phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt, + void *pInfo + ) +{ + /*Copy status code*/ + NFCSTATUS TrcvStatus = ((phNfc_sCompletionInfo_t *)pInfo)->status; + /*Update next state*/ + Hal4Ctxt->Hal4NextState = (eHal4StateTransaction + == Hal4Ctxt->Hal4NextState?eHal4StateInvalid:Hal4Ctxt->Hal4NextState); + /*Reset SelectSectorFlag for Mifare*/ + if (Hal4Ctxt->SelectSectorFlag == 2) + { + TrcvStatus = NFCSTATUS_SUCCESS; + PHDBG_INFO("Inside Hal4TrcvComplete SelectSectorFlag is 2"); + Hal4Ctxt->SelectSectorFlag = 0; + } + + if(NULL == Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData) + { + /*if recv buffer is Null*/ + phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1); + TrcvStatus = NFCSTATUS_FAILED; + } + else if(TrcvStatus == NFCSTATUS_SUCCESS) + { + /*Check if recvdata buffer given by upper layer is big enough to + receive all response bytes.If it is not big enough ,copy number + of bytes requested by upper layer to the buffer.Remaining + bytes are retained in Hal4 and upper layer has to issue another + transceive call to read the same.*/ + if(((phNfc_sTransactionInfo_t *)pInfo) + ->length > Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length ) + { + TrcvStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_MORE_INFORMATION); + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length + = ((phNfc_sTransactionInfo_t *)pInfo)->length + - Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length; + + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer + = (uint8_t *)phOsalNfc_GetMemory( + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length + ); + if(NULL != Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer) + { + (void)memcpy( + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.buffer, + (((phNfc_sTransactionInfo_t *)pInfo)->buffer + + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData + ->length) + ,Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length + ); + } + else + { + TrcvStatus = PHNFCSTVAL(CID_NFC_HAL, + NFCSTATUS_INSUFFICIENT_RESOURCES); + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0); + } + + } + else/*Buffer provided by upper layer is big enough to hold all read + bytes*/ + { + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length + = ((phNfc_sTransactionInfo_t *)pInfo)->length; + Hal4Ctxt->psTrcvCtxtInfo->sLowerRecvData.length = 0; + } + (void)memcpy(Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->buffer, + ((phNfc_sTransactionInfo_t *)pInfo)->buffer, + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length + ); + + } + else/*Error scenario.Set received bytes length to zero*/ + { + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length = 0; + } + (void)memset((void *)&(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params), + 0, + sizeof(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.params) + ); + Hal4Ctxt->psTrcvCtxtInfo->LowerRecvBufferOffset = 0; + /*Issue transceive callback*/ + (*Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb)( + Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt, + Hal4Ctxt->sTgtConnectInfo.psConnectedDevice, + Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData, + TrcvStatus + ); + return; +} diff --git a/libnfc-nxp/phHciNfc.c b/libnfc-nxp/phHciNfc.c new file mode 100644 index 0000000..d6990c1 --- /dev/null +++ b/libnfc-nxp/phHciNfc.c @@ -0,0 +1,1782 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc.c * +* \brief HCI Interface Source for the HCI Management. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Thu Apr 22 17:49:47 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.90 $ * +* $Aliases: NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + + +/* +################################################################################ +***************************** Header File Inclusion **************************** +################################################################################ +*/ + +#include +#include +#include +#include +#include +#include +#include +#ifdef ENABLE_P2P +#include +#endif +#include +#include +#include +#include + +/**/ + +/* +*************************** Static Function Declaration ************************** +*/ + + +static +NFCSTATUS +phHciNfc_Config_Emulation ( + void *psHciHandle, + void *pHwRef, + phHal_sEmulationCfg_t *pEmulationConfig + + ); + + +/* +*************************** Function Definitions ************************** +*/ + + +/*! + * \brief Initialises the HCI Interface + * + * This function initialises the resources for the HCI Command and + * Response Mechanism + */ + + NFCSTATUS + phHciNfc_Initialise ( + void *psHciHandle, + void *pHwRef, + phHciNfc_Init_t init_mode, + phHal_sHwConfig_t *pHwConfig, + pphNfcIF_Notification_CB_t pHalNotify, + void *psContext, + phNfcLayer_sCfg_t *psHciLayerCfg + ) +{ + phHciNfc_sContext_t *psHciContext = NULL; + phNfcIF_sReference_t hciReference = { NULL, 0, 0 }; + phNfcIF_sCallBack_t if_callback = { NULL, NULL, NULL, NULL }; + phNfc_sLowerIF_t *plower_if = NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t lower_index=0; + + if( (NULL == psHciHandle) || (NULL == pHwRef) || (NULL == pHalNotify) + || (NULL== psContext) || (NULL == psHciLayerCfg) || (NULL == pHwConfig) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL != *(phHciNfc_sContext_t **)psHciHandle ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_ALREADY_INITIALISED ); + } + else + { + /* Create the memory for HCI Context */ + psHciContext = (phHciNfc_sContext_t *) + phOsalNfc_GetMemory(sizeof(phHciNfc_sContext_t)); + + if(psHciContext != NULL) + { + (void)memset((void *)psHciContext,0, + sizeof(phHciNfc_sContext_t)); + + psHciContext->hci_state.cur_state = hciState_Reset; + psHciContext->hci_mode = hciMode_Reset; + psHciContext->p_hw_ref = pHwRef; + psHciContext->host_rf_type = phHal_eUnknown_DevType; + HCI_PRINT("HCI Initialisation in Progress.... \n"); + +#ifdef ESTABLISH_SESSION + /*(void)memcpy(((phHal_sHwReference_t *)pHwRef)->session_id, + DEFAULT_SESSION, (sizeof(DEFAULT_SESSION) > 0x01) ? + sizeof(DEFAULT_SESSION): + sizeof(((phHal_sHwReference_t *)pHwRef)->session_id));*/ + (void)memcpy(pHwConfig->session_id, + DEFAULT_SESSION, ((sizeof(DEFAULT_SESSION) > 0x01) + && (sizeof(DEFAULT_SESSION) <= 0x08 )) ? + sizeof(DEFAULT_SESSION): + sizeof(pHwConfig->session_id)); +#endif + HCI_DEBUG("Sizeof Default Session %u\n",sizeof(DEFAULT_SESSION)); + psHciContext->p_upper_notify = pHalNotify; + psHciContext->p_upper_context = psContext; + + if_callback.pif_ctxt = psHciContext ; + if_callback.send_complete = &phHciNfc_Send_Complete; + if_callback.receive_complete= &phHciNfc_Receive_Complete; + if_callback.notify = &phHciNfc_Notify_Event; + plower_if = hciReference.plower_if = &(psHciContext->lower_interface); + *((phHciNfc_sContext_t **)psHciHandle) = psHciContext; + psHciContext->init_mode = init_mode; + psHciContext->p_hci_layer = psHciLayerCfg ; + lower_index = psHciLayerCfg->layer_index - 1; + + if(NULL != psHciLayerCfg->layer_next->layer_registry) + { + status = psHciLayerCfg->layer_next->layer_registry( + &hciReference, if_callback, + (void *)&psHciLayerCfg[lower_index]); + HCI_DEBUG("HCI Lower Layer Register, Status = %02X\n",status); + } + if( (NFCSTATUS_SUCCESS == status) && (NULL != plower_if->init) ) + { + status = phHciNfc_FSM_Update ( psHciContext, + hciState_Initialise + ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = ADMIN_INIT_SEQ; + psHciContext->target_release = FALSE; + psHciContext->config_type = POLL_LOOP_CFG; + psHciContext->p_config_params = pHwConfig ; + status = plower_if->init((void *)plower_if->pcontext, + (void *)psHciContext->p_hw_ref); + HCI_DEBUG("HCI Lower Layer Initialisation, Status = %02X\n",status); + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + else + { + /* TODO: Handle Initialisation in the Invalid State */ + } + }/* End of Lower Layer Init */ + } /* End of Status Check for Memory */ + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + + HCI_PRINT("HCI Context Memory Allocation Failed\n"); + } + + } + return status; +} + + +/*! + * \brief Release of the HCI Interface . + * + * This function Closes all the open pipes and frees all the resources used by + * HCI Layer + */ + + NFCSTATUS + phHciNfc_Release ( + void *psHciHandle, + void *pHwRef, + pphNfcIF_Notification_CB_t pHalReleaseCB, + void *psContext + ) +{ + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + /* This Scenario Forces the HCI and the lower layers + * to release its Resources + */ + else if ( NULL == pHalReleaseCB ) + { + /* Release the lower layer Resources */ + phHciNfc_Release_Lower( psHciContext, pHwRef ); + /* Release the HCI layer Resources */ + phHciNfc_Release_Resources( &psHciContext ); + } + else if ( NULL == psContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + HCI_PRINT("HCI Release in Progress.... \n"); + psHciContext->p_hw_ref = pHwRef; + status = phHciNfc_FSM_Update ( psHciContext, hciState_Release ); + if ((NFCSTATUS_SUCCESS == status) +#ifdef NXP_HCI_SHUTDOWN_OVERRIDE + || (NFCSTATUS_INVALID_STATE == PHNFCSTATUS(status)) +#endif + ) + { + psHciContext->p_upper_notify = pHalReleaseCB; + psHciContext->p_upper_context = psContext; + /* psHciContext->hci_seq = EMULATION_REL_SEQ;*/ + /* psHciContext->hci_seq = READER_MGMT_REL_SEQ; */ + if (HCI_SELF_TEST != psHciContext->init_mode) + { + psHciContext->hci_seq = PL_STOP_SEQ; + } + else + { + psHciContext->hci_seq = ADMIN_REL_SEQ; + } + +#ifdef NXP_HCI_SHUTDOWN_OVERRIDE + if (NFCSTATUS_SUCCESS != status) + { + psHciContext->hci_state.next_state = (uint8_t) hciState_Release; + status = NFCSTATUS_PENDING; + } + else +#endif + { + status = phHciNfc_Release_Sequence(psHciContext,pHwRef); + } + + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + else + { + /* TODO: Return appropriate Error */ + } + + } + + return status; +} + +#if 0 +/*! + * \brief Interface to Starts the RF Device Discovery. + * + * This function Starts the Discovery Wheel. + */ + + + NFCSTATUS + phHciNfc_Start_Discovery ( + void *psHciHandle, + void *pHwRef + ) +{ + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if ( (NULL == psHciHandle) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = phHciNfc_ReaderMgmt_Enable_Discovery( psHciContext, pHwRef ); + } + + return status; +} + + +/*! + * \brief Interface to Stop the RF Device Discovery. + * + * This function Stops the Discovery Wheel. + */ + + + NFCSTATUS + phHciNfc_Stop_Discovery ( + void *psHciHandle, + void *pHwRef + ) +{ + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if ( (NULL == psHciHandle) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = phHciNfc_ReaderMgmt_Disable_Discovery( psHciContext, pHwRef ); + } + + return status; +} + + +#endif + +/*! + * \brief Interface to Configure the Device With the appropriate + * Configuration Parameters . + * + * This function configures the Devices with the provided + * configuration attributes. + */ + + + NFCSTATUS + phHciNfc_Configure ( + void *psHciHandle, + void *pHwRef, + phHal_eConfigType_t config_type, + phHal_uConfig_t *pConfig + ) + { + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + || (NULL == pConfig) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + switch(config_type) + { + case NFC_P2P_CONFIG: + { +#ifdef ENABLE_P2P + phHciNfc_sContext_t *psHciContext = + ((phHciNfc_sContext_t *)psHciHandle); + status = phHciNfc_FSM_Update ( psHciContext, hciState_Config ); + + if (NFCSTATUS_SUCCESS == status) + { + psHciContext->config_type = NFC_GENERAL_CFG; + psHciContext->p_config_params = &(pConfig->nfcIPConfig); + psHciContext->hci_seq = INITIATOR_GENERAL_SEQ; + status = phHciNfc_NfcIP_SetATRInfo( psHciHandle, + pHwRef, NFCIP_INITIATOR, + &(pConfig->nfcIPConfig)); + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + else + { + psHciContext->hci_seq = TARGET_GENERAL_SEQ; + } + } +#else + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + +#endif + break; + } + case NFC_EMULATION_CONFIG: + { + status = phHciNfc_Config_Emulation( psHciHandle, + pHwRef, &(pConfig->emuConfig)); + break; + } + case NFC_SE_PROTECTION_CONFIG: + { + phHciNfc_sContext_t *psHciContext = + ((phHciNfc_sContext_t *)psHciHandle); + status = phHciNfc_FSM_Update ( psHciContext, hciState_Config ); + + if (NFCSTATUS_SUCCESS == status) + { + psHciContext->config_type = SWP_PROTECT_CFG; + psHciContext->p_config_params = &(pConfig->protectionConfig); + psHciContext->hci_seq = HCI_END_SEQ; + status = phHciNfc_SWP_Protection( psHciHandle, + pHwRef, pConfig->protectionConfig.mode); + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + }/* End of the Configuration Switch */ + } + + return status; + } + + +/*! + * \brief Interface to Configure the RF Device Discovery using + * HCI Polling Loop Gate . + * + * This function configures the HCI Polling Loop Gate with the provided + * configuration attributes. + */ + + NFCSTATUS + phHciNfc_Config_Discovery ( + void *psHciHandle, + void *pHwRef, + phHal_sADD_Cfg_t *pPollConfig + ) +{ + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + || (NULL == pPollConfig) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + HCI_PRINT("HCI Poll Configuration .... \n"); + status = phHciNfc_FSM_Update ( psHciContext, hciState_Config ); + + if (NFCSTATUS_SUCCESS == status) + { +#if 0 + if(pPollConfig->PollDevInfo.PollEnabled) + { + psHciContext->hci_seq = PL_DURATION_SEQ; + } + else + { + psHciContext->hci_seq = PL_CONFIG_PHASE_SEQ; + /* psHciContext->hci_seq = (pPollConfig->NfcIP_Mode != 0 )? + PL_CONFIG_PHASE_SEQ: + READER_DISABLE_SEQ; */ + } +#endif + psHciContext->hci_seq = PL_DURATION_SEQ; + psHciContext->config_type = POLL_LOOP_CFG; + psHciContext->p_config_params = pPollConfig; + status = phHciNfc_PollLoop_Sequence( psHciContext, pHwRef ); + + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + else + { + /* TODO: Return appropriate Error */ + } + } + return status; +} + +/*! + * \brief Interface to Restart the RF Device Discovery. + * + * This function restarts the Discovery Wheel. + */ + + + NFCSTATUS + phHciNfc_Restart_Discovery ( + void *psHciHandle, + void *pHwRef, + uint8_t re_poll + ) +{ + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHal_eRemDevType_t target_type = phHal_eUnknown_DevType; + + if ( (NULL == psHciHandle) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + + /* To be back in the Poll State to Re-Poll the Target */ + status = phHciNfc_FSM_Update ( psHciContext, hciState_Initialise ); + if (NFCSTATUS_SUCCESS == status) + { + switch (psHciContext->host_rf_type) + { + case phHal_eISO14443_A_PCD: + { + target_type = phHal_eISO14443_A_PICC; + break; + } + case phHal_eNfcIP1_Initiator: + { + target_type = phHal_eNfcIP1_Target; + break; + } +#ifdef TYPE_B + case phHal_eISO14443_B_PCD: + { + target_type = phHal_eISO14443_B_PICC; + break; + } +#endif +#ifdef TYPE_FELICA + case phHal_eFelica_PCD: + { + target_type = phHal_eFelica_PICC; + break; + } +#endif +#ifdef TYPE_JEWEL + case phHal_eJewel_PCD: + { + target_type = phHal_eJewel_PICC; + break; + } +#endif +#ifdef TYPE_ISO15693 + case phHal_eISO15693_PCD: + { + target_type = phHal_eISO15693_PICC; + break; + } +#endif /* #ifdef TYPE_ISO15693 */ +#ifndef TYPE_B + case phHal_eISO14443_B_PCD: +#endif +#ifndef TYPE_FELICA + case phHal_eFelica_PCD: +#endif +#ifndef TYPE_JEWEL + case phHal_eJewel_PCD: +#endif +#ifndef TYPE_B_PRIME + case phHal_eISO14443_BPrime_PCD: +#endif + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + case phHal_eUnknown_DevType: + default: + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + }/* End of the Remote Target Type Switch */ + if( NFCSTATUS_SUCCESS == status ) + { + status = phHciNfc_ReaderMgmt_Deselect( + psHciContext, pHwRef, target_type, re_poll); + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + else + { + psHciContext->host_rf_type = phHal_eUnknown_DevType; + } + } + } + else + { + /* TODO: Return appropriate Error */ + } + } + + return status; +} + + + +/*! + * \brief Interface to Configure the device to emulation as + * the tag, smart tag or p2p target . + * + * This function configures the HCI Polling Loop Gate with the provided + * configuration attributes. + */ + + static + NFCSTATUS + phHciNfc_Config_Emulation ( + void *psHciHandle, + void *pHwRef, + phHal_sEmulationCfg_t *pEmulationCfg + ) +{ + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + || (NULL == pEmulationCfg) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + + HCI_PRINT("HCI Configure Emulation .... \n"); + status = phHciNfc_FSM_Update ( psHciContext, hciState_Config ); + + if (NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = EMULATION_CONFIG_SEQ; + psHciContext->p_config_params = pEmulationCfg; + switch( pEmulationCfg->emuType ) + { + case NFC_SMARTMX_EMULATION: + { + psHciContext->config_type = SMX_WI_CFG; + status = phHciNfc_Emulation_Cfg(psHciContext, + pHwRef, SMX_WI_CFG); + break; + } + case NFC_UICC_EMULATION: + { + psHciContext->config_type = UICC_SWP_CFG; + psHciContext->hci_seq = EMULATION_CONFIG_SEQ; + (void)phHciNfc_SWP_Update_Sequence( + psHciContext, CONFIG_SEQ ); + status = phHciNfc_EmulationCfg_Sequence( + psHciContext, pHwRef); + break; + } + case NFC_HOST_CE_A_EMULATION: + case NFC_HOST_CE_B_EMULATION: +#if defined(HOST_EMULATION) + { + if(TRUE == pEmulationCfg->config. + hostEmuCfg_A.enableEmulation) + { + psHciContext->hci_seq = ADMIN_CE_SEQ; + } + status = phHciNfc_EmulationCfg_Sequence( + psHciContext, pHwRef); + break; + } +#endif + default: + { + break; + } + + } /* End of Config Switch */ + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + else + { + /* TODO: Return appropriate Error */ + } + } + + return status; +} + + NFCSTATUS + phHciNfc_Switch_SwpMode ( + void *psHciHandle, + void *pHwRef, + phHal_eSWP_Mode_t swp_mode /* , + void *pSwpCfg */ + ) +{ + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + + HCI_PRINT("HCI SWP Switch .... "); + status = phHciNfc_FSM_Update ( psHciContext, hciState_Config ); + if (NFCSTATUS_SUCCESS == status) + { + psHciContext->config_type = SWP_EVT_CFG; + status = phHciNfc_SWP_Configure_Mode( psHciContext, pHwRef , + (uint8_t) swp_mode ); + + /* Send the Success Status as this is an event */ + status = ((status == NFCSTATUS_SUCCESS)? + NFCSTATUS_PENDING : status); + + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + + HCI_PRINT(" Execution Error \n"); + } + else + { + HCI_PRINT(" Successful \n"); + } + } + else + { + HCI_PRINT(" Not allowed - Invalid State \n"); + /* TODO: Return appropriate Error */ + } + } + + return status; +} + + + +/*! + * \brief Interface to Switch the Mode of the SmartMx from Virtual/Wired + * to the other mode. + * + * This function switches the mode of the SmartMX connected through WI(S2C) + * Interface to virtual/wired mode. + */ + + + NFCSTATUS + phHciNfc_Switch_SmxMode ( + void *psHciHandle, + void *pHwRef, + phHal_eSmartMX_Mode_t smx_mode, + phHal_sADD_Cfg_t *pPollConfig + ) +{ + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + || (NULL == pPollConfig) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + + HCI_PRINT("HCI Smart MX Mode Switch .... \n"); + status = phHciNfc_FSM_Update ( psHciContext, hciState_Config ); + + if (NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = READER_DISABLE_SEQ; + if ( (eSmartMx_Wired == psHciContext->smx_mode) + && ( hciState_Connect == psHciContext->hci_state.cur_state) + &&( eSmartMx_Wired != smx_mode) + ) + { + /* Workaround: For Wired Mode Disconnect + All the statemachine updates should be done only with the + Statemachine API and should not be overridden. + */ + psHciContext->hci_state.cur_state = hciState_Disconnect; + } + psHciContext->config_type = SMX_WI_MODE; + psHciContext->smx_mode = smx_mode; + psHciContext->p_config_params = pPollConfig; + status = phHciNfc_SmartMx_Mode_Sequence( psHciContext, pHwRef ); + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + else + { + /* TODO: Return appropriate Error */ + } + } + + return status; +} + + +/*! + * \brief Interface to Select the Next Remote Target Discovered during the + * discovery sequence using the particular HCI Reader Gate . + * + * + * This function Selects and Activates the next Remote Target + * Detected using the particular HCI Reader Gate. + */ + + + +NFCSTATUS +phHciNfc_Select_Next_Target ( + void *psHciHandle, + void *pHwRef + ) +{ + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + status = phHciNfc_FSM_Update ( psHciContext, hciState_Select ); + if (NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = READER_SELECT_SEQ; + status = phHciNfc_ReaderMgmt_Activate_Next( psHciContext, pHwRef ); + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + } + } + + return status; + +} + + +/*! + * \brief Interface to Connect the Remote Target Discovered during the + * discovery sequence using the particular HCI Reader Gate . + * + * + * This function connects the Remote Target Detected using the particular + * HCI Reader Gate with the appropriate configuration setup. + */ + + + NFCSTATUS + phHciNfc_Connect ( + void *psHciHandle, + void *pHwRef, + phHal_sRemoteDevInformation_t *p_target_info + ) + { + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + /* phHal_eRemDevType_t target_type = phHal_eUnknown_DevType; */ + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + || (NULL == p_target_info) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + status = phHciNfc_FSM_Update ( psHciContext, hciState_Connect ); + if (NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = READER_SELECT_SEQ; + switch (p_target_info->RemDevType) + { + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_4A_PICC: + case phHal_eMifare_PICC: + case phHal_eISO14443_3A_PICC: +#ifdef ENABLE_P2P + case phHal_eNfcIP1_Target: +#endif +#ifdef TYPE_B + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4B_PICC: +#endif +#ifdef TYPE_FELICA + case phHal_eFelica_PICC: +#endif +#ifdef TYPE_JEWEL + case phHal_eJewel_PICC: +#endif +#ifdef TYPE_ISO15693 + case phHal_eISO15693_PICC: +#endif /* #ifdef TYPE_ISO15693 */ + + { + psHciContext->p_target_info = p_target_info; + status = phHciNfc_ReaderMgmt_Select( + psHciContext, pHwRef, + p_target_info->RemDevType ); + break; + } +#ifndef TYPE_B_PRIME + case phHal_eISO14443_BPrime_PICC: +#endif + case phHal_eUnknown_DevType: + default: + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + }/* End of the Remote Target Type Switch */ + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + } + + } /* End of the HCI Handle Validation */ + + return status; +} + + +/*! + * \brief Interface to Reactivate the Remote Targets Discovered during the + * discovery sequence using the particular HCI Reader Gate . + * + * + * This function reactivates the Remote Target Detected using the particular + * HCI Reader Gate with the appropriate configuration setup. + */ + + + NFCSTATUS + phHciNfc_Reactivate ( + void *psHciHandle, + void *pHwRef, + phHal_sRemoteDevInformation_t *p_target_info + ) + { + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + /* phHal_eRemDevType_t target_type = phHal_eUnknown_DevType; */ + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + || (NULL == p_target_info) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + status = phHciNfc_FSM_Update ( psHciContext, hciState_Reactivate ); + if (NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = READER_REACTIVATE_SEQ; + switch (p_target_info->RemDevType) + { + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_4A_PICC: + case phHal_eMifare_PICC: + case phHal_eISO14443_3A_PICC: + { + psHciContext->host_rf_type = phHal_eISO14443_A_PCD; + break; + } + case phHal_eNfcIP1_Target: + { + psHciContext->host_rf_type = phHal_eNfcIP1_Initiator; + break; + } +#ifdef TYPE_B + case phHal_eISO14443_4B_PICC: + case phHal_eISO14443_B_PICC: + { + psHciContext->host_rf_type = phHal_eISO14443_B_PCD; + break; + } +#endif +#ifdef TYPE_FELICA + case phHal_eFelica_PICC: + { + psHciContext->host_rf_type = phHal_eFelica_PCD; + break; + } +#endif +#ifdef TYPE_B_PRIME + case phHal_eISO14443_BPrime_PICC: +#endif + /* Reactivate for Jewel is not Supported */ + case phHal_eJewel_PICC: + case phHal_eUnknown_DevType: + default: + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + }/* End of the Remote Target Type Switch */ + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + } + + if(NFCSTATUS_SUCCESS == status ) + { + psHciContext->p_target_info = p_target_info; + status = phHciNfc_ReaderMgmt_Reactivate( + psHciContext, pHwRef, p_target_info->RemDevType ); + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + } /* End of the HCI Handle Validation */ + + + return status; +} + + +/*! + * \brief Interface to Disconnect the selected target. + * + * This function disconnects the remote target selected. + */ + + + NFCSTATUS + phHciNfc_Disconnect ( + void *psHciHandle, + void *pHwRef, + uint8_t re_poll + ) + { + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHal_eRemDevType_t target_type = phHal_eUnknown_DevType; + /* phHal_eSmartMX_Mode_t smx_mode = (phHal_eSmartMX_Mode_t)type; */ + static uint8_t repoll=0; + + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + || ( NULL == psHciContext->p_target_info) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + repoll = re_poll; + psHciContext->p_config_params = &repoll; + /* psHciContext->hci_seq = HCI_END_SEQ; */ + + /* To be back in the Poll State to Re-Poll the Target */ + status = phHciNfc_FSM_Update ( psHciContext, hciState_Disconnect ); + if (NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = READER_UICC_DISPATCH_SEQ; + target_type = psHciContext->p_target_info->RemDevType; + switch (target_type) + { + case phHal_eMifare_PICC: + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_4A_PICC: + case phHal_eISO14443_3A_PICC: + case phHal_eNfcIP1_Target: +#ifdef TYPE_B + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4B_PICC: +#endif +#ifdef TYPE_FELICA + case phHal_eFelica_PICC: +#endif +#ifdef TYPE_JEWEL + case phHal_eJewel_PICC: +#endif +#ifdef TYPE_ISO15693 + case phHal_eISO15693_PICC: +#endif /* #ifdef TYPE_ISO15693 */ + + { + status = phHciNfc_Disconnect_Sequence( + psHciContext, pHwRef ); + break; + } +#ifndef TYPE_B + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4B_PICC: +#endif +#ifndef TYPE_FELICA + case phHal_eFelica_PICC: +#endif +#ifndef TYPE_JEWEL + case phHal_eJewel_PICC: +#endif +#ifndef TYPE_B_PRIME + case phHal_eISO14443_BPrime_PICC: +#endif + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + case phHal_eUnknown_DevType: + default: + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + }/* End of the Remote Target Type Switch */ + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + else + { + /* TODO: Return appropriate Error */ + } + } /* End of the HCI Handle Validation */ + + return status; +} + +/*! + * \brief Interface to exchange the data to/from + * the selected target. + * + * This function sends and receives the data to/from + * the selected remote target. + */ + + NFCSTATUS + phHciNfc_Exchange_Data ( + void *psHciHandle, + void *pHwRef, + phHal_sRemoteDevInformation_t *p_target_info, + phHciNfc_XchgInfo_t *p_xchg_info + ) + { + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + || (NULL == p_target_info) + || (NULL == p_xchg_info) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if (p_target_info != psHciContext->p_target_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_REMOTE_DEVICE); + } + else + { + psHciContext->p_hw_ref = pHwRef; + status = phHciNfc_FSM_Update ( psHciContext, hciState_Transact ); + if (NFCSTATUS_SUCCESS == status) + { + switch (p_target_info->RemDevType) + { + case phHal_eMifare_PICC: + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_4A_PICC: + case phHal_eISO14443_3A_PICC: +#ifdef TYPE_B + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4B_PICC: +#endif +#ifdef TYPE_FELICA + case phHal_eFelica_PICC: +#endif +#ifdef TYPE_JEWEL + case phHal_eJewel_PICC: +#endif +#ifdef TYPE_ISO15693 + case phHal_eISO15693_PICC: +#endif /* #ifdef TYPE_ISO15693 */ + { + psHciContext->p_xchg_info = p_xchg_info; + status = phHciNfc_ReaderMgmt_Exchange_Data( + psHciContext, pHwRef, p_xchg_info ); + break; + } +#ifndef TYPE_B + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4B_PICC: +#endif +#ifndef TYPE_FELICA + case phHal_eFelica_PICC: +#endif +#ifndef TYPE_JEWEL + case phHal_eJewel_PICC: +#endif + case phHal_eNfcIP1_Target: +#ifndef TYPE_B_PRIME + case phHal_eISO14443_BPrime_PICC: +#endif + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + case phHal_eUnknown_DevType: + default: + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + + }/* End of the Remote Target Type Switch */ + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + } + } /* End of the HCI Handle Validation */ + + return status; +} + +/*! + * \brief Interface to Send the data to/from + * the selected NfcIP. + * + * This function sends and receives the data to/from + * the selected remote target. + */ + + NFCSTATUS + phHciNfc_Send_Data ( + void *psHciHandle, + void *pHwRef, + phHal_sRemoteDevInformation_t *p_remote_dev_info, + phHciNfc_XchgInfo_t *p_send_param + ) + { + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + || (NULL == p_send_param) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + status = phHciNfc_FSM_Update ( psHciContext, hciState_Transact ); + if (NFCSTATUS_SUCCESS == status) + { + switch (psHciContext->host_rf_type) + { + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4A_PICC: + case phHal_eISO14443_4B_PICC: + { + break; + } +#ifdef ENABLE_P2P + case phHal_eNfcIP1_Initiator: + { + if (p_remote_dev_info != + psHciContext->p_target_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_REMOTE_DEVICE); + } + else + { + psHciContext->p_xchg_info = p_send_param; + status = phHciNfc_NfcIP_Send_Data( psHciContext, + pHwRef, p_send_param ); + } + break; + } + case phHal_eNfcIP1_Target: + { + psHciContext->p_xchg_info = p_send_param; + status = phHciNfc_NfcIP_Send_Data( psHciContext, + pHwRef, p_send_param ); + break; + } +#endif +#ifdef TYPE_B_PRIME + case phHal_eISO14443_BPrime_PCD: + case phHal_eFelica_PCD: + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } +#endif + case phHal_eUnknown_DevType: + default: + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + + }/* End of the Remote Target Type Switch */ +#if defined( ENABLE_P2P ) || defined (TYPE_B_PRIME) + if( NFCSTATUS_PENDING != status ) +#endif + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + } + } /* End of the HCI Handle Validation */ + + return status; + + } + +#if 0 + +/*! + * \brief Interface to Send the data from + * the selected NfcIP. + * + * This function sends and receives the data to/from + * the selected remote target. + */ + + NFCSTATUS + phHciNfc_Receive_Data ( + void *psHciHandle, + void *pHwRef, + uint8_t *p_data, + uint8_t length + ) + { + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciHandle) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if (NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_Receive(psHciHandle, pHwRef, p_data, length); + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + } + return status; + + } + +#endif + + /*! + * \brief Interface to Check for the presence of + * the selected target in the field . + * + * This function checks the presence of the + * the selected remote target in the field . + */ + + + +NFCSTATUS +phHciNfc_Presence_Check ( + void *psHciHandle, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + ((phHciNfc_sContext_t *)psHciHandle); + phHal_eRemDevType_t target_type = phHal_eUnknown_DevType; + + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + status = phHciNfc_FSM_Update ( psHciContext, hciState_Presence ); + if (NFCSTATUS_SUCCESS == status) + { + target_type = psHciContext->p_target_info->RemDevType; + switch (target_type) + { + case phHal_eISO14443_A_PICC: + case phHal_eMifare_PICC: + case phHal_eISO14443_4A_PICC: + case phHal_eISO14443_3A_PICC: +#ifdef TYPE_B + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4B_PICC: +#endif +#ifdef TYPE_FELICA + case phHal_eFelica_PICC: +#endif +#ifdef TYPE_JEWEL + case phHal_eJewel_PICC: +#endif +#ifdef TYPE_ISO15693 + case phHal_eISO15693_PICC: +#endif /* #ifdef TYPE_ISO15693 */ +#ifdef ENABLE_P2P + case phHal_eNfcIP1_Target: +#endif + { + status = phHciNfc_ReaderMgmt_Presence_Check( + psHciContext, pHwRef ); + break; + } +#ifdef TYPE_B_PRIME + case phHal_eISO14443_BPrime_PICC: +#endif +#ifndef TYPE_B + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4B_PICC: +#endif +#ifndef TYPE_FELICA + case phHal_eFelica_PICC: +#endif +#ifndef TYPE_JEWEL + case phHal_eJewel_PICC: +#endif + case phHal_eUnknown_DevType: + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + default: + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + + }/* End of the Remote Target Type Switch */ + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + } + } /* End of the HCI Handle Validation */ + + return status; +} + + NFCSTATUS + phHciNfc_PRBS_Test ( + void *psHciHandle, + void *pHwRef, + uint32_t test_type, + phNfc_sData_t *test_param + ) + { + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + ((phHciNfc_sContext_t *)psHciHandle); + + if( (NULL == psHciContext) + || (NULL == pHwRef) + || (test_type != DEVMGMT_PRBS_TEST) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + status = phHciNfc_FSM_Update ( psHciContext, hciState_IO ); + if (NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_DevMgmt_Test(psHciContext, pHwRef, + (uint8_t)(test_type & DEVMGMT_TEST_MASK), test_param); + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + } + return status; + } + + + NFCSTATUS + phHciNfc_System_Test ( + void *psHciHandle, + void *pHwRef, + uint32_t test_type, + phNfc_sData_t *test_param + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + ((phHciNfc_sContext_t *)psHciHandle); + static phNfc_sData_t test_result; + static uint8_t gpio_status = 0; + + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + status = phHciNfc_FSM_Update ( psHciContext, hciState_Test ); + if (NFCSTATUS_SUCCESS == status) + { + if (test_type != NFC_GPIO_READ) + { + status = phHciNfc_DevMgmt_Test(psHciContext, pHwRef, + (uint8_t)(test_type & DEVMGMT_TEST_MASK), test_param); + } + else + { + test_result.buffer = &gpio_status; + status = phHciNfc_DevMgmt_Get_Info(psHciContext, pHwRef, + (uint16_t)NFC_GPIO_READ, test_result.buffer); + + } + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + } + + return status; +} + + + NFCSTATUS + phHciNfc_System_Configure ( + void *psHciHandle, + void *pHwRef, + uint32_t config_type, + uint8_t config_value + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + ((phHciNfc_sContext_t *)psHciHandle); + + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + status = phHciNfc_FSM_Update ( psHciContext, hciState_IO ); + if (NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_DevMgmt_Configure(psHciContext, pHwRef, + (uint16_t)config_type, config_value); + + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + } + return status; +} + +NFCSTATUS + phHciNfc_System_Get_Info( + void *psHciHandle, + void *pHwRef, + uint32_t config_type, + uint8_t *p_config_value + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + ((phHciNfc_sContext_t *)psHciHandle); + + if( (NULL == psHciContext) + || (NULL == pHwRef) + || (NULL == p_config_value) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + status = phHciNfc_FSM_Update ( psHciContext, hciState_IO ); + if (NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_DevMgmt_Get_Info(psHciContext, pHwRef, + (uint16_t)config_type, p_config_value); + + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + } + + return status; +} + + + NFCSTATUS + phHciNfc_Get_Link_Status( + void *psHciHandle, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + ((phHciNfc_sContext_t *)psHciHandle); + + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->p_hw_ref = pHwRef; + status = phHciNfc_FSM_Update ( psHciContext, hciState_IO ); + if (NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_LinkMgmt_Open(psHciContext, pHwRef); + + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + } + } + + return status; +} + + + diff --git a/libnfc-nxp/phHciNfc.h b/libnfc-nxp/phHciNfc.h new file mode 100644 index 0000000..4f52b4a --- /dev/null +++ b/libnfc-nxp/phHciNfc.h @@ -0,0 +1,761 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc.h * +* \brief HCI Header for the Generic HCI Management. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Mon Apr 5 14:37:06 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.39 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + + +/*@{*/ + +#ifndef PHHCINFC_H +#define PHHCINFC_H + +/*@}*/ +/** + * \name HCI + * + * File: \ref phHciNfc.h + * + */ +/*@{*/ +#define PH_HCINFC_FILEREVISION "$Revision: 1.39 $" /**< \ingroup grp_file_attributes */ +#define PH_HCINFC_FILEALIASES "$Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +################################################################################ +***************************** Header File Inclusion **************************** +################################################################################ +*/ + +#include +#include +#ifdef ANDROID +#include +#endif + +/* +################################################################################ +****************************** Macro Definitions ******************************* +################################################################################ +*/ + + +/* +################################################################################ +******************** Enumeration and Structure Definition ********************** +################################################################################ +*/ + +typedef enum phHciNfc_Init +{ + HCI_SESSION = 0x00, + HCI_NFC_DEVICE_TEST, + HCI_CUSTOM_INIT, + HCI_SELF_TEST +}phHciNfc_Init_t; + +/** \ingroup grp_hal_hci + * + * \if hal + * \brief HCI Tag Exchange Information + * \else + * \brief HCI-Specific + * \endif + * + * The Tag Exchange Info Structure holds the exchange information to + * the connected tag . + * + * \note All members of this structure are in parameters [in]. + * + */ + +typedef struct phHciNfc_Tag_XchgInfo +{ + /** \internal RF Reader Command Type */ + uint8_t cmd_type; + /** \internal Address Field required for only Mifare + * Family Proprietary Cards. + * The Address Size is Valid only upto 255 Blocks limit + * i:e for Mifare 4K + */ + uint8_t addr; +}phHciNfc_Tag_XchgInfo_t; + +/** \ingroup grp_hal_hci + * + * \if hal + * \brief HCI NFC-IP Exchange Information + * \else + * \brief HCI-Specific + * \endif + * + * The NFC-IP Exchange Info Structure holds the exchange information to + * the connected NFC-IP target . + * + * \note All members of this structure are in parameters [in]. + * + */ + +typedef struct phHciNfc_NfcIP_XchgInfo +{ + /** \internal NFC-IP DEP Meta Chining Information */ + uint8_t more_info; + +}phHciNfc_NfcIP_XchgInfo_t; + +/** \ingroup grp_hal_hci + * + * \if hal + * \brief HCI Target Exchange Information + * \else + * \brief HCI-Specific + * \endif + * + * The Target Exchange Info Structure holds all the exchange information to + * the connected target . + * + * \note All members of this structure are in parameters [in]. + * + */ + + +typedef struct phHciNfc_XchgInfo +{ + /** \internal Exchange Data/NFC-IP DEP + * Exchange Buffer */ + uint8_t *tx_buffer; + /** \internal Exchange Data/NFC-IP DEP + * Exchange Buffer Length*/ + uint16_t tx_length; + + union + { + phHciNfc_Tag_XchgInfo_t tag_info; + phHciNfc_NfcIP_XchgInfo_t nfc_info; + }params; + +}phHciNfc_XchgInfo_t; + + + +/* +################################################################################ +*********************** Function Prototype Declaration ************************* +################################################################################ +*/ + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Initialise function initialises the HCI context and all other + * resources used in the HCI Layer for the corresponding interface link. + * + * \param[in,out] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] init_mode init_mode specifies the kind of the + * Initialisation for the HCI layer . + * \param[in] pHwConfig pHwConfig is the Information required + * to configure the parameters of the + * NFC Device . + * \param[in] pHalNotify Upper layer Notification function + * pointer. + * \param[in] psContext psContext is the context of + * the Upper Layer. + * \param[in] psHciLayerCfg Pointer to the HCI Layer configuration + * Structure. + * + * \retval NFCSTATUS_PENDING Initialisation of HCI Layer is in Progress. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + extern + NFCSTATUS + phHciNfc_Initialise ( + void *psHciHandle, + void *pHwRef, + phHciNfc_Init_t init_mode, + phHal_sHwConfig_t *pHwConfig, + pphNfcIF_Notification_CB_t pHalNotify, + void *psContext, + phNfcLayer_sCfg_t *psHciLayerCfg + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Release function releases all the resources used in the HCI + * Layer for the corresponding interface link, described by the HCI handle. + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] pHalReleaseCB Upper layer release callback function + * pointer . + * \param[in] psContext psContext is the context of + * the Upper Layer. + * + * \retval NFCSTATUS_PENDING Releasing of HCI Resources are in Progress. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + extern + NFCSTATUS + phHciNfc_Release ( + void *psHciHandle, + void *pHwRef, + pphNfcIF_Notification_CB_t pHalReleaseCB, + void *psContext + ); + + +extern +NFCSTATUS +phHciNfc_Config_Discovery ( + void *psHciHandle, + void *pHwRef, + phHal_sADD_Cfg_t *pPollConfig + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Restart_Discovery function restarts the Polling Wheel. + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] discovery_type If True: Start re-polling of the target + * after the Target Device is de-activated + * or else - continue discovery with next + * technology. + * \retval NFCSTATUS_PENDING The Discovery Wheel retarted. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + extern + NFCSTATUS + phHciNfc_Restart_Discovery ( + void *psHciHandle, + void *pHwRef, + uint8_t discovery_type + ); + + + /** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Start_Discovery function Starts the Polling Wheel. + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \retval NFCSTATUS_PENDING The Discovery Wheel Started. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + extern + NFCSTATUS + phHciNfc_Start_Discovery ( + void *psHciHandle, + void *pHwRef + ); + + + /** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Stop_Discovery function Stops the Polling Wheel. + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \retval NFCSTATUS_PENDING The Discovery Wheel Stopped. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + extern + NFCSTATUS + phHciNfc_Stop_Discovery ( + void *psHciHandle, + void *pHwRef + ); + + + /** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Configure function Configures Configures the Polling Wheel to + * select the kind of Tags to be polled. This also allows to enable/disable + * the Tag Emulation. This also configures the Secure elements the UICC, WI and + * Target to Emulate the Tag or Target. + * + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] config_type config_type specifies the type of the + * Parameter configuration. + * \param[in] pConfig pConfig is the Information for + * Configuring the Device. + * \retval NFCSTATUS_PENDING The Emulation configuration pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + extern + NFCSTATUS + phHciNfc_Configure ( + void *psHciHandle, + void *pHwRef, + phHal_eConfigType_t config_type, + phHal_uConfig_t *pConfig + ); + + /** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Switch_SmxMode function Switches the WI(S2C) interface + * from Wired/Virtual to vice versa. + * + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] smx_mode smx_mode specifies the type of the switch + * configuration. + * \param[in] pPollConfig pPollConfig is the Information for + * polling the SmartMX Device. + * \retval NFCSTATUS_PENDING The SmartMX Mode Switch pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + NFCSTATUS + phHciNfc_Switch_SmxMode ( + void *psHciHandle, + void *pHwRef, + phHal_eSmartMX_Mode_t smx_mode, + phHal_sADD_Cfg_t *pPollConfig + ); + + + /** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Switch_SwpMode function Switches the SWP Link + * from On/Off to vice versa. + * + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] swp_mode swp_mode specifies to switch on/off the + * SWP Link. + * \retval NFCSTATUS_PENDING The SWP Mode Switch pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + NFCSTATUS + phHciNfc_Switch_SwpMode ( + void *psHciHandle, + void *pHwRef, + phHal_eSWP_Mode_t swp_mode /* , + void *pSwpCfg */ + ); + + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Connect function selects the discovered target to + * perform the transactions on it. + * + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] p_remote_dev_info p_remote_dev_info is the information + * of the Target Device to be connected . + * \retval NFCSTATUS_PENDING To select the remote target pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + extern + NFCSTATUS + phHciNfc_Connect ( + void *psHciHandle, + void *pHwRef, + phHal_sRemoteDevInformation_t *p_remote_dev_info + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Reactiavte function reactivates the discovered target to + * and selects that target perform the transactions on it. + * + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] p_remote_dev_info p_remote_dev_info is the information + * of the Target Device to be reactivated . + * \retval NFCSTATUS_PENDING To reactivate the remote target pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + + extern + NFCSTATUS + phHciNfc_Reactivate ( + void *psHciHandle, + void *pHwRef, + phHal_sRemoteDevInformation_t *p_target_info + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Disconnect function de-selects the selected target and + * any ongoing transactions . + * + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] discovery_type If NFC_RF_DISCOVERY_REPOLL: Start re-polling of + * the target after the Target Device is + * de-activatedor if NFC_RF_DISCOVERY_CONTINUE - + * continue discovery with next technology or + * stop the discovery wheel. + * + * \retval NFCSTATUS_PENDING To De-select the remote target pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + extern + NFCSTATUS + phHciNfc_Disconnect ( + void *psHciHandle, + void *pHwRef, + uint8_t discovery_type + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Presence_Check function checks for the presence of the target + * selected in the vicinity of the Reader's RF Field . + * + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \retval NFCSTATUS_PENDING Presence Check of the remote target + * pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_Presence_Check ( + void *psHciHandle, + void *pHwRef + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Select_Next_Target function selects and activates the + * next target present in the the Reader's RF Field . + * + * + * \param[in] psHciHandle psHciHandle is the handle or the + * context of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \retval NFCSTATUS_PENDING selection and activation of the next + * remote target pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_Select_Next_Target ( + void *psHciHandle, + void *pHwRef + ); + + + /** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Exchange_Data function exchanges the data + * to/from the selected remote target device. + * + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] p_remote_dev_info p_remote_dev_info is the information of the + * selected target to which data + * should be sent. + * \param[in] p_xchg_info The exchange info contains the command type, + * addr and data to be sent to the connected + * remote target device. + * \retval NFCSTATUS_PENDING Data to remote target pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + extern + NFCSTATUS + phHciNfc_Exchange_Data ( + void *psHciHandle, + void *pHwRef, + phHal_sRemoteDevInformation_t *p_remote_dev_info, + phHciNfc_XchgInfo_t *p_xchg_info + ); + + /** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Send_Data function Sends the data provided + * to the appropriate remote target device. + * + * + * \param[in] psHciHandle psHciHandle is the handle or the context + * of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] p_remote_dev_info p_remote_dev_info is the information + * of the selected target to which data + * should be sent. + * \param[in] p_send_param The send param contains the + * data to be sent to the + * remote device. + * \retval NFCSTATUS_PENDING Data to remote device pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + extern + NFCSTATUS + phHciNfc_Send_Data ( + void *psHciHandle, + void *pHwRef, + phHal_sRemoteDevInformation_t *p_remote_dev_info, + phHciNfc_XchgInfo_t *p_send_param + ); + + /** + * \ingroup grp_hci_nfc + * + * The phHciNfc_System_Test function performs the System Management Tests + * provided by the NFC Peripheral device. + * + * \param[in] psContext psContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] test_type test_type is the type of the Self Test + * that needs to be performed on the device. + * \param[in] test_param test_param is the parameter for the Self Test + * that needs to be performed on the device. + * + * + * \retval NFCSTATUS_PENDING System Test on the System Management + * is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_System_Test( + void *psContext, + void *pHwRef, + uint32_t test_type, + phNfc_sData_t *test_param + ); + + /** + * \ingroup grp_hci_nfc + * + * The phHciNfc_System_Configure function performs the System Management + * Configuration with the value provided. + * + * \param[in] psContext psContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] config_type config_type is the type of the configuration + * that needs to be performed on the device. + * \param[in] config_value config_value is the value for the configuring + * that needs to be performed on the device. + * + * + * \retval NFCSTATUS_PENDING Configuration of the provided information to + * the is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ +extern +NFCSTATUS +phHciNfc_System_Configure ( + void *psHciHandle, + void *pHwRef, + uint32_t config_type, + uint8_t config_value + ); + + /** + * \ingroup grp_hci_nfc + * + * The phHciNfc_System_Get_Info function obtains the System Management + * information from the address provided. + * + * \param[in] psContext psContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] info_type info_type is the type of the Information + * that needs to be obtained from the device. + * \param[in,out] p_val p_val is the pointer to which the + * information need to be updated. + * + * + * \retval NFCSTATUS_PENDING Get information from the NFC Device + * is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ +extern +NFCSTATUS +phHciNfc_System_Get_Info( + void *psHciHandle, + void *pHwRef, + uint32_t info_type, + uint8_t *p_val + ); + +extern +NFCSTATUS +phHciNfc_PRBS_Test ( + void *psHciHandle, + void *pHwRef, + uint32_t test_type, + phNfc_sData_t *test_param + ); + +#if 0 + extern + NFCSTATUS + phHciNfc_Receive_Data ( + void *psHciHandle, + void *pHwRef, + uint8_t *p_data, + uint8_t length + ); + +#endif + + +#endif + diff --git a/libnfc-nxp/phHciNfc_AdminMgmt.c b/libnfc-nxp/phHciNfc_AdminMgmt.c new file mode 100644 index 0000000..45298a1 --- /dev/null +++ b/libnfc-nxp/phHciNfc_AdminMgmt.c @@ -0,0 +1,1202 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file hHciNfc_AdminMgmt.c * +* \brief HCI Admin Gate Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Mon Apr 5 19:23:34 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.47 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include +#include +/* +****************************** Macro Definitions ******************************* +*/ + +#define SESSION_INDEX 0x01U +#define MAX_PIPE_INDEX 0x02U +#define WHITELIST_INDEX 0x03U +#define HOST_LIST_INDEX 0x04U + +/* Max Whitelist Supported by the Device*/ +#define SESSIONID_LEN 0x08U +#define WHITELIST_MAX_LEN 0x03U +#define HOST_LIST_MAX_LEN 0x05U + +/* Address Definitions for HW Configuration */ +#define NFC_ADDRESS_UICC_SESSION 0x9EA2U + + + +/* +*************************** Structure and Enumeration *************************** +*/ + +typedef enum phHciNfc_Admin_Seq{ + ADMIN_PIPE_OPEN = 0x00U, + ADMIN_GET_HOST_LIST, + ADMIN_GET_WHITE_LIST, + ADMIN_GET_SESSION, + ADMIN_VERIFY_SESSION, + ADMIN_CLEAR_UICC_PIPES, + ADMIN_CLEAR_PIPES, + ADMIN_PIPE_REOPEN, + ADMIN_CREATE_PIPES, + ADMIN_SET_SESSION, + ADMIN_SET_WHITE_LIST, + ADMIN_UPDATE_PIPES, + ADMIN_PIPE_CLOSE, + ADMIN_DELETE_PIPES, + ADMIN_END_SEQUENCE +} phHciNfc_Admin_Seq_t; + + +/* Information structure for the Admin Gate */ +typedef struct phHciNfc_AdminGate_Info{ + /* Current running Sequence of the Admin Management */ + phHciNfc_Admin_Seq_t current_seq; + /* Next running Sequence of the Admin Management */ + phHciNfc_Admin_Seq_t next_seq; + /* Pointer to the Admin Pipe Information */ + phHciNfc_Pipe_Info_t *admin_pipe_info; + /* Sequence for the Pipe Initialisation */ + phHciNfc_PipeMgmt_Seq_t pipe_seq; + /* Session ID of the Device */ + uint8_t session_id[SESSIONID_LEN]; + /* Max number of pipes that can be created on the Device */ + uint8_t max_pipe; + /* List of Hosts that can be access the device Admin Gate. */ + uint8_t whitelist[WHITELIST_MAX_LEN]; + /* Host List from the Host Controller */ + uint8_t host_list[HOST_LIST_MAX_LEN]; +} phHciNfc_AdminGate_Info_t; + +/* +*************************** Static Function Declaration ************************** +*/ + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Recv_Admin_Response function interprets the received AdminGate + * response from the Host Controller Gate. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in,out] pResponse Response received from the Host Cotroller + * Admin gate. + * \param[in] length length contains the length of the + * response received from the Host Controller. + * + * \retval NFCSTATUS_PENDING AdminGate Response to be received is pending. + * \retval NFCSTATUS_SUCCESS AdminGate Response received Successfully. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +static +NFCSTATUS +phHciNfc_Recv_Admin_Response( + void *psHciContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + +static +NFCSTATUS +phHciNfc_Admin_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + phHal_sHwReference_t *pHwRef, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); + +static + NFCSTATUS + phHciNfc_Recv_Admin_Cmd ( + void *psContext, + void *pHwRef, + uint8_t *pCmd, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + +static + NFCSTATUS + phHciNfc_Recv_Admin_Event ( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + +/* +*************************** Function Definitions *************************** +*/ + + + +/*! + * \brief Initialisation of Admin Gate and Establish the Session . + * + * This function initialses the Admin Gates and Establishes the Session by creating + * all the required pipes and sets the Session ID + * + */ + +NFCSTATUS +phHciNfc_Admin_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_AdminGate_Info_t *p_admin_info=NULL; + uint8_t length = 0; + + if( (NULL == psHciContext) + || (NULL == pHwRef ) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( ( NULL == psHciContext->p_admin_info ) + && (phHciNfc_Allocate_Resource((void **)(&p_admin_info), + sizeof(phHciNfc_AdminGate_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_admin_info = (void *) p_admin_info; + p_admin_info->current_seq = ADMIN_PIPE_OPEN; + p_admin_info->next_seq = ADMIN_END_SEQUENCE; + p_admin_info->admin_pipe_info = NULL; + } + else + { + p_admin_info = (phHciNfc_AdminGate_Info_t * ) + psHciContext->p_admin_info ; + } + + if( NULL == p_admin_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + switch(p_admin_info->current_seq) + { + /* Admin pipe open sequence , Initially open the Admin Pipe */ + case ADMIN_PIPE_OPEN: + { + if(phHciNfc_Allocate_Resource((void **)(&p_pipe_info), + sizeof(phHciNfc_Pipe_Info_t))!= NFCSTATUS_SUCCESS) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + /* Populate the pipe information in the pipe handle */ + ((phHciNfc_Pipe_Info_t *)p_pipe_info)->pipe.pipe_id = + PIPETYPE_STATIC_ADMIN; + ((phHciNfc_Pipe_Info_t *)p_pipe_info)->recv_resp = + &phHciNfc_Recv_Admin_Response; + ((phHciNfc_Pipe_Info_t *)p_pipe_info)->recv_cmd = + &phHciNfc_Recv_Admin_Cmd; + ((phHciNfc_Pipe_Info_t *)p_pipe_info)->recv_event = + &phHciNfc_Recv_Admin_Event; + psHciContext->p_pipe_list[PIPETYPE_STATIC_ADMIN] = + p_pipe_info ; + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef,p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_admin_info->admin_pipe_info = p_pipe_info ; + p_admin_info->next_seq = ADMIN_GET_SESSION; + status = NFCSTATUS_PENDING; + } + } + break; + } + case ADMIN_GET_SESSION: + { + p_pipe_info = p_admin_info->admin_pipe_info; + p_pipe_info->reg_index = SESSION_INDEX; + p_pipe_info->prev_status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + (uint8_t)HCI_ADMIN_PIPE_ID, + (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == p_pipe_info->prev_status ) + { +#ifdef UICC_SESSION_RESET + p_admin_info->next_seq = ADMIN_CLEAR_UICC_PIPES; +#elif defined (ESTABLISH_SESSION) + p_admin_info->next_seq = ADMIN_VERIFY_SESSION; +#else + p_admin_info->next_seq = ADMIN_CLEAR_PIPES; +#endif + status = NFCSTATUS_PENDING; + } + break; + } +#ifdef UICC_SESSION_RESET + case ADMIN_CLEAR_UICC_PIPES: + { + uint8_t config = 0x00; + p_pipe_info = p_admin_info->admin_pipe_info; + /* TODO: Implement the Clear UICC PIPES Using + * Memory configuration. + */ + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_UICC_SESSION , config ); + if(NFCSTATUS_PENDING == status ) + { + p_admin_info->next_seq = ADMIN_CLEAR_PIPES; + status = NFCSTATUS_PENDING; + } + break; + } +#endif + case ADMIN_VERIFY_SESSION: + { + phHal_sHwConfig_t *p_hw_config = + (phHal_sHwConfig_t *) psHciContext->p_config_params; + phHal_sHwReference_t *p_hw_ref = + (phHal_sHwReference_t *) pHwRef; + int cmp_val = 0; + p_pipe_info = p_admin_info->admin_pipe_info; + cmp_val = phOsalNfc_MemCompare(p_hw_config->session_id , + p_hw_ref->session_id , + sizeof(p_hw_ref->session_id)); + if((cmp_val == 0) + && ( HCI_SESSION == psHciContext->init_mode) + ) + { + psHciContext->hci_mode = hciMode_Session; + status = phHciNfc_Update_Pipe( psHciContext, pHwRef, + &p_admin_info->pipe_seq ); + if((status == NFCSTATUS_SUCCESS) + && (NULL != p_pipe_info)) + { + + p_pipe_info->reg_index = MAX_PIPE_INDEX; + status = phHciNfc_Send_Generic_Cmd( psHciContext, + pHwRef, (uint8_t)HCI_ADMIN_PIPE_ID, + (uint8_t)ANY_GET_PARAMETER ); + p_pipe_info->prev_status = status; + if(NFCSTATUS_PENDING == status ) + { + p_admin_info->next_seq = ADMIN_PIPE_CLOSE; + status = NFCSTATUS_SUCCESS; + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + break; + } + else + { + /* To clear the pipe information*/ + psHciContext->hci_mode = hciMode_Override; + p_admin_info->current_seq = ADMIN_CLEAR_PIPES; + } + } + /* fall through */ + case ADMIN_CLEAR_PIPES: + { + p_pipe_info = p_admin_info->admin_pipe_info; + p_pipe_info->prev_status = + phHciNfc_Send_Admin_Cmd( psHciContext, + pHwRef, ADM_CLEAR_ALL_PIPE, + length, p_pipe_info); + status = ((p_pipe_info->prev_status == NFCSTATUS_PENDING)? + NFCSTATUS_SUCCESS : + p_pipe_info->prev_status); + if(status == NFCSTATUS_SUCCESS) + { + p_admin_info->next_seq = ADMIN_PIPE_REOPEN; + status = NFCSTATUS_PENDING; + } + break; + } + /* Admin pipe Re-Open sequence , Re-Open the Admin Pipe */ + case ADMIN_PIPE_REOPEN: + { + p_pipe_info = p_admin_info->admin_pipe_info; + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef,p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_admin_info->next_seq = ADMIN_CREATE_PIPES; + status = NFCSTATUS_PENDING; + } + break; + } + case ADMIN_CREATE_PIPES: + { + status = phHciNfc_Create_All_Pipes( psHciContext, pHwRef, + &p_admin_info->pipe_seq ); + if(status == NFCSTATUS_SUCCESS) + { + p_admin_info->next_seq = ADMIN_GET_WHITE_LIST; + status = NFCSTATUS_PENDING; + } + break; + } + case ADMIN_GET_WHITE_LIST: + { + p_pipe_info = p_admin_info->admin_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + p_pipe_info->reg_index = WHITELIST_INDEX; + status = phHciNfc_Send_Generic_Cmd( psHciContext, + pHwRef, (uint8_t)HCI_ADMIN_PIPE_ID, + (uint8_t)ANY_GET_PARAMETER ); + p_pipe_info->prev_status = status; + if(HCI_SELF_TEST == psHciContext->init_mode) + { + status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); + } + else + { + if(NFCSTATUS_PENDING == status ) + { + p_admin_info->next_seq = ADMIN_GET_HOST_LIST; + /* status = NFCSTATUS_SUCCESS; */ + } + } + } + break; + } + case ADMIN_GET_HOST_LIST: + { + p_pipe_info = p_admin_info->admin_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + p_pipe_info->reg_index = HOST_LIST_INDEX; + status = phHciNfc_Send_Generic_Cmd( psHciContext, + pHwRef, (uint8_t)HCI_ADMIN_PIPE_ID, + (uint8_t)ANY_GET_PARAMETER ); + p_pipe_info->prev_status = status; + if(NFCSTATUS_PENDING == status ) + { + +#if defined(HOST_WHITELIST) + p_admin_info->next_seq = ADMIN_SET_WHITE_LIST; +#else + p_admin_info->next_seq = ADMIN_SET_SESSION; + status = NFCSTATUS_SUCCESS; +#endif + } + } + break; + } + case ADMIN_SET_WHITE_LIST: + { + p_pipe_info = p_admin_info->admin_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + uint8_t i = 0; + + for (i = 0; i < WHITELIST_MAX_LEN - 2; i++ ) + { + p_admin_info->whitelist[i] = i + 2; + } + status = phHciNfc_Set_Param(psHciContext, pHwRef, + p_pipe_info, WHITELIST_INDEX, + (uint8_t *)p_admin_info->whitelist, i ); + if(NFCSTATUS_PENDING == status ) + { + p_admin_info->next_seq = ADMIN_SET_SESSION; + status = NFCSTATUS_SUCCESS; + } + } + break; + } + case ADMIN_SET_SESSION: + { + phHal_sHwConfig_t *p_hw_config = + (phHal_sHwConfig_t *) psHciContext->p_config_params; + p_pipe_info = p_admin_info->admin_pipe_info; + status = phHciNfc_Set_Param(psHciContext, pHwRef, p_pipe_info, + SESSION_INDEX, (uint8_t *)(p_hw_config->session_id), + sizeof(p_hw_config->session_id)); + if(NFCSTATUS_PENDING == p_pipe_info->prev_status ) + { + p_admin_info->next_seq = ADMIN_PIPE_CLOSE; + status = NFCSTATUS_SUCCESS; + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + + }/* End of the Sequence Switch */ + + }/* End of the Admin Info Memory Check */ + + }/* End of Null context Check */ + + return status; +} + +#ifdef HOST_EMULATION + +/*! + * \brief Creates the Card Emulation Gate Pipes . + * + * This function Creates the Card Emulation Gate. + */ + +NFCSTATUS +phHciNfc_Admin_CE_Init( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_GateID_t ce_gate + + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + /* phHciNfc_Pipe_Info_t *pipe_info = NULL; */ + phHciNfc_AdminGate_Info_t *p_admin_info=NULL; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( NULL != psHciContext->p_admin_info ) + { + p_admin_info = psHciContext->p_admin_info; + + switch(ce_gate) + { + /* Card Emulation A Gate Pipe Creation */ + case phHciNfc_CETypeAGate: + { + p_admin_info->pipe_seq = PIPE_CARD_A_CREATE; + break; + } + /* Card Emulation B Gate Pipe Creation */ + case phHciNfc_CETypeBGate: + { + p_admin_info->pipe_seq = PIPE_CARD_B_CREATE; + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_HCI_GATE_NOT_SUPPORTED); + break; + } + } /* End of CE Gate Switch */ + + if (NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_CE_Pipes_OP( psHciContext, + pHwRef, &p_admin_info->pipe_seq ); + if(status == NFCSTATUS_SUCCESS) + { + p_admin_info->next_seq = ADMIN_END_SEQUENCE; + /* status = NFCSTATUS_PENDING; */ + } + } + + }/* End of NULL Check for the Admin_Info */ + } /* End of Null Check for the Context */ + return status; +} + +#endif + +/*! + * \brief Releases the resources allocated the Admin Management. + * + * This function Releases the resources allocated the Admin Management + * and resets the hardware to the reset state. + */ + +NFCSTATUS +phHciNfc_Admin_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_HostID_t host_type + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( NULL != psHciContext->p_admin_info ) + { + if(phHciNfc_UICCHostID != host_type) + { + p_pipe_info = psHciContext->p_pipe_list[PIPETYPE_STATIC_ADMIN]; + + status = phHciNfc_Close_Pipe( psHciContext, + pHwRef, p_pipe_info ); + } + + }/* End of NULL Check for the Admin_Info */ + } /* End of Null Check for the Context */ + return status; +} + + +/*! + * \brief Sends the HCI Admin Event to the corresponding peripheral device. + * + * This function sends the HCI Admin Events to the connected NFC Pheripheral + * device + */ + + NFCSTATUS + phHciNfc_Send_Admin_Event ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t event, + uint8_t length, + void *params + ) +{ + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_AdminGate_Info_t *p_admin_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + psHciContext->tx_total = 0 ; + length += HCP_HEADER_LEN ; + p_admin_info = psHciContext->p_admin_info; + + if( EVT_HOT_PLUG == event ) + { + + /* Use the HCP Packet Structure to Construct the send HCP + * Packet data. + */ + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) HCI_ADMIN_PIPE_ID, + HCP_MSG_TYPE_EVENT, event); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INSTRUCTION); + } + + if( NFCSTATUS_SUCCESS == status ) + { + p_admin_info->admin_pipe_info->sent_msg_type = HCP_MSG_TYPE_EVENT; + p_admin_info->admin_pipe_info->prev_msg = event ; + p_admin_info->admin_pipe_info->param_info = params ; + psHciContext->tx_total = length; + psHciContext->response_pending = FALSE ; + status = phHciNfc_Send_HCP( (void *)psHciContext, (void *)pHwRef ); + p_admin_info->admin_pipe_info->prev_status = NFCSTATUS_PENDING; + } + } + + return status; +} + + +/*! + * \brief Sends the HCI Admin Commands to the corresponding peripheral device. + * + * This function sends the HCI Admin Commands to the connected NFC Pheripheral + * device + */ + + NFCSTATUS + phHciNfc_Send_Admin_Cmd ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t cmd, + uint8_t length, + void *params + ) +{ + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + phHciNfc_AdminGate_Info_t *p_admin_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t i=0; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || (NULL == pHwRef) + || (NULL == params) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + p_pipe_info = (phHciNfc_Pipe_Info_t *) params; + psHciContext->tx_total = 0 ; + length += HCP_HEADER_LEN ; + p_admin_info = psHciContext->p_admin_info; + switch( cmd ) + { + case ADM_CREATE_PIPE: + { + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Use the HCP Packet Structure to Construct the send HCP + * Packet data. + */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) HCI_ADMIN_PIPE_ID, + HCP_MSG_TYPE_COMMAND, cmd); + hcp_message = &(hcp_packet->msg.message); + + /* Source HOST ID Parameter is not passed as a + * parameter in the HCI SPEC */ + + /* hcp_message->payload[i++] = p_pipe_info->pipe.source.host_id; */ + hcp_message->payload[i++] = p_pipe_info->pipe.source.gate_id; + hcp_message->payload[i++] = p_pipe_info->pipe.dest.host_id; + hcp_message->payload[i++] = p_pipe_info->pipe.dest.gate_id; + break; + } + case ADM_DELETE_PIPE: + { + uint8_t pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + + pipe_id = p_pipe_info->pipe.pipe_id; + if( pipe_id < PIPETYPE_DYNAMIC ) + { + /* The Static Pipes cannot be Deleted */ + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_PARAMETER ); + HCI_DEBUG("phHciNfc_Send_Admin_Cmd: Static Pipe %u " + "Cannot be Deleted \n",pipe_id); + } + else + { + + /* Use the HCP Packet Structure to Construct the send HCP + * Packet data. + */ + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) HCI_ADMIN_PIPE_ID, + HCP_MSG_TYPE_COMMAND, cmd); + hcp_message = &(hcp_packet->msg.message); + hcp_message->payload[i++] = pipe_id ; + } + break; + } + case ADM_CLEAR_ALL_PIPE: + { + + /* Use the HCP Packet Structure to Construct the send HCP + * Packet data. + */ + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) HCI_ADMIN_PIPE_ID, + HCP_MSG_TYPE_COMMAND, cmd); + hcp_message = &(hcp_packet->msg.message); + break; + } + /* These are notifications and can not be sent by the Host */ + /* case ADM_NOTIFY_PIPE_CREATED: */ + /* case ADM_NOTIFY_PIPE_DELETED: */ + /* case ADM_NOTIFY_ALL_PIPE_CLEARED: */ + default: + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_COMMAND); + break; + } + if( NFCSTATUS_SUCCESS == status ) + { + p_admin_info->admin_pipe_info->sent_msg_type = HCP_MSG_TYPE_COMMAND; + p_admin_info->admin_pipe_info->prev_msg = cmd; + p_admin_info->admin_pipe_info->param_info = p_pipe_info; + psHciContext->tx_total = length; + psHciContext->response_pending = TRUE; + status = phHciNfc_Send_HCP( (void *)psHciContext, (void *)pHwRef ); + p_admin_info->admin_pipe_info->prev_status = NFCSTATUS_PENDING; + } + } + + return status; +} + + +/*! + * \brief Receives the HCI Response from the corresponding peripheral device. + * + * This function receives the HCI Command Response from the connected NFC + * Pheripheral device. + */ + +static +NFCSTATUS +phHciNfc_Recv_Admin_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_AdminGate_Info_t *p_admin_info = NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + uint8_t prev_cmd = 0; + NFCSTATUS prev_status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_admin_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + hcp_packet = (phHciNfc_HCP_Packet_t *)pResponse; + hcp_message = &hcp_packet->msg.message; + p_admin_info = psHciContext->p_admin_info; + prev_cmd = p_admin_info->admin_pipe_info->prev_msg ; + prev_status = p_admin_info->admin_pipe_info->prev_status ; + if(prev_status == NFCSTATUS_PENDING) + { + switch(prev_cmd) + { + case ANY_SET_PARAMETER: + { + break; + } + case ANY_GET_PARAMETER: + { + status = phHciNfc_Admin_InfoUpdate(psHciContext, + (phHal_sHwReference_t *)pHwRef, + p_admin_info->admin_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); + break; + } + case ANY_OPEN_PIPE: + { + break; + } + case ANY_CLOSE_PIPE: + { + phOsalNfc_FreeMemory(p_admin_info->admin_pipe_info); + p_admin_info->admin_pipe_info = NULL; + psHciContext->p_pipe_list[PIPETYPE_STATIC_ADMIN] = NULL; + break; + } + case ADM_CREATE_PIPE: + { + p_pipe_info = (phHciNfc_Pipe_Info_t *) + p_admin_info->admin_pipe_info->param_info; + pipe_id = hcp_message->payload[RESPONSE_PIPEID_OFFSET]; + status = phHciNfc_Update_PipeInfo(psHciContext, + &(p_admin_info->pipe_seq), pipe_id, p_pipe_info); + if(NFCSTATUS_SUCCESS == status ) + { + psHciContext->p_pipe_list[pipe_id] = p_pipe_info; + p_pipe_info->pipe.pipe_id = pipe_id; + } + break; + } + case ADM_DELETE_PIPE: + { + p_pipe_info = (phHciNfc_Pipe_Info_t *) + p_admin_info->admin_pipe_info->param_info; + if ( NULL != p_pipe_info ) + { + pipe_id = p_pipe_info->pipe.pipe_id; + status = phHciNfc_Update_PipeInfo( + psHciContext, &(p_admin_info->pipe_seq), + (uint8_t) HCI_UNKNOWN_PIPE_ID, p_pipe_info); + if(NFCSTATUS_SUCCESS == status ) + { + phOsalNfc_FreeMemory(p_pipe_info); + psHciContext->p_pipe_list[pipe_id] = NULL; + } + } + break; + } + case ADM_CLEAR_ALL_PIPE: + { + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + HCI_DEBUG("%s: Default Statement Should Not Occur \n", + "phHciNfc_Recv_Admin_Response"); + break; + } + } + } + if( NFCSTATUS_SUCCESS == status ) + { + if( NULL != p_admin_info->admin_pipe_info) + { + p_admin_info->admin_pipe_info->prev_status = NFCSTATUS_SUCCESS; + } + p_admin_info->current_seq = p_admin_info->next_seq; + } + } + return status; +} + +/*! + * \brief Receives the HCI Admin Commands from the corresponding peripheral device. + * + * This function receives the HCI Admin Commands from the connected NFC Pheripheral + * device + */ +static + NFCSTATUS + phHciNfc_Recv_Admin_Cmd ( + void *psContext, + void *pHwRef, + uint8_t *pCmd, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + phHciNfc_AdminGate_Info_t *p_admin_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t index=0; + uint8_t pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + uint8_t cmd = (uint8_t) HCP_MSG_INSTRUCTION_INVALID; + uint8_t response = (uint8_t) ANY_OK; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || (NULL == pHwRef) + || (HCP_HEADER_LEN > length ) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + hcp_packet = (phHciNfc_HCP_Packet_t *)pCmd; + hcp_message = &hcp_packet->msg.message; + p_admin_info = psHciContext->p_admin_info; + /* Get the Command instruction bits from the Message Header */ + cmd = (uint8_t) GET_BITS8( hcp_message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + + switch( cmd ) + { + /* These are notifications sent by the Host Controller */ + case ADM_NOTIFY_PIPE_CREATED: + { + pipe_id = hcp_message->payload[RESPONSE_PIPEID_OFFSET]; + p_pipe_info = (phHciNfc_Pipe_Info_t *) + phOsalNfc_GetMemory(sizeof(phHciNfc_Pipe_Info_t)); + memset(p_pipe_info, 0, sizeof(phHciNfc_Pipe_Info_t)); + if(NULL != p_pipe_info) + { + /* The Source Host is the UICC Host */ + p_pipe_info->pipe.source.host_id = + hcp_message->payload[index++]; + /* The Source Gate is same as the Destination Gate */ + p_pipe_info->pipe.source.gate_id = + hcp_message->payload[index++]; + /* The Source Host is the Terminal Host */ + p_pipe_info->pipe.dest.host_id = + hcp_message->payload[index++]; + p_pipe_info->pipe.dest.gate_id = + hcp_message->payload[index++]; + p_pipe_info->pipe.pipe_id = + hcp_message->payload[index++]; + } + status = phHciNfc_Update_PipeInfo(psHciContext, + &(p_admin_info->pipe_seq), pipe_id, p_pipe_info); + + if( NFCSTATUS_SUCCESS == status ) + { + psHciContext->p_pipe_list[pipe_id] = p_pipe_info; + if (NULL != p_pipe_info) + { + p_pipe_info->pipe.pipe_id = pipe_id; + } + } + break; + } + case ADM_NOTIFY_PIPE_DELETED: + { + pipe_id = hcp_message->payload[index++]; + p_pipe_info = psHciContext->p_pipe_list[pipe_id]; + if ( NULL != p_pipe_info ) + { + status = phHciNfc_Update_PipeInfo( + psHciContext, &(p_admin_info->pipe_seq), + (uint8_t) HCI_UNKNOWN_PIPE_ID, p_pipe_info); + if(NFCSTATUS_SUCCESS == status ) + { + phOsalNfc_FreeMemory(p_pipe_info); + psHciContext->p_pipe_list[pipe_id] = NULL; + } + } + break; + } + /* TODO: Since we receive the Host ID, we need to clear + * all the pipes created with the host + */ + case ADM_NOTIFY_ALL_PIPE_CLEARED: + { + break; + } + /* case ADM_CREATE_PIPE: */ + /* case ADM_DELETE_PIPE: */ + /* case ADM_CLEAR_ALL_PIPE: */ + default: + { + response = ANY_E_CMD_NOT_SUPPORTED; + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_COMMAND_NOT_SUPPORTED); + break; + } + } + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) HCI_ADMIN_PIPE_ID, + HCP_MSG_TYPE_RESPONSE, response ); + psHciContext->tx_total = HCP_HEADER_LEN; + status = phHciNfc_Send_HCP( (void *)psHciContext, (void *)pHwRef ); + + p_admin_info->admin_pipe_info->recv_msg_type = HCP_MSG_TYPE_COMMAND; + p_admin_info->admin_pipe_info->sent_msg_type = HCP_MSG_TYPE_RESPONSE; + p_admin_info->admin_pipe_info->prev_msg = response; + p_admin_info->admin_pipe_info->prev_status = NFCSTATUS_PENDING; + } + return status; +} + +/*! + * \brief Receives the HCI Admin Event from the corresponding peripheral device. + * + * This function receives the HCI Admin Events from the connected NFC Pheripheral + * device + */ +static + NFCSTATUS + phHciNfc_Recv_Admin_Event ( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + uint8_t event = (uint8_t) HCP_MSG_INSTRUCTION_INVALID; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || (NULL == pHwRef) + || (HCP_HEADER_LEN > length ) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + hcp_packet = (phHciNfc_HCP_Packet_t *)pEvent; + hcp_message = &hcp_packet->msg.message; + /* Get the Command instruction bits from the Message Header */ + event = (uint8_t) GET_BITS8( hcp_message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + + if( EVT_HOT_PLUG == event ) + { + status = phHciNfc_Send_Admin_Event ( psHciContext, pHwRef, + EVT_HOT_PLUG, 0 ,NULL); + + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INSTRUCTION); + } + + + } + return status; +} + + +static +NFCSTATUS +phHciNfc_Admin_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + phHal_sHwReference_t *pHwRef, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + phHciNfc_AdminGate_Info_t *p_admin_info=NULL; + uint8_t i=0; + NFCSTATUS status = NFCSTATUS_SUCCESS; + if(NULL == reg_value) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + p_admin_info = psHciContext->p_admin_info ; + HCI_PRINT_BUFFER("Admin Mgmt Info Buffer",reg_value,reg_length); + switch(index) + { + case SESSION_INDEX : + { + for(i=0 ;(reg_length == SESSIONID_LEN)&&(i < reg_length); i++) + { + p_admin_info->session_id[i] = reg_value[i]; + pHwRef->session_id[i] = reg_value[i]; + } + break; + } + case MAX_PIPE_INDEX : + { + p_admin_info->max_pipe = reg_value[i]; + break; + } + case WHITELIST_INDEX : + { + for(i=0 ;(reg_length <= WHITELIST_MAX_LEN)&&(i < reg_length); i++) + { + p_admin_info->whitelist[i] = reg_value[i]; + } + break; + } + case HOST_LIST_INDEX : + { + for(i=0 ;(reg_length <= HOST_LIST_MAX_LEN)&&(i < reg_length); i++) + { + p_admin_info->host_list[i] = reg_value[i]; + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } /*End of the default Switch Case */ + + } /*End of the Index Switch */ + + } /* End of Context and the Identity information validity check */ + + return status; +} + diff --git a/libnfc-nxp/phHciNfc_AdminMgmt.h b/libnfc-nxp/phHciNfc_AdminMgmt.h new file mode 100644 index 0000000..cf1ac3a --- /dev/null +++ b/libnfc-nxp/phHciNfc_AdminMgmt.h @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_AdminMgmt.h * +* \brief HCI Header for the Admin Gate Management. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Mon Mar 29 17:34:48 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.7 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + + +#ifndef PHHCINFC_ADMINMGMT_H +#define PHHCINFC_ADMINMGMT_H + +/*@}*/ + + +/** + * \name HCI + * + * File: \ref phHciNfc_AdminMgmt.h + * + */ +/*@{*/ +#define PHHCINFC_ADMINMGMT_FILEREVISION "$Revision: 1.7 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_ADMINMGMT_FILEALIASES "$Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +#define EVT_HOT_PLUG 0x03 + +/* +******************** Enumeration and Structure Definition ********************** +*/ + +/** \defgroup grp_hci_nfc HCI Component + * + * + */ + + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Admin_Initialise function Initialises the AdminGate and opens the + * Admin Gate pipe + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING AdminGate Initialisation is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_Admin_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Admin_Release function closes the opened pipes between + * the Host Controller Device and the NFC Device. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] host_type host_type is the type of the host + * to be released. + * + * \retval NFCSTATUS_PENDING Release of the Admingate resources are + * pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_Admin_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_HostID_t host_type + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Send_Admin_Cmd function Sends the Particular AdminGate + * command to the Host Controller Device. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] cmd cmd to be sent to the Admin gate of the + * Host controller. + * \param[in] length Size of the data sent in the parameter. + * \param[in,out] params params contains the parameters that are + * required by the particular HCI command. + * + * \retval None + * + */ + +extern +NFCSTATUS +phHciNfc_Send_Admin_Cmd ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t cmd, + uint8_t length, + void *params + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Send_Admin_Cmd function Sends the Particular AdminGate + * command to the Host Controller Device. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] Event Event to be sent to the Admin gate of the + * Host controller. + * \param[in] length Size of the data sent in the parameter. + * \param[in,out] params params contains the parameters that are + * required by the particular HCI command. + * + * \retval None + * + */ + +extern +NFCSTATUS +phHciNfc_Send_Admin_Event ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t event, + uint8_t length, + void *params + ); + +extern +NFCSTATUS +phHciNfc_Admin_CE_Init( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_GateID_t ce_gate + ); + + +#endif + diff --git a/libnfc-nxp/phHciNfc_CE_A.c b/libnfc-nxp/phHciNfc_CE_A.c new file mode 100644 index 0000000..511a3c5 --- /dev/null +++ b/libnfc-nxp/phHciNfc_CE_A.c @@ -0,0 +1,732 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_CE_A.c * +* \brief HCI card emulation A management routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Aug 21 18:35:05 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.14 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include +#include +/* +****************************** Macro Definitions ******************************* +*/ +#if defined (HOST_EMULATION) +#include + +#define CE_A_EVT_NFC_SEND_DATA 0x10U +#define CE_A_EVT_NFC_FIELD_ON 0x11U +#define CE_A_EVT_NFC_DEACTIVATED 0x12U +#define CE_A_EVT_NFC_ACTIVATED 0x13U +#define CE_A_EVT_NFC_FIELD_OFF 0x14U + +/* +*************************** Structure and Enumeration *************************** +*/ + + +/* +*************************** Static Function Declaration ************************** +*/ + +static +NFCSTATUS +phHciNfc_Recv_CE_A_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_CE_A_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +#if defined (SEND_DATA_EVENT) +static +NFCSTATUS +phHciNfc_CE_A_ProcessData( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t *pData, + uint8_t length + ); +#endif /* #if defined (SEND_DATA_EVENT) */ + +/* +*************************** Function Definitions *************************** +*/ +NFCSTATUS +phHciNfc_CE_A_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_CE_A_Info_t *ps_ce_a_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( + ( NULL == psHciContext->p_ce_a_info ) && + (phHciNfc_Allocate_Resource((void **)(&ps_ce_a_info), + sizeof(phHciNfc_CE_A_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_ce_a_info = ps_ce_a_info; + ps_ce_a_info->current_seq = HOST_CE_A_INVALID_SEQ; + ps_ce_a_info->next_seq = HOST_CE_A_INVALID_SEQ; + ps_ce_a_info->pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + return status; +} + +NFCSTATUS +phHciNfc_CE_A_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + /* + 1. Open Pipe, + 2. Set all parameters + */ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t sak = HOST_CE_A_SAK_DEFAULT; + static uint8_t atqa_info[] = { NXP_CE_A_ATQA_HIGH, + NXP_CE_A_ATQA_LOW}; + + if ((NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_ce_a_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_CE_A_Info_t *ps_ce_a_info = ((phHciNfc_CE_A_Info_t *) + psHciContext->p_ce_a_info ); + phHciNfc_Pipe_Info_t *ps_pipe_info = NULL; + + ps_pipe_info = ps_ce_a_info->p_pipe_info; + if(NULL == ps_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + switch(ps_ce_a_info->current_seq) + { + case HOST_CE_A_PIPE_OPEN: + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, ps_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + ps_ce_a_info->next_seq = HOST_CE_A_SAK_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + case HOST_CE_A_SAK_SEQ: + { + /* HOST Card Emulation A SAK Configuration */ + ps_pipe_info->reg_index = HOST_CE_A_SAK_INDEX; + /* Configure the SAK of Host Card Emulation A */ + sak = (uint8_t)HOST_CE_A_SAK_DEFAULT; + ps_pipe_info->param_info =(void*)&sak ; + ps_pipe_info->param_length = sizeof(sak) ; + status = phHciNfc_Send_Generic_Cmd(psHciContext,pHwRef, + ps_pipe_info->pipe.pipe_id, + (uint8_t)ANY_SET_PARAMETER); + if(status == NFCSTATUS_PENDING) + { + ps_ce_a_info->next_seq = HOST_CE_A_ATQA_SEQ; + } + break; + } + case HOST_CE_A_ATQA_SEQ: + { + /* HOST Card Emulation A ATQA Configuration */ + ps_pipe_info->reg_index = HOST_CE_A_ATQA_INDEX; + /* Configure the ATQA of Host Card Emulation A */ + ps_pipe_info->param_info = (void*)atqa_info ; + ps_pipe_info->param_length = sizeof(atqa_info) ; + status = phHciNfc_Send_Generic_Cmd(psHciContext,pHwRef, + ps_pipe_info->pipe.pipe_id, + (uint8_t)ANY_SET_PARAMETER); + if(status == NFCSTATUS_PENDING) + { + ps_ce_a_info->next_seq = HOST_CE_A_ENABLE_SEQ; + } + break; + } + case HOST_CE_A_ENABLE_SEQ: + { + status = phHciNfc_CE_A_Mode( psHciContext, + pHwRef, HOST_CE_MODE_ENABLE ); + if(status == NFCSTATUS_PENDING) + { + ps_ce_a_info->next_seq = HOST_CE_A_DISABLE_SEQ; + status = NFCSTATUS_SUCCESS; + } + break; + } + default : + { + break; + } + } + } + } + + return status; +} + +NFCSTATUS +phHciNfc_CE_A_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + /* + 1. Close pipe + */ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if ((NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_ce_a_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_CE_A_Info_t *ps_ce_a_info = ((phHciNfc_CE_A_Info_t *) + psHciContext->p_ce_a_info ); + phHciNfc_Pipe_Info_t *ps_pipe_info = NULL; + + ps_pipe_info = ps_ce_a_info->p_pipe_info; + if(NULL == ps_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_NOT_ALLOWED); + } + else + { + switch(ps_ce_a_info->current_seq) + { + case HOST_CE_A_DISABLE_SEQ: + { + status = phHciNfc_CE_A_Mode( psHciContext, + pHwRef, HOST_CE_MODE_DISABLE ); + if(status == NFCSTATUS_PENDING) + { + ps_ce_a_info->next_seq = HOST_CE_A_PIPE_CLOSE; + } + break; + } + case HOST_CE_A_PIPE_CLOSE: + { + /* HOST Card Emulation A pipe close sequence */ + status = phHciNfc_Close_Pipe( psHciContext, + pHwRef, ps_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + ps_ce_a_info->next_seq = HOST_CE_A_PIPE_DELETE; + status = NFCSTATUS_PENDING; + } + break; + } + case HOST_CE_A_PIPE_DELETE: + { + /* HOST Card Emulation A pipe delete sequence */ + status = phHciNfc_Delete_Pipe( psHciContext, + pHwRef, ps_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { +#if 0 + ps_ce_a_info->pipe_id = HCI_UNKNOWN_PIPE_ID; + psHciContext->p_pipe_list[ps_ce_a_info->pipe_id] = NULL; + phOsalNfc_FreeMemory((void *)ps_ce_a_info->p_pipe_info); + ps_ce_a_info->p_pipe_info = NULL; +#endif + ps_ce_a_info->next_seq = HOST_CE_A_PIPE_OPEN; + } + break; + } + default : + { + break; + } + } + } + } + return status; +} + +NFCSTATUS +phHciNfc_CE_A_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_ce_a_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_CE_A_Info_t *ps_ce_a_info=NULL; + ps_ce_a_info = (phHciNfc_CE_A_Info_t *) + psHciContext->p_ce_a_info ; + + ps_ce_a_info->current_seq = HOST_CE_A_PIPE_OPEN; + ps_ce_a_info->next_seq = HOST_CE_A_PIPE_OPEN; + /* Update the pipe_id of the card emulation A Gate o + btained from the HCI Response */ + ps_ce_a_info->pipe_id = pipeID; + if (HCI_UNKNOWN_PIPE_ID != pipeID) + { + ps_ce_a_info->p_pipe_info = pPipeInfo; + if (NULL != pPipeInfo) + { + /* Update the Response Receive routine of the card + emulation A Gate */ + pPipeInfo->recv_resp = &phHciNfc_Recv_CE_A_Response; + /* Update the event Receive routine of the card emulation A Gate */ + pPipeInfo->recv_event = &phHciNfc_Recv_CE_A_Event; + } + } + else + { + ps_ce_a_info->p_pipe_info = NULL; + } + } + + return status; +} + +NFCSTATUS +phHciNfc_CE_A_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_ce_a_info ) + ) + { + phHciNfc_CE_A_Info_t *ps_ce_a_info=NULL; + ps_ce_a_info = (phHciNfc_CE_A_Info_t *) + psHciContext->p_ce_a_info ; + *ppipe_id = ps_ce_a_info->pipe_id ; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + +#ifdef CE_A_SEND_EVENT +NFCSTATUS +phHciNfc_CE_A_SendData_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, + uint8_t length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + return status; +} +#endif /* #ifdef CE_A_SEND_EVENT */ + +static +NFCSTATUS +phHciNfc_Recv_CE_A_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_ce_a_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_CE_A_Info_t *ps_ce_a_info=NULL; + uint8_t prev_cmd = ANY_GET_PARAMETER; + ps_ce_a_info = (phHciNfc_CE_A_Info_t *) + psHciContext->p_ce_a_info ; + if( NULL == ps_ce_a_info->p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + prev_cmd = ps_ce_a_info->p_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_GET_PARAMETER: + { +#if 0 + status = phHciNfc_CE_A_InfoUpdate(psHciContext, + ps_ce_a_info->p_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (length - HCP_HEADER_LEN)); +#endif /* #if 0 */ + break; + } + case ANY_SET_PARAMETER: + { + HCI_PRINT("CE A Parameter Set \n"); + break; + } + case ANY_OPEN_PIPE: + { + HCI_PRINT("CE A open pipe complete\n"); + break; + } + case ANY_CLOSE_PIPE: + { + HCI_PRINT("CE A close pipe complete\n"); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + status = phHciNfc_CE_A_Update_Seq(psHciContext, + UPDATE_SEQ); + ps_ce_a_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; + } + } + } + return status; +} + +NFCSTATUS +phHciNfc_CE_A_Update_Seq( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t seq_type + ) +{ + phHciNfc_CE_A_Info_t *ps_ce_a_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_ce_a_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + ps_ce_a_info = (phHciNfc_CE_A_Info_t *) + psHciContext->p_ce_a_info ; + switch(seq_type) + { + case RESET_SEQ: + case INIT_SEQ: + { + ps_ce_a_info->next_seq = HOST_CE_A_PIPE_OPEN; + ps_ce_a_info->current_seq = HOST_CE_A_PIPE_OPEN; + break; + } + case UPDATE_SEQ: + { + ps_ce_a_info->current_seq = ps_ce_a_info->next_seq; + break; + } + case INFO_SEQ: + { + break; + } + case REL_SEQ: + { + ps_ce_a_info->next_seq = HOST_CE_A_DISABLE_SEQ; + ps_ce_a_info->current_seq = HOST_CE_A_DISABLE_SEQ; + break; + } + default: + { + break; + } + } + } + return status; +} + + +NFCSTATUS +phHciNfc_CE_A_Mode( + void *psHciHandle, + void *pHwRef, + uint8_t enable_type + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t param = 0 ; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + + if((NULL == psHciContext)||(NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_ce_a_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_CE_A_Info_t *ps_ce_a_info = (phHciNfc_CE_A_Info_t *) + psHciContext->p_ce_a_info ; + phHciNfc_Pipe_Info_t *p_pipe_info = ps_ce_a_info->p_pipe_info; + + if (NULL != p_pipe_info) + { + p_pipe_info->reg_index = HOST_CE_A_MODE_INDEX; + /* Enable/Disable Host Card Emulation A */ + param = (uint8_t)enable_type; + p_pipe_info->param_info =(void*)¶m ; + p_pipe_info->param_length = sizeof(param) ; + status = phHciNfc_Send_Generic_Cmd(psHciContext,pHwRef, + ps_ce_a_info->pipe_id,(uint8_t)ANY_SET_PARAMETER); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_HCI_GATE_NOT_SUPPORTED); + } + } + return status; +} + + + +static +NFCSTATUS +phHciNfc_Recv_CE_A_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_ce_a_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_CE_A_Info_t *ps_ce_a_info=NULL; + phHciNfc_HCP_Message_t *message = NULL; + static phHal_sEventInfo_t event_info; + uint8_t instruction=0; + + ps_ce_a_info = (phHciNfc_CE_A_Info_t *) + psHciContext->p_ce_a_info ; + + /* Variable was set but never used (ARM warning) */ + PHNFC_UNUSED_VARIABLE(ps_ce_a_info); + + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &p_packet->msg.message; + /* Get the instruction bits from the Message Header */ + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, + HCP_MSG_INSTRUCTION_LEN); + psHciContext->host_rf_type = phHal_eISO14443_A_PICC; + event_info.eventHost = phHal_eHostController; + event_info.eventSource = phHal_eISO14443_A_PICC; + switch(instruction) + { + case CE_A_EVT_NFC_ACTIVATED: + { + event_info.eventType = NFC_EVT_ACTIVATED; + /* Notify to the HCI Generic layer To Update the FSM */ + break; + } + case CE_A_EVT_NFC_DEACTIVATED: + { + event_info.eventType = NFC_EVT_DEACTIVATED; + HCI_PRINT("CE A Target Deactivated\n"); + break; + } + case CE_A_EVT_NFC_SEND_DATA: + { + HCI_PRINT("CE A data is received from the PN544\n"); +#if defined (SEND_DATA_EVENT) + if(length > HCP_HEADER_LEN) + { + status = phHciNfc_CE_A_ProcessData( + psHciContext, pHwRef, + &pEvent[HCP_HEADER_LEN], + (length - HCP_HEADER_LEN)); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } +#endif /* #if defined (SEND_DATA_EVENT) */ + break; + } + case CE_A_EVT_NFC_FIELD_ON: + { + HCI_PRINT("CE A field on\n"); + event_info.eventType = NFC_EVT_FIELD_ON; + break; + } + case CE_A_EVT_NFC_FIELD_OFF: + { + HCI_PRINT("CE A field off\n"); + event_info.eventType = NFC_EVT_FIELD_OFF; + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INSTRUCTION); + break; + } + } + if(NFCSTATUS_SUCCESS == status) + { + phHciNfc_Notify_Event(psHciContext, pHwRef, + NFC_NOTIFY_EVENT, + &event_info); + } + } + return status; +} + +#if defined (SEND_DATA_EVENT) +static +NFCSTATUS +phHciNfc_CE_A_ProcessData( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t *pData, + uint8_t length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + static uint8_t send_data[] = {0x6D, 0x80}; + status = phHciNfc_CE_A_SendData_Event( + (void *)psHciContext, pHwRef, + send_data, sizeof(send_data)); + + return status; +} +#endif /* #if defined (SEND_DATA_EVENT) */ + +#endif /* #if defined (HOST_EMULATION) */ + + diff --git a/libnfc-nxp/phHciNfc_CE_A.h b/libnfc-nxp/phHciNfc_CE_A.h new file mode 100644 index 0000000..aab5b24 --- /dev/null +++ b/libnfc-nxp/phHciNfc_CE_A.h @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_CE_A.h * +* \brief HCI card emulation management routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Aug 14 17:01:27 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.5 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + + +#ifndef PHHCINFC_CE_A_H +#define PHHCINFC_CE_A_H + +/*@}*/ + + +/** +* \name HCI +* +* File: \ref phHciNfc_CE_A.h +* +*/ +/*@{*/ +#define PHHCINFC_CE_A_FILEREVISION "$Revision: 1.5 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_CE_A_FILEALIASES "$Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +#define HOST_CE_A_MODE_INDEX (0x01U) +#define HOST_CE_A_UID_REG_INDEX (0x02U) +#define HOST_CE_A_SAK_INDEX (0x03U) +#define HOST_CE_A_ATQA_INDEX (0x04U) +#define HOST_CE_A_APP_DATA_INDEX (0x05U) +#define HOST_CE_A_FWI_SFGT_INDEX (0x06U) +#define HOST_CE_A_CID_INDEX (0x07U) +#define HOST_CE_A_CLT_INDEX (0x08U) +#define HOST_CE_A_DATA_RATE_INDEX (0x09U) + + +/* +******************** Enumeration and Structure Definition ********************** +*/ + +/* Sequence list */ +typedef enum phHciNfc_CE_A_Seq{ + HOST_CE_A_INVALID_SEQ, + HOST_CE_A_PIPE_OPEN, + HOST_CE_A_SAK_SEQ, + HOST_CE_A_ATQA_SEQ, + HOST_CE_A_ENABLE_SEQ, + HOST_CE_A_DISABLE_SEQ, + HOST_CE_A_PIPE_CLOSE, + HOST_CE_A_PIPE_DELETE +}phHciNfc_CE_A_Seq_t; + +/* Information structure for the card emulation A Gate */ +typedef struct phHciNfc_CE_A_Info{ + + phHciNfc_CE_A_Seq_t current_seq; + phHciNfc_CE_A_Seq_t next_seq; + /* Pointer to the card emulation A pipe information */ + phHciNfc_Pipe_Info_t *p_pipe_info; + uint8_t pipe_id; + +} phHciNfc_CE_A_Info_t; + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/*! + * \brief Allocates the resources of card emulation A management gate. + * + * This function Allocates the resources of the card emulation A management + * gate Information Structure. + * + */ +extern +NFCSTATUS +phHciNfc_CE_A_Init_Resources( + phHciNfc_sContext_t *psHciContext + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_A_Get_PipeID function gives the pipe id of the card +* emulation A gate +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_CE_A_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_A_Update_PipeInfo function updates the pipe_id of the card +* emulation A gate management Structure. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pipeID pipeID of the card emulation A gate +* \param[in] pPipeInfo Update the pipe Information of the reader +* A gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ + +extern +NFCSTATUS +phHciNfc_CE_A_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_A_SendData_Event function sends data to the lo +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] pipeID pipeID of the card emulation A gate +* \param[in] pPipeInfo Update the pipe Information of the reader +* A gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +#ifdef CE_A_SEND_EVENT +extern +NFCSTATUS +phHciNfc_CE_A_SendData_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, + uint8_t length + ); +#endif /* #ifdef CE_A_SEND_EVENT */ + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_A_Mode function sends data to the set the card emulation mode +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] enable_type type to enable +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_CE_A_Mode( + void *psHciHandle, + void *pHwRef, + uint8_t enable_type + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_A_Initialise function opens the CE A and set all the +* required parameters for CE A +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_CE_A_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_A_Initialise function close the CE A and reset all the +* required parameters to default value of CE A +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_CE_A_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_A_Update_Seq function to update CE A sequence depending on the +* specified \ref seq_type +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] seq_type sequence type specified in +* \ref phHciNfc_eSeqType_t +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_CE_A_Update_Seq( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t seq_type + ); +#endif /* PHHCINFC_CE_A_H */ + + diff --git a/libnfc-nxp/phHciNfc_CE_B.c b/libnfc-nxp/phHciNfc_CE_B.c new file mode 100644 index 0000000..4b985a3 --- /dev/null +++ b/libnfc-nxp/phHciNfc_CE_B.c @@ -0,0 +1,729 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_CEA.c * +* \brief HCI card emulation A management routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Aug 21 18:35:05 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.13 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include +#include +/* +****************************** Macro Definitions ******************************* +*/ +#if defined (HOST_EMULATION) +#include + +#define CE_B_EVT_NFC_SEND_DATA 0x10U +#define CE_B_EVT_NFC_FIELD_ON 0x11U +#define CE_B_EVT_NFC_DEACTIVATED 0x12U +#define CE_B_EVT_NFC_ACTIVATED 0x13U +#define CE_B_EVT_NFC_FIELD_OFF 0x14U + +/* +*************************** Structure and Enumeration *************************** +*/ + + +/* +*************************** Static Function Declaration ************************** +*/ + +static +NFCSTATUS +phHciNfc_Recv_CE_B_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_CE_B_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +#if defined (SEND_DATA_EVENT) +static +NFCSTATUS +phHciNfc_CE_B_ProcessData( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t *pData, + uint8_t length + ); +#endif /* #if defined (SEND_DATA_EVENT) */ + +/* +*************************** Function Definitions *************************** +*/ +NFCSTATUS +phHciNfc_CE_B_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_CE_B_Info_t *ps_ce_b_info = NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( + ( NULL == psHciContext->p_ce_b_info ) && + (phHciNfc_Allocate_Resource((void **)(&ps_ce_b_info), + sizeof(phHciNfc_CE_B_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_ce_b_info = ps_ce_b_info; + ps_ce_b_info->current_seq = HOST_CE_B_INVALID_SEQ; + ps_ce_b_info->next_seq = HOST_CE_B_INVALID_SEQ; + ps_ce_b_info->pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + return status; +} + +NFCSTATUS +phHciNfc_CE_B_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t pupi[] = {0, 0, 0, 0}; + static uint8_t atqb_info[] = {0x04, 0x00}; + + if ((NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_ce_b_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_CE_B_Info_t *ps_ce_b_info = ((phHciNfc_CE_B_Info_t *) + psHciContext->p_ce_b_info ); + phHciNfc_Pipe_Info_t *ps_pipe_info = NULL; + + ps_pipe_info = ps_ce_b_info->p_pipe_info; + if(NULL == ps_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + switch(ps_ce_b_info->current_seq) + { + case HOST_CE_B_PIPE_OPEN: + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, ps_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { +#if defined (CE_B_CONTINUE_SEQ) + ps_ce_b_info->next_seq = HOST_CE_B_PUPI_SEQ; +#else + ps_ce_b_info->next_seq = HOST_CE_B_ENABLE_SEQ; +#endif /* #if defined (CE_CONTINUE_SEQ) */ + status = NFCSTATUS_PENDING; + } + break; + } + case HOST_CE_B_PUPI_SEQ: + { + /* HOST Card Emulation B PUPI Configuration */ + ps_pipe_info->reg_index = HOST_CE_B_ATQB_INDEX; + + ps_pipe_info->param_info =(void*)&pupi ; + ps_pipe_info->param_length = sizeof(pupi) ; + status = phHciNfc_Send_Generic_Cmd(psHciContext,pHwRef, + ps_pipe_info->pipe.pipe_id, + (uint8_t)ANY_SET_PARAMETER); + if(status == NFCSTATUS_PENDING) + { + ps_ce_b_info->next_seq = HOST_CE_B_ATQB_SEQ; + } + break; + } + case HOST_CE_B_ATQB_SEQ: + { + /* HOST Card Emulation B ATQB Configuration */ + ps_pipe_info->reg_index = HOST_CE_B_ATQB_INDEX; + /* Configure the ATQA of Host Card Emulation B */ + ps_pipe_info->param_info = (void*)atqb_info ; + ps_pipe_info->param_length = sizeof(atqb_info) ; + status = phHciNfc_Send_Generic_Cmd(psHciContext,pHwRef, + ps_pipe_info->pipe.pipe_id, + (uint8_t)ANY_SET_PARAMETER); + if(status == NFCSTATUS_PENDING) + { + ps_ce_b_info->next_seq = HOST_CE_B_ENABLE_SEQ; + } + break; + } + case HOST_CE_B_ENABLE_SEQ: + { + status = phHciNfc_CE_B_Mode( psHciContext, + pHwRef, HOST_CE_MODE_ENABLE ); + if(status == NFCSTATUS_PENDING) + { + ps_ce_b_info->next_seq = HOST_CE_B_DISABLE_SEQ; + status = NFCSTATUS_SUCCESS; + } + break; + } + default : + { + break; + } + } + } + } + + return status; +} + +NFCSTATUS +phHciNfc_CE_B_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if ((NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_ce_b_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_CE_B_Info_t *ps_ce_b_info = ((phHciNfc_CE_B_Info_t *) + psHciContext->p_ce_b_info ); + phHciNfc_Pipe_Info_t *ps_pipe_info = NULL; + + ps_pipe_info = ps_ce_b_info->p_pipe_info; + if(NULL == ps_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + switch(ps_ce_b_info->current_seq) + { + case HOST_CE_B_DISABLE_SEQ: + { + status = phHciNfc_CE_B_Mode( psHciContext, + pHwRef, HOST_CE_MODE_DISABLE ); + if(status == NFCSTATUS_PENDING) + { + ps_ce_b_info->next_seq = HOST_CE_B_PIPE_CLOSE; + } + break; + } + case HOST_CE_B_PIPE_CLOSE: + { + /* HOST Card Emulation B pipe close sequence */ + status = phHciNfc_Close_Pipe( psHciContext, + pHwRef, ps_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + ps_ce_b_info->next_seq = HOST_CE_B_PIPE_DELETE; + status = NFCSTATUS_PENDING; + } + break; + } + case HOST_CE_B_PIPE_DELETE: + { + /* HOST Card Emulation A pipe delete sequence */ + status = phHciNfc_Delete_Pipe( psHciContext, + pHwRef, ps_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { +#if 0 + ps_ce_b_info->pipe_id = HCI_UNKNOWN_PIPE_ID; + psHciContext->p_pipe_list[ps_ce_b_info->pipe_id] = NULL; + phOsalNfc_FreeMemory((void *)ps_ce_b_info->p_pipe_info); + ps_ce_b_info->p_pipe_info = NULL; +#endif + ps_ce_b_info->next_seq = HOST_CE_B_PIPE_OPEN; + } + break; + } + default : + { + break; + } + } + } + } + return status; +} + + + +NFCSTATUS +phHciNfc_CE_B_Mode( + void *psHciHandle, + void *pHwRef, + uint8_t enable_type + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t param = 0 ; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + + if((NULL == psHciContext)||(NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_ce_b_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_CE_B_Info_t *ps_ce_b_info = (phHciNfc_CE_B_Info_t *) + psHciContext->p_ce_b_info ; + phHciNfc_Pipe_Info_t *ps_pipe_info = ps_ce_b_info->p_pipe_info; + + if (NULL != ps_pipe_info) + { + ps_pipe_info->reg_index = HOST_CE_B_MODE_INDEX; + /* Enable/Disable Host Card Emulation A */ + param = (uint8_t)enable_type; + ps_pipe_info->param_info =(void*)¶m ; + ps_pipe_info->param_length = sizeof(param) ; + status = phHciNfc_Send_Generic_Cmd(psHciContext,pHwRef, + ps_ce_b_info->pipe_id,(uint8_t)ANY_SET_PARAMETER); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_HCI_GATE_NOT_SUPPORTED); + } + } + return status; +} + + + +NFCSTATUS +phHciNfc_CE_B_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_ce_b_info ) + ) + { + phHciNfc_CE_B_Info_t *ps_ce_b_info=NULL; + ps_ce_b_info = (phHciNfc_CE_B_Info_t *) + psHciContext->p_ce_b_info ; + *ppipe_id = ps_ce_b_info->pipe_id ; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + +NFCSTATUS +phHciNfc_CE_B_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_ce_b_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_CE_B_Info_t *ps_ce_b_info=NULL; + ps_ce_b_info = (phHciNfc_CE_B_Info_t *) + psHciContext->p_ce_b_info ; + + ps_ce_b_info->current_seq = HOST_CE_B_PIPE_OPEN; + ps_ce_b_info->next_seq = HOST_CE_B_PIPE_OPEN; + /* Update the pipe_id of the card emulation A Gate o + btained from the HCI Response */ + ps_ce_b_info->pipe_id = pipeID; + if (HCI_UNKNOWN_PIPE_ID != pipeID) + { + ps_ce_b_info->p_pipe_info = pPipeInfo; + if (NULL != pPipeInfo) + { + /* Update the Response Receive routine of the card + emulation A Gate */ + pPipeInfo->recv_resp = &phHciNfc_Recv_CE_B_Response; + /* Update the event Receive routine of the card emulation A Gate */ + pPipeInfo->recv_event = &phHciNfc_Recv_CE_B_Event; + } + } + else + { + ps_ce_b_info->p_pipe_info = NULL; + } + } + + return status; +} + +#ifdef CE_B_SEND_EVENT +NFCSTATUS +phHciNfc_CE_B_SendData_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, + uint8_t length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + return status; +} +#endif /* #ifdef CE_B_SEND_EVENT */ + +static +NFCSTATUS +phHciNfc_Recv_CE_B_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_ce_b_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_CE_B_Info_t *ps_ce_b_info=NULL; + uint8_t prev_cmd = ANY_GET_PARAMETER; + ps_ce_b_info = (phHciNfc_CE_B_Info_t *) + psHciContext->p_ce_b_info ; + if( NULL == ps_ce_b_info->p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + prev_cmd = ps_ce_b_info->p_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_GET_PARAMETER: + { +#if 0 + status = phHciNfc_CE_B_InfoUpdate(psHciContext, + ps_ce_b_info->p_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (length - HCP_HEADER_LEN)); +#endif /* #if 0 */ + break; + } + case ANY_SET_PARAMETER: + { + HCI_PRINT("CE B Parameter Set \n"); + break; + } + case ANY_OPEN_PIPE: + { + HCI_PRINT("CE B open pipe complete\n"); + break; + } + case ANY_CLOSE_PIPE: + { + HCI_PRINT("CE B close pipe complete\n"); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + status = phHciNfc_CE_B_Update_Seq(psHciContext, + UPDATE_SEQ); + ps_ce_b_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; + } + } + } + return status; +} + +NFCSTATUS +phHciNfc_CE_B_Update_Seq( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t seq_type + ) +{ + phHciNfc_CE_B_Info_t *ps_ce_b_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_ce_b_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + ps_ce_b_info = (phHciNfc_CE_B_Info_t *) + psHciContext->p_ce_b_info ; + switch(seq_type) + { + case RESET_SEQ: + case INIT_SEQ: + { + ps_ce_b_info->next_seq = HOST_CE_B_PIPE_OPEN; + ps_ce_b_info->current_seq = HOST_CE_B_PIPE_OPEN; + break; + } + case UPDATE_SEQ: + { + ps_ce_b_info->current_seq = ps_ce_b_info->next_seq; + break; + } + case INFO_SEQ: + { + break; + } + case REL_SEQ: + { + ps_ce_b_info->next_seq = HOST_CE_B_DISABLE_SEQ; + ps_ce_b_info->current_seq = HOST_CE_B_DISABLE_SEQ; + break; + } + default: + { + break; + } + } + } + return status; +} + + +static +NFCSTATUS +phHciNfc_Recv_CE_B_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_ce_b_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_CE_B_Info_t *ps_ce_b_info=NULL; + phHciNfc_HCP_Message_t *message = NULL; + static phHal_sEventInfo_t event_info; + uint8_t instruction=0; + + ps_ce_b_info = (phHciNfc_CE_B_Info_t *) + psHciContext->p_ce_b_info ; + + /* Variable was set but never used (ARM warning) */ + PHNFC_UNUSED_VARIABLE(ps_ce_b_info); + + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &p_packet->msg.message; + /* Get the instruction bits from the Message Header */ + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, + HCP_MSG_INSTRUCTION_LEN); + psHciContext->host_rf_type = phHal_eISO14443_B_PICC; + event_info.eventHost = phHal_eHostController; + event_info.eventSource = phHal_eISO14443_B_PICC; + switch(instruction) + { + case CE_B_EVT_NFC_ACTIVATED: + { + event_info.eventType = NFC_EVT_ACTIVATED; + /* Notify to the HCI Generic layer To Update the FSM */ + break; + } + case CE_B_EVT_NFC_DEACTIVATED: + { + event_info.eventType = NFC_EVT_DEACTIVATED; + HCI_PRINT("CE B Target Deactivated\n"); + break; + } + case CE_B_EVT_NFC_SEND_DATA: + { +#if defined (SEND_DATA_EVENT) + HCI_PRINT("CE B data is received from the PN544\n"); + if(length > HCP_HEADER_LEN) + { + status = phHciNfc_CE_B_ProcessData( + psHciContext, pHwRef, + &pEvent[HCP_HEADER_LEN], + (length - HCP_HEADER_LEN)); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } +#endif /* #if defined (SEND_DATA_EVENT) */ + break; + } + case CE_B_EVT_NFC_FIELD_ON: + { + HCI_PRINT("CE B field on\n"); + event_info.eventType = NFC_EVT_FIELD_ON; + break; + } + case CE_B_EVT_NFC_FIELD_OFF: + { + HCI_PRINT("CE B field off\n"); + event_info.eventType = NFC_EVT_FIELD_OFF; + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INSTRUCTION); + break; + } + } + if(NFCSTATUS_SUCCESS == status) + { + phHciNfc_Notify_Event(psHciContext, pHwRef, + NFC_NOTIFY_EVENT, + &event_info); + } + } + return status; +} + +#if defined (SEND_DATA_EVENT) +static +NFCSTATUS +phHciNfc_CE_B_ProcessData( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t *pData, + uint8_t length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + static uint8_t send_data[] = {0x6D, 0x80}; + status = phHciNfc_CE_B_SendData_Event( + (void *)psHciContext, pHwRef, + send_data, sizeof(send_data)); + return status; +} + +#endif /* #if defined (SEND_DATA_EVENT) */ + +#endif /* #if defined (HOST_EMULATION) */ + diff --git a/libnfc-nxp/phHciNfc_CE_B.h b/libnfc-nxp/phHciNfc_CE_B.h new file mode 100644 index 0000000..e34e2db --- /dev/null +++ b/libnfc-nxp/phHciNfc_CE_B.h @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_CE_B.h * +* \brief HCI card emulation management routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Aug 14 17:01:26 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.4 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + + +#ifndef PHHCINFC_CE_B_H +#define PHHCINFC_CE_B_H + +/*@}*/ + + +/** +* \name HCI +* +* File: \ref phHciNfc_CE_B.h +* +*/ +/*@{*/ +#define PHHCINFC_CE_B_FILEREVISION "$Revision: 1.4 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_CE_B_FILEALIASES "$Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ +#define HOST_CE_B_MODE_INDEX (0x01U) +#define HOST_CE_B_PUPI_INDEX (0x02U) +#define HOST_CE_B_AFI_INDEX (0x03U) +#define HOST_CE_B_ATQB_INDEX (0x04U) +#define HOST_CE_B_HIGH_LAYER_RESP_INDEX (0x05U) +#define HOST_CE_B_DATA_RATE_MAX_INDEX (0x05U) + +/* +******************** Enumeration and Structure Definition ********************** +*/ + +/* Sequence list */ +typedef enum phHciNfc_CE_B_Seq{ + HOST_CE_B_INVALID_SEQ, + HOST_CE_B_PIPE_OPEN, + HOST_CE_B_PUPI_SEQ, + HOST_CE_B_ATQB_SEQ, + HOST_CE_B_ENABLE_SEQ, + HOST_CE_B_DISABLE_SEQ, + HOST_CE_B_PIPE_CLOSE, + HOST_CE_B_PIPE_DELETE +}phHciNfc_CE_B_Seq_t; + +/* Information structure for the card emulation B gate */ +typedef struct phHciNfc_CE_B_Info{ + phHciNfc_CE_B_Seq_t current_seq; + phHciNfc_CE_B_Seq_t next_seq; + /* Pointer to the card emulation B pipe information */ + phHciNfc_Pipe_Info_t *p_pipe_info; + uint8_t pipe_id; + +} phHciNfc_CE_B_Info_t; + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/*! + * \brief Allocates the resources of card emulation B management gate. + * + * This function Allocates the resources of the card emulation B management + * gate Information Structure. + * + */ +extern +NFCSTATUS +phHciNfc_CE_B_Init_Resources( + phHciNfc_sContext_t *psHciContext + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_B_Get_PipeID function gives the pipe id of the card +* emulation B gate +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_CE_B_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_B_Update_PipeInfo function updates the pipe_id of the card +* emulation B gate management Structure. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pipeID pipeID of the card emulation A gate +* \param[in] pPipeInfo Update the pipe Information of the reader +* A gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ + +extern +NFCSTATUS +phHciNfc_CE_B_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_B_SendData_Event function sends data to the PN544 +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] pipeID pipeID of the card emulation B gate +* \param[in] pPipeInfo Update the pipe Information of the card +* emulation B gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +#ifdef CE_B_SEND_EVENT +extern +NFCSTATUS +phHciNfc_CE_B_SendData_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, + uint8_t length + ); +#endif /* #ifdef CE_B_SEND_EVENT */ + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_B_Mode function sends data to the set the card emulation mode +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] enable_type type to enable +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +NFCSTATUS +phHciNfc_CE_B_Mode( + void *psHciHandle, + void *pHwRef, + uint8_t enable_type + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_B_Initialise function opens the CE B and set all the +* required parameters for CE B +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_CE_B_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_B_Initialise function close the CE B and reset all the +* required parameters to default value of CE B +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_CE_B_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_CE_B_Update_Seq function to update CE B sequence depending on the +* specified \ref seq_type +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] seq_type sequence type specified in +* \ref phHciNfc_eSeqType_t +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_CE_B_Update_Seq( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t seq_type + ); + +#endif /* PHHCINFC_CE_B_H */ + + diff --git a/libnfc-nxp/phHciNfc_DevMgmt.c b/libnfc-nxp/phHciNfc_DevMgmt.c new file mode 100644 index 0000000..358f8eb --- /dev/null +++ b/libnfc-nxp/phHciNfc_DevMgmt.c @@ -0,0 +1,1630 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_DevMgmt.c * +* \brief HCI PN544 Device Management Gate Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Mar 12 10:21:54 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.29 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_3,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include +#include +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +/* Commands for System Management module */ +#define NXP_RF_CHECK_SETTINGS 0x10U +#define NXP_RF_UPDATE_SETTINGS 0x11U + +/* Self Test Commands */ +#define NXP_SELF_TEST_ANTENNA 0x20U +#define NXP_SELF_TEST_SWP 0x21U +#define NXP_SELF_TEST_NFCWI 0x22U +#define NXP_SELF_TEST_PRBS 0x25U + +/* System Management propreitary control */ +#define NXP_DBG_READ 0x3EU +#define NXP_DBG_WRITE 0x3FU + +/* System Management Events */ +#define NXP_EVT_SET_AUTONOMOUS 0x01U +#define NXP_EVT_CLF_WAKEUP 0x02U + +/* System Management Information Events */ +#define NXP_EVT_INFO_TXLDO_OVERCUR 0x10U +#define NXP_EVT_INFO_PMUVCC 0x11U +#define NXP_EVT_INFO_EXT_RF_FIELD 0x12U +#define NXP_EVT_INFO_MEM_VIOLATION 0x13U +#define NXP_EVT_INFO_TEMP_OVERHEAT 0x14U +#define NXP_EVT_INFO_LLC_ERROR 0x15U + +#define NFC_DEV_TXLDO_MASK 0x03U + + +/* +*************************** Structure and Enumeration *************************** +*/ + + +/** \defgroup grp_hci_nfc HCI PN544 Device Management Component + * + * + */ + +typedef enum phHciNfc_DevMgmt_Seq{ + DEV_MGMT_PIPE_OPEN = 0x00U, + DEV_MGMT_SET_PWR_STATUS, + DEV_MGMT_SET_INFO_EVT, + DEV_MGMT_GET_EEPROM_INFO, + DEV_MGMT_GPIO_PDIR, + DEV_MGMT_GPIO_PEN, + DEV_MGMT_TX_LDO, + DEV_MGMT_IFC_TO_RX_H, + DEV_MGMT_IFC_TO_RX_L, + DEV_MGMT_IFC_TO_TX_H, + DEV_MGMT_IFC_TO_TX_L, + DEV_MGMT_ANAIRQ_CONF, + DEV_MGMT_PMOS_MOD, + DEV_MGMT_CLK_REQ, + DEV_MGMT_INPUT_CLK, + DEV_MGMT_UICC_PWR_REQUEST, + DEV_MGMT_ACTIVE_GUARD_TO, + DEV_MGMT_MAX_ACT_TO_LOW, + DEV_MGMT_MAX_ACT_TO_HIGH, + DEV_MGMT_UICC_CE_A_ACCESS, + DEV_MGMT_UICC_CE_B_ACCESS, + DEV_MGMT_UICC_CE_BP_ACCESS, + DEV_MGMT_UICC_CE_F_ACCESS, + DEV_MGMT_UICC_RD_A_ACCESS, + DEV_MGMT_UICC_RD_B_ACCESS, + DEV_MGMT_UICC_BIT_RATE, + DEV_MGMT_UICC_RX_ERR_CNT, + DEV_MGMT_UICC_TX_ERR_CNT, + DEV_MGMT_LLC_GRD_TO_H, + DEV_MGMT_LLC_GRD_TO_L, + DEV_MGMT_LLC_ACK_TO_H, + DEV_MGMT_LLC_ACK_TO_L, + DEV_MGMT_FELICA_RC, + DEV_MGMT_EVT_AUTONOMOUS, + DEV_MGMT_PIPE_CLOSE +} phHciNfc_DevMgmt_Seq_t; + + +typedef struct phHciNfc_DevMgmt_Info{ + phHciNfc_DevMgmt_Seq_t current_seq; + phHciNfc_DevMgmt_Seq_t next_seq; + phHciNfc_Pipe_Info_t *p_pipe_info; + uint8_t test_status; + uint8_t value; + uint8_t rf_status; + uint8_t pmuvcc_status; + uint8_t overheat_status; + uint8_t *p_val; + uint8_t eeprom_crc; + phNfc_sData_t test_result; + +} phHciNfc_DevMgmt_Info_t; + + +/* +*************************** Static Function Declaration ************************** +*/ + +static +NFCSTATUS +phHciNfc_DevMgmt_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + phHal_sHwReference_t *pHwRef, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); + +static +NFCSTATUS +phHciNfc_Recv_DevMgmt_Response( + void *psHciContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_DevMgmt_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + +static +NFCSTATUS +phHciNfc_Send_DevMgmt_Command ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ); + +static + NFCSTATUS + phHciNfc_Send_DevMgmt_Event ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t event + ); + +/* +*************************** Function Definitions *************************** +*/ + + +NFCSTATUS +phHciNfc_DevMgmt_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_DevMgmt_Info_t *p_device_mgmt_info=NULL; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if(( NULL == psHciContext->p_device_mgmt_info ) && + (phHciNfc_Allocate_Resource((void **)(&p_device_mgmt_info), + sizeof(phHciNfc_DevMgmt_Info_t))== NFCSTATUS_SUCCESS)) + { + psHciContext->p_device_mgmt_info = p_device_mgmt_info; + p_device_mgmt_info->current_seq = DEV_MGMT_PIPE_OPEN; + p_device_mgmt_info->next_seq = DEV_MGMT_PIPE_OPEN; + p_device_mgmt_info->p_pipe_info = NULL; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + } + return status; +} + + +NFCSTATUS +phHciNfc_DevMgmt_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_device_mgmt_info ) + ) + { + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + p_pipe_info = ((phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info)->p_pipe_info ; + if (NULL != p_pipe_info) + { + *ppipe_id = p_pipe_info->pipe.pipe_id ; + } + else + { + *ppipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + } + + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + return status; +} + + +NFCSTATUS +phHciNfc_DevMgmt_Get_Test_Result( + phHciNfc_sContext_t *psHciContext, + phNfc_sData_t *p_test_result + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL != psHciContext) + && ( NULL != p_test_result ) + && ( NULL != psHciContext->p_device_mgmt_info ) + ) + { + phHciNfc_DevMgmt_Info_t *p_device_mgmt_info=NULL; + p_device_mgmt_info = (phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info ; + p_test_result->buffer = p_device_mgmt_info->test_result.buffer; + p_test_result->length = p_device_mgmt_info->test_result.length; + + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + + return status; +} + + +NFCSTATUS +phHciNfc_DevMgmt_Set_Test_Result( + phHciNfc_sContext_t *psHciContext, + uint8_t test_status + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL != psHciContext) + && ( NULL != psHciContext->p_device_mgmt_info ) + ) + { + phHciNfc_DevMgmt_Info_t *p_device_mgmt_info=NULL; + p_device_mgmt_info = (phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info ; + p_device_mgmt_info->test_status = test_status; + + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + + return status; +} + + + +NFCSTATUS +phHciNfc_DevMgmt_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_device_mgmt_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_DevMgmt_Info_t *p_device_mgmt_info=NULL; + p_device_mgmt_info = (phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info ; + /* Update the pipe_info of the Device Management Gate obtained + * from HCI Response */ + p_device_mgmt_info->p_pipe_info = pPipeInfo; + if (( NULL != pPipeInfo) + && ((uint8_t)HCI_UNKNOWN_PIPE_ID != pipeID) + ) + { + /* Update the Response Receive routine of the Device + * Managment Gate */ + pPipeInfo->recv_resp = &phHciNfc_Recv_DevMgmt_Response; + pPipeInfo->recv_event = &phHciNfc_Recv_DevMgmt_Event; + } + } + + return status; +} + + + NFCSTATUS + phHciNfc_DevMgmt_Configure ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint16_t address, + uint8_t value + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + uint8_t i=0; + uint8_t params[5]; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_device_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_pipe_info = ((phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info)->p_pipe_info ; + + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + pipe_id = p_pipe_info->pipe.pipe_id ; + params[i++] = 0x00; + params[i++] = (uint8_t)(address >> BYTE_SIZE); + params[i++] = (uint8_t)address; + params[i++] = value; + p_pipe_info->param_info = ¶ms; + p_pipe_info->param_length = i ; + status = phHciNfc_Send_DevMgmt_Command( psHciContext, pHwRef, + pipe_id, (uint8_t)NXP_DBG_WRITE ); + } + } + return status; +} + + + NFCSTATUS + phHciNfc_DevMgmt_Get_Info ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint16_t address, + uint8_t *p_val + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + uint8_t i=0; + uint8_t params[5]; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_device_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_pipe_info = ((phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info)->p_pipe_info ; + + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + ((phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info)->p_val = p_val; + pipe_id = p_pipe_info->pipe.pipe_id ; + params[i++] = 0x00; + params[i++] = (uint8_t)(address >> BYTE_SIZE); + params[i++] = (uint8_t) address; + p_pipe_info->param_info = ¶ms; + p_pipe_info->param_length = i ; + status = phHciNfc_Send_DevMgmt_Command( psHciContext, pHwRef, + pipe_id, (uint8_t)NXP_DBG_READ ); + } + } + return status; + +} + +/*! + * \brief Initialisation of PN544 Device Managment Gate. + * + * This function initialses the PN544 Device Management gate and + * populates the PN544 Device Management Information Structure + * + */ + +NFCSTATUS +phHciNfc_DevMgmt_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_DevMgmt_Info_t *p_device_mgmt_info=NULL; + static uint8_t config = 0x10; + + if( ( NULL == psHciContext ) + || (NULL == pHwRef ) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if (NULL == psHciContext->p_device_mgmt_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + }/* End of the PN544 Device Info Memory Check */ + else + { + p_device_mgmt_info = (phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info ; + p_pipe_info = p_device_mgmt_info->p_pipe_info; + + if (NULL == p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + switch(p_device_mgmt_info->current_seq ) + { + /* PN544 Device Mgmt pipe open sequence */ + case DEV_MGMT_PIPE_OPEN: + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_FELICA_RC; + status = NFCSTATUS_PENDING; + } + break; + } + case DEV_MGMT_GET_EEPROM_INFO: + { + p_pipe_info->reg_index = DEVICE_INFO_EEPROM_INDEX; + status = phHciNfc_Send_Generic_Cmd( psHciContext, + pHwRef, (uint8_t)p_pipe_info->pipe.pipe_id, + (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { +#if ( NXP_NFC_IFC_TIMEOUT & 0x01 ) + p_device_mgmt_info->next_seq = + DEV_MGMT_IFC_TO_TX_H; +#else + p_device_mgmt_info->next_seq = + DEV_MGMT_TX_LDO; +#endif /* #if ( NXP_NFC_IFC_TIMEOUT & 0x01 ) */ + } + break; + } + case DEV_MGMT_GPIO_PDIR: + { + config = 0x00; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_GPIO_PDIR , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_GPIO_PEN; + } + break; + } + case DEV_MGMT_GPIO_PEN: + { + config = NXP_NFC_GPIO_MASK(NXP_DOWNLOAD_GPIO)| 0x03 ; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_GPIO_PEN , config ); + if(NFCSTATUS_PENDING == status ) + { +#if ( NXP_NFC_IFC_TIMEOUT & 0x01 ) + p_device_mgmt_info->next_seq = + DEV_MGMT_IFC_TO_TX_H; +#else + p_device_mgmt_info->next_seq = + DEV_MGMT_TX_LDO; +#endif /* #if ( NXP_NFC_IFC_TIMEOUT & 0x01 ) */ + } + break; + } + case DEV_MGMT_FELICA_RC: + { + config = 0x00; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_FELICA_RC_ADDR , config ); + if(NFCSTATUS_PENDING == status ) + { + + if ((HCI_SELF_TEST == psHciContext->init_mode ) + || (HCI_NFC_DEVICE_TEST == psHciContext->init_mode )) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_GPIO_PDIR; + } + else + { + p_device_mgmt_info->next_seq = + DEV_MGMT_GET_EEPROM_INFO; + } + } + break; + } + +#if ( NXP_NFC_IFC_TIMEOUT & 0x01 ) + + case DEV_MGMT_IFC_TO_TX_H: + { + config = (uint8_t) + ( NXP_NFC_IFC_CONFIG_DEFAULT >> BYTE_SIZE ) /* 0x03 */; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_IFC_TO_TX_H , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_IFC_TO_TX_L; + } + break; + } + case DEV_MGMT_IFC_TO_TX_L: + { + config = (uint8_t) + ( NXP_NFC_IFC_CONFIG_DEFAULT & BYTE_MASK ) /* 0xE8 */; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_IFC_TO_TX_L , config ); + if(NFCSTATUS_PENDING == status ) + { +#if ( NXP_NFC_IFC_TIMEOUT & 0x02 ) + p_device_mgmt_info->next_seq = + DEV_MGMT_IFC_TO_RX_H; +#else + p_device_mgmt_info->next_seq = + DEV_MGMT_TX_LDO; +#endif /* #if ( NXP_NFC_IFC_TIMEOUT & 0x02 ) */ + } + break; + } + case DEV_MGMT_IFC_TO_RX_H: + { + config = 0x10; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_IFC_TO_RX_H , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_IFC_TO_RX_L; + } + break; + } + case DEV_MGMT_IFC_TO_RX_L: + { + config = 0x1E; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_IFC_TO_RX_L , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_TX_LDO; + } + break; + } + +#endif /* #if ( NXP_NFC_IFC_TIMEOUT & 0x01 ) */ + case DEV_MGMT_TX_LDO: + { +#if ( NXP_HAL_VERIFY_EEPROM_CRC & 0x01U ) + if (0 != p_device_mgmt_info->eeprom_crc) + { + status = NFCSTATUS_FAILED; + } + else +#endif + { + config = (NFC_DEV_HWCONF_DEFAULT | + (NXP_DEFAULT_TX_LDO & NFC_DEV_TXLDO_MASK)); + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_HW_CONF , config ); + if(NFCSTATUS_PENDING == status ) + { +#if ( SW_TYPE_RF_TUNING_BF & 0x01) + p_device_mgmt_info->next_seq = DEV_MGMT_ANAIRQ_CONF; +#else + p_device_mgmt_info->next_seq = DEV_MGMT_CLK_REQ; +#endif + /* status = NFCSTATUS_SUCCESS; */ + } + } + break; + } +#if ( SW_TYPE_RF_TUNING_BF & 0x01) + /* The Analogue IRQ Configuartion */ + case DEV_MGMT_ANAIRQ_CONF: + { + config = 0x04; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_ANAIRQ_CONF , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_PMOS_MOD; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + /* The PMOS Modulation Index */ + case DEV_MGMT_PMOS_MOD: + { + config = NFC_DEV_PMOS_MOD_DEFAULT; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_PMOS_MOD , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_CLK_REQ; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } +#endif /* #if ( SW_TYPE_RF_TUNING_BF & 0x01) */ + case DEV_MGMT_CLK_REQ: + { + config = ((phHal_sHwConfig_t *) + psHciContext->p_config_params)->clk_req ; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_CLK_REQ , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_INPUT_CLK; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case DEV_MGMT_INPUT_CLK: + { + config = ((phHal_sHwConfig_t *) + psHciContext->p_config_params)->input_clk; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_CLK_INPUT , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_UICC_PWR_REQUEST; + } + break; + } + case DEV_MGMT_UICC_PWR_REQUEST: + { + config = NXP_UICC_PWR_REQUEST; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_SWP_PWR_REQ , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_UICC_RD_A_ACCESS; + } + break; + } + case DEV_MGMT_UICC_RD_A_ACCESS: + { +#if ( NXP_UICC_RD_RIGHTS & 0x01 ) + config = (uint8_t) phHciNfc_RFReaderAGate; +#else + config = 0xFFU; +#endif /* #if ( NXP_UICC_RD_RIGHTS & 0x01 ) */ + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_UICC_RD_A_ACCESS , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_UICC_RD_B_ACCESS; + } + break; + } + case DEV_MGMT_UICC_RD_B_ACCESS: + { +#if ( NXP_UICC_RD_RIGHTS & 0x02 ) + config = (uint8_t) phHciNfc_RFReaderBGate; +#else + config = 0xFFU; +#endif /* #if ( NXP_UICC_RD_RIGHTS & 0x02 ) */ + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_UICC_RD_B_ACCESS , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_UICC_CE_A_ACCESS; + } + break; + } + case DEV_MGMT_UICC_CE_A_ACCESS: + { +#if defined(HOST_EMULATION) || ( NXP_UICC_CE_RIGHTS & 0x01 ) + config = (uint8_t) phHciNfc_CETypeAGate; +#else + config = 0xFFU; +#endif /* #if ( NXP_UICC_CE_RIGHTS & 0x01 ) */ + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_UICC_CE_A_ACCESS , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_UICC_CE_B_ACCESS; + } + break; + } + case DEV_MGMT_UICC_CE_B_ACCESS: + { +#if defined(HOST_EMULATION) || ( NXP_UICC_CE_RIGHTS & 0x02 ) + config = (uint8_t) phHciNfc_CETypeBGate; +#else + config = 0xFFU; +#endif /* #if ( NXP_UICC_CE_RIGHTS & 0x02 ) */ + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_UICC_CE_B_ACCESS , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_UICC_CE_BP_ACCESS; + } + break; + } + case DEV_MGMT_UICC_CE_BP_ACCESS: + { +#if defined(HOST_EMULATION) || ( NXP_UICC_CE_RIGHTS & 0x04 ) + config = (uint8_t) phHciNfc_CETypeBPrimeGate; +#else + config = 0xFFU; +#endif /* #if ( NXP_UICC_CE_RIGHTS & 0x04 ) */ + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_UICC_CE_BP_ACCESS , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_UICC_CE_F_ACCESS; + } + break; + } + case DEV_MGMT_UICC_CE_F_ACCESS: + { +#if defined(HOST_EMULATION) || ( NXP_UICC_CE_RIGHTS & 0x08 ) + config = (uint8_t) phHciNfc_CETypeFGate; +#else + config = 0xFFU; +#endif /* #if ( NXP_UICC_CE_RIGHTS & 0x08 ) */ + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_UICC_CE_F_ACCESS , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_UICC_BIT_RATE; + } + break; + } + case DEV_MGMT_UICC_BIT_RATE: + { + config = NXP_UICC_BIT_RATE; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_SWP_BITRATE , config ); + if(NFCSTATUS_PENDING == status ) + { +#if defined (CFG_PWR_STATUS) + p_device_mgmt_info->next_seq = + DEV_MGMT_SET_PWR_STATUS; +#else + p_device_mgmt_info->next_seq = + DEV_MGMT_SET_INFO_EVT; +#endif + } + break; + } +#ifdef CFG_PWR_STATUS + case DEV_MGMT_SET_PWR_STATUS: + { + config = NXP_SYSTEM_PWR_STATUS; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_PWR_STATUS , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_SET_INFO_EVT; + } + break; + } +#endif + case DEV_MGMT_SET_INFO_EVT: + { + config = NXP_SYSTEM_EVT_INFO; + status = phHciNfc_Set_Param(psHciContext, pHwRef, + p_pipe_info, DEVICE_INFO_EVT_INDEX, + (uint8_t *)&config, sizeof(config) ); + if(NFCSTATUS_PENDING == status ) + { +#if ( HOST_LINK_TIMEOUT & 0x01 ) + p_device_mgmt_info->next_seq = + DEV_MGMT_LLC_GRD_TO_H; +#else + p_device_mgmt_info->next_seq = + DEV_MGMT_EVT_AUTONOMOUS; + status = NFCSTATUS_SUCCESS; +#endif /* #if ( HOST_LINK_TIMEOUT & 0x01 ) */ + } + break; + } +#if ( HOST_LINK_TIMEOUT & 0x01 ) + + case DEV_MGMT_LLC_GRD_TO_H: + { + config =(uint8_t) + ( NXP_NFC_LINK_GRD_CFG_DEFAULT >> BYTE_SIZE ) /* 0x00 */; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_LLC_GRD_TO_H , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_LLC_GRD_TO_L; + } + break; + } + case DEV_MGMT_LLC_GRD_TO_L: + { + config = (uint8_t) + ( NXP_NFC_LINK_GRD_CFG_DEFAULT & BYTE_MASK ) /* 0x32 */; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_LLC_GRD_TO_L , config ); + if(NFCSTATUS_PENDING == status ) + { +#if ( HOST_LINK_TIMEOUT & 0x02 ) + p_device_mgmt_info->next_seq = + DEV_MGMT_LLC_ACK_TO_H; +#else + p_device_mgmt_info->next_seq = + DEV_MGMT_EVT_AUTONOMOUS; + status = NFCSTATUS_SUCCESS; +#endif /* #if ( HOST_LINK_TIMEOUT & 0x02 ) */ + } + break; + } + case DEV_MGMT_LLC_ACK_TO_H: + { + config = (uint8_t) + ( NXP_NFC_LINK_ACK_CFG_DEFAULT >> BYTE_SIZE )/* 0x00 */; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_LLC_ACK_TO_H , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_LLC_ACK_TO_L; + } + break; + } + case DEV_MGMT_LLC_ACK_TO_L: + { + config = (uint8_t) + ( NXP_NFC_LINK_ACK_CFG_DEFAULT & BYTE_MASK ) /* 0x00 */;; + status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef, + NFC_ADDRESS_LLC_ACK_TO_L , config ); + if(NFCSTATUS_PENDING == status ) + { + p_device_mgmt_info->next_seq = + DEV_MGMT_EVT_AUTONOMOUS; + status = NFCSTATUS_SUCCESS; + } + break; + } + +#endif /* #if ( HOST_LINK_TIMEOUT & 0x01 ) */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + + }/* End of the Sequence Switch */ + } + + } /* End of Null Context Check */ + + return status; +} + +/*! + * \brief Releases the resources allocated the PN544 Device Management. + * + * This function Releases the resources allocated the PN544 Device Management + * and resets the hardware to the reset state. + */ + +NFCSTATUS +phHciNfc_DevMgmt_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_DevMgmt_Info_t *p_device_mgmt_info=NULL; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( NULL != psHciContext->p_device_mgmt_info ) + { + p_device_mgmt_info = (phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info ; + switch(p_device_mgmt_info->current_seq) + { + + /* PN544 Device pipe close sequence */ + case DEV_MGMT_EVT_AUTONOMOUS: + { + p_pipe_info = p_device_mgmt_info->p_pipe_info; + + p_pipe_info->param_info = NULL; + p_pipe_info->param_length = HCP_ZERO_LEN; + + status = phHciNfc_Send_DevMgmt_Event(psHciContext, pHwRef, + p_pipe_info->pipe.pipe_id, NXP_EVT_SET_AUTONOMOUS); + if(status == NFCSTATUS_PENDING) + { + p_device_mgmt_info->next_seq = DEV_MGMT_PIPE_OPEN; + status = NFCSTATUS_SUCCESS; + } + break; + } + /* PN544 Device pipe close sequence */ + case DEV_MGMT_PIPE_CLOSE: + { + p_pipe_info = p_device_mgmt_info->p_pipe_info; + + status = phHciNfc_Close_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_device_mgmt_info->next_seq = DEV_MGMT_PIPE_OPEN; + /* status = NFCSTATUS_PENDING; */ + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + + }/* End of the Sequence Switch */ + + }/* End of the PN544 Device Info Memory Check */ + + } /* End of Null Context Check */ + + return status; +} + +NFCSTATUS +phHciNfc_DevMgmt_Update_Sequence( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t DevMgmt_seq + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_DevMgmt_Info_t *p_device_mgmt_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_device_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_device_mgmt_info = (phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info ; + switch(DevMgmt_seq) + { + case RESET_SEQ: + case INIT_SEQ: + { + p_device_mgmt_info->current_seq = DEV_MGMT_PIPE_OPEN; + p_device_mgmt_info->next_seq = DEV_MGMT_PIPE_OPEN ; + break; + } + case UPDATE_SEQ: + { + p_device_mgmt_info->current_seq = p_device_mgmt_info->next_seq; + + break; + } + case REL_SEQ: + { + p_device_mgmt_info->current_seq = DEV_MGMT_EVT_AUTONOMOUS; + p_device_mgmt_info->next_seq = DEV_MGMT_EVT_AUTONOMOUS ; + break; + } + default: + { + break; + } + }/* End of Update Sequence Switch */ + } + return status; + +} + + + +/*! + * \brief Perform the System Management Tests + * provided by the corresponding peripheral device. + * + * This function performs the System Management Tests provided by the NFC + * Peripheral device. + */ + +NFCSTATUS +phHciNfc_DevMgmt_Test( + void *psContext, + void *pHwRef, + uint8_t test_type, + phNfc_sData_t *test_param + ) +{ + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_device_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_DevMgmt_Info_t *p_device_mgmt_info = (phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info ; + p_pipe_info = ((phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info)->p_pipe_info ; + switch(test_type) + { + case NXP_SELF_TEST_ANTENNA: + case NXP_SELF_TEST_SWP: + case NXP_SELF_TEST_PRBS: + /* case NXP_SELF_TEST_NFCWI: */ + { + if (NULL != p_pipe_info) + { + pipe_id = p_pipe_info->pipe.pipe_id ; + if ( NULL != test_param ) + { + p_pipe_info->param_info = test_param->buffer; + p_pipe_info->param_length = (uint8_t)test_param->length; + } + p_device_mgmt_info->test_result.buffer = NULL; + p_device_mgmt_info->test_result.length = 0; + status = + phHciNfc_Send_DevMgmt_Command( psHciContext, pHwRef, + pipe_id, (uint8_t)test_type ); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + } + + } + return status; +} + + +/*! + * \brief Receives the HCI Response from the corresponding peripheral device. + * + * This function receives the HCI Command Response from the connected NFC + * Peripheral device. + */ +static +NFCSTATUS +phHciNfc_Recv_DevMgmt_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + phHciNfc_DevMgmt_Info_t *p_device_mgmt_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t prev_cmd = ANY_GET_PARAMETER; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_device_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + p_device_mgmt_info = (phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info ; + prev_cmd = p_device_mgmt_info->p_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_GET_PARAMETER: + { + status = phHciNfc_DevMgmt_InfoUpdate(psHciContext, + (phHal_sHwReference_t *)pHwRef, + p_device_mgmt_info->p_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); + break; + } + case ANY_SET_PARAMETER: + { + break; + } + case ANY_OPEN_PIPE: + { + break; + } + case ANY_CLOSE_PIPE: + { + phOsalNfc_FreeMemory(p_device_mgmt_info->p_pipe_info); + p_device_mgmt_info->p_pipe_info = NULL; + psHciContext->p_pipe_list[PIPETYPE_STATIC_LINK] = NULL; + break; + } + case NXP_DBG_READ: + /* fall through */ + case NXP_DBG_WRITE: + { + if( NULL != p_device_mgmt_info->p_val ) + { + *p_device_mgmt_info->p_val = (uint8_t)( length > HCP_HEADER_LEN ) ? + pResponse[HCP_HEADER_LEN]: 0; + p_device_mgmt_info->p_val = NULL; + } + break; + } + /* Self Test Commands */ + case NXP_SELF_TEST_ANTENNA: + case NXP_SELF_TEST_SWP: + case NXP_SELF_TEST_NFCWI: + case NXP_SELF_TEST_PRBS: + { + p_device_mgmt_info->test_status = (uint8_t) ( length > HCP_HEADER_LEN ) ? + pResponse[HCP_HEADER_LEN]: 0; + p_device_mgmt_info->test_result.buffer = (uint8_t)( length > HCP_HEADER_LEN ) ? + &pResponse[HCP_HEADER_LEN]: NULL; + p_device_mgmt_info->test_result.length = ( length - HCP_HEADER_LEN ); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + if( NULL != p_device_mgmt_info->p_pipe_info) + { + p_device_mgmt_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; + } + p_device_mgmt_info->current_seq = p_device_mgmt_info->next_seq; + } + + } + return status; +} + +/*! + * \brief Receives the HCI Event from the corresponding peripheral device. + * + * This function receives the HCI Event from the connected NFC + * Peripheral device. + */ + +static +NFCSTATUS +phHciNfc_Recv_DevMgmt_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + phHciNfc_DevMgmt_Info_t *p_device_mgmt_info=NULL; + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHal_sEventInfo_t event_info; + uint8_t event = (uint8_t) HCP_MSG_INSTRUCTION_INVALID; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_device_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + p_device_mgmt_info = (phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info ; + hcp_packet = (phHciNfc_HCP_Packet_t *)pEvent; + hcp_message = &hcp_packet->msg.message; + + /* Get the Event instruction bits from the Message Header */ + event = (uint8_t) GET_BITS8( hcp_message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + event_info.eventHost = phHal_eHostController ; + event_info.eventSource = phHal_ePCD_DevType; + + switch(event) + { + /* Information Events */ + case NXP_EVT_INFO_TXLDO_OVERCUR: + { + event_info.eventType = NFC_INFO_TXLDO_OVERCUR; + break; + } + case NXP_EVT_INFO_PMUVCC: + { + p_device_mgmt_info->pmuvcc_status = (uint8_t) ( length > HCP_HEADER_LEN ) ? + pEvent[HCP_HEADER_LEN]: 0; + break; + } + case NXP_EVT_INFO_EXT_RF_FIELD: + { + event_info.eventSource = phHal_ePICC_DevType ; + p_device_mgmt_info->rf_status = (uint8_t) ( length > HCP_HEADER_LEN ) ? + pEvent[HCP_HEADER_LEN]: 0; +#ifdef EVT_INFO_EXT_EVT_DIRECT + event_info.eventType = ( CE_EVT_NFC_FIELD_ON == + (p_device_mgmt_info->rf_status & 0x1FU))? + NFC_EVT_FIELD_ON : NFC_EVT_FIELD_OFF; +#else + event_info.eventType = (TRUE == p_device_mgmt_info->rf_status)? + NFC_EVT_FIELD_ON : NFC_EVT_FIELD_OFF; +#endif + break; + } + case NXP_EVT_INFO_MEM_VIOLATION: + { + event_info.eventType = NFC_INFO_MEM_VIOLATION; + ALOGW("Your NFC controller is kinda hosed, take it to npelly@ to fix"); + break; + } + case NXP_EVT_INFO_TEMP_OVERHEAT: + { + p_device_mgmt_info->overheat_status = (uint8_t)( length > HCP_HEADER_LEN ) ? + pEvent[HCP_HEADER_LEN]: 0; + event_info.eventType = NFC_INFO_TEMP_OVERHEAT; + event_info.eventInfo.overheat_status = + p_device_mgmt_info->overheat_status; + break; + } + case NXP_EVT_INFO_LLC_ERROR: + { + event_info.eventType = NFC_INFO_LLC_ERROR; + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + if( NULL != p_device_mgmt_info->p_pipe_info) + { + p_device_mgmt_info->p_pipe_info->prev_status = + NFCSTATUS_SUCCESS; + } + p_device_mgmt_info->current_seq = + p_device_mgmt_info->next_seq; + phHciNfc_Notify_Event(psHciContext, pHwRef, + NFC_NOTIFY_EVENT, &event_info); + } + } + return status; +} + + +static +NFCSTATUS +phHciNfc_DevMgmt_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + phHal_sHwReference_t *pHwRef, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + phHciNfc_DevMgmt_Info_t *p_device_mgmt_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t i=0; + + PHNFC_UNUSED_VARIABLE(pHwRef); + if( (NULL == psHciContext) + || (NULL == reg_value) + || (reg_length == 0) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_device_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_device_mgmt_info = (phHciNfc_DevMgmt_Info_t *) + psHciContext->p_device_mgmt_info ; + + switch(index) + { + case DEVICE_INFO_EEPROM_INDEX: + { + p_device_mgmt_info->eeprom_crc = reg_value[i]; + break; + } + default: + { + break; + } + } + + } /* End of Context and the PN544 Device information validity check */ + + return status; +} + + + +/*! + * \brief Sends the RF Settings HCI Additonal Commands to the connected + * reader device. + * + * This function Sends the RF Settings HCI Command frames in the HCP packet + * format to the connected reader device. + */ +static + NFCSTATUS + phHciNfc_Send_DevMgmt_Command ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ) + { + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t length=0; + uint8_t i = 0; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || ( pipe_id > PHHCINFC_MAX_PIPE) + ||(NULL == psHciContext->p_pipe_list[pipe_id]) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + HCI_DEBUG("%s: Invalid Arguments passed \n", + "phHciNfc_Send_DevMgmt_Command"); + } + else + { + p_pipe_info = (phHciNfc_Pipe_Info_t *) + psHciContext->p_pipe_list[pipe_id]; + psHciContext->tx_total = 0 ; + length += HCP_HEADER_LEN ; + switch( cmd ) + { + /* Self Test Commands */ + case NXP_SELF_TEST_ANTENNA: + case NXP_SELF_TEST_SWP: + case NXP_SELF_TEST_NFCWI: + case NXP_SELF_TEST_PRBS: + /* Internal Properietary Commands */ + case NXP_DBG_READ: + case NXP_DBG_WRITE: + { + + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + hcp_message = &(hcp_packet->msg.message); + /* Append the RF Setting Parameter also the optional Value */ + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, p_pipe_info->param_info, + p_pipe_info->param_length); + length =(uint8_t)(length + i + p_pipe_info->param_length); + break; + } + default: + { + status = PHNFCSTVAL( CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED ); + HCI_DEBUG("%s: Statement Should Not Occur \n", + "phHciNfc_Send_DevMgmt_Command"); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + p_pipe_info->sent_msg_type = HCP_MSG_TYPE_COMMAND; + p_pipe_info->prev_msg = cmd; + psHciContext->tx_total = length; + psHciContext->response_pending = TRUE ; + + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef ); + p_pipe_info->prev_status = NFCSTATUS_PENDING; + } + } + + return status; +} + + + +/*! + * \brief Sends the RF Settings HCI Additonal Events to the connected + * reader device. + * + * This function Sends the RF Settings HCI Events frames in the HCP packet + * format to the connected reader device. + */ + +static + NFCSTATUS + phHciNfc_Send_DevMgmt_Event ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t event + ) + { + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t length=0; + uint8_t i = 0; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || ( pipe_id > PHHCINFC_MAX_PIPE) + ||(NULL == psHciContext->p_pipe_list[pipe_id]) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + HCI_DEBUG("%s: Invalid Arguments passed \n", + "phHciNfc_Send_DevMgmt_Event"); + } + else + { + p_pipe_info = (phHciNfc_Pipe_Info_t *) + psHciContext->p_pipe_list[pipe_id]; + psHciContext->tx_total = 0 ; + length += HCP_HEADER_LEN ; + if( NXP_EVT_SET_AUTONOMOUS == event ) + { + + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_EVENT, event); + hcp_message = &(hcp_packet->msg.message); + /* Append the RF Setting Parameter also the optional Value */ + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, p_pipe_info->param_info, + p_pipe_info->param_length); + length =(uint8_t)(length + i + p_pipe_info->param_length); + } + else + { + status = PHNFCSTVAL( CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED ); + HCI_DEBUG("%s: Statement Should Not Occur \n", + "phHciNfc_Send_DevMgmt_Event"); + } + if( NFCSTATUS_SUCCESS == status ) + { + p_pipe_info->sent_msg_type = HCP_MSG_TYPE_EVENT; + p_pipe_info->prev_msg = event; + psHciContext->tx_total = length; + + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef ); + p_pipe_info->prev_status = NFCSTATUS_PENDING; + } + } + + return status; +} + + + + + diff --git a/libnfc-nxp/phHciNfc_DevMgmt.h b/libnfc-nxp/phHciNfc_DevMgmt.h new file mode 100644 index 0000000..e886013 --- /dev/null +++ b/libnfc-nxp/phHciNfc_DevMgmt.h @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_DevMgmt.h * +* \brief HCI Header for the PN544 Device Management Gate. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Tue Jun 8 09:30:49 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.15 $ * +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + + +#ifndef PHHCINFC_DEVMGMT_H +#define PHHCINFC_DEVMGMT_H + +/*@}*/ + + +/** + * \name HCI + * + * File: \ref phHciNfc_DevMgmt.h + * + */ +/*@{*/ +#define PHHCINFC_DEVICE_MGMT_FILEREVISION "$Revision: 1.15 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_DEVICE_MGMT_FILEALIASES "$Aliases: NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +#define DEVICE_PWR_STATUS_INDEX 0x01U +#define DEVICE_INFO_EVT_INDEX 0x02U +#define DEVICE_INFO_EEPROM_INDEX 0x03U + +#define NXP_DOWNLOAD_GPIO 0x04U + +/* GPIO PIN Mask Macro */ +#define NXP_NFC_GPIO_MASK(n) ((uint8_t)(1U << (n))) + +/* Address Definitions for GPIO Register Configuration */ +#define NFC_ADDRESS_GPIO_PDIR 0xF821U +#define NFC_ADDRESS_GPIO_PEN 0xF829U + + +/* Address Definitions for SWP Configuration */ +#define NFC_ADDRESS_SWP_BITRATE 0x9C01U +#define NFC_ADDRESS_SWP_PWR_REQ 0x9EB4U + +/* Address Definitions for UICC Host Configuration */ +#define NFC_ADDRESS_UICC_RD_A_ACCESS 0x9ED9U +#define NFC_ADDRESS_UICC_RD_B_ACCESS 0x9EDAU +#define NFC_ADDRESS_UICC_CE_A_ACCESS 0x9EDBU +#define NFC_ADDRESS_UICC_CE_B_ACCESS 0x9EDCU +#define NFC_ADDRESS_UICC_CE_BP_ACCESS 0x9EDDU +#define NFC_ADDRESS_UICC_CE_F_ACCESS 0x9EDEU + +/* Address Definitions for SE Configuration */ + +/* Address Definitions for HW Configuration */ +#define NFC_ADDRESS_CLK_REQ 0x9E71U +#define NFC_ADDRESS_CLK_INPUT 0x9809U +#define NFC_ADDRESS_HW_CONF 0x9810U +#define NFC_ADDRESS_PWR_STATUS 0x9EAAU + +/* Address Definitions for RF Configuration */ + + +/* Address Definitions for Interframe Character Timeout Configuration */ +#define NFC_ADDRESS_IFC_TO_RX_H 0x9C0CU +#define NFC_ADDRESS_IFC_TO_RX_L 0x9C0DU +#define NFC_ADDRESS_IFC_TO_TX_H 0x9C12U +#define NFC_ADDRESS_IFC_TO_TX_L 0x9C13U + + +/* Address Definitions for LLC Configuration */ +#define NFC_ADDRESS_LLC_ACK_TO_H 0x9C27U +#define NFC_ADDRESS_LLC_ACK_TO_L 0x9C28U +#define NFC_ADDRESS_LLC_GRD_TO_H 0x9C31U +#define NFC_ADDRESS_LLC_GRD_TO_L 0x9C32U + +#define NFC_ADDRESS_ACT_GRD_TO 0x9916U + +/* The Address Definition for the TYPE B Tuning */ + +#ifdef SW_TYPE_RF_TUNING_BF +#define NFC_ADDRESS_ANAIRQ_CONF 0x9801U +#define NFC_ADDRESS_PMOS_MOD 0x997AU +#endif + +#define NFC_FELICA_RC_ADDR 0x9F9AU + +/* The Address Definition for the Enabling the EVT_HOT_PLUG */ +#define NFC_ADDRESS_HOTPLUG_EVT 0x9FF0U + + +/* +******************** Enumeration and Structure Definition ********************** +*/ + + + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/************************ Function Prototype Declaration *************************/ + +/*! + * \brief Allocates the resources required for PN544 Device management gate. + * + * This function Allocates necessary resources as requiered by PN544 Device + * gate management + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * + * \retval NFCSTATUS_SUCCESS Function execution is successful + * + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid + */ + +extern +NFCSTATUS +phHciNfc_DevMgmt_Init_Resources(phHciNfc_sContext_t *psHciContext); + + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_DevMgmt_Get_PipeID function gives the pipe id of the PN544 Device +* management gate +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] ppipe_id ppipe_id of the Device management Gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ + +extern +NFCSTATUS +phHciNfc_DevMgmt_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_DevMgmt_Initialise function creates and the opens the pipe + * PN544 Device Management Gate in the NFC Device + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Device Mgmt Gate Initialisation is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_DevMgmt_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_DevMgmt_Test function performs the System Management Tests + * provided by the NFC Peripheral device. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] test_type test_type is the type of the Self Test + * that needs to be performed on the device. + * \param[in] test_param test_param is the parameter for the Self Test + * that needs to be performed on the device. + * + * + * \retval NFCSTATUS_PENDING Self Test on the Device Management gate + * is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_DevMgmt_Test( + void *psContext, + void *pHwRef, + uint8_t test_type, + phNfc_sData_t *test_param + ); + +extern +NFCSTATUS +phHciNfc_DevMgmt_Get_Info ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint16_t address, + uint8_t *p_val + ); + +extern +NFCSTATUS +phHciNfc_DevMgmt_Configure ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint16_t address, + uint8_t value + ); + +extern +NFCSTATUS +phHciNfc_DevMgmt_Get_Test_Result( + phHciNfc_sContext_t *psHciContext, + phNfc_sData_t *test_result + ); + + +/** +* \ingroup grp_hci_nfc +* +* \brief Allocates the resources required for PN544 Device +* management gate +* This function Allocates necessary resources as requiered by PN544 +* Device management gate +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* \param[in] pipeID pipeID of the Device management Gate +* \param[in] pPipeInfo Update the pipe Information of the Device +* Management Gate. +* +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ +extern +NFCSTATUS +phHciNfc_DevMgmt_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_DevMgmt_Release function closes the opened pipes between + * the Device Management Gate in the Host Controller Device + * and the NFC Device. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Release of the Device Management gate + * resources are pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ +extern +NFCSTATUS +phHciNfc_DevMgmt_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +extern +NFCSTATUS +phHciNfc_DevMgmt_Update_Sequence( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t DevMgmt_seq + ); + +extern +NFCSTATUS +phHciNfc_DevMgmt_Set_Test_Result( + phHciNfc_sContext_t *psHciContext, + uint8_t test_status + ) +; + +#endif + diff --git a/libnfc-nxp/phHciNfc_Emulation.c b/libnfc-nxp/phHciNfc_Emulation.c new file mode 100644 index 0000000..5309f3a --- /dev/null +++ b/libnfc-nxp/phHciNfc_Emulation.c @@ -0,0 +1,1384 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_Emulation.c * +* \brief HCI Emulation management routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Tue Jun 8 09:30:37 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.52 $ * +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include +#include +#include +#include +#ifdef ENABLE_P2P +#include +#endif +#ifdef HOST_EMULATION +#include +#include +#endif +#include +/* +****************************** Macro Definitions ******************************* +*/ + + + +/* +*************************** Structure and Enumeration *************************** +*/ + +/** \defgroup grp_hci_nfc HCI Emulation Management Component +* +* +*/ + +typedef enum phHciNfc_EmulationMgmt_Seq{ + NFCIP_TARGET_PIPE_OPEN = 0x00U, + NFCIP_TARGET_MODE_CONFIG, + NFCIP_TARGET_MERGE_SAK, + NFCIP_TARGET_PIPE_CLOSE, + + HOST_CE_A_INIT, + HOST_CE_A_RELEASE, + + HOST_CE_B_INIT, + HOST_CE_B_RELEASE, + + WI_PIPE_OPEN, + WI_ENABLE_EMULATION, + WI_DEFAULT_EMULATION, + WI_DISABLE_EMULATION, + + WI_ENABLE_NOTIFICATION, + WI_DISABLE_NOTIFICATION, + + WI_SWITCH_WIRED_MODE, + WI_SWITCH_DEFAULT_MODE, + + WI_PIPE_CLOSE, + + SWP_PIPE_OPEN, + SWP_ENABLE_EMULATION, + SWP_DEFAULT_EMULATION, + SWP_DETECTION, + SWP_DISABLE_EMULATION, + SWP_GET_BIT_RATE, + SWP_PIPE_CLOSE, + + CONFIG_DEFAULT_EMULATION, + + END_EMULATION_SEQ +} phHciNfc_EmulationMgmt_Seq_t; + +typedef struct phHciNfc_EmulationMgmt_Info{ + phHal_eEmulationType_t se_default; + uint8_t smx_powerless; + uint8_t uicc_enable; + uint8_t uicc_powerless; + uint8_t uicc_id; + /* Application ID of the UICC Transaction performed */ + uint8_t uicc_aid[MAX_AID_LEN]; + uint8_t uicc_param[MAX_UICC_PARAM_LEN]; + uint8_t uicc_param_len; + phHciNfc_Pipe_Info_t *p_uicc_pipe_info; + phHciNfc_EmulationMgmt_Seq_t emulation_cur_seq; + phHciNfc_EmulationMgmt_Seq_t emulation_next_seq; + + +} phHciNfc_EmulationMgmt_Info_t; + + +/* +*************************** Static Function Declaration ************************** +*/ + +static +NFCSTATUS +phHciNfc_Recv_Uicc_Cmd ( + void *psContext, + void *pHwRef, + uint8_t *pCmd, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_Uicc_Event ( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + +/* +*************************** Function Definitions *************************** +*/ + +void +phHciNfc_Uicc_Connectivity( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *pPipeInfo = NULL; + phHciNfc_EmulationMgmt_Info_t *p_emulation_mgmt_info = NULL; + + if( NULL != psHciContext->p_emulation_mgmt_info ) + { + p_emulation_mgmt_info = (phHciNfc_EmulationMgmt_Info_t *) + psHciContext->p_emulation_mgmt_info ; + pPipeInfo = psHciContext->p_pipe_list[NXP_PIPE_CONNECTIVITY]; + if( (TRUE == ((phHal_sHwReference_t *)pHwRef)->uicc_connected) + && (NULL == pPipeInfo)) + { + status = phHciNfc_Allocate_Resource((void **)&pPipeInfo, + sizeof(phHciNfc_Pipe_Info_t)); + if((NULL != pPipeInfo) + && (NFCSTATUS_SUCCESS == status)) + { + /* The Source Host is the UICC Host */ + pPipeInfo->pipe.source.host_id = + (uint8_t) phHciNfc_UICCHostID; + /* The Source Gate is same as the Destination Gate */ + pPipeInfo->pipe.source.gate_id = + (uint8_t) phHciNfc_ConnectivityGate; + /* The Destination Host is the Terminal Host */ + pPipeInfo->pipe.dest.host_id = + (uint8_t) phHciNfc_TerminalHostID; + /* The Source Gate is same as the Destination Gate */ + pPipeInfo->pipe.dest.gate_id = + (uint8_t) phHciNfc_ConnectivityGate; + /* The Pipe ID is Hardcoded to Connectivity */ + pPipeInfo->pipe.pipe_id = (uint8_t) NXP_PIPE_CONNECTIVITY; + + + status = phHciNfc_Uicc_Update_PipeInfo(psHciContext, + NXP_PIPE_CONNECTIVITY, pPipeInfo); + if (NFCSTATUS_SUCCESS == status) + { + psHciContext->p_pipe_list[NXP_PIPE_CONNECTIVITY] = pPipeInfo; + p_emulation_mgmt_info->uicc_enable = TRUE; + } + else + { + (void)phOsalNfc_FreeMemory(pPipeInfo); + } + } + } + } + return; +} + +/*! + * \brief Get the pipe_id of Connectivity Managment Gate. + * + * This function Get the pipe_id of Connectivity Managment Gate. + * + */ + + +NFCSTATUS +phHciNfc_Uicc_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_EmulationMgmt_Info_t *p_emulation_mgmt_info = NULL; + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_emulation_mgmt_info ) + ) + { + p_emulation_mgmt_info = (phHciNfc_EmulationMgmt_Info_t *) + psHciContext->p_emulation_mgmt_info ; + *ppipe_id = p_emulation_mgmt_info->uicc_id ; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + + +/* Function to Update the Pipe Information */ +NFCSTATUS +phHciNfc_Uicc_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipe_id, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + phHciNfc_EmulationMgmt_Info_t *p_emulation_mgmt_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_emulation_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_emulation_mgmt_info = (phHciNfc_EmulationMgmt_Info_t *) + psHciContext->p_emulation_mgmt_info ; + /* Update the pipe_id of the Connectivity Gate + * obtained from the HCI Response */ + p_emulation_mgmt_info->uicc_id = pipe_id; + p_emulation_mgmt_info->p_uicc_pipe_info = pPipeInfo; + if ( NULL != pPipeInfo) + { + /* Update the Response Receive routine of the Connectivity Gate */ + /* pPipeInfo->recv_resp = phHciNfc_Recv_Uicc_Response; */ + pPipeInfo->recv_cmd = &phHciNfc_Recv_Uicc_Cmd; + pPipeInfo->recv_event = &phHciNfc_Recv_Uicc_Event; + } + } + + return status; +} + + +/*! +* \brief Updates the Sequence of Emulation Managment Gate. +* +* This function Resets/Updates the sequence of the Emulation Management +* gate. +* +*/ + + +NFCSTATUS +phHciNfc_EmuMgmt_Update_Seq( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t seq_type + ) +{ + phHciNfc_EmulationMgmt_Info_t *p_emulation_mgmt_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( NULL == psHciContext->p_emulation_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_emulation_mgmt_info = (phHciNfc_EmulationMgmt_Info_t *) + psHciContext->p_emulation_mgmt_info ; + switch(seq_type) + { + case RESET_SEQ: + case INIT_SEQ: + { +#ifdef ENABLE_P2P + p_emulation_mgmt_info->emulation_cur_seq = NFCIP_TARGET_PIPE_OPEN; +#else + p_emulation_mgmt_info->emulation_cur_seq = WI_PIPE_OPEN; +#endif + p_emulation_mgmt_info->emulation_next_seq = END_EMULATION_SEQ ; + break; + } + case UPDATE_SEQ: + { + p_emulation_mgmt_info->emulation_cur_seq = + p_emulation_mgmt_info->emulation_next_seq; + break; + } + case INFO_SEQ: + { + p_emulation_mgmt_info->emulation_cur_seq = SWP_ENABLE_EMULATION; + p_emulation_mgmt_info->emulation_next_seq = END_EMULATION_SEQ ; + break; + } + case REL_SEQ: + { + p_emulation_mgmt_info->emulation_cur_seq = WI_DISABLE_EMULATION; + p_emulation_mgmt_info->emulation_next_seq = END_EMULATION_SEQ ; + break; + } + default: + { + break; + } + } + } + } + + return status; +} + + +/*! +* \brief Initialisation of RF Emulation Gates. +* +* This function initialses the RF Emulation Management and +* populates the Reader Management Information Structure +* +*/ + + +NFCSTATUS +phHciNfc_EmuMgmt_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_EmulationMgmt_Info_t *p_emulation_mgmt_info=NULL; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + + if( ( NULL == psHciContext->p_emulation_mgmt_info ) + && (phHciNfc_Allocate_Resource((void **)(&p_emulation_mgmt_info), + sizeof(phHciNfc_EmulationMgmt_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_emulation_mgmt_info = p_emulation_mgmt_info; +#ifdef ENABLE_P2P + p_emulation_mgmt_info->emulation_cur_seq = NFCIP_TARGET_PIPE_OPEN; +#else + p_emulation_mgmt_info->emulation_cur_seq = WI_PIPE_OPEN; +#endif + p_emulation_mgmt_info->emulation_next_seq = END_EMULATION_SEQ; + p_emulation_mgmt_info->uicc_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + } + else + { + p_emulation_mgmt_info = (phHciNfc_EmulationMgmt_Info_t *) + psHciContext->p_emulation_mgmt_info ; + } + + if( NULL == psHciContext->p_emulation_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INSUFFICIENT_RESOURCES); + } +#ifdef ESTABLISH_SESSION + else if(( hciMode_Session == psHciContext->hci_mode ) + && (NFCIP_TARGET_PIPE_OPEN == p_emulation_mgmt_info->emulation_cur_seq ) + ) + { + status = NFCSTATUS_SUCCESS; + } +#endif + else + { + switch(p_emulation_mgmt_info->emulation_cur_seq ) + { +#ifdef ENABLE_P2P + /* NFCIP Target Open sequence */ + case NFCIP_TARGET_PIPE_OPEN: + { + p_pipe_info = ((phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info)->p_tgt_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_emulation_mgmt_info->emulation_next_seq = + NFCIP_TARGET_MODE_CONFIG; + status = NFCSTATUS_PENDING; + } + } + break; + } + /* NFCIP Target Mode Config sequence */ + case NFCIP_TARGET_MODE_CONFIG: + { +#define NFCIP_ACTIVE_SHIFT 0x03U +#define NFCIP_PASSIVE_MASK 0x07U + uint8_t mode = ( NXP_NFCIP_ACTIVE_DEFAULT << NFCIP_ACTIVE_SHIFT ) | + ( DEFAULT_NFCIP_TARGET_MODE_SUPPORT & NFCIP_PASSIVE_MASK ); + status = phHciNfc_NfcIP_SetMode( psHciContext, pHwRef, + NFCIP_TARGET, mode); + if(status == NFCSTATUS_PENDING ) + { +#ifdef TGT_MERGE_SAK + p_emulation_mgmt_info->emulation_next_seq = + NFCIP_TARGET_MERGE_SAK; +#else + p_emulation_mgmt_info->emulation_next_seq = + WI_PIPE_OPEN; +#endif /* #ifdef TGT_MERGE_SAK */ + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } +#ifdef TGT_MERGE_SAK + /* NFCIP Target SAK Merge sequence */ + case NFCIP_TARGET_MERGE_SAK: + { + status = phHciNfc_NfcIP_SetMergeSak( psHciContext, pHwRef, + TRUE ); + if(status == NFCSTATUS_PENDING ) + { + p_emulation_mgmt_info->emulation_next_seq = + WI_PIPE_OPEN; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } +#endif /* #ifdef TGT_MERGE_SAK */ +#endif /* #ifdef ENABLE_P2P */ + /* Secure Element WI pipe open sequence */ + case WI_PIPE_OPEN: + { + p_pipe_info = ((phHciNfc_WI_Info_t *) + psHciContext->p_wi_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { +#ifdef DISABLE_WI_NOTIFICATION + p_emulation_mgmt_info->emulation_next_seq = + SWP_PIPE_OPEN; +#else + p_emulation_mgmt_info->emulation_next_seq = + WI_ENABLE_NOTIFICATION; +#endif + status = NFCSTATUS_PENDING; + } + } + break; + } + /* Enable the SmartMx Notifications through WI */ + case WI_ENABLE_NOTIFICATION: + { + p_pipe_info = ((phHciNfc_WI_Info_t *) + psHciContext->p_wi_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_WI_Configure_Notifications( + psHciContext, pHwRef, eEnableEvents ); + if(status == NFCSTATUS_PENDING) + { + p_emulation_mgmt_info->emulation_next_seq = + SWP_PIPE_OPEN; + } + } + break; + } + /* Enable the SmartMx Emulation by Default through WI */ + case WI_ENABLE_EMULATION: + { + p_pipe_info = ((phHciNfc_WI_Info_t *) + psHciContext->p_wi_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_WI_Configure_Default( psHciContext, + pHwRef, TRUE ); + if(status == NFCSTATUS_PENDING) + { + p_emulation_mgmt_info->emulation_next_seq = + SWP_PIPE_OPEN; + } + } + break; + } + /* SWP pipe open sequence */ + case SWP_PIPE_OPEN: + { + p_pipe_info = ((phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_emulation_mgmt_info->emulation_next_seq = + SWP_ENABLE_EMULATION; +#ifndef ESTABLISH_SESSION + status = NFCSTATUS_PENDING; +#endif + } + } + break; + } + /* Enable the UICC Emulation through SWP */ + case SWP_ENABLE_EMULATION: + { + p_pipe_info = ((phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { +#ifdef SWP_EVENT_USAGE + status = phHciNfc_SWP_Configure_Mode( psHciContext, pHwRef, + UICC_SWITCH_MODE_ON ); + /* UICC_SWITCH_MODE_DEFAULT */ +#else + status = phHciNfc_SWP_Configure_Default( psHciContext, + pHwRef, TRUE ); +#endif + if(status == NFCSTATUS_PENDING) + { + p_emulation_mgmt_info->emulation_next_seq = + SWP_DETECTION; + /* status = NFCSTATUS_SUCCESS; */ + } + } + break; + } + /* Disable the UICC Emulation through SWP */ + case SWP_DETECTION: + { + p_pipe_info = ((phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + break; + } + else + { + status = phHciNfc_Uicc_Connect_Status( + psHciContext, pHwRef ); + if(status == NFCSTATUS_SUCCESS) + { + uint8_t uicc_connect = ((phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info)->uicc_status; + if(UICC_CONNECTED == uicc_connect) + { +#ifdef SWP_EVENT_USAGE + p_emulation_mgmt_info->emulation_next_seq = + SWP_DISABLE_EMULATION; +#else + p_emulation_mgmt_info->emulation_next_seq = + WI_DISABLE_EMULATION; +#endif + ((phHal_sHwReference_t *) + pHwRef)->uicc_connected = TRUE; + status = NFCSTATUS_PENDING; + } + else + { + status = phHciNfc_SWP_Configure_Mode( psHciContext, + pHwRef, UICC_SWITCH_MODE_DEFAULT ); + (NFCSTATUS_PENDING == status)? + (p_emulation_mgmt_info->emulation_next_seq = + WI_DISABLE_EMULATION): + (p_emulation_mgmt_info->emulation_next_seq = + SWP_DETECTION); + break; + } + } + else + { + break; + } + } + } + /* fall through */ + /* Disable the SmartMx Emulation through WI */ + case WI_DISABLE_EMULATION: + { + p_pipe_info = ((phHciNfc_WI_Info_t *) + psHciContext->p_wi_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_WI_Configure_Mode( psHciContext, + pHwRef, eSmartMx_Default ); + if(status == NFCSTATUS_PENDING) + { + p_emulation_mgmt_info->emulation_next_seq = + SWP_DISABLE_EMULATION; + status = NFCSTATUS_SUCCESS; + } + } + break; + } +#ifndef SWP_EVENT_USAGE + /* fall through */ + /* Get the UICC Baud Rate Status */ + case SWP_GET_BIT_RATE: + { + p_pipe_info = ((phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_SWP_Get_Bitrate( + psHciContext, pHwRef ); + if(status == NFCSTATUS_PENDING) + { + p_emulation_mgmt_info->emulation_next_seq = + SWP_DISABLE_EMULATION; + status = NFCSTATUS_SUCCESS; + } + } + break; + } +#endif + /* fall through */ + /* Disable the UICC Emulation through SWP */ + case SWP_DISABLE_EMULATION: + { + p_pipe_info = ((phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_SWP_Configure_Mode( psHciContext, + pHwRef, UICC_SWITCH_MODE_DEFAULT ); + if(status == NFCSTATUS_PENDING) + { + p_emulation_mgmt_info->emulation_next_seq = + WI_DISABLE_EMULATION; + /* Disable WI Emulation for Previous Wired + * Mode Set */ + /* status = NFCSTATUS_SUCCESS; */ + } + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + + }/* End of the Sequence Switch */ + + }/* End of the Reader Info Memory Check */ + + } /* End of Null Context Check */ + + return status; +} + +/*! +* \brief Connection Routine for the Uicc. +* +* This function tries to enable and initialise the UICC connected +* through SWP. +* +*/ + + +NFCSTATUS +phHciNfc_Uicc_Connect_Status( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + /* phHciNfc_Pipe_Info_t *p_pipe_info = NULL; */ + /* phHciNfc_EmulationMgmt_Info_t *p_emulation_mgmt_info=NULL; */ + static uint32_t uicc_connection_retry = 0; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + phHciNfc_SWP_Status_t uicc_status = + ((phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info)->uicc_status; + if(uicc_connection_retry == 0) + { +#ifdef UICC_STATUS_DELAY + for( ;uicc_connection_retry < UICC_STATUS_DELAY_COUNT; + uicc_connection_retry ++ ); + uicc_connection_retry = 0; +#endif + status = phHciNfc_SWP_Get_Status( + psHciContext, pHwRef ); + if (NFCSTATUS_PENDING == status) + { + uicc_connection_retry++; + } + } + else + { + switch(uicc_status) + { + case UICC_CONNECTION_ONGOING: + case UICC_DISCONNECTION_ONGOING: + case UICC_NOT_CONNECTED: + { + if(uicc_connection_retry < + UICC_MAX_CONNECT_RETRY) + { + status = phHciNfc_SWP_Get_Status( + psHciContext, pHwRef ); + if (NFCSTATUS_PENDING == status) + { + uicc_connection_retry++; + } + } + break; + } + case UICC_CONNECTED: + { + break; + } + case UICC_CONNECTION_LOST: + case UICC_CONNECTION_FAILED: + default: + { + uicc_connection_retry = 0; + break; + } + } /* End of the Status Switch */ + } + + if( NFCSTATUS_PENDING != status ) + { + uicc_connection_retry = 0; + /* Error Scenario due to SWP Disable Config */ + } + + } /* End of Null Context Check */ + + return status; +} + +/*! +* \brief Release of RF Emulation Gate Configuration. +* +* This function initialses the RF Emulation Management and +* populates the Reader Management Information Structure +* +*/ + + +NFCSTATUS +phHciNfc_EmuMgmt_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_EmulationMgmt_Info_t *p_emulation_mgmt_info=NULL; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + + p_emulation_mgmt_info = (phHciNfc_EmulationMgmt_Info_t *) + psHciContext->p_emulation_mgmt_info ; + + if( NULL == psHciContext->p_emulation_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + switch(p_emulation_mgmt_info->emulation_cur_seq ) + { + /* Enable/Disable the SmartMx Emulation through WI + * After the power down + */ + /* Enable the SmartMx Emulation by Default through WI */ + case WI_DEFAULT_EMULATION: + { + p_pipe_info = ((phHciNfc_WI_Info_t *) + psHciContext->p_wi_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_WI_Configure_Default( psHciContext, + pHwRef, p_emulation_mgmt_info->smx_powerless ); + if(status == NFCSTATUS_PENDING) + { + p_emulation_mgmt_info->emulation_next_seq = + WI_DISABLE_EMULATION; + } + } + break; + } + /* SmartMx In Default Mode */ + case WI_DISABLE_EMULATION: + { + p_pipe_info = ((phHciNfc_WI_Info_t *) + psHciContext->p_wi_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_WI_Configure_Mode( psHciContext, + pHwRef, eSmartMx_Default ); + if(status == NFCSTATUS_SUCCESS ) + { + p_emulation_mgmt_info->emulation_next_seq = + SWP_DISABLE_EMULATION; + status = phHciNfc_EmuMgmt_Update_Seq(psHciContext, + UPDATE_SEQ); + /* status = NFCSTATUS_PENDING; */ + } + } + break; + } + /* Enable/Disable the UICC Emulation through SWP + * After the power down + */ + /* Enable the UICC Emulation by Default through SWP */ + case SWP_DEFAULT_EMULATION: + { + p_pipe_info = ((phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_SWP_Configure_Default( psHciContext, + pHwRef, p_emulation_mgmt_info->uicc_powerless ); + if(status == NFCSTATUS_PENDING) + { + p_emulation_mgmt_info->emulation_next_seq = + SWP_DISABLE_EMULATION; + /* status = NFCSTATUS_SUCCESS; */ + } + } + break; + } + /* Disable the UICC Emulation through SWP */ + case SWP_DISABLE_EMULATION: + { + p_pipe_info = ((phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_SWP_Configure_Mode( psHciContext, + pHwRef, UICC_SWITCH_MODE_DEFAULT ); + if(status == NFCSTATUS_PENDING) + { + p_emulation_mgmt_info->emulation_next_seq = + CONFIG_DEFAULT_EMULATION; + status = phHciNfc_EmuMgmt_Update_Seq(psHciContext, + UPDATE_SEQ); + status = NFCSTATUS_SUCCESS; + } + } + break; + } + /* Configure the Default Secure Element Emulation */ + case CONFIG_DEFAULT_EMULATION: + { +#if 0 + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + /* status = phHciNfc_DevMgmt_Configure( psHciContext, + pHwRef, , ); */ + if(status == NFCSTATUS_PENDING) + { + p_emulation_mgmt_info->emulation_next_seq = + END_EMULATION_SEQ; + status = phHciNfc_EmuMgmt_Update_Seq(psHciContext, + UPDATE_SEQ); + status = NFCSTATUS_SUCCESS; + } + } +#endif + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + + }/* End of the Sequence Switch */ + + }/* End of the Reader Info Memory Check */ + + } /* End of Null Context Check */ + + return status; +} + +#if 0 +NFCSTATUS +phHciNfc_Emulation_Start ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + return status; +} +#endif + +NFCSTATUS +phHciNfc_Emulation_Cfg ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eConfigType_t cfg_type + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_EmulationMgmt_Info_t *p_emulation_mgmt_info=NULL; + phHal_sEmulationCfg_t *p_emulation_cfg = NULL; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( ( NULL == psHciContext->p_emulation_mgmt_info ) + || ( NULL == psHciContext->p_config_params ) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_emulation_mgmt_info = (phHciNfc_EmulationMgmt_Info_t *) + psHciContext->p_emulation_mgmt_info ; + p_emulation_cfg = psHciContext->p_config_params; + switch(cfg_type) + { + case SMX_WI_CFG: + { + phHal_sSmartMX_Cfg_t *smx_config = + &p_emulation_cfg->config.smartMxCfg; + p_emulation_mgmt_info->smx_powerless = + (uint8_t)(FALSE != smx_config->lowPowerMode ); + status = phHciNfc_WI_Configure_Default( psHciContext, pHwRef, + smx_config->enableEmulation ); + break; + } + case UICC_SWP_CFG: + { +#ifdef SWP_CFG_SEQ + phHal_sUiccEmuCfg_t *uicc_config = + &p_emulation_cfg->config.uiccEmuCfg; + p_emulation_mgmt_info->uicc_powerless = + (uint8_t)(FALSE != uicc_config->lowPowerMode ); + { +#ifdef SWP_EVENT_USAGE + status = phHciNfc_SWP_Configure_Mode( psHciContext, pHwRef, + ((TRUE == uicc_config->enableUicc)? /* UICC_SWITCH_MODE_DEFAULT */ + UICC_SWITCH_MODE_ON :UICC_SWITCH_MODE_OFF)); +#else + status = phHciNfc_SWP_Configure_Default( psHciContext, pHwRef, + uicc_config->enableUicc ); +#endif + } +#else + status = phHciNfc_SWP_Config_Sequence( psHciContext, + pHwRef, p_emulation_cfg); +#endif + break; + } + case SWP_EVT_CFG: + { + phHal_sUiccEmuCfg_t *uicc_config = + &p_emulation_cfg->config.uiccEmuCfg; + p_emulation_mgmt_info->uicc_powerless = + (uint8_t)(FALSE != uicc_config->lowPowerMode ); + { + status = phHciNfc_SWP_Configure_Mode( psHciContext, pHwRef, + ((TRUE == uicc_config->enableUicc)? /* UICC_SWITCH_MODE_DEFAULT */ + UICC_SWITCH_MODE_ON :UICC_SWITCH_MODE_DEFAULT)); + } + break; + } +#ifdef HOST_EMULATION + case NFC_CE_A_CFG: + { + phHal_sHostEmuCfg_A_t *host_ce_a_cfg = + &p_emulation_cfg->config.hostEmuCfg_A; + if(host_ce_a_cfg->enableEmulation == TRUE ) + { + status = phHciNfc_CE_A_Initialise( psHciContext, pHwRef); + } + else + { + status = phHciNfc_CE_A_Release( psHciContext, pHwRef); + } + break; + } + case NFC_CE_B_CFG: + { + phHal_sHostEmuCfg_B_t *host_ce_b_cfg = + &p_emulation_cfg->config.hostEmuCfg_B; + if(host_ce_b_cfg->enableEmulation == TRUE ) + { + status = phHciNfc_CE_B_Initialise( psHciContext, pHwRef); + } + else + { + status = phHciNfc_CE_B_Release( psHciContext, pHwRef); + } + break; + } +#endif + /* case INVALID_CFG: + case POLL_LOOP_CFG: */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + break; + } + + } /* End of the Configuration Switch */ + } + + return status; +} + + +static +NFCSTATUS +phHciNfc_Recv_Uicc_Cmd ( + void *psContext, + void *pHwRef, + uint8_t *pCmd, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + uint8_t pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + uint8_t cmd = (uint8_t) HCP_MSG_INSTRUCTION_INVALID; + uint8_t response = (uint8_t) ANY_OK; + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_EmulationMgmt_Info_t *p_emulation_mgmt_info=NULL; + + if( (NULL == psHciContext) + || (NULL == pHwRef) + || (HCP_HEADER_LEN > length ) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + hcp_packet = (phHciNfc_HCP_Packet_t *)pCmd; + hcp_message = &hcp_packet->msg.message; + p_emulation_mgmt_info = psHciContext->p_emulation_mgmt_info; + + /* Get the Command instruction bits from the Message Header */ + cmd = (uint8_t) GET_BITS8( hcp_message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + pipe_id = p_emulation_mgmt_info->uicc_id; + p_pipe_info = psHciContext->p_pipe_list[pipe_id]; + + switch( cmd ) + { + /* These are Commands are sent from the UICC Controller */ + case ANY_OPEN_PIPE: + { + p_emulation_mgmt_info->uicc_enable = TRUE ; + break; + } + case ANY_CLOSE_PIPE: + { + if(TRUE != p_emulation_mgmt_info->uicc_enable) + { + response = ANY_E_PIPE_NOT_OPENED; + /* status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FAILED); */ + } + else + { + p_emulation_mgmt_info->uicc_enable = FALSE; + } + break; + } + case ANY_SET_PARAMETER: + case ANY_GET_PARAMETER: + case PRO_HOST_REQUEST: + { + response = ANY_E_CMD_NOT_SUPPORTED; + /* status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_COMMAND_NOT_SUPPORTED);*/ + break; + } + default: + { + response = ANY_E_NOK; + /* status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_COMMAND); */ + break; + } + } + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + pipe_id, HCP_MSG_TYPE_RESPONSE, response ); + psHciContext->tx_total = HCP_HEADER_LEN; + status = phHciNfc_Send_HCP( (void *)psHciContext, (void *)pHwRef ); + + p_pipe_info->recv_msg_type = HCP_MSG_TYPE_COMMAND; + p_pipe_info->sent_msg_type = HCP_MSG_TYPE_RESPONSE; + p_pipe_info->prev_msg = response ; + p_pipe_info->prev_status = status; + status = NFCSTATUS_SUCCESS; + + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_Uicc_Event ( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + uint8_t event = (uint8_t) HCP_MSG_INSTRUCTION_INVALID; + uint32_t i = 0; + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + phHal_sEventInfo_t event_info; + phHciNfc_EmulationMgmt_Info_t *p_emulation_mgmt_info = + psHciContext->p_emulation_mgmt_info ; + + + if( (NULL == p_emulation_mgmt_info) + || ( TRUE != p_emulation_mgmt_info->uicc_enable) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + hcp_packet = (phHciNfc_HCP_Packet_t *)pEvent; + hcp_message = &hcp_packet->msg.message; + + /* Get the Event instruction bits from the Message Header */ + event = (uint8_t) GET_BITS8( hcp_message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + event_info.eventHost = phHal_eUICCHost ; + event_info.eventSource = phHal_ePICC_DevType ; + + switch( event ) + { + case EVT_END_OF_TRANSACTION: + { + event_info.eventType = NFC_EVT_END_OF_TRANSACTION; + break; + } + case EVT_TRANSACTION: + { + if(length > HCP_HEADER_LEN + TRANSACTION_MIN_LEN) + { + event_info.eventType = NFC_EVT_TRANSACTION; + + for(;i<(length-HCP_HEADER_LEN);) + { + switch (hcp_message->payload[i]) + { + case TRANSACTION_AID: + { + /* AID LENGTH INDEX */ + i++; + /* Fill the event_info.eventInfo.aid + * Structure with the Received Transaction AID. + */ + event_info.eventInfo.aid.length = + hcp_message->payload[i++]; + (void) memcpy((void *)p_emulation_mgmt_info->uicc_aid, + &(hcp_message->payload[i]), + event_info.eventInfo.aid.length ); + event_info.eventInfo.aid.buffer = (uint8_t *) + p_emulation_mgmt_info->uicc_aid; + i = i + event_info.eventInfo.aid.length; + break; + } + case TRANSACTION_PARAM: + { + /* Parameter Length Index */ + i++; + /* Fill the event_info.eventInfo.param + * Structure with the Received Parameter. + */ + p_emulation_mgmt_info->uicc_param_len = + hcp_message->payload[i++]; + (void) memcpy((void *)p_emulation_mgmt_info->uicc_param, + &(hcp_message->payload[i]), + p_emulation_mgmt_info->uicc_param_len ); + event_info.eventInfo.uicc_info.param.length = + p_emulation_mgmt_info->uicc_param_len; + event_info.eventInfo.uicc_info.param.buffer = (uint8_t *) + p_emulation_mgmt_info->uicc_param; + i = i + event_info.eventInfo.uicc_info.param.length; + break; + } + default: + { + + status = PHNFCSTVAL( CID_NFC_HCI, + NFCSTATUS_FEATURE_NOT_SUPPORTED ); + i = length; + HCI_DEBUG("%s: Statement Should Not Occur \n", + "phHciNfc_Recv_Uicc_Event"); + break; + } + } /* End of Transaction Switch */ + } + } + break; + } + case EVT_CONNECTIVITY: + { + event_info.eventType = NFC_EVT_CONNECTIVITY; + break; + } + case EVT_OPERATION_ENDED: + { + event_info.eventType = NFC_EVT_OPERATION_ENDED; + break; + } + default: + { + status = PHNFCSTVAL( CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED ); + HCI_DEBUG("%s: Statement Should Not Occur \n","phHciNfc_Recv_Uicc_Event"); + break; + } + } + if ( NFCSTATUS_SUCCESS == status ) + { + phHciNfc_Notify_Event( psHciContext, pHwRef, + NFC_NOTIFY_EVENT, (void *)&event_info ); + } + } + return status; +} + + diff --git a/libnfc-nxp/phHciNfc_Emulation.h b/libnfc-nxp/phHciNfc_Emulation.h new file mode 100644 index 0000000..b4669f3 --- /dev/null +++ b/libnfc-nxp/phHciNfc_Emulation.h @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_Emulation.h * +* \brief HCI emulation management routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Aug 14 17:01:26 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.10 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + + +#ifndef PHHCINFC_EMULATION_H +#define PHHCINFC_EMULATION_H + +/*@}*/ + + +/** +* \name HCI +* +* File: \ref phHciNfc_Emulation.h +* +*/ +/*@{*/ +#define PHHCINFC_EMULATION_FILEREVISION "$Revision: 1.10 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_EMULATION_FILEALIASES "$Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ +/* Connectivity Gate Command Support */ +#define PRO_HOST_REQUEST (0x10U) + +/* Connectivity Gate Event Support */ +#define EVT_CONNECTIVITY (0x10U) +#define EVT_END_OF_TRANSACTION (0x11U) +#define EVT_TRANSACTION (0x12U) +#define EVT_OPERATION_ENDED (0x13U) + +#define TRANSACTION_MIN_LEN (0x03U) +#define TRANSACTION_AID (0x81U) +#define TRANSACTION_PARAM (0x82U) + +#define HOST_CE_MODE_ENABLE (0x02U) +#define HOST_CE_MODE_DISABLE (0xFFU) + +#define NXP_PIPE_CONNECTIVITY (0x60U) + + +/* Card Emulation Gate Events */ +#define CE_EVT_NFC_SEND_DATA (0x10U) +#define CE_EVT_NFC_FIELD_ON (0x11U) +#define CE_EVT_NFC_DEACTIVATED (0x12U) +#define CE_EVT_NFC_ACTIVATED (0x13U) +#define CE_EVT_NFC_FIELD_OFF (0x14U) + +/* +******************** Enumeration and Structure Definition ********************** +*/ + + + +/* +*********************** Function Prototype Declaration ************************* +*/ + +extern +NFCSTATUS +phHciNfc_Uicc_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipe_id, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +extern +NFCSTATUS +phHciNfc_EmuMgmt_Update_Seq( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t seq_type + ); + +extern +NFCSTATUS +phHciNfc_EmuMgmt_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +extern +NFCSTATUS +phHciNfc_EmuMgmt_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +extern +NFCSTATUS +phHciNfc_Emulation_Cfg ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eConfigType_t cfg_type + ); + +extern +NFCSTATUS +phHciNfc_Uicc_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + +extern +NFCSTATUS +phHciNfc_Uicc_Connect_Status( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +extern +void +phHciNfc_Uicc_Connectivity( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +#endif /* PHHCINFC_EMULATION_H */ diff --git a/libnfc-nxp/phHciNfc_Felica.c b/libnfc-nxp/phHciNfc_Felica.c new file mode 100644 index 0000000..2897690 --- /dev/null +++ b/libnfc-nxp/phHciNfc_Felica.c @@ -0,0 +1,996 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_Felica.c * +* \brief HCI Felica Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Wed Feb 17 16:19:04 2010 $ * +* $Author: ing02260 $ * +* $Revision: 1.11 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include + +#if defined(TYPE_FELICA) +#include +/* +****************************** Macro Definitions ******************************* +*/ + +#define FEL_SINGLE_TAG_FOUND 0x00U +#define FEL_MULTIPLE_TAGS_FOUND 0x03U +#define NXP_WRA_CONTINUE_ACTIVATION 0x12U + +#define NXP_FEL_SYS_CODE 0x01U +#define NXP_FEL_POLREQ_SYS_CODE 0x02U +#define NXP_FEL_CURRENTIDM 0x04U +#define NXP_FEL_CURRENTPMM 0x05U + +#define NXP_FEL_SYS_CODE_LEN 0x02U +#define NXP_FEL_CUR_IDM_PMM_LEN 0x08U + +#define FELICA_STATUS 0x00U + +uint8_t nxp_nfc_felica_timeout = NXP_FELICA_XCHG_TIMEOUT; + +/* Presence check command for felica tag */ +#define FELICA_REQ_MODE 0x04U + +/* +*************************** Structure and Enumeration *************************** +*/ + + +/* +*************************** Static Function Declaration ************************** +*/ +static +NFCSTATUS +phHciNfc_Recv_Felica_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_Felica_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Felica_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); + +static +NFCSTATUS +phHciNfc_Recv_Felica_Packet( + phHciNfc_sContext_t *psHciContext, + uint8_t cmd, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); +/* +*************************** Function Definitions *************************** +*/ + +NFCSTATUS +phHciNfc_Felica_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_felica_info ) + ) + { + phHciNfc_Felica_Info_t *p_fel_info = NULL; + p_fel_info = (phHciNfc_Felica_Info_t *)psHciContext->p_felica_info ; + *ppipe_id = p_fel_info->pipe_id ; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + + +NFCSTATUS +phHciNfc_Felica_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Felica_Info_t *p_fel_info = NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( + ( NULL == psHciContext->p_felica_info ) && + (phHciNfc_Allocate_Resource((void **)(&p_fel_info), + sizeof(phHciNfc_Felica_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_felica_info = p_fel_info; + p_fel_info->current_seq = FELICA_INVALID_SEQ; + p_fel_info->next_seq = FELICA_INVALID_SEQ; + p_fel_info->pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + return status; +} + +NFCSTATUS +phHciNfc_Felica_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_felica_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_Felica_Info_t *p_fel_info=NULL; + p_fel_info = (phHciNfc_Felica_Info_t *)psHciContext->p_felica_info ; + + /* Update the pipe_id of the Felica Gate obtained from the HCI + Response */ + p_fel_info->pipe_id = pipeID; + p_fel_info->p_pipe_info = pPipeInfo; + /* Update the Response Receive routine of the Felica Gate */ + pPipeInfo->recv_resp = phHciNfc_Recv_Felica_Response; + /* Update the event Receive routine of the Felica Gate */ + pPipeInfo->recv_event = phHciNfc_Recv_Felica_Event; + } + + return status; +} + +NFCSTATUS +phHciNfc_Felica_Update_Info( + phHciNfc_sContext_t *psHciContext, + uint8_t infotype, + void *fel_info + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if (NULL == psHciContext) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_felica_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_Felica_Info_t *p_fel_info=NULL; + p_fel_info = (phHciNfc_Felica_Info_t *) + psHciContext->p_felica_info ; + + switch(infotype) + { + case HCI_FELICA_ENABLE: + { + if (NULL != fel_info) + { + p_fel_info->enable_felica_gate = + *((uint8_t *)fel_info); + } + break; + } + case HCI_FELICA_INFO_SEQ: + { + p_fel_info->current_seq = FELICA_SYSTEMCODE; + p_fel_info->next_seq = FELICA_SYSTEMCODE; + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + } + } + return status; +} + +NFCSTATUS +phHciNfc_Felica_Info_Sequence ( + void *psHciHandle, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + ((phHciNfc_sContext_t *)psHciHandle); + + HCI_PRINT ("HCI : phHciNfc_Felica_Info_Sequence called... \n"); + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_felica_info) || + (HCI_FELICA_ENABLE != + ((phHciNfc_Felica_Info_t *)(psHciContext->p_felica_info))-> + enable_felica_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_Felica_Info_t *p_fel_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_fel_info = (phHciNfc_Felica_Info_t *) + psHciContext->p_felica_info ; + p_pipe_info = p_fel_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + HCI_DEBUG ("HCI : p_fel_info->current_seq : %02X\n", p_fel_info->current_seq); + switch(p_fel_info->current_seq) + { + case FELICA_SYSTEMCODE: + { + p_pipe_info->reg_index = NXP_FEL_SYS_CODE; + pipeid = p_fel_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_fel_info->next_seq = FELICA_CURRENTIDM; + } + break; + } + case FELICA_CURRENTIDM: + { + p_pipe_info->reg_index = NXP_FEL_CURRENTIDM; + pipeid = p_fel_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_fel_info->next_seq = FELICA_CURRENTPMM; + } + break; + } + case FELICA_CURRENTPMM: + { + p_pipe_info->reg_index = NXP_FEL_CURRENTPMM; + pipeid = p_fel_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_fel_info->next_seq = FELICA_END_SEQUENCE; + } + break; + } + case FELICA_END_SEQUENCE: + { + phNfc_sCompletionInfo_t CompInfo; + if (FEL_MULTIPLE_TAGS_FOUND == + p_fel_info->multiple_tgts_found) + { + CompInfo.status = NFCSTATUS_MULTIPLE_TAGS; + } + else + { + CompInfo.status = NFCSTATUS_SUCCESS; + } + + CompInfo.info = &(p_fel_info->felica_info); + + p_fel_info->felica_info.RemDevType = phHal_eFelica_PICC; + p_fel_info->current_seq = FELICA_SYSTEMCODE; + p_fel_info->next_seq = FELICA_SYSTEMCODE; + status = NFCSTATUS_SUCCESS; + HCI_DEBUG ("HCI : p_fel_info->felica_info.RemDevType : %02X\n", p_fel_info->felica_info.RemDevType); + HCI_DEBUG ("HCI : status notified: %02X\n", CompInfo.status); + /* Notify to the upper layer */ + phHciNfc_Tag_Notify(psHciContext, + pHwRef, + NFC_NOTIFY_TARGET_DISCOVERED, + &CompInfo); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + HCI_DEBUG ("HCI : p_fel_info->current_seq after : %02X\n", p_fel_info->current_seq); + HCI_DEBUG ("HCI : p_fel_info->next_seq : %02X\n", p_fel_info->next_seq); + } + } + HCI_PRINT ("HCI : phHciNfc_Felica_Info_Sequence end\n"); + return status; +} + +static +NFCSTATUS +phHciNfc_Felica_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Felica_Info_t *p_fel_info=NULL; + phHal_sFelicaInfo_t *p_fel_tag_info = NULL; + + p_fel_info = (phHciNfc_Felica_Info_t *)(psHciContext->p_felica_info ); + p_fel_tag_info = &(p_fel_info->felica_info.RemoteDevInfo.Felica_Info); + + switch(index) + { + case NXP_FEL_SYS_CODE: + { + if (NXP_FEL_SYS_CODE_LEN == reg_length) + { + /* System code from registry is invalid in this case */ + p_fel_tag_info->SystemCode[0] = 0; + p_fel_tag_info->SystemCode[1] = 0; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_FEL_CURRENTIDM: + { + if (NXP_FEL_CUR_IDM_PMM_LEN == reg_length) + { + HCI_PRINT_BUFFER("\tFelica ID data", reg_value, reg_length); + /* Update current PM values */ + (void)memcpy(p_fel_tag_info->IDm, reg_value, + reg_length); + p_fel_tag_info->IDmLength = reg_length; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_FEL_CURRENTPMM: + { + if (NXP_FEL_CUR_IDM_PMM_LEN == reg_length) + { + HCI_PRINT_BUFFER("\tFelica PM data", reg_value, reg_length); + /* Update current PM values */ + (void)memcpy(p_fel_tag_info->PMm, reg_value, + reg_length); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + return status; +} + + +static +NFCSTATUS +phHciNfc_Recv_Felica_Packet( + phHciNfc_sContext_t *psHciContext, + uint8_t cmd, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t index = 0; + + /* To remove "warning (VS C4100) : unreferenced formal parameter" */ + + PHNFC_UNUSED_VARIABLE(length); + + if (NXP_FELICA_RAW == cmd) + { + if (FELICA_STATUS == pResponse[index]) /* Status byte */ + { + index = (index + 1); + psHciContext->rx_index = (HCP_HEADER_LEN + 1); + HCI_PRINT_BUFFER("Felica Bytes received", &pResponse[index], (length - index)); + /* If Poll response received then update IDm and PMm parameters, when presence check going on */ + if (pResponse[index + 1] == 0x01) + { + if (length >= 19) + { + /* IDm */ + (void) memcpy(psHciContext->p_target_info->RemoteDevInfo.Felica_Info.IDm, + &pResponse[index + 2], 8); + /* PMm */ + (void) memcpy(psHciContext->p_target_info->RemoteDevInfo.Felica_Info.PMm, + &pResponse[index + 2 + 8], 8); + index = index + 2 + 8 + 8; + + /* SC */ + if (length >= 21) + { + /* Copy SC if available */ + psHciContext->p_target_info->RemoteDevInfo.Felica_Info.SystemCode[0] = pResponse[index]; + psHciContext->p_target_info->RemoteDevInfo.Felica_Info.SystemCode[1] = pResponse[index + 1]; + } + else + { + /* If SC is not available in packet then set to zero */ + psHciContext->p_target_info->RemoteDevInfo.Felica_Info.SystemCode[0] = 0; + psHciContext->p_target_info->RemoteDevInfo.Felica_Info.SystemCode[1] = 0; + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + } + else + { + psHciContext->rx_index = HCP_HEADER_LEN; + + /* command NXP_FELICA_CMD: so give Felica data to the upper layer */ + HCI_PRINT_BUFFER("Felica Bytes received", pResponse, length); + } + + return status; +} + + +static +NFCSTATUS +phHciNfc_Recv_Felica_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse) + || (0 == length)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_felica_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_Felica_Info_t *p_fel_info=NULL; + uint8_t prev_cmd = ANY_GET_PARAMETER; + p_fel_info = (phHciNfc_Felica_Info_t *) + psHciContext->p_felica_info ; + if( NULL == p_fel_info->p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + prev_cmd = p_fel_info->p_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_GET_PARAMETER: + { + status = phHciNfc_Felica_InfoUpdate(psHciContext, + p_fel_info->p_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); + break; + } + case ANY_SET_PARAMETER: + { + HCI_PRINT("Felica Parameter Set \n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + p_fel_info->next_seq = FELICA_SYSTEMCODE; + break; + } + case ANY_OPEN_PIPE: + { + HCI_PRINT("Felica open pipe complete\n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + p_fel_info->next_seq = FELICA_SYSTEMCODE; + break; + } + case ANY_CLOSE_PIPE: + { + HCI_PRINT("Felica close pipe complete\n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + break; + } + + case NXP_FELICA_RAW: + case NXP_FELICA_CMD: + case WR_XCHGDATA: + { + HCI_PRINT("Felica packet received \n"); + if (length >= HCP_HEADER_LEN) + { + phHciNfc_Append_HCPFrame(psHciContext->recv_buffer, + 0, pResponse, length); + psHciContext->rx_total = length; + status = phHciNfc_Recv_Felica_Packet(psHciContext, + prev_cmd, + &pResponse[HCP_HEADER_LEN], + (length - HCP_HEADER_LEN)); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_WRA_CONTINUE_ACTIVATION: + case NXP_WR_ACTIVATE_ID: + { + HCI_PRINT("Felica continue activation or "); + HCI_PRINT("reactivation completed \n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + break; + } + case NXP_WR_PRESCHECK: + { + HCI_PRINT("Presence check completed \n"); + break; + } + case NXP_WR_ACTIVATE_NEXT: + { + HCI_PRINT("Activate next completed \n"); + if (length > HCP_HEADER_LEN) + { + if (FEL_MULTIPLE_TAGS_FOUND == pResponse[HCP_HEADER_LEN]) + { + p_fel_info->multiple_tgts_found = + FEL_MULTIPLE_TAGS_FOUND; + } + else + { + p_fel_info->multiple_tgts_found = FALSE; + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_WR_DISPATCH_TO_UICC: + { + switch(length) + { + case HCP_HEADER_LEN: + { + /* Optional error code, if no error code field + in the response, then this command is + successfully completed */ + p_fel_info->uicc_activation = + UICC_CARD_ACTIVATION_SUCCESS; + break; + } + case (HCP_HEADER_LEN + 1): + { + p_fel_info->uicc_activation = + pResponse[HCP_HEADER_LEN]; + break; + } /* End of case (HCP_HEADER_LEN + index) */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if (NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + p_fel_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; + p_fel_info->current_seq = p_fel_info->next_seq; + } + } + } + return status; +} + + +static +NFCSTATUS +phHciNfc_Recv_Felica_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + + HCI_PRINT ("HCI : phHciNfc_Recv_Felica_Event called...\n"); + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent) + || (0 == length)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_felica_info) || + (HCI_FELICA_ENABLE != + ((phHciNfc_Felica_Info_t *)(psHciContext->p_felica_info))-> + enable_felica_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_Felica_Info_t *p_fel_info = NULL; + phHciNfc_HCP_Message_t *message = NULL; + uint8_t instruction=0, + i = 0; + + p_fel_info = (phHciNfc_Felica_Info_t *) + psHciContext->p_felica_info ; + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &p_packet->msg.message; + /* Get the instruction bits from the Message Header */ + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + + HCI_DEBUG ("HCI : instruction : %02X\n", instruction); + HCI_DEBUG ("HCI : Multiple tag found : %02X\n", message->payload[i]); + if ((EVT_TARGET_DISCOVERED == instruction) + && ((FEL_MULTIPLE_TAGS_FOUND == message->payload[i] ) + || (FEL_SINGLE_TAG_FOUND == message->payload[i])) + ) + { + static phNfc_sCompletionInfo_t pCompInfo; + + if (FEL_MULTIPLE_TAGS_FOUND == message->payload[i]) + { + p_fel_info->multiple_tgts_found = FEL_MULTIPLE_TAGS_FOUND; + pCompInfo.status = NFCSTATUS_MULTIPLE_TAGS; + } + else + { + p_fel_info->multiple_tgts_found = FALSE; + pCompInfo.status = NFCSTATUS_SUCCESS; + } + + HCI_DEBUG ("HCI : psHciContext->host_rf_type : %02X\n", psHciContext->host_rf_type); + HCI_DEBUG ("HCI : p_fel_info->felica_info.RemDevType : %02X\n", p_fel_info->felica_info.RemDevType); + HCI_DEBUG ("HCI : p_fel_info->current_seq : %02X\n", p_fel_info->current_seq); + + psHciContext->host_rf_type = phHal_eFelica_PCD; + p_fel_info->felica_info.RemDevType = phHal_eFelica_PICC; + p_fel_info->current_seq = FELICA_SYSTEMCODE; + + /* Notify to the HCI Generic layer To Update the FSM */ + phHciNfc_Notify_Event(psHciContext, pHwRef, + NFC_NOTIFY_TARGET_DISCOVERED, + &pCompInfo); + + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + } + } + HCI_PRINT ("HCI : phHciNfc_Recv_Felica_Event end\n"); + return status; +} + + +NFCSTATUS +phHciNfc_Felica_Request_Mode( + phHciNfc_sContext_t *psHciContext, + void *pHwRef) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t pres_chk_data[6] = {0}; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + phHciNfc_Felica_Info_t *ps_fel_info = NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info = NULL; + phHal_sFelicaInfo_t *ps_rem_fel_info = NULL; + + ps_fel_info = (phHciNfc_Felica_Info_t *) + psHciContext->p_felica_info ; + ps_pipe_info = ps_fel_info->p_pipe_info; + + if(NULL == ps_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + ps_rem_fel_info = + &(ps_fel_info->felica_info.RemoteDevInfo.Felica_Info); + + pres_chk_data[0] = sizeof(pres_chk_data); + pres_chk_data[1] = 0x00; // Felica poll + pres_chk_data[2] = 0xFF; + pres_chk_data[3] = 0xFF; + pres_chk_data[4] = 0x01; + pres_chk_data[5] = 0x00; + + ps_pipe_info->param_info = pres_chk_data; + ps_pipe_info->param_length = sizeof(pres_chk_data); + status = phHciNfc_Send_Felica_Command( + psHciContext, pHwRef, + ps_pipe_info->pipe.pipe_id, + NXP_FELICA_RAW); + } + } + + return status; +} + +NFCSTATUS +phHciNfc_Send_Felica_Command( + phHciNfc_sContext_t *psContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_felica_info) || + (HCI_FELICA_ENABLE != + ((phHciNfc_Felica_Info_t *)(psHciContext->p_felica_info))-> + enable_felica_gate) || + (HCI_UNKNOWN_PIPE_ID == + ((phHciNfc_Felica_Info_t *)(psHciContext->p_felica_info))-> + pipe_id) || + (pipe_id != + ((phHciNfc_Felica_Info_t *)(psHciContext->p_felica_info))-> + pipe_id)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_Felica_Info_t *p_fel_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + uint8_t i = 0, + length = HCP_HEADER_LEN; + + p_fel_info = (phHciNfc_Felica_Info_t *) + psHciContext->p_felica_info ; + p_pipe_info = p_fel_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + psHciContext->tx_total = 0 ; + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + switch(cmd) + { + case NXP_FELICA_RAW: + { + /* + Buffer shall be updated with + TO - Time out (1 byte) + Status - b0 to b2 indicate valid bits (1 byte) + Data - params received from this function + */ + hcp_message = &(hcp_packet->msg.message); + + /* Time out */ + hcp_message->payload[i++] = nxp_nfc_felica_timeout ; + /* Status */ + hcp_message->payload[i++] = FELICA_STATUS; + + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, (uint8_t *)p_pipe_info->param_info, + p_pipe_info->param_length); + length =(uint8_t)(length + i + p_pipe_info->param_length); + break; + } + case NXP_FELICA_CMD: + { + /* + Buffer shall be updated with + Cmd - Authentication A/B, read/write + (1 byte) + Data - params received from this function + */ + hcp_message = &(hcp_packet->msg.message); + + /* Command */ + hcp_message->payload[i++] = + psHciContext->p_xchg_info->params.tag_info.cmd_type ; + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, (uint8_t *)p_pipe_info->param_info, + p_pipe_info->param_length); + length =(uint8_t)(length + i + p_pipe_info->param_length); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_COMMAND); + break; + } + } + if (NFCSTATUS_SUCCESS == status) + { + p_pipe_info->sent_msg_type = (uint8_t)HCP_MSG_TYPE_COMMAND; + p_pipe_info->prev_msg = cmd; + psHciContext->tx_total = length; + psHciContext->response_pending = TRUE; + + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef); + p_pipe_info->prev_status = status; + } + } + } + return status; +} + +#endif /* #if defined(TYPE_FELICA) */ diff --git a/libnfc-nxp/phHciNfc_Felica.h b/libnfc-nxp/phHciNfc_Felica.h new file mode 100644 index 0000000..f399417 --- /dev/null +++ b/libnfc-nxp/phHciNfc_Felica.h @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_Felica.h * +* \brief HCI Felica Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Jun 5 12:10:53 2009 $ * +* $Author: ing02260 $ * +* $Revision: 1.3 $ * +* $Aliases: NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + +#ifndef PHHCINFC_FELICA_H +#define PHHCINFC_FELICA_H + +/*@}*/ + + +/** +* \name HCI +* +* File: \ref phHciNfc_Felica.h +* +*/ +/*@{*/ +#define PHHCINFC_FELICA_FILEREVISION "$Revision: 1.3 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_FELICA_FILEALIASES "$Aliases: NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +/* Commands exposed to the upper layer */ + +/* Enable the Felica */ +#define HCI_FELICA_ENABLE 0x01U +#define HCI_FELICA_INFO_SEQ 0x02U + +/* Felica read write commands */ +#define NXP_FELICA_RAW 0x20U +#define NXP_FELICA_CMD 0x21U + +/* +******************** Enumeration and Structure Definition ********************** +*/ +typedef enum phHciNfc_Felica_Seq{ + FELICA_SYSTEMCODE, + FELICA_CURRENTIDM, + FELICA_CURRENTPMM, + FELICA_END_SEQUENCE, + FELICA_INVALID_SEQ +} phHciNfc_Felica_Seq_t; + +/* Information structure for the Felica Gate */ +typedef struct phHciNfc_Felica_Info{ + /* Current running Sequence of the Felica Management */ + phHciNfc_Felica_Seq_t current_seq; + /* Next running Sequence of the Felica Management */ + phHciNfc_Felica_Seq_t next_seq; + /* Pointer to the Felica pipe information */ + phHciNfc_Pipe_Info_t *p_pipe_info; + uint8_t pipe_id; + /* Flag to say about the multiple targets */ + uint8_t multiple_tgts_found; + /* Felica information */ + phHal_sRemoteDevInformation_t felica_info; + /* Enable or disable reader gate */ + uint8_t enable_felica_gate; + /* UICC re-activation status */ + uint8_t uicc_activation; +} phHciNfc_Felica_Info_t; + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/*! +* \brief Allocates the resources of Felica management gate. +* +* This function Allocates the resources of the Felica management +* gate Information Structure. +* +*/ +extern +NFCSTATUS +phHciNfc_Felica_Init_Resources( + phHciNfc_sContext_t *psHciContext + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Felica_Get_PipeID function gives the pipe id of the Felica +* gate +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_Felica_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Felica_Update_PipeInfo function updates the pipe_id of the Felica +* gate management Structure. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pipeID pipeID of the Felica gate +* \param[in] pPipeInfo Update the pipe Information of the reader +* A gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ + +extern +NFCSTATUS +phHciNfc_Felica_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderA_Update_Info function updated the felica gate info. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] infotype To enable the felica gate +* \param[in] fel_info felica gate info +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +*/ +extern +NFCSTATUS +phHciNfc_Felica_Update_Info( + phHciNfc_sContext_t *psHciContext, + uint8_t infotype, + void *fel_info + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Felica_Info_Sequence function executes the sequence of operations, to +* get the SYSTEM CODE, IDM, PPM. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_Felica_Info_Sequence ( + void *psHciHandle, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Felica_Request_Mode function is to know about the felica tag is +* in the field or not +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_Felica_Request_Mode( + phHciNfc_sContext_t *psHciContext, + void *pHwRef); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Send_Felica_Command function executes the command sent by the +* upper layer, depending on the commands defined. +* +* \param[in] psContext psContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] pipe_id pipeID of the Felica gate +* \param[in] cmd command that needs to be sent to the device +* \param[in] length information length sent by the caller +* \param[in] params information related to the command +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +*/ +extern +NFCSTATUS +phHciNfc_Send_Felica_Command( + phHciNfc_sContext_t *psContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ); + +#endif /* #ifndef PHHCINFC_FELICA_H */ + + diff --git a/libnfc-nxp/phHciNfc_Generic.c b/libnfc-nxp/phHciNfc_Generic.c new file mode 100644 index 0000000..875e295 --- /dev/null +++ b/libnfc-nxp/phHciNfc_Generic.c @@ -0,0 +1,2059 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_Generic.c * +* \brief Generic HCI Source for the HCI Management. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Tue Jun 8 09:31:49 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.108 $ * +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +################################################################################ +***************************** Header File Inclusion **************************** +################################################################################ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +################################################################################ +****************************** Macro Definitions ******************************* +################################################################################ +*/ + +/* HCI timeout value */ +uint32_t nxp_nfc_hci_response_timeout = NXP_NFC_HCI_TIMEOUT; + +/* +################################################################################ +************************ Static Variable Definitions *************************** +################################################################################ +*/ + + +#if (NXP_NFC_HCI_TIMER == 1) + +#define NXP_HCI_RESPONSE_TIMEOUT (NXP_NFC_HCI_TIMEOUT) + +#include +/** \internal HCI Response Timer to detect the + * Stalled HCI Response */ +static uint32_t hci_resp_timer_id = NXP_INVALID_TIMER_ID; +static phHciNfc_sContext_t *gpsHciContext= NULL; + +#endif /* (NXP_NFC_HCI_TIMER == 1) */ + + +/* +################################################################################ +************************* Function Prototype Declaration *********************** +################################################################################ +*/ + +#if (NXP_NFC_HCI_TIMER == 1) + +static +void +phHciNfc_Response_Timeout ( + uint32_t resp_timer_id, void *pContext + ); + +#endif /* (NXP_NFC_HCI_TIMER == 1) */ + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Send function sends the HCI Commands to the + * corresponding peripheral device, described by the HCI Context Structure. + * + * \param[in] psContext psContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] pdata Pointer to the buffer containing + * the command to be sent. + * \param[in] length Variable that receives + * the number of bytes actually sent. + * + * \retval NFCSTATUS_PENDING Command successfully sent. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the lower layers + * + */ + +static + NFCSTATUS + phHciNfc_Send( + void *psContext, + void *pHwRef, + uint8_t *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + static + NFCSTATUS + phHciNfc_Process_HCP ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + void *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + +static +NFCSTATUS +phHciNfc_Process_Response ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + void *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Error_Response ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + void *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Process_Event ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + void *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + +static +NFCSTATUS +phHciNfc_Process_Command ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + void *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + +static +void +phHciNfc_Reset_Pipe_MsgInfo( + phHciNfc_Pipe_Info_t *p_pipe_info + ); + +static +void +phHciNfc_Build_HCPMessage( + phHciNfc_HCP_Packet_t *hcp_packet, + uint8_t msg_type, + uint8_t instruction + ); + +static +void +phHciNfc_Build_HCPHeader( + phHciNfc_HCP_Packet_t *hcp_packet, + uint8_t chainbit, + uint8_t pipe_id + ); +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Receive_HCP function receive the HCI Host Control Packet + * Frames from the device. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] pdata Pointer to the response buffer that + * receives the response read. + * \param[in] length Variable that receives + * the number of bytes read. + * + * \retval NFCSTATUS_PENDING HCP Frame receive pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + * + */ + + +static +NFCSTATUS +phHciNfc_Receive_HCP ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + +/* +################################################################################ +***************************** Function Definitions ***************************** +################################################################################ +*/ + + +#if (NXP_NFC_HCI_TIMER == 1) + +static +void +phHciNfc_Response_Timeout ( + uint32_t resp_timer_id, void *pContext + ) +{ + phNfc_sCompletionInfo_t comp_info = {0,0,0}; + + if ( ( NULL != gpsHciContext) + && (resp_timer_id == hci_resp_timer_id )) + { + pphNfcIF_Notification_CB_t p_upper_notify = + gpsHciContext->p_upper_notify; + void *p_upper_context = + gpsHciContext->p_upper_context; + phHal_sHwReference_t *pHwRef = gpsHciContext->p_hw_ref; + uint32_t i = 0; + + + HCI_DEBUG(" HCI TIMEOUT: HCI Response Timeout Occurred in %X Timer\n" + ,resp_timer_id); + /* Stop the Response Timer */ + phOsalNfc_Timer_Stop( hci_resp_timer_id ); + + comp_info.status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_BOARD_COMMUNICATION_ERROR); + /* Roll Back to the Select State */ + phHciNfc_FSM_Rollback(gpsHciContext); + + for(i=0;i < PHHCINFC_MAX_PIPE; i++) + { + phHciNfc_Reset_Pipe_MsgInfo(gpsHciContext->p_pipe_list[i]); + } + + /* Notify the Error/Success Scenario to the upper layer */ + phHciNfc_Notify( p_upper_notify, p_upper_context, + pHwRef, (uint8_t) NFC_NOTIFY_DEVICE_ERROR, &comp_info ); + } + + return ; + +} + +#endif /* (NXP_NFC_HCI_TIMER == 1) */ + + + +/*! + * \brief Allocation of the HCI Interface resources. + * + * This function releases and frees all the resources used by HCI Command and + * Response Mechanism + */ + + NFCSTATUS + phHciNfc_Allocate_Resource ( + void **ppBuffer, + uint16_t size + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + *ppBuffer = (void *) phOsalNfc_GetMemory(size); + if( *ppBuffer != NULL ) + { + (void )memset(((void *)*ppBuffer), 0, + size); + } + else + { + *ppBuffer = NULL; + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + return status; +} + + + +/*! + * \brief Release of the HCI Interface resources. + * + * This function releases and frees all the resources used by HCI Command and + * Response Mechanism + */ + void + phHciNfc_Release_Resources ( + phHciNfc_sContext_t **ppsHciContext + ) +{ + uint8_t i = 0; + + +#if (NXP_NFC_HCI_TIMER == 1) + + if ( NXP_INVALID_TIMER_ID != hci_resp_timer_id ) + { + /* Stop and Un-Intialise the Response Timer */ + phOsalNfc_Timer_Stop( hci_resp_timer_id ); + phOsalNfc_Timer_Delete( hci_resp_timer_id ); + HCI_DEBUG(" HCI : Timer %X Stopped and Released\n", + hci_resp_timer_id); + hci_resp_timer_id = NXP_INVALID_TIMER_ID; + } + gpsHciContext = NULL; + +#endif /* (NXP_NFC_HCI_TIMER == 1) */ + + + if(NULL != (*ppsHciContext)->p_admin_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_admin_info); + (*ppsHciContext)->p_admin_info = NULL; + } + if(NULL !=(*ppsHciContext)->p_link_mgmt_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_link_mgmt_info); + (*ppsHciContext)->p_link_mgmt_info = NULL; + } + if(NULL !=(*ppsHciContext)->p_identity_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_identity_info); + (*ppsHciContext)->p_identity_info = NULL; + } + if(NULL !=(*ppsHciContext)->p_device_mgmt_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_device_mgmt_info); + (*ppsHciContext)->p_device_mgmt_info = NULL; + } + if(NULL !=(*ppsHciContext)->p_reader_mgmt_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_reader_mgmt_info); + (*ppsHciContext)->p_reader_mgmt_info = NULL; + } + if(NULL !=(*ppsHciContext)->p_poll_loop_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_poll_loop_info); + (*ppsHciContext)->p_poll_loop_info = NULL; + } + if(NULL !=(*ppsHciContext)->p_reader_a_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_reader_a_info); + (*ppsHciContext)->p_reader_a_info = NULL; + } +#ifdef TYPE_B + if(NULL !=(*ppsHciContext)->p_reader_b_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_reader_b_info); + (*ppsHciContext)->p_reader_b_info = NULL; + } +#endif +#ifdef TYPE_FELICA + if(NULL !=(*ppsHciContext)->p_felica_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_felica_info); + (*ppsHciContext)->p_felica_info = NULL; + } +#endif +#ifdef TYPE_JEWEL + if(NULL !=(*ppsHciContext)->p_jewel_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_jewel_info); + (*ppsHciContext)->p_jewel_info = NULL; + } +#endif +#ifdef TYPE_ISO15693 + if(NULL !=(*ppsHciContext)->p_iso_15693_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_iso_15693_info); + (*ppsHciContext)->p_iso_15693_info = NULL; + } +#endif /* #ifdef TYPE_ISO15693 */ +#ifdef ENABLE_P2P + if(NULL !=(*ppsHciContext)->p_nfcip_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_nfcip_info); + (*ppsHciContext)->p_nfcip_info = NULL; + } +#endif + if(NULL !=(*ppsHciContext)->p_emulation_mgmt_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_emulation_mgmt_info); + (*ppsHciContext)->p_emulation_mgmt_info = NULL; + } + if(NULL !=(*ppsHciContext)->p_wi_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_wi_info); + (*ppsHciContext)->p_wi_info = NULL; + } + if(NULL !=(*ppsHciContext)->p_swp_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_swp_info); + (*ppsHciContext)->p_swp_info = NULL; + } + if(NULL !=(*ppsHciContext)->p_uicc_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_uicc_info); + (*ppsHciContext)->p_uicc_info = NULL; + } +#ifdef HOST_EMULATION + if(NULL !=(*ppsHciContext)->p_ce_a_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_ce_a_info); + (*ppsHciContext)->p_ce_a_info = NULL; + } + if(NULL !=(*ppsHciContext)->p_ce_b_info) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_ce_b_info); + (*ppsHciContext)->p_ce_b_info = NULL; + } +#endif + + for(i=0;i < PHHCINFC_MAX_PIPE; i++) + { + if(NULL != (*ppsHciContext)->p_pipe_list[i]) + { + phOsalNfc_FreeMemory((*ppsHciContext)->p_pipe_list[i]); + } + } + + + phOsalNfc_FreeMemory((*ppsHciContext)); + (*ppsHciContext) = NULL; + + return ; +} + +static +void +phHciNfc_Reset_Pipe_MsgInfo( + phHciNfc_Pipe_Info_t *p_pipe_info + ) +{ + if (p_pipe_info != NULL) + { + p_pipe_info->sent_msg_type = HCP_MSG_TYPE_RESERVED; + p_pipe_info->prev_msg = MSG_INSTRUCTION_UNKNWON; + p_pipe_info->prev_status = NFCSTATUS_INVALID_HCI_INSTRUCTION; + p_pipe_info->param_info = NULL; + p_pipe_info->param_length = FALSE ; + } + return; +} + + +void +phHciNfc_Release_Lower( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + phNfc_sLowerIF_t *plower_if = + &(psHciContext->lower_interface); + NFCSTATUS status = NFCSTATUS_SUCCESS; + + PHNFC_UNUSED_VARIABLE(status); + if(NULL != plower_if->release) + { + status = plower_if->release((void *)plower_if->pcontext, + (void *)pHwRef); + (void) memset((void *)plower_if, 0, sizeof(phNfc_sLowerIF_t)); + HCI_DEBUG(" HCI Releasing the Lower Layer Resources: Status = %02X\n" + ,status); + } + + return; +} + + + +/*! + * \brief Sends the HCI Commands to the corresponding peripheral device. + * + * This function sends the HCI Commands to the connected NFC Pheripheral device + */ + static + NFCSTATUS + phHciNfc_Send ( + void *psContext, + void *pHwRef, + uint8_t *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_sContext_t *psHciContext= (phHciNfc_sContext_t *)psContext; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + phNfc_sLowerIF_t *plower_if = &(psHciContext->lower_interface); + + if( (NULL != plower_if) + && (NULL != plower_if->send) + ) + { + HCI_DEBUG("HCI: In Function: %s \n", __FUNCTION__); + HCI_DEBUG("HCI: Response Pending status --> %s \n", + (psHciContext->response_pending)?"TRUE":"FALSE"); + HCI_PRINT_BUFFER("Send Buffer",pdata,length); + /* psHciContext->hci_transact_state = NFC_TRANSACT_SEND_IN_PROGRESS; */ + +#if (NXP_NFC_HCI_TIMER == 1) + + if ( + (TRUE != psHciContext->tx_hcp_chaining) + && (TRUE == psHciContext->response_pending) + && ( NXP_INVALID_TIMER_ID != hci_resp_timer_id ) + ) + { + /* Start the HCI Response Timer */ + phOsalNfc_Timer_Start( hci_resp_timer_id, + nxp_nfc_hci_response_timeout, phHciNfc_Response_Timeout, NULL ); + HCI_DEBUG(" HCI : Timer %X Started \n", hci_resp_timer_id); + } + +#endif /* (NXP_NFC_HCI_TIMER == 1) */ + + status = plower_if->send((void *)plower_if->pcontext, + (void *)pHwRef, pdata, length); + } + + return status; +} + + +/*! + * \brief Receives the HCI Response from the corresponding peripheral device. + * + * This function receives the HCI Command Response to the connected NFC + * Pheripheral device. + */ + +NFCSTATUS +phHciNfc_Receive( + void *psContext, + void *pHwRef, + uint8_t *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_sContext_t *psHciContext= (phHciNfc_sContext_t *)psContext; + phNfc_sLowerIF_t *plower_if = NULL ; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if(NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + plower_if = &(psHciContext->lower_interface); + + if( (NULL != plower_if) + && (NULL != plower_if->receive) + ) + { + /* psHciContext->hci_transact_state = NFC_TRANSACT_RECV_IN_PROGRESS; */ + status = plower_if->receive((void *)plower_if->pcontext, + (void *)pHwRef, pdata, length); + } + } + return status; +} + + +/*! + * \brief Sends the HCP Packet to the lower link layer . + * + * This function Sends the HCI Data in the HCP packet format to the below + * Link layer. + */ + + NFCSTATUS + phHciNfc_Send_HCP ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_HCP_Packet_t *tx_data = (phHciNfc_HCP_Packet_t *) + psHciContext->send_buffer; + /* Skip the HCP Header Byte initially */ + uint16_t tx_length = psHciContext->tx_total - 1 ; + uint16_t hcp_index = HCP_ZERO_LEN; + uint8_t pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + static uint8_t chain_bit = HCP_CHAINBIT_DEFAULT; + + pipe_id = (uint8_t) GET_BITS8( tx_data->hcp_header, + HCP_PIPEID_OFFSET, HCP_PIPEID_LEN); + + /* Fragmentation of the HCP Frames */ + if ( tx_length > PHHCINFC_MAX_PACKET_DATA ) + { + tx_data = &psHciContext->tx_packet; + (void)memset((void *)tx_data, FALSE, + sizeof(phHciNfc_HCP_Packet_t)); + if (HCP_CHAINBIT_DEFAULT == chain_bit) + { + /* HCI Chaining Needs to be Done */ + psHciContext->tx_remain = tx_length; + psHciContext->tx_hcp_frgmnt_index = HCP_ZERO_LEN ; + chain_bit = HCP_CHAINBIT_BEGIN; + /* Increment the Fragment index to skip the HCP Header */ + psHciContext->tx_hcp_frgmnt_index++; + psHciContext->tx_hcp_chaining = TRUE ; + tx_length = PHHCINFC_MAX_PACKET_DATA ; + } + else if ( psHciContext->tx_remain > PHHCINFC_MAX_PACKET_DATA ) + { + /* Intermediate Chained HCI Frames */ + tx_length = PHHCINFC_MAX_PACKET_DATA ; + } + else + { + /* End of Chaining Reached */ + chain_bit = HCP_CHAINBIT_END; + tx_length = psHciContext->tx_remain ; + psHciContext->tx_hcp_chaining = FALSE ; + } + + /* Build the HCP Header to have Chaining Enabled */ + phHciNfc_Build_HCPHeader(tx_data, chain_bit , pipe_id ); + + phHciNfc_Append_HCPFrame((uint8_t *)tx_data->msg.payload, hcp_index, + (&psHciContext->send_buffer[psHciContext->tx_hcp_frgmnt_index]) + , tx_length ); + } + else + { + /* No Chaining Required */ + chain_bit = HCP_CHAINBIT_DEFAULT; + + psHciContext->tx_hcp_chaining = FALSE ; + + psHciContext->tx_remain = tx_length ; + } + + /* Include the Skipped HCP Header Byte */ + tx_length++; + + status = phHciNfc_Send ( (void *) psHciContext, pHwRef, + (uint8_t *)tx_data, tx_length ); + + return status; +} + + +/*! + * \brief Receives the HCP Packet from the lower link layer . + * + * This function receives the HCI Data in the HCP packet format from the below + * Link layer. + */ + static + NFCSTATUS + phHciNfc_Receive_HCP ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_HCP_Packet_t *packet = NULL; + uint8_t chainbit = HCP_CHAINBIT_DEFAULT; + uint16_t hcp_index = 0; + + packet = (phHciNfc_HCP_Packet_t *)pdata; + chainbit = (uint8_t) GET_BITS8( packet->hcp_header, + HCP_CHAINBIT_OFFSET, HCP_CHAINBIT_LEN); + hcp_index = psHciContext->rx_hcp_frgmnt_index; + HCI_PRINT_BUFFER("Receive Buffer",((uint8_t *)pdata),length); + if (HCP_CHAINBIT_BEGIN == chainbit) + { + /* pdata = (uint8_t *)&psHciContext->rx_packet; */ + /* De Fragmentation of the Received HCP Frames */ + /* Subsequent Chaining Frames */ + if( hcp_index > 0 ) + { + /* Copy the obtained fragment and receive the next fragment */ + phHciNfc_Append_HCPFrame( + psHciContext->recv_buffer, hcp_index, + (uint8_t *)&pdata[HCP_MESSAGE_LEN], + (length - HCP_MESSAGE_LEN) ); + psHciContext->rx_hcp_frgmnt_index =(uint16_t) + (hcp_index + length - HCP_MESSAGE_LEN); + } + /* First Chaining Frame*/ + else + { + psHciContext->rx_hcp_chaining = TRUE ; + /* Copy the obtained fragment and receive the next fragment */ + phHciNfc_Append_HCPFrame(psHciContext->recv_buffer, + hcp_index, pdata, length); + psHciContext->rx_hcp_frgmnt_index = ( hcp_index + length ) ; + + } + status = phHciNfc_Receive ( (void *) psHciContext, pHwRef, + pdata, length); + } + else + { + if(TRUE == psHciContext->rx_hcp_chaining) + { + /* If the chaining was done earlier */ + psHciContext->rx_hcp_chaining = FALSE ; + /* Copy the Remaining buffer to the RX_BUFFER */ + phHciNfc_Append_HCPFrame( + psHciContext->recv_buffer, hcp_index, + (uint8_t *)&pdata[HCP_MESSAGE_LEN], + (length - HCP_MESSAGE_LEN) ); + /* If there is chaining done the return the same data */ + psHciContext->rx_total = + (hcp_index + length - HCP_MESSAGE_LEN); + psHciContext->rx_hcp_frgmnt_index = FALSE ; + } + else + { + (void) memcpy( psHciContext->recv_buffer, pdata, length); + /* If there is no chaining done then return the same data */ + psHciContext->rx_total = (hcp_index + length); + + } + } + + return status; +} + + +/*! + * \brief Receives the HCP Packet from the lower link layer . + * + * This function receives the HCI Data in the HCP packet format from the below + * Link layer. + */ + + static + NFCSTATUS + phHciNfc_Process_HCP ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + void *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_HCP_Packet_t *packet = NULL; + phHciNfc_HCP_Message_t *message = NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t msg_type = 0; + + if( (NULL == pdata) + || ( length < HCP_HEADER_LEN ) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + status = phHciNfc_Receive_HCP( psHciContext, pHwRef, pdata, length ); + }/* End of the Valid Data Handling */ + + if( NFCSTATUS_SUCCESS == status ) + { + packet = (phHciNfc_HCP_Packet_t *)psHciContext->recv_buffer; + length = +#ifdef ONE_BYTE_LEN + (uint8_t) +#endif + psHciContext->rx_total ; + message = &packet->msg.message; + /* HCI_PRINT_BUFFER("Total Receive Buffer",((uint8_t *)pdata),length); */ + msg_type = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_TYPE_OFFSET, HCP_MSG_TYPE_LEN); + switch ( msg_type ) + { + case HCP_MSG_TYPE_RESPONSE: + { + status = phHciNfc_Process_Response( psHciContext, + pHwRef, (void *)packet, length ); + break; + } + case HCP_MSG_TYPE_EVENT: + { + status = phHciNfc_Process_Event( psHciContext, + pHwRef,(void *)packet, length ); + break; + } + case HCP_MSG_TYPE_COMMAND: + { + + status = phHciNfc_Process_Command( psHciContext, + pHwRef, (void *)packet, length ); + break; + } + /* case HCP_MSG_TYPE_RESERVED: */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + }/* End of Receive HCP Status */ + return status; +} + + + static + NFCSTATUS + phHciNfc_Process_Response ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + void *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_HCP_Packet_t *packet = NULL; + phHciNfc_HCP_Message_t *message = NULL; + uint8_t instruction=0; + uint8_t pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + + NFCSTATUS status = NFCSTATUS_SUCCESS; + + packet = (phHciNfc_HCP_Packet_t *)pdata; + message = &packet->msg.message; + /* Get the instruction bits from the Message Header */ + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + /* Get the Pipe ID from the HCP Header */ + pipe_id = (uint8_t) GET_BITS8( packet->hcp_header, + HCP_PIPEID_OFFSET, HCP_PIPEID_LEN); + +#if (NXP_NFC_HCI_TIMER == 1) + + if ( NXP_INVALID_TIMER_ID != hci_resp_timer_id ) + { + /* Stop the HCI Response Timer */ + HCI_DEBUG(" HCI : Timer %X Stopped \n", hci_resp_timer_id); + phOsalNfc_Timer_Stop( hci_resp_timer_id ); + } + +#endif /* (NXP_NFC_HCI_TIMER == 1) */ + + if (pipe_id >= PHHCINFC_MAX_PIPE ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else if( ((uint8_t) ANY_OK != instruction) + && ( (pipe_id != PIPETYPE_STATIC_ADMIN ) + && ( ADM_CLEAR_ALL_PIPE != (psHciContext->p_pipe_list[pipe_id])->prev_msg )) + ) + { + status = phHciNfc_Error_Response( psHciContext, pHwRef, pdata, length ); + } + else + { + p_pipe_info = psHciContext->p_pipe_list[pipe_id]; + if( ( NULL != p_pipe_info ) + && ( HCP_MSG_TYPE_COMMAND == p_pipe_info->sent_msg_type ) + && ( NULL != p_pipe_info->recv_resp ) + ) + { + status = psHciContext->p_pipe_list[pipe_id]->recv_resp( psHciContext, + pHwRef, pdata, length ); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + /* There is no Pending Response */ + psHciContext->response_pending = FALSE ; + HCI_DEBUG("HCI: Response Pending status --> FALSE, %s \n", + __FUNCTION__); + if( NFCSTATUS_SUCCESS == status ) + { + phHciNfc_Reset_Pipe_MsgInfo(psHciContext->p_pipe_list[pipe_id]); + status = phHciNfc_Resume_Sequence(psHciContext, pHwRef); + + }/* End of Success Status validation */ + else + { + HCI_DEBUG("HCI: Status --> %X \n", status ); + } + + } /* End of the Valid Response handling */ + return status; +} + + +static + NFCSTATUS + phHciNfc_Error_Response ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + void *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + + phHciNfc_HCP_Packet_t *packet = (phHciNfc_HCP_Packet_t *)pdata; + phHciNfc_HCP_Message_t *message = &packet->msg.message; + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; +#if defined(HCI_TRACE) || defined (ERROR_INSTRUCTION) + uint8_t instruction = 0; + instruction = (uint8_t) GET_BITS8(message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); +#endif + + /* Get the Pipe ID from the HCP Header */ + pipe_id = (uint8_t) GET_BITS8( packet->hcp_header, + HCP_PIPEID_OFFSET, HCP_PIPEID_LEN); + /* Process the Error Response based on the obtained instruction */ +#ifdef ERROR_INSTRUCTION + switch(instruction) + { + case ANY_E_NOT_CONNECTED: + case ANY_E_CMD_PAR_UNKNOWN: + case ANY_E_NOK: + case ANY_E_PIPES_FULL: + case ANY_E_REG_PAR_UNKNOWN: + case ANY_E_PIPE_NOT_OPENED: + case ANY_E_CMD_NOT_SUPPORTED: + case ANY_E_TIMEOUT: + case ANY_E_REG_ACCESS_DENIED: + case ANY_E_PIPE_ACCESS_DENIED: + { + /* Receive Error Notification to the Upper Layer */ + status = PHNFCSTVAL( CID_NFC_HCI, \ + message->msg_header); + phHciNfc_Error_Sequence(psHciContext, pHwRef, status , pdata, length ); + /* Return Success as the Error Sequence is already handled */ + psHciContext->response_pending = FALSE ; + HCI_DEBUG("HCI: Response Pending status --> FALSE, %s \n", + __FUNCTION__); + status = NFCSTATUS_SUCCESS; + break; + } + /* The Statement should not reach this case */ + /* case ANY_OK: */ + default: + { + /* status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); */ + break; + } + } +#else + status = PHNFCSTVAL( CID_NFC_HCI, message->msg_header); + HCI_DEBUG("HCI Error Response(%u) from the Device \n", instruction); + psHciContext->response_pending = FALSE ; + HCI_DEBUG("HCI: Response Pending status --> FALSE, %s \n", + __FUNCTION__); + phHciNfc_Reset_Pipe_MsgInfo(psHciContext->p_pipe_list[pipe_id]); + phHciNfc_Error_Sequence(psHciContext, pHwRef, status , pdata, (uint8_t) length ); + /* Return Success as the Error Sequence is already handled */ + status = NFCSTATUS_SUCCESS; +#endif + + return status; +} + + +static + NFCSTATUS + phHciNfc_Process_Event ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + void *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_HCP_Packet_t *packet = NULL; + phHciNfc_HCP_Message_t *message = NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t instruction=0; + uint8_t pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + + NFCSTATUS status = NFCSTATUS_SUCCESS; + + packet = (phHciNfc_HCP_Packet_t *)pdata; + message = &packet->msg.message; + /* Get the instruction bits from the Message Header */ + PHNFC_UNUSED_VARIABLE(instruction); + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + /* Get the Pipe ID from the HCP Header */ + pipe_id = (uint8_t) GET_BITS8( packet->hcp_header, + HCP_PIPEID_OFFSET, HCP_PIPEID_LEN); + + if (pipe_id >= PHHCINFC_MAX_PIPE ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_pipe_info = psHciContext->p_pipe_list[pipe_id]; + } + + if( (p_pipe_info != NULL ) ) + { + if( NULL != p_pipe_info->recv_event) + { + status = p_pipe_info->recv_event( psHciContext, pHwRef, + pdata, length ); + } + else + { + HCI_DEBUG(" Event Handling Not Supported by the #%u Pipe \n", + pipe_id); + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + + HCI_DEBUG("HCI: In Function: %s \n", + __FUNCTION__); + HCI_DEBUG("HCI: Response Pending status --> %s \n", + (psHciContext->response_pending)?"TRUE":"FALSE"); + HCI_DEBUG("HCI: Event Pending status --> %s \n", + (psHciContext->event_pending)?"TRUE":"FALSE"); + + if ((TRUE == psHciContext->response_pending) + || (TRUE == psHciContext->event_pending)) + { + (void)memset(psHciContext->recv_buffer, + FALSE, PHHCINFC_MAX_BUFFERSIZE); + (void)memset((void *)&psHciContext->rx_packet, + FALSE, sizeof(phHciNfc_HCP_Packet_t)); + + /* Reset the Received Data Index */ + psHciContext->rx_index = ZERO; + /* Reset the size of the total response data received */ + psHciContext->rx_total = ZERO; + + /* psHciContext->hci_transact_state = NFC_TRANSACT_SEND_COMPLETE;*/ + /* Receive the Response Packet */ + + status = phHciNfc_Receive( psHciContext, pHwRef, + (uint8_t *)(&psHciContext->rx_packet), + sizeof(phHciNfc_HCP_Packet_t) ); + + /* HCI_DEBUG("HCI Lower Layer Send Completion After Receive,\ + Status = %02X\n",status); */ + } + else + { + if( +/* #define EVENT_NOTIFY */ +#ifndef EVENT_NOTIFY + ( NFCSTATUS_SUCCESS == status ) + || ( NFCSTATUS_RF_TIMEOUT == status ) + || (( NFCSTATUS_MORE_INFORMATION == status ) +#else + ((FALSE == psHciContext->event_pending ) +#endif + && ( pipe_id <= PHHCINFC_MAX_PIPE )) + ) + { + /* phHciNfc_Reset_Pipe_MsgInfo(psHciContext->p_pipe_list[pipe_id]); */ + status = phHciNfc_Resume_Sequence(psHciContext, pHwRef); + + }/* End of Success Status validation */ + else + { + HCI_DEBUG(" HCI: Pipe-ID --> %02X \n", pipe_id); + HCI_DEBUG(" HCI: PROCESS EVENT - Pending/Invalid Status : %X\n", status); + } + } + + return status; +} + +static + NFCSTATUS + phHciNfc_Process_Command ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + void *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_HCP_Packet_t *packet = NULL; + phHciNfc_HCP_Message_t *message = NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t instruction=0; + uint8_t pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + + NFCSTATUS status = NFCSTATUS_SUCCESS; + + packet = (phHciNfc_HCP_Packet_t *)pdata; + message = &packet->msg.message; + /* Get the instruction bits from the Message Header */ + PHNFC_UNUSED_VARIABLE(instruction); + + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + /* Get the Pipe ID from the HCP Header */ + pipe_id = (uint8_t) GET_BITS8( packet->hcp_header, + HCP_PIPEID_OFFSET, HCP_PIPEID_LEN); + if (pipe_id >= PHHCINFC_MAX_PIPE ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_pipe_info = psHciContext->p_pipe_list[pipe_id]; + } + + if( (p_pipe_info != NULL ) + ) + { + if( NULL != p_pipe_info->recv_cmd) + { + status = p_pipe_info->recv_cmd( psHciContext, pHwRef, + pdata, length ); + } + else + { + HCI_DEBUG(" Command Handling Not Supported by the #%u Pipe \n", + pipe_id); + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + + HCI_DEBUG("HCI: In Function: %s \n", __FUNCTION__); + HCI_DEBUG("HCI: Response Pending status --> %s \n", + (psHciContext->response_pending)?"TRUE":"FALSE"); + + if(( NFCSTATUS_SUCCESS == status ) + && (TRUE != psHciContext->response_pending) + ) + { + /* Reset the Pipe Information Stored in the particular Pipe */ + /* phHciNfc_Reset_Pipe_MsgInfo(psHciContext->p_pipe_list[pipe_id]); */ + /* Resume the Execution Sequence */ + status = phHciNfc_Resume_Sequence(psHciContext, pHwRef); + + }/* End of Success Status validation */ + + return status; +} + + +static +void +phHciNfc_Build_HCPMessage( + phHciNfc_HCP_Packet_t *hcp_packet, + uint8_t msg_type, + uint8_t instruction + ) +{ + phHciNfc_HCP_Message_t *hcp_message = NULL; + + hcp_message = &(hcp_packet->msg.message); + /* Set the type to the provided message type in the HCP Message Header */ + hcp_message->msg_header = (uint8_t) SET_BITS8(hcp_message->msg_header,HCP_MSG_TYPE_OFFSET, + HCP_MSG_TYPE_LEN, msg_type); + /* Set the instruction to the kind of instruction in the HCP Message Header */ + hcp_message->msg_header = (uint8_t) SET_BITS8(hcp_message->msg_header,HCP_MSG_INSTRUCTION_OFFSET, + HCP_MSG_INSTRUCTION_LEN, instruction); + /* hcp_message->msg_header = hcp_message->msg_header | temp ; */ + +} + + +static +void +phHciNfc_Build_HCPHeader( + phHciNfc_HCP_Packet_t *hcp_packet, + uint8_t chainbit, + uint8_t pipe_id + ) +{ + /* Set the Chaining bit to the default type */ + hcp_packet->hcp_header = (uint8_t) SET_BITS8(hcp_packet->hcp_header, + HCP_CHAINBIT_OFFSET, HCP_CHAINBIT_LEN, chainbit); + /* Populate the Pipe ID to the HCP Header */ + hcp_packet->hcp_header = (uint8_t) SET_BITS8(hcp_packet->hcp_header,HCP_PIPEID_OFFSET, + HCP_PIPEID_LEN, pipe_id); + +} + +/*! + * \brief Builds the HCP Frame Packet. + * + * This function builds the HCP Frame in the HCP packet format to send to the + * connected reader device. + */ + +void + phHciNfc_Build_HCPFrame ( + phHciNfc_HCP_Packet_t *hcp_packet, + uint8_t chainbit, + uint8_t pipe_id, + uint8_t msg_type, + uint8_t instruction + ) +{ + /* Fills the HCP Header in the packet */ + phHciNfc_Build_HCPHeader( hcp_packet,chainbit,pipe_id ); + /* Fills the HCP Message in the packet */ + phHciNfc_Build_HCPMessage( hcp_packet,msg_type,instruction ); +} + +/*! + * \brief Appends the HCP Frame Packet. + * + * This function Appends the HCP Frame of the HCP packet to complete the + * entire HCP Packet. + */ + +void + phHciNfc_Append_HCPFrame ( +/* phHciNfc_sContext_t *psHciContext, */ + uint8_t *hcp_data, + uint16_t hcp_index, + uint8_t *src_data, + uint16_t src_len + ) +{ + uint16_t src_index = 0; + if( (NULL != src_data) + /* && (hcp_index >= 0) */ + && (src_len > 0) + ) + { + for(src_index=0; src_index < src_len ; src_index++) + { + hcp_data[hcp_index + src_index] = src_data[src_index]; + } + } + return; +} + + +/*! + * \brief Sends the Generic HCI Commands to the connected reader device. + * + * This function Sends the Generic HCI Command frames in the HCP packet format to the + * connected reader device. + */ + + NFCSTATUS + phHciNfc_Send_Generic_Cmd ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ) + { + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint16_t length = 0; + uint16_t i=0; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if((NULL == psHciContext) + || ( pipe_id > PHHCINFC_MAX_PIPE) + ||(NULL == psHciContext->p_pipe_list[pipe_id]) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + HCI_DEBUG("%s: Invalid Arguments passed \n", + "phHciNfc_Send_Generic_Cmd"); + } + else + { + p_pipe_info = (phHciNfc_Pipe_Info_t *) + psHciContext->p_pipe_list[pipe_id]; + psHciContext->tx_total = 0 ; + length += HCP_HEADER_LEN ; + switch( cmd ) + { + case ANY_SET_PARAMETER: + { + + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + hcp_message = &(hcp_packet->msg.message); + hcp_message->payload[i++] = p_pipe_info->reg_index ; + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, (uint8_t *)p_pipe_info->param_info, + p_pipe_info->param_length); + length =(uint16_t)(length + i + p_pipe_info->param_length); + break; + } + case ANY_GET_PARAMETER: + { + + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + hcp_message = &(hcp_packet->msg.message); + hcp_message->payload[i++] = p_pipe_info->reg_index ; + length =(uint16_t)(length + i); + break; + } + case ANY_OPEN_PIPE: + case ANY_CLOSE_PIPE: + { + + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + break; + } + default: + { + status = PHNFCSTVAL( CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED ); + HCI_DEBUG("%s: Statement Should Not Occur \n","phHciNfc_Send_Generic_Cmd"); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + p_pipe_info->sent_msg_type = HCP_MSG_TYPE_COMMAND; + p_pipe_info->prev_msg = cmd; + psHciContext->tx_total = length; + psHciContext->response_pending = TRUE ; + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef ); + p_pipe_info->prev_status = NFCSTATUS_PENDING; + } + } + + return status; +} + + +/*! + * \brief Sets the parameter of the registers in a particular Pipe. + * + * This function configures the registers in a particular Pipe. + */ + +NFCSTATUS +phHciNfc_Set_Param ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_Pipe_Info_t *p_pipe_info, + uint8_t reg_index, + void *p_param, + uint16_t param_length + ) + { + NFCSTATUS status = NFCSTATUS_SUCCESS ; + + if( (NULL == p_pipe_info) + || (NULL == p_param) + || (0 == param_length) + ) + { + status = PHNFCSTVAL( CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION ); + } + else + { + p_pipe_info->param_info = (uint8_t *)p_param; + p_pipe_info->param_length = param_length; + p_pipe_info->reg_index = reg_index; + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + (uint8_t)p_pipe_info->pipe.pipe_id, + (uint8_t)ANY_SET_PARAMETER); + p_pipe_info->prev_status = status; + } + + return status; + } + + +#if 0 + /*! + * \brief Gets the parameter of the registers in a particular Pipe. + * + * This function configures the registers in a particular Pipe. + */ + + NFCSTATUS + phHciNfc_Get_Param ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_Pipe_Info_t *p_pipe_info, + uint8_t reg_index, + ) + { + NFCSTATUS status = NFCSTATUS_SUCCESS ; + + return status; + } +#endif + + +void +phHciNfc_Send_Complete ( + void *psContext, + void *pHwRef, + phNfc_sTransactionInfo_t *pInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS ; + uint16_t length = 0; + + HCI_PRINT("HCI Send Completion....\n"); + if ( (NULL != psContext) + && (NULL != pInfo) + && (NULL != pHwRef) + ) + { + phHciNfc_sContext_t *psHciContext = (phHciNfc_sContext_t *)psContext; + status = pInfo->status ; + length = pInfo->length ; + /* HCI_DEBUG("HCI Lower Layer Send Completion Before Receive,\ + Status = %02X\n",status); */ + if(status != NFCSTATUS_SUCCESS) + { + /* Handle the Error Scenario */ + (void)memset(psHciContext->send_buffer, + FALSE, PHHCINFC_MAX_BUFFERSIZE); + /* psHciContext->hci_transact_state = NFC_TRANSACT_COMPLETE;*/ + phHciNfc_Error_Sequence( psHciContext, pHwRef, status, NULL, 0 ); + } + else + { + HCI_DEBUG("HCI Send Completion... Length = %02X\n", length); + /* To complete the send complete with the send + * or receive with chaining. + */ + if( (TRUE == psHciContext->tx_hcp_chaining) + &&( psHciContext->tx_remain > HCP_ZERO_LEN )) + { + /* Skip the HCP Header Byte Sent */ + psHciContext->tx_remain -= length - 1; + + /* Skip the HCP Header Byte Sent */ + psHciContext->tx_hcp_frgmnt_index += length - 1; + + /* Send the Remaining HCP Data Frames */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef ); + + HCI_DEBUG("HCI (Chaining) Send Resume: Status = %02X\n", status); + + if( ( NFCSTATUS_SUCCESS != status ) + && (NFCSTATUS_PENDING != status ) + ) + { + phHciNfc_Error_Sequence( psHciContext, pHwRef, status, NULL, 0 ); + }/* End of the Status check */ + } + else + { + psHciContext->tx_total = HCP_ZERO_LEN ; + psHciContext->tx_remain = HCP_ZERO_LEN ; + psHciContext->tx_hcp_frgmnt_index = HCP_ZERO_LEN ; + HCI_DEBUG("HCI: %s: response_pending=%s, event_pending=%s", + __FUNCTION__, + (psHciContext->response_pending)?"TRUE":"FALSE", + (psHciContext->event_pending)?"TRUE":"FALSE" + ); + if ((TRUE == psHciContext->response_pending) + || (TRUE == psHciContext->event_pending)) + { + (void) memset(psHciContext->recv_buffer, + FALSE, PHHCINFC_MAX_BUFFERSIZE); + (void) memset((void *)&psHciContext->rx_packet, + FALSE, sizeof(phHciNfc_HCP_Packet_t)); + + /* Reset the Received Data Index */ + psHciContext->rx_index = ZERO; + /* Reset the size of the total response data received */ + psHciContext->rx_total = ZERO; + + /* psHciContext->hci_transact_state = NFC_TRANSACT_SEND_COMPLETE;*/ + /* Receive the Response Packet */ + status = phHciNfc_Receive( psHciContext, pHwRef, + (uint8_t *)(&psHciContext->rx_packet), + sizeof(phHciNfc_HCP_Packet_t) ); + + /* HCI_DEBUG("HCI Lower Layer Send Completion After Receive,\ + Status = %02X\n",status); */ + + if( ( NFCSTATUS_SUCCESS != status ) + && (NFCSTATUS_PENDING != status ) + ) + { + phHciNfc_Error_Sequence( psHciContext, pHwRef, status, NULL, 0 ); + }/* End of the Status check */ + } + else + { + status = phHciNfc_Resume_Sequence(psHciContext, pHwRef ); + } + } + + } /* End of status != Success */ + + } /* End of Context != NULL */ +} + + +void +phHciNfc_Receive_Complete ( + void *psContext, + void *pHwRef, + phNfc_sTransactionInfo_t *pInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS ; + void *pdata = NULL ; + uint16_t length = 0 ; + + HCI_PRINT("HCI Receive Completion....\n"); + if ( (NULL != psContext) + && (NULL != pInfo) + && (NULL != pHwRef) + ) + { + phHciNfc_sContext_t *psHciContext = (phHciNfc_sContext_t *)psContext; + + status = pInfo->status ; + pdata = pInfo->buffer ; + length = pInfo->length ; + HCI_DEBUG("HCI Lower Layer Receive Completion, Status = %02X\n",status); + if( NFCSTATUS_SUCCESS != status ) + { + /* Handle the Error Scenario */ + /* psHciContext->hci_transact_state = NFC_TRANSACT_COMPLETE; */ + phHciNfc_Error_Sequence(psHciContext, pHwRef, status , pdata, (uint8_t)length ); + } + else + { + /* Receive the remaining Response Packet */ + /* psHciContext->hci_transact_state = NFC_TRANSACT_RECV_COMPLETE; */ + status = phHciNfc_Process_HCP( psHciContext, pHwRef, pdata,(uint8_t) length ); + if( ( NFCSTATUS_SUCCESS != status ) + && (NFCSTATUS_PENDING != status ) + ) + { + phHciNfc_Error_Sequence(psHciContext, pHwRef, status , pdata, (uint8_t) length ); + } + } + } +} + +void +phHciNfc_Notify( + pphNfcIF_Notification_CB_t p_upper_notify, + void *p_upper_context, + void *pHwRef, + uint8_t type, + void *pInfo + ) +{ + if( ( NULL != p_upper_notify) ) + { + /* Notify the to the Upper Layer */ + (p_upper_notify)(p_upper_context, pHwRef, type, pInfo); + } + +} + + +void +phHciNfc_Tag_Notify( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t type, + void *pInfo + ) +{ + phNfc_sCompletionInfo_t *psCompInfo = + (phNfc_sCompletionInfo_t *)pInfo; + pphNfcIF_Notification_CB_t p_upper_notify = psHciContext->p_upper_notify; + void *pcontext = psHciContext->p_upper_context; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + switch( psHciContext->hci_state.next_state ) + { + case hciState_Activate: + { + /* Roll Back to the Select State */ + phHciNfc_FSM_Rollback(psHciContext); + break; + } + case hciState_Select: + { + status = phHciNfc_FSM_Complete(psHciContext); + break; + } + default: + { + /* Roll Back to the Select State */ + phHciNfc_FSM_Rollback(psHciContext); + break; + } + + } + + if(NFCSTATUS_SUCCESS == status ) + { + /* Notify the Tag Events to the Upper layer */ + phHciNfc_Notify( p_upper_notify, pcontext , pHwRef, + type, psCompInfo); + } + else + { + phHciNfc_Error_Sequence( psHciContext, pHwRef, status, NULL, 0 ); + } +} + + +void +phHciNfc_Target_Select_Notify( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t type, + void *pInfo + ) +{ + phNfc_sCompletionInfo_t *psCompInfo = + (phNfc_sCompletionInfo_t *)pInfo; + pphNfcIF_Notification_CB_t p_upper_notify = psHciContext->p_upper_notify; + void *pcontext = psHciContext->p_upper_context; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + switch( psHciContext->hci_state.next_state ) + { + case hciState_Listen: + { + /* Roll Back to the Select State */ + status = phHciNfc_FSM_Complete(psHciContext); + break; + } + case hciState_Select: + { + status = phHciNfc_FSM_Complete(psHciContext); + break; + } + default: + { + /* Roll Back to the Select State */ + phHciNfc_FSM_Rollback(psHciContext); + break; + } + + } + + if(NFCSTATUS_SUCCESS == status ) + { + /* Notify the Tag Events to the Upper layer */ + phHciNfc_Notify( p_upper_notify, pcontext , pHwRef, + type, psCompInfo); + } + else + { + phHciNfc_Error_Sequence( psHciContext, pHwRef, status, NULL, 0 ); + } + +} + + + + +void +phHciNfc_Release_Notify( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t type, + void *pInfo + ) +{ + phNfc_sCompletionInfo_t *psCompInfo = + (phNfc_sCompletionInfo_t *)pInfo; + pphNfcIF_Notification_CB_t p_upper_notify = psHciContext->p_upper_notify; + void *pcontext = psHciContext->p_upper_context; + phHciNfc_Release_Resources( &psHciContext ); + /* Notify the Failure to the Upper Layer */ + phHciNfc_Notify( p_upper_notify, pcontext , pHwRef, + type, psCompInfo); +} + + +void +phHciNfc_Notify_Event( + void *psContext, + void *pHwRef, + uint8_t type, + void *pInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if ( (NULL != psContext) + && (NULL != pInfo) + && (NULL != pHwRef) + ) + { + phHciNfc_sContext_t *psHciContext = (phHciNfc_sContext_t *)psContext; + + /* Process based on the Notification type */ + switch(type) + { + case NFC_NOTIFY_INIT_COMPLETED: + { + phNfc_sCompletionInfo_t *psCompInfo = + (phNfc_sCompletionInfo_t *)pInfo; + if(NFCSTATUS_SUCCESS == psCompInfo->status) + { + +#if (NXP_NFC_HCI_TIMER == 1) + if ( NXP_INVALID_TIMER_ID == hci_resp_timer_id ) + { + /* Create and Intialise the Response Timer */ + hci_resp_timer_id = phOsalNfc_Timer_Create( ); + HCI_DEBUG(" HCI : Timer %X Created \n", + hci_resp_timer_id); + } + else + { + HCI_DEBUG(" HCI : Timer Already Created, Timer ID : %X\n", + hci_resp_timer_id); + } + gpsHciContext = psHciContext; + +#endif /* (NXP_NFC_HCI_TIMER == 1) */ + + /* Complete the Initialisation Sequence */ + status = phHciNfc_Resume_Sequence(psContext ,pHwRef); + } + else + { + /* Notify the Error Scenario to the Upper Layer */ + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_ERROR, psCompInfo); + } + break; + } + case NFC_NOTIFY_INIT_FAILED: + { + /* Notify the Failure to the Upper Layer */ + phHciNfc_Release_Notify( psContext,pHwRef, + type, pInfo ); + break; + } + case NFC_NOTIFY_RECV_COMPLETED: + { + /* Receive Completed from the Lower Layer */ + phHciNfc_Receive_Complete(psContext,pHwRef,pInfo); + + break; + } + case NFC_NOTIFY_SEND_COMPLETED: + { + /* Receive Completed from the Lower Layer */ + phHciNfc_Send_Complete(psContext,pHwRef,pInfo); + + break; + } + case NFC_NOTIFY_TRANSCEIVE_COMPLETED: + { + /* TODO: TO handle Both Send and Receive Complete */ + break; + } + case NFC_NOTIFY_TARGET_DISCOVERED: + { + HCI_PRINT(" PICC Discovery ! Obtain PICC Info .... \n"); + /* psHciContext->hci_seq = PL_DURATION_SEQ; */ + if ( hciState_Unknown == psHciContext->hci_state.next_state ) + { + + status = phHciNfc_FSM_Update ( psHciContext, hciState_Select ); + + + if (NFCSTATUS_SUCCESS != status) + { + status = phHciNfc_ReaderMgmt_Deselect( + psHciContext, pHwRef, phHal_eISO14443_A_PICC, FALSE); + } + } + else + { +#ifdef SW_RELEASE_TARGET + /*status = phHciNfc_ReaderMgmt_Deselect( + psHciContext, pHwRef, phHal_eISO14443_A_PICC, FALSE); */ + psHciContext->target_release = TRUE; +#else + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); +#endif + } + break; + } + /* To Notify the Target Released Notification + * to the Above Layer */ + case NFC_NOTIFY_TARGET_RELEASED: + /* To Notify the NFC Secure Element Transaction + * Information to the Above Layer */ + /* case NFC_NOTIFY_TRANSACTION: */ + /* To Notify the Generic Events To the Upper + * Layer */ + case NFC_NOTIFY_EVENT: + /* To Notify the Data Receive Notification + * to the Above Layer */ + case NFC_NOTIFY_RECV_EVENT: + { + phNfc_sCompletionInfo_t *psCompInfo = + (phNfc_sCompletionInfo_t *)pInfo; + + if (((TRUE == psHciContext->event_pending) || + (NFCSTATUS_RF_TIMEOUT == psCompInfo->status)) + && ( hciState_Transact == psHciContext->hci_state.next_state)) + { + /* Rollback due to Transmission Error */ + phHciNfc_FSM_Rollback(psHciContext); + } + psHciContext->event_pending = FALSE; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + type, pInfo); + break; + } + case NFC_NOTIFY_DEVICE_ACTIVATED: + { + HCI_PRINT(" Device Activated! Obtaining Remote Reader Info .... \n"); + if ( hciState_Unknown == psHciContext->hci_state.next_state ) + { + switch (psHciContext->host_rf_type) + { + case phHal_eISO14443_A_PCD: + case phHal_eISO14443_B_PCD: + case phHal_eISO14443_BPrime_PCD: + case phHal_eFelica_PCD: + { + break; + } + case phHal_eNfcIP1_Initiator: + case phHal_eNfcIP1_Target: + { + break; + } + case phHal_eUnknown_DevType: + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_PARAMETER); + break; + } + + } + status = phHciNfc_FSM_Update ( psHciContext, hciState_Listen ); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + } + break; + } + case NFC_NOTIFY_DEVICE_DEACTIVATED: + { + HCI_PRINT(" Device De-Activated! \n"); + if ( hciState_Unknown == psHciContext->hci_state.next_state ) + { + status = phHciNfc_FSM_Update ( psHciContext, hciState_Initialise ); + if(NFCSTATUS_SUCCESS == status) + { + /* Complete to the Select State */ + status = phHciNfc_FSM_Complete(psHciContext); + } + else + { + HCI_PRINT(" Device Deactivated.. But Invalid State \n"); + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + } + } + else + { + status = phHciNfc_ReaderMgmt_Update_Sequence( + psHciContext, INFO_SEQ ); + + if(( hciState_Listen == psHciContext->hci_state.next_state) + || (hciState_Transact == psHciContext->hci_state.next_state)) + { + psHciContext->hci_state.next_state = hciState_Initialise; + /* Roll Back to the Default State */ + status = phHciNfc_FSM_Complete(psHciContext); + } + } + psHciContext->event_pending = FALSE; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_EVENT, pInfo); + break; + } + case NFC_NOTIFY_DEVICE_ERROR: + { + phNfc_sCompletionInfo_t *psCompInfo = + (phNfc_sCompletionInfo_t *)pInfo; + + psCompInfo->status = ( NFCSTATUS_BOARD_COMMUNICATION_ERROR + != PHNFCSTATUS(psCompInfo->status))? + NFCSTATUS_BOARD_COMMUNICATION_ERROR: + psCompInfo->status ; + +#if (NXP_NFC_HCI_TIMER == 1) + + if ( NXP_INVALID_TIMER_ID != hci_resp_timer_id ) + { + HCI_DEBUG(" HCI : Response Timer Stop, Status:%02X", + psCompInfo->status); + /* Stop and Un-Intialise the Response Timer */ + phOsalNfc_Timer_Stop( hci_resp_timer_id ); + } + +#endif /* (NXP_NFC_HCI_TIMER == 1) */ + + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + (uint8_t) NFC_NOTIFY_DEVICE_ERROR, pInfo); + + break; + } + + case NFC_NOTIFY_ERROR: + default: + { + phNfc_sCompletionInfo_t *psCompInfo = + (phNfc_sCompletionInfo_t *)pInfo; + +#if (NXP_NFC_HCI_TIMER == 1) + + if (( NFCSTATUS_BOARD_COMMUNICATION_ERROR == PHNFCSTATUS(psCompInfo->status)) + && ( NXP_INVALID_TIMER_ID != hci_resp_timer_id )) + { + HCI_DEBUG(" HCI : Response Timer Stop, Status:%02X", + psCompInfo->status); + /* Stop the HCI Response Timer */ + phOsalNfc_Timer_Stop( hci_resp_timer_id ); + } + +#endif /* (NXP_NFC_HCI_TIMER == 1) */ + + phHciNfc_Error_Sequence( psHciContext, pHwRef, + psCompInfo->status, NULL, 0); + break; + } + } /* End of Switch */ + } /* End of Context != NULL */ +} + diff --git a/libnfc-nxp/phHciNfc_Generic.h b/libnfc-nxp/phHciNfc_Generic.h new file mode 100644 index 0000000..de4bbfd --- /dev/null +++ b/libnfc-nxp/phHciNfc_Generic.h @@ -0,0 +1,1231 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_Generic.h * +* \brief Common HCI Header for the Generic HCI Management. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Mon Mar 29 17:34:47 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.73 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/*@{*/ +#ifndef PHHCINFC_GENERIC_H +#define PHHCINFC_GENERIC_H + +/*@}*/ + + +/** + * \name HCI + * + * File: \ref phHciNfc_Generic.h + * + */ +/*@{*/ +#define PHHCINFC_GENERIC_FILEREVISION "$Revision: 1.73 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_GENERIC_FILEALIASES "$Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ +/* + +################################################################################ +***************************** Header File Inclusion **************************** +################################################################################ +*/ +#define LOG_TAG "NFC-HCI" +#include +#include +#include +#include +/* +################################################################################ +****************************** Macro Definitions ******************************* +################################################################################ +*/ + +#define Trace_buffer phOsalNfc_DbgTraceBuffer + +/* HCI TRACE Macros */ +#if defined(HCI_TRACE)&& !defined(SILENT_HCI) +#include +#include +extern char phOsalNfc_DbgTraceBuffer[]; +#define MAX_TRACE_BUFFER 150 +/* #define HCI_PRINT( str ) phOsalNfc_DbgTrace(str) */ +#define HCI_PRINT( str ) phOsalNfc_DbgString(str) +#define HCI_DEBUG(...) ALOGD(__VA_ARGS__) + + + + +#define HCI_PRINT_BUFFER(msg,buf,len) \ + { \ + snprintf(Trace_buffer,MAX_TRACE_BUFFER,"\t %s:",msg); \ + phOsalNfc_DbgString(Trace_buffer); \ + phOsalNfc_DbgTrace(buf,len); \ + phOsalNfc_DbgString("\r"); \ + \ + } +#else +#include +#if defined(PHDBG_TRACES) && !defined(HCI_TRACE) +#define HCI_PRINT( str ) PHDBG_INFO(str) +#define HCI_DEBUG(str, arg) +#define HCI_PRINT_BUFFER(msg,buf,len) +#else +#define HCI_PRINT( str ) +#define HCI_DEBUG(...) +#define HCI_PRINT_BUFFER(msg,buf,len) +#endif /* #if defined(PHDBG_TRACES) */ +/* #if defined(PHDBG_INFO) && defined (PHDBG_CRITICAL_ERROR) */ + +#endif /* #if defined(HCI_TRACE) */ + +#define ZERO 0x00U + + +#ifdef MASK_BITS +#define BYTE_SIZE 0x08U + +/* HCI GET and SET BITS Macros */ +#define MASK_BITS8(p,l) \ + ( ( (((uint8_t)(p))+((uint8_t)(l)))<=BYTE_SIZE )? \ + (~(0xFFU<<((p)+(l))) & (0xFFU<<(p))):(0U) ) +#ifdef MASK_BITS +#define GET_BITS8(num,p,l) \ + ( ((((uint8_t)(p))+((uint8_t)(l)))<=BYTE_SIZE)? \ + (((num)& (MASK_BITS8(p,l)))>>(p)):(0U) ) +#else +#define GET_BITS8(num,p,l) \ + ( ((((p)+(l))<=BYTE_SIZE))? \ + (((num)>>(p))& (~(0xFFU<<(l)))):(0U) ) +#endif +#define SET_BITS8(num,p,l,val) \ + ( ((((uint8_t)(p))+((uint8_t)(l)))<=BYTE_SIZE)? \ + (((num)& (~MASK_BITS8(p,l)))|((val)<<(p))):(0U)) + +#endif + +/** \ingroup grp_hci_retval + The Corresponding HCI Gate Not Supported. + */ +#define NFCSTATUS_HCI_GATE_NOT_SUPPORTED (0x71U) + +/** \ingroup grp_hci_retval + Invalid Command from the HCI Layer + */ +#define NFCSTATUS_INVALID_HCI_COMMAND (0x72U) + +/** \ingroup grp_hci_retval + HCI Command not supported . */ +#define NFCSTATUS_COMMAND_NOT_SUPPORTED (0x73U) + +/** \ingroup grp_hci_retval + Invalide Response from the HCI Layer + */ +#define NFCSTATUS_INVALID_HCI_RESPONSE (0x74U) + +/** \ingroup grp_hci_retval + The Invalid Instruction type (Neither Command/Response nor Event ). + */ +#define NFCSTATUS_INVALID_HCI_INSTRUCTION (0x75U) + +/** \ingroup grp_hci_retval + The Invalid Instruction type (Neither Command/Response nor Event ). + */ +#define NFCSTATUS_INVALID_HCI_INFORMATION (0x76U) + +/** \ingroup grp_hci_retval + The Invalid HCI Sequence. + */ +#define NFCSTATUS_INVALID_HCI_SEQUENCE (0x78U) + + +/** \ingroup grp_hci_retval + The HCI Error Response with Response code. + */ +#define NFCSTATUS_HCI_RESPONSE(code) (code) + + +/* Length of the HCP and the HCP Message Header in Bytes */ +#define HCP_HEADER_LEN 0x02U + +/* Length of the HCP Message Header in Bytes */ +#define HCP_MESSAGE_LEN 0x01U + +/* HCP Header Chaining Bit Offset */ +#define HCP_CHAINBIT_OFFSET 0x07U +/* HCP Header Chaining Bit Length */ +#define HCP_CHAINBIT_LEN 0x01U + +/* Chaining Bit Values */ +#define HCP_CHAINBIT_DEFAULT 0x01U +#define HCP_CHAINBIT_BEGIN 0x00U +#define HCP_CHAINBIT_END HCP_CHAINBIT_DEFAULT + +/* HCP Header Pipe ID Offset */ +#define HCP_PIPEID_OFFSET 0x00U +/* HCP Header Pipe ID Length */ +#define HCP_PIPEID_LEN 0x07U + +/* HCP Message Header Type Offset */ +#define HCP_MSG_TYPE_OFFSET 0x06U +/* HCP Message Header Type Length */ +#define HCP_MSG_TYPE_LEN 0x02U + +/* HCP Message Type Values */ +#define HCP_MSG_TYPE_COMMAND 0x00U +#define HCP_MSG_TYPE_EVENT 0x01U +#define HCP_MSG_TYPE_RESPONSE 0x02U +#define HCP_MSG_TYPE_RESERVED 0x03U + +/* HCP Message Header Instruction Offset */ +#define HCP_MSG_INSTRUCTION_OFFSET 0x00U +/* HCP Message Header Instruction Length */ +#define HCP_MSG_INSTRUCTION_LEN 0x06U +/* HCP Invalid Message Instruction */ +#define HCP_MSG_INSTRUCTION_INVALID 0x3FU + + +/* HCP Packet Zero Length */ +#define HCP_ZERO_LEN 0x00U + + + + /** \internal Generic HCI Commands for all the Gates */ +#define ANY_SET_PARAMETER 0x01U +#define ANY_GET_PARAMETER 0x02U +#define ANY_OPEN_PIPE 0x03U +#define ANY_CLOSE_PIPE 0x04U +#define ANY_GENERIC_CMD_RFU_B 0x05U +#define ANY_GENERIC_CMD_RFU_E 0x0FU + +/* + * 0x05-0x0F is Reserved for Future Use + */ + +/** \internal HCI Administration Com mands for the Management of the Host Network */ + +#define ADM_CREATE_PIPE 0x10U +#define ADM_DELETE_PIPE 0x11U +#define ADM_NOTIFY_PIPE_CREATED 0x12U +#define ADM_NOTIFY_PIPE_DELETED 0x13U +#define ADM_CLEAR_ALL_PIPE 0x14U +#define ADM_NOTIFY_ALL_PIPE_CLEARED 0x15U +#define ADM_CMD_RFU_B 0x16U +#define ADM_CMD_RFU_E 0x3FU + +#define MSG_INSTRUCTION_UNKNWON 0x3FU + + /* + * 0x16-0x3F is Reserved for Future Use + */ + + +/** \internal HCI Generic Responses from the Gates */ +#define ANY_OK 0x00U +#define ANY_E_NOT_CONNECTED 0x01U +#define ANY_E_CMD_PAR_UNKNOWN 0x02U +#define ANY_E_NOK 0x03U +#define ANY_E_PIPES_FULL 0x04U +#define ANY_E_REG_PAR_UNKNOWN 0x05U +#define ANY_E_PIPE_NOT_OPENED 0x06U +#define ANY_E_CMD_NOT_SUPPORTED 0x07U +#define ANY_E_INHIBITED 0x08U +#define ANY_E_TIMEOUT 0x09U +#define ANY_E_REG_ACCESS_DENIED 0x0AU +#define ANY_E_PIPE_ACCESS_DENIED 0x0BU + +/* Response Error Code for RF Reader Gate */ +#define WR_RF_ERROR 0x10U + +/* +* 0x08, 0x0B-0x3F is Reserved for Future Use +*/ + + +/** \internal HCI Generic Events from the Gates */ +#define EVT_HCI_END_OF_OPERATION 0x01 +#define EVT_POST_DATA 0x02 +#define EVT_HOT_PLUG 0x03 + + +/* Maximum Buffer Size for the HCI Data */ +#define PHHCINFC_MAX_BUFFERSIZE (PHHAL_MAX_DATASIZE + 0x50U) + +#define PHHCINFC_MAX_OPENPIPE 0x6FU +#define PHHCINFC_MAX_PIPE 0x6FU +#define PHHCINFC_MIN_PIPE 0x02U + + +/* Maximum Payload Length of HCI. */ +#define PHHCINFC_MAX_PACKET_DATA 0x1CU +#define PHHCINFC_MAX_HCP_LEN PHHCINFC_MAX_PACKET_DATA + 1 + + + +/* Maximum Payload Length of HCI. */ + + +/* +################################################################################ +******************** Enumeration and Structure Definition ********************** +################################################################################ +*/ +#if 1 +typedef NFCSTATUS (*pphHciNfc_Pipe_Receive_t) ( + void *pContext, + void *pHwRef, + uint8_t *data, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); +#else + +typedef pphNfcIF_Transact_t pphHciNfc_Pipe_Receive_t; + +#endif + +/** \defgroup grp_hci_nfc HCI Component + * + * + */ + +typedef enum phHciNfc_HostID { + phHciNfc_HostControllerID = 0x00U, + phHciNfc_TerminalHostID = 0x01U, + phHciNfc_UICCHostID = 0x02U +/* + phHciNfc_HostID_RFU_B = 0x03U, + phHciNfc_HostID_RFU_E = 0xBFU, + phHciNfc_HostIDProprietary_B = 0xC0U, + phHciNfc_HostIDProprietary_E = 0xFFU +*/ +}phHciNfc_HostID_t; + + +typedef enum phHciNfc_GateID{ + phHciNfc_AdminGate = 0x00U, +/* + phHciNfc_evGateIDProprietary_B = 0x01U, + phHciNfc_evGateIDProprietary_E = 0x03U, +*/ + phHciNfc_LoopBackGate = 0x04U, + phHciNfc_IdentityMgmtGate = 0x05U, + phHciNfc_LinkMgmtGate = 0x06U, +/* + phHciNfc_GateID_RFU_B = 0x07U, + phHciNfc_GateID_RFU_E = 0x0FU, +*/ + +/* TODO: Fillin Other Gate Information */ + /* ETSI HCI Specific RF Reader Gates */ + phHciNfc_RFReaderAGate = 0x13, + phHciNfc_RFReaderBGate = 0x11, + + /* Proprietary Reader Gate */ + phHciNfc_ISO15693Gate = 0x12, + phHciNfc_RFReaderFGate = 0x14, + phHciNfc_JewelReaderGate = 0x15, + + /* ETSI HCI Card RF Gates */ + phHciNfc_CETypeBGate = 0x21, + phHciNfc_CETypeBPrimeGate = 0x22, + phHciNfc_CETypeAGate = 0x23, + phHciNfc_CETypeFGate = 0x24, + + /* NFC-IP1 Gates */ + phHciNfc_NFCIP1InitRFGate = 0x30, + phHciNfc_NFCIP1TargetRFGate = 0x31, + + /* ETSI HCI Connectivity Gate */ + phHciNfc_ConnectivityGate = 0x41, + + + /* Device Configuration Gates */ + phHciNfc_PN544MgmtGate = 0x90, + phHciNfc_HostCommGate = 0x91, + phHciNfc_GPIOGate = 0x92, + phHciNfc_RFMgmtGate = 0x93, + phHciNfc_PollingLoopGate = 0x94, + phHciNfc_DownloadMgmtGate = 0x95, + + /* Card Emulation Managment Gates */ + phHciNfc_SwpMgmtGate = 0xA0, + phHciNfc_NfcWIMgmtGate = 0xA1, + phHciNfc_UnknownGate = 0xFF + +}phHciNfc_GateID_t; + + +typedef enum phHciNfc_PipeID{ + HCI_LINKMGMT_PIPE_ID = 0x00U, + HCI_ADMIN_PIPE_ID = 0x01U, + HCI_DYNAMIC_PIPE_ID = 0x02U, + HCI_RESERVED_PIPE_ID = 0x70U, + HCI_UNKNOWN_PIPE_ID = PHHCINFC_MAX_PIPE +/* + phHciNfc_evOtherGatePipeID_B = 0x02U, + phHciNfc_evOtherGatePipeID_E = 0x6FU, + phHciNfc_evGatePipeID_RFU_B = 0x70U, + phHciNfc_evGatePipeID_RFU_E = 0x7FU, +*/ +}phHciNfc_PipeID_t; + + +typedef enum phHciNfc_eState { + hciState_Reset = 0x00U, + hciState_Initialise, + hciState_Test, + hciState_Config, + hciState_IO, + hciState_Select, + hciState_Listen, + hciState_Activate, + hciState_Reactivate, + hciState_Connect, + hciState_Transact, + hciState_Disconnect, + hciState_Presence, + hciState_Release, + hciState_Unknown +}phHciNfc_eState_t; + +typedef enum phHciNfc_eMode { + hciMode_Reset = 0x00U, + hciMode_Session, + hciMode_Override, + hciMode_Test, + hciMode_Unknown +}phHciNfc_eMode_t; + + +typedef enum phHciNfc_eSeq{ + /* HCI Admin Sequence */ + ADMIN_INIT_SEQ = 0x00U, + ADMIN_SESSION_SEQ, + ADMIN_CE_SEQ, + ADMIN_REL_SEQ, + ADMIN_EVT_HOTPLUG_SEQ, + + /* HCI Link Management Sequence */ + LINK_MGMT_INIT_SEQ, + LINK_MGMT_REL_SEQ, + + /* HCI Identity Management Sequence */ + IDENTITY_INIT_SEQ, + IDENTITY_INFO_SEQ, + IDENTITY_REL_SEQ, + + /* HCI Polling Loop Sequence */ + PL_INIT_SEQ, + PL_DURATION_SEQ, + PL_CONFIG_PHASE_SEQ, + PL_TGT_DISABLE_SEQ, + PL_RESTART_SEQ, + PL_STOP_SEQ, + PL_REL_SEQ, + + /* HCI Device Management Sequence */ + DEV_INIT_SEQ, + DEV_HAL_INFO_SEQ, + DEV_CONFIG_SEQ, + DEV_REL_SEQ, + + /* HCI Reader Management Sequence */ + READER_MGMT_INIT_SEQ, + READER_ENABLE_SEQ, + READER_SELECT_SEQ, + READER_REACTIVATE_SEQ, + READER_SW_AUTO_SEQ, + READER_PRESENCE_CHK_SEQ, + READER_UICC_DISPATCH_SEQ, + READER_DESELECT_SEQ, + READER_RESELECT_SEQ, + READER_DISABLE_SEQ, + READER_MGMT_REL_SEQ, + + /* HCI NFC-IP1 Sequence */ + NFCIP1_INIT_SEQ, + INITIATOR_SPEED_SEQ, + INITIATOR_GENERAL_SEQ, + TARGET_GENERAL_SEQ, + TARGET_SPEED_SEQ, + NFCIP1_REL_SEQ, + + /* HCI Emulation Management Sequence */ + EMULATION_INIT_SEQ, + EMULATION_SWP_SEQ, + EMULATION_CONFIG_SEQ, + EMULATION_REL_SEQ, + + HCI_END_SEQ, + HCI_INVALID_SEQ +} phHciNfc_eSeq_t; + + + +typedef enum phHciNfc_eSeqType{ + RESET_SEQ = 0x00U, + INIT_SEQ, + UPDATE_SEQ, + INFO_SEQ, + CONFIG_SEQ, + REL_SEQ, + END_SEQ +} phHciNfc_eSeqType_t; + + +typedef enum phHciNfc_eConfigType{ + INVALID_CFG = 0x00U, + POLL_LOOP_CFG, + SMX_WI_CFG, + SMX_WI_MODE, + UICC_SWP_CFG, + SWP_EVT_CFG, + SWP_PROTECT_CFG, + NFC_GENERAL_CFG, + NFC_TARGET_CFG, + NFC_CE_A_CFG, + NFC_CE_B_CFG +} phHciNfc_eConfigType_t; + + +typedef struct phHciNfc_HCP_Message{ + /** \internal Identifies the Type and Kind of Instruction */ + uint8_t msg_header; + /** \internal Host Controller Protocol (HCP) Packet Message Payload */ + uint8_t payload[PHHCINFC_MAX_PACKET_DATA - 1]; +}phHciNfc_HCP_Message_t; + + +typedef struct phHciNfc_HCP_Packet{ + /** \internal Chaining Information and Pipe Identifier */ + uint8_t hcp_header; + /** \internal Host Controller Protocol (HCP) Packet Message or Payload */ + union + { + /** \internal Host Controller Protocol (HCP) Packet Message */ + phHciNfc_HCP_Message_t message; + /** \internal Host Controller Protocol (HCP) Packet Payload */ + uint8_t payload[PHHCINFC_MAX_PACKET_DATA]; + }msg; +}phHciNfc_HCP_Packet_t; + + + +typedef struct phHciNfc_Gate_Info{ + /** \internal HCI Host Identifier */ + uint8_t host_id; + /** \internal HCI Gate Identifier */ + uint8_t gate_id; +}phHciNfc_Gate_Info_t; + + +typedef struct phHciNfc_Pipe_Params{ + /** \internal HCI Source Gate Information for the pipe */ + phHciNfc_Gate_Info_t source; + /** \internal HCI Destination Gate Information for the pipe */ + phHciNfc_Gate_Info_t dest; + /** \internal HCI Pipe Identifier */ + uint8_t pipe_id; +}phHciNfc_Pipe_Params_t; + + +typedef struct phHciNfc_Pipe_Info{ + /** \internal Structure containing the created dynamic pipe information */ + phHciNfc_Pipe_Params_t pipe; + /** \internal Status of the previous command sent to this pipe */ + NFCSTATUS prev_status; + /** \internal previous message type Sent to this pipe */ + uint8_t sent_msg_type; + /** \internal Message type Received in this pipe */ + uint8_t recv_msg_type; + /** \internal previous message sent to this pipe */ + uint8_t prev_msg; + /** \internal Index of the previous Set/Get Parameter command + * sent to this pipe */ + uint8_t reg_index; + /** \internal length of Parameter of the Set/Get Parameter + * command sent to this pipe */ + uint16_t param_length; + /** \internal Parameter of the Set/Get Parameter command + * sent to this pipe */ + void *param_info; + /** \internal Pointer to a Pipe specific Receive Response function */ + pphHciNfc_Pipe_Receive_t recv_resp; + /** \internal Pointer to a Pipe specific Receive Event function */ + pphHciNfc_Pipe_Receive_t recv_event; + /** \internal Pointer to a Pipe specific Receive Command function */ + pphHciNfc_Pipe_Receive_t recv_cmd; +}phHciNfc_Pipe_Info_t; + + +typedef struct phHciNfc_sContext{ + /** \internal HCI Layer Pointer from the upper layer for + lower layer function registration */ + phNfcLayer_sCfg_t *p_hci_layer; + /** \internal Pointer to the upper layer context */ + void *p_upper_context; + /** \internal Pointer to the Hardware Reference Sturcture */ + phHal_sHwReference_t *p_hw_ref; + /** \internal Pointer to the upper layer notification callback function */ + pphNfcIF_Notification_CB_t p_upper_notify; + /** \internal Structure to store the lower interface operations */ + phNfc_sLowerIF_t lower_interface; + /** \internal Execution Sequence using the HCI Context */ + volatile phHciNfc_eSeq_t hci_seq; + + /** \internal State of the HCI Context */ + volatile phNfc_sState_t hci_state; + + /** \internal Mode of HCI Initialisation */ + phHciNfc_Init_t init_mode; + + /** \internal Memory Information for HCI Initialisation */ + uint8_t hal_mem_info[NXP_HAL_MEM_INFO_SIZE]; + + /** \internal HCI Configuration Type */ + phHciNfc_eConfigType_t config_type; + /** \internal HCI SmartMX Mode Configuration */ + phHal_eSmartMX_Mode_t smx_mode; + /** \internal HCI Configuration Information */ + void *p_config_params; + + /** \internal Current RF Reader/Emulation Gate in Use */ + phHal_eRFDevType_t host_rf_type; + + /** \internal Connected Target Information */ + phHal_sRemoteDevInformation_t *p_target_info; + + /** \internal Information of all the pipes created and opened */ + phHciNfc_Pipe_Info_t *p_pipe_list[PHHCINFC_MAX_PIPE+1]; + + /** \internal Tag */ + phHciNfc_XchgInfo_t *p_xchg_info; + + /** \internal Information of the HCI Gates */ + /** \internal HCI Admin Management Gate Information */ + void *p_admin_info; + /** \internal HCI Link Management Gate Information */ + void *p_link_mgmt_info; + /** \internal HCI Identity Management Gate Information */ + void *p_identity_info; + /** \internal HCI Polling Loop Gate Information */ + void *p_poll_loop_info; + /** \internal HCI NFC Device Management Information */ + void *p_device_mgmt_info; + /** \internal HCI RF Reader Gates Management Information */ + void *p_reader_mgmt_info; + /** \internal HCI Card Application Gates and Emulation + Information */ + void *p_emulation_mgmt_info; + /** \internal HCI RF Reader A Gate Information */ + void *p_reader_a_info; +#ifdef TYPE_B + /** \internal HCI RF Reader B Gate Information */ + void *p_reader_b_info; +#endif +#ifdef TYPE_FELICA + /** \internal HCI Felica Reader Gate Information */ + void *p_felica_info; +#endif +#ifdef TYPE_JEWEL + /** \internal HCI Jewel Reader Gate Information */ + void *p_jewel_info; +#endif +#ifdef TYPE_ISO15693 + /** \internal HCI ISO15693 Reader Gate Information */ + void *p_iso_15693_info; +#endif + +#ifdef ENABLE_P2P + /** \internal HCI NFC-IP1 Peer to Peer Information */ + void *p_nfcip_info; +#endif + /** \internal HCI Secure Element Management Information */ + void *p_wi_info; + /** \internal HCI UICC Information */ + void *p_uicc_info; + /** \internal HCI SWP Information */ + void *p_swp_info; +#ifdef HOST_EMULATION + /** \internal HCI Card Emulation A Gate Information */ + void *p_ce_a_info; + /** \internal HCI Card Emulation B Gate Information */ + void *p_ce_b_info; +#endif + + /** \internal HCI Packet Data to be sent to the lower layer */ + phHciNfc_HCP_Packet_t tx_packet; + /** \internal HCI Packet Data to be received from the lower layer */ + phHciNfc_HCP_Packet_t rx_packet; + + /** \internal Previous Status (To Store the Error Status ) */ + NFCSTATUS error_status; + + /** \internal Pointer to HCI Send Buffer */ + uint8_t send_buffer[PHHCINFC_MAX_BUFFERSIZE]; + /** \internal Pointer to HCI Receive Buffer */ + uint8_t recv_buffer[PHHCINFC_MAX_BUFFERSIZE]; + + /** \internal Total Number of bytes to be Sent */ + volatile uint16_t tx_total; + /** \internal Number of bytes Remaining to be Sent */ + volatile uint16_t tx_remain; + /** \internal Number of bytes sent */ + volatile uint16_t tx_sent; + + volatile uint16_t rx_index; + + /** \internal Total Number of bytes received */ + volatile uint16_t rx_total; + /** \internal Number of bytes received */ + volatile uint16_t rx_recvd; + /** \internal Index of the received data in the + * response packet + */ + + /** \internal Send HCP Chaining Information */ + volatile uint8_t tx_hcp_chaining; + /** \internal Send HCP Fragment Index */ + volatile uint16_t tx_hcp_frgmnt_index; + + /** \internal Receive HCP Chaining Information */ + volatile uint8_t rx_hcp_chaining; + /** \internal Receive HCP Fragment Index */ + volatile uint16_t rx_hcp_frgmnt_index; + + /** \internal The Device under Test */ + volatile uint8_t hci_mode; + /** \internal Wait for Response if Response is Pending */ + volatile uint8_t response_pending; + /** \internal Notify the Event if Notifcation is Pending */ + volatile uint8_t event_pending; + + /** \internal Pending Release of the detected Target */ + uint8_t target_release; + +}phHciNfc_sContext_t; + +/* +################################################################################ +*********************** Function Prototype Declaration ************************* +################################################################################ +*/ + + +/** + * + * \ingroup grp_hci_nfc + * + * The phHciNfc_Receive function receives the HCI Events or Response from the + * corresponding peripheral device, described by the HCI Context Structure. + * + * \param[in] psContext psContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[out] pdata Pointer to the response buffer that + * receives the response read. + * \param[in] length Variable that receives + * the number of bytes read. + * + * \retval NFCSTATUS_PENDING Data successfully read. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + */ + +extern +NFCSTATUS +phHciNfc_Receive( + void *psContext, + void *pHwRef, + uint8_t *pdata, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Send_Complete function acknowledges the completion of the HCI + * Commands sent to the device. + * + * \param[in] psContext psContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] pInfo Transaction information like + * status and length after the + * completion of the send. + * + * \retval NONE. + * + */ + +extern +void +phHciNfc_Send_Complete ( + void *psContext, + void *pHwRef, + phNfc_sTransactionInfo_t *pInfo + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Receive_Complete function acknowledges the completion of the HCI + * Event Information or Response received from the device. + * + * \param[in] psContext psContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] pInfo Transaction information like status + * data and length after the completely + * receiving the response . + * \retval NONE. + * + * + */ + +extern +void +phHciNfc_Receive_Complete ( + void *psContext, + void *pHwRef, + phNfc_sTransactionInfo_t *pInfo + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Notify_Event function notifies the occurence of the HCI + * Event from the device. + * + * \param[in] psContext psContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] type reason returned for the notification to + * the HCI. + * \param[in] pInfo Notification information like status + * data,length etc from the lower layer + * to the HCI Layer. + * \retval NONE. + * + */ + +extern +void +phHciNfc_Notify_Event( + void *psContext, + void *pHwRef, + uint8_t type, + void *pInfo + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Tag_Notify function notifies the the upper layer + * with the Tag Specific Notifications . + * + * \param[in] psContext psContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] type reason returned for the notification to + * the HCI. + * \param[in] pInfo Notification information like status + * data,length etc from the lower layer + * to the HCI Layer. + * \retval NONE. + * + */ +extern +void +phHciNfc_Tag_Notify( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t type, + void *pInfo + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Tag_Notify function notifies the the upper layer + * with the Tag Specific Notifications . + * + * \param[in] psContext psContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] type reason returned for the notification to + * the HCI. + * \param[in] pInfo Notification information like status + * data,length etc from the lower layer + * to the HCI Layer. + * \retval NONE. + * + */ + +extern +void +phHciNfc_Target_Select_Notify( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t type, + void *pInfo + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Transceive_Notify function notifies the the upper layer + * with the after the transceive operation. + * + * \param[in] psContext psContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] type reason returned for the notification to + * the HCI. + * \param[in] pInfo Notification information like status + * data,length etc from the lower layer + * to the HCI Layer. + * \retval NONE. + * + */ +extern +void +phHciNfc_Transceive_Notify( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t type, + void *pInfo + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Notify function calls the upper layer notification callback. + * + * \param[in] pUpperNotify pUpperNotify is the notification + * callback of the upper HAL Layer. + * \param[in] pUpperContext pUpperContext is the context of + * the upper HAL Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] type type of the notification to + * the upper HAL layer. + * \param[in] pInfo completion information returned + * to the Upper HAL Layer. + * NFCSTATUS_SUCCESS Notification successfully completed . + * NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * Other errors Errors related to the HCI or lower layers + * + * \retval NONE. + * + */ + +extern +void +phHciNfc_Notify( + pphNfcIF_Notification_CB_t p_upper_notify, + void *p_upper_context, + void *pHwRef, + uint8_t type, + void *pInfo + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Release_Notify function Releases HCI and notifies + * the upper layer. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] type reason returned for the notification to + * the HCI. + * \param[in] pInfo Notification information like status + * data,length etc from the lower layer + * to the HCI Layer. + * \retval NONE. + * + */ +extern +void +phHciNfc_Release_Notify( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t type, + void *pInfo + ); + + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Send_Generic_Cmd function sends the HCI Generic Commands + * to the device. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] pipe_id The pipe to which the command + * is being sent. + * \param[in] cmd The HCI Generic command sent to a + * particular pipe . + * + * \retval NFCSTATUS_PENDING HCI Generic Command send in progress . + * \retval + * NFCSTATUS_INSUFFICIENT_RESOURCES The memory could not be allocated + * as required amount of memory + * is not sufficient. + * + */ + +extern +NFCSTATUS +phHciNfc_Send_Generic_Cmd ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Set_Param function configures the Gate specific register + * with the provided value. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] p_pipe_info Pointer to pipe specific information. + * \param[in] reg_index Index of the register to be + * configured . + * \param[in] p_param Value to the configured in + * particular register. + * \param[in] param_length Length of the parameter provided + * for the configuration. + * + * \retval NFCSTATUS_PENDING HCI Set parameter in progress . + * \retval + * NFCSTATUS_INVALID_HCI_INFORMATION The Information like p_pipe_info, + * p_param or param_length is invalid + * + */ + +extern +NFCSTATUS +phHciNfc_Set_Param ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_Pipe_Info_t *p_pipe_info, + uint8_t reg_index, + void *p_param, + uint16_t param_length + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Send_HCP function sends the HCI Host Control Packet + * Frames to the device. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING HCP Frame send pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + * + */ + +extern +NFCSTATUS +phHciNfc_Send_HCP ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Build_HCPFrame function initially builds the HCP Packet Frame + * with the values passed in the arguments . + * + * \param[in] hcp_packet hcp_packet is the frame packet structure + * in which the frame is populated with the + * appropriate fields. + * \param[in] chainbit chainbit specifies whether the following + * HCP frames are chained or the frame is a + * normal frame. + * \param[in] pipe_id pipe_id of the pipe to which the frame has + * to be sent. + * \param[in] msg_type type of message sent to the pipe. + * \param[in] instruction type of message instruction send to the pipe. + * + * \retval NONE. + * + */ + + +extern +void +phHciNfc_Build_HCPFrame ( + phHciNfc_HCP_Packet_t *hcp_packet, + uint8_t chainbit, + uint8_t pipe_id, + uint8_t msg_type, + uint8_t instruction + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Append_HCPFrame function Appends the HCP Packet Frame + * with the values passed in the arguments . + * + * \param[in] hcp_data hcp_data is the pointer to the HCP + * payload to which the data is to be + * appended. + * \param[in] hcp_index hcp_index is the index from which + * the data source needs to be appended. + * \param[in] src_data src_data that is to be appended to the + * HCP packet. + * \param[in] src_len The length of the data source that is + * to be appended. + * \retval NONE. + * + */ + +extern +void + phHciNfc_Append_HCPFrame ( + uint8_t *hcp_data, + uint16_t hcp_index, + uint8_t *src_data, + uint16_t src_len + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Allocate_Resource function allocates and initialises the + * resource memory for the HCI layer. + * + * \param[in] ppBuffer ppBuffer is the pointer to which the + * resource memory is allocated. + * \param[in] size Variable that specifies the size of + * the memory that needs to be created. + * + * \retval NFCSTATUS_SUCCESS The Resource Memory was allocated + * successfully . + * \retval + * NFCSTATUS_INSUFFICIENT_RESOURCES The memory could not be allocated + * as required amount of memory + * is not suffient. + * + */ + +extern +NFCSTATUS + phHciNfc_Allocate_Resource ( + void **ppBuffer, + uint16_t size + ); +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Release_Resources function releases all the resources + * allocated in the HCI Layer. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * + * \retval NONE. + * + */ + +extern + void + phHciNfc_Release_Resources ( + phHciNfc_sContext_t **ppsHciContext + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Release_Lower function initiates the release of the + * lower layers. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NONE. + * + */ + +extern +void +phHciNfc_Release_Lower( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + + +#endif + diff --git a/libnfc-nxp/phHciNfc_IDMgmt.c b/libnfc-nxp/phHciNfc_IDMgmt.c new file mode 100644 index 0000000..092e7d9 --- /dev/null +++ b/libnfc-nxp/phHciNfc_IDMgmt.c @@ -0,0 +1,872 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_IDMgmt.c * +* \brief HCI Identity Management Gate Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Jun 11 11:19:25 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.23 $ * +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +#define FW_VERSION_INDEX 0x01U +#define HCI_VERSION_INDEX 0x02U +#define HW_VERSION_INDEX 0x03U +#define VENDOR_NAME_INDEX 0x04U +#define MODEL_ID_INDEX 0x05U +#define GATES_LIST_INDEX 0x06U +#define FULL_VERSION_INDEX 0x10U + +#define VERSION_LEN 0x03U +#define GATES_LIST_LEN 0x20U + +/* +*************************** Structure and Enumeration *************************** +*/ + + +/** \defgroup grp_hci_nfc HCI Identity Management Component + * + * + */ + +typedef enum phHciNfc_IDMgmt_Seq{ + IDMGMT_PIPE_OPEN = 0x00U, + IDMGMT_GET_FULL_VERSION, + IDMGMT_GET_FW_VERSION, + IDMGMT_GET_HW_VERSION, + IDMGMT_GET_HCI_VERSION, + IDMGMT_GET_VENDOR_NAME, + IDMGMT_GET_MODEL_ID, + IDMGMT_GET_GATES_LIST, + IDMGMT_PIPE_CLOSE +} phHciNfc_IDMgmt_Seq_t; + +typedef struct phHciNfc_IDMgmt_Info{ + phHciNfc_IDMgmt_Seq_t id_cur_seq; + phHciNfc_IDMgmt_Seq_t id_next_seq; + phHciNfc_Pipe_Info_t *p_pipe_info; + uint8_t pipe_id; + uint32_t fw_version; + uint32_t hw_version; + utf8_t vendor_name[VENDOR_NAME_LEN]; + uint8_t model_id; + uint8_t hci_version; + uint8_t gates_list[GATES_LIST_LEN]; + uint8_t full_version[NXP_FULL_VERSION_LEN]; +} phHciNfc_IDMgmt_Info_t; + +/* +*************************** Static Function Declaration ************************** +*/ + +static +NFCSTATUS +phHciNfc_IDMgmt_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + phHal_sHwReference_t *pHwRef, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); + +static +NFCSTATUS +phHciNfc_Recv_IDMgmt_Response( + void *psHciContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + +/* +*************************** Function Definitions *************************** +*/ + +/*! + * \brief Allocates the resources of Identity Managment Gate. + * + * This function Allocates the resources of the Identity Management + * gate Information Structure. + * + */ + +NFCSTATUS +phHciNfc_IDMgmt_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_IDMgmt_Info_t *p_identity_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( ( NULL == psHciContext->p_identity_info ) + && (phHciNfc_Allocate_Resource((void **)(&p_identity_info), + sizeof(phHciNfc_IDMgmt_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_identity_info = p_identity_info; + p_identity_info->id_cur_seq = IDMGMT_PIPE_OPEN; + p_identity_info->id_next_seq = IDMGMT_PIPE_OPEN; + p_identity_info->pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + } + return status; +} + +/*! + * \brief Get the pipe_id of Identity Managment Gate. + * + * This function Get the pipe_id of Identity Managment Gate. + * + */ + + +NFCSTATUS +phHciNfc_IDMgmt_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_IDMgmt_Info_t *p_identity_info=NULL; + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_identity_info ) + ) + { + p_identity_info = (phHciNfc_IDMgmt_Info_t *) + psHciContext->p_identity_info ; + *ppipe_id = p_identity_info->pipe_id ; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + +NFCSTATUS +phHciNfc_IDMgmt_Update_Sequence( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t reader_seq + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_IDMgmt_Info_t *p_identity_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( NULL == psHciContext->p_identity_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_identity_info = (phHciNfc_IDMgmt_Info_t *) + psHciContext->p_identity_info ; + switch(reader_seq) + { + case RESET_SEQ: + case INIT_SEQ: + { + p_identity_info->id_cur_seq = IDMGMT_PIPE_OPEN; + p_identity_info->id_next_seq = IDMGMT_PIPE_OPEN; + break; + } + case UPDATE_SEQ: + { + p_identity_info->id_cur_seq = + p_identity_info->id_next_seq; + break; + } + case INFO_SEQ: + { + p_identity_info->id_cur_seq = IDMGMT_GET_FW_VERSION; + p_identity_info->id_next_seq = IDMGMT_GET_FW_VERSION; + break; + } + case REL_SEQ: + { + p_identity_info->id_cur_seq = IDMGMT_PIPE_CLOSE; + p_identity_info->id_next_seq = IDMGMT_PIPE_CLOSE; + break; + } + default: + { + break; + } + } + } + } + + return status; + +} + + + +/*! + * \brief Initialisation of Identity Managment Gate. + * + * This function initialses the Identity Management gate and + * populates the Identity Management Information Structure + * + */ + +NFCSTATUS +phHciNfc_IDMgmt_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_IDMgmt_Info_t *p_identity_info=NULL; +#ifndef ESTABLISH_SESSION + uint8_t id_pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; +#endif + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + + if( NULL == psHciContext->p_identity_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_identity_info = (phHciNfc_IDMgmt_Info_t *) + psHciContext->p_identity_info ; + p_pipe_info = p_identity_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_NOT_ALLOWED); + } + else + { + switch(p_identity_info->id_cur_seq ) + { + /* Identity Mgmt pipe open sequence */ + case IDMGMT_PIPE_OPEN: + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_identity_info->id_next_seq = IDMGMT_GET_FW_VERSION; +#ifndef ESTABLISH_SESSION + status = NFCSTATUS_PENDING; +#endif + } + break; + } +#ifndef ESTABLISH_SESSION + case IDMGMT_GET_FW_VERSION: + { + p_pipe_info->reg_index = FW_VERSION_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_GET_HW_VERSION; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case IDMGMT_GET_HW_VERSION: + { + p_pipe_info->reg_index = HW_VERSION_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_GET_HCI_VERSION; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case IDMGMT_GET_HCI_VERSION: + { + p_pipe_info->reg_index = HCI_VERSION_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_GET_VENDOR_NAME; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case IDMGMT_GET_VENDOR_NAME: + { + p_pipe_info->reg_index = VENDOR_NAME_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_GET_MODEL_ID; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case IDMGMT_GET_MODEL_ID: + { + p_pipe_info->reg_index = MODEL_ID_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_GET_GATES_LIST; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case IDMGMT_GET_GATES_LIST: + { + p_pipe_info->reg_index = GATES_LIST_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_GET_FULL_VERSION; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case IDMGMT_GET_FULL_VERSION: + { + p_pipe_info->reg_index = FULL_VERSION_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_PIPE_CLOSE; + status = NFCSTATUS_SUCCESS; + } + break; + } +#endif + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + + }/* End of the Sequence Switch */ + }/* End of Pipe Info Memory Check */ + + }/* End of the Identity Info Memory Check */ + + } /* End of Null Context Check */ + + return status; +} + + + +/*! + * \brief Initialisation of Identity Managment Gate. + * + * This function initialses the Identity Management gate and + * populates the Identity Management Information Structure + * + */ + +NFCSTATUS +phHciNfc_IDMgmt_Info_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_IDMgmt_Info_t *p_identity_info=NULL; + uint8_t id_pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + + if( NULL == psHciContext->p_identity_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_identity_info = (phHciNfc_IDMgmt_Info_t *) + psHciContext->p_identity_info ; + p_pipe_info = p_identity_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_NOT_ALLOWED); + } + else + { + switch(p_identity_info->id_cur_seq ) + { + case IDMGMT_GET_FW_VERSION: + { + p_pipe_info->reg_index = FW_VERSION_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_GET_HW_VERSION; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case IDMGMT_GET_HW_VERSION: + { + p_pipe_info->reg_index = HW_VERSION_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_GET_HCI_VERSION; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case IDMGMT_GET_HCI_VERSION: + { + p_pipe_info->reg_index = HCI_VERSION_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_GET_VENDOR_NAME; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case IDMGMT_GET_VENDOR_NAME: + { + p_pipe_info->reg_index = VENDOR_NAME_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_GET_MODEL_ID; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case IDMGMT_GET_MODEL_ID: + { + p_pipe_info->reg_index = MODEL_ID_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_GET_GATES_LIST; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case IDMGMT_GET_GATES_LIST: + { + p_pipe_info->reg_index = GATES_LIST_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_GET_FULL_VERSION; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case IDMGMT_GET_FULL_VERSION: + { + p_pipe_info->reg_index = FULL_VERSION_INDEX; + id_pipe_id = p_identity_info->pipe_id ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + id_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_identity_info->id_next_seq = IDMGMT_PIPE_CLOSE; + status = NFCSTATUS_SUCCESS; + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + + }/* End of the Sequence Switch */ + }/* End of Pipe Info Memory Check */ + + }/* End of the Identity Info Memory Check */ + + } /* End of Null Context Check */ + + return status; +} + +/*! + * \brief Releases the resources allocated the Identity Management. + * + * This function Releases the resources allocated the Identity Management. + */ + +NFCSTATUS +phHciNfc_IDMgmt_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_IDMgmt_Info_t *p_identity_info=NULL; + /* static phHciNfc_IDMgmt_Seq_t identity_init_seq = IDMGMT_PIPE_CREATE; */ + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( NULL != psHciContext->p_identity_info ) + { + p_identity_info = (phHciNfc_IDMgmt_Info_t *) + psHciContext->p_identity_info ; + p_pipe_info = p_identity_info->p_pipe_info; + + status = phHciNfc_Close_Pipe( psHciContext, + pHwRef, p_pipe_info ); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_NOT_ALLOWED); + + }/* End of the Identity Info Memory Check */ + + } /* End of Null Context Check */ + + return status; +} + + +/*! + * \brief Receives the HCI Response from the corresponding peripheral device. + * + * This function receives the HCI Command Response from the connected NFC + * Pheripheral device. + */ +static +NFCSTATUS +phHciNfc_Recv_IDMgmt_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + phHciNfc_IDMgmt_Info_t *p_identity_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t prev_cmd = ANY_GET_PARAMETER; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_identity_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + p_identity_info = (phHciNfc_IDMgmt_Info_t *) + psHciContext->p_identity_info ; + if( NULL != p_identity_info->p_pipe_info) + { + prev_cmd = p_identity_info->p_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_GET_PARAMETER: + { + status = phHciNfc_IDMgmt_InfoUpdate(psHciContext, + (phHal_sHwReference_t *)pHwRef, + p_identity_info->p_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); + break; + } + case ANY_SET_PARAMETER: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + case ANY_OPEN_PIPE: + { + break; + } + case ANY_CLOSE_PIPE: + { + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + p_identity_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; + p_identity_info->id_cur_seq = p_identity_info->id_next_seq; + } + } + } + return status; +} + +/* Function to Update the Pipe Information */ +NFCSTATUS +phHciNfc_IDMgmt_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipe_id, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + phHciNfc_IDMgmt_Info_t *p_identity_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_identity_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_identity_info = (phHciNfc_IDMgmt_Info_t *) + psHciContext->p_identity_info ; + /* Update the pipe_id of the ID Mgmt Gate obtained from the HCI Response */ + p_identity_info->pipe_id = pipe_id; + p_identity_info->p_pipe_info = pPipeInfo; + if ( NULL != pPipeInfo) + { + /* Update the Response Receive routine of the IDMgmt Gate */ + pPipeInfo->recv_resp = &phHciNfc_Recv_IDMgmt_Response; + } + } + + return status; +} + +static +NFCSTATUS +phHciNfc_IDMgmt_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + phHal_sHwReference_t *pHwRef, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + phHciNfc_IDMgmt_Info_t *p_identity_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t i=0; + if( (NULL == psHciContext) + || (NULL == reg_value) + || (reg_length == 0) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_identity_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_identity_info = (phHciNfc_IDMgmt_Info_t *) + psHciContext->p_identity_info ; + + switch(index) + { + case FW_VERSION_INDEX : + { + HCI_PRINT_BUFFER("\tFW Version:",reg_value,reg_length); + for(i=0 ;(reg_length == VERSION_LEN)&&(i < reg_length); i++) + { + p_identity_info->fw_version |= + (uint32_t)(reg_value[VERSION_LEN - i - 1] << (BYTE_SIZE * i)); + } + pHwRef->device_info.fw_version = p_identity_info->fw_version ; + break; + } + case HW_VERSION_INDEX : + { + HCI_PRINT_BUFFER("\tHW Version:",reg_value,reg_length); + for(i=0 ;(reg_length == VERSION_LEN)&&(i < reg_length); i++) + { + p_identity_info->hw_version |= + (uint32_t)(reg_value[VERSION_LEN - i - 1] << (BYTE_SIZE * i)); + } + pHwRef->device_info.hw_version = p_identity_info->hw_version ; + break; + } + case VENDOR_NAME_INDEX : + { + for(i=0 ;(reg_length <= VENDOR_NAME_LEN)&&(i < reg_length); i++) + { + p_identity_info->vendor_name[i] = reg_value[i]; + pHwRef->device_info.vendor_name[i]= reg_value[i]; + } + HCI_DEBUG("\tVendor Name:%s",p_identity_info->vendor_name); + break; + } + case MODEL_ID_INDEX : + { + HCI_PRINT_BUFFER("\tModel ID:",reg_value,reg_length); + p_identity_info->model_id = reg_value[i] ; + pHwRef->device_info.model_id = p_identity_info->model_id ; +#ifndef NXP_HAL_ENABLE_SMX + if( NFC_HW_PN65N == pHwRef->device_info.model_id) +#endif + { + pHwRef->smx_connected = TRUE; + } + break; + } + case HCI_VERSION_INDEX : + { + HCI_PRINT_BUFFER("\tHCI Version:",reg_value,reg_length); + p_identity_info->hci_version = reg_value[i] ; + pHwRef->device_info.hci_version = p_identity_info->hci_version ; + break; + } + case GATES_LIST_INDEX : + { + HCI_PRINT_BUFFER("\tGates List:",reg_value,reg_length); + for(i=0 ;(reg_length <= GATES_LIST_LEN)&&(i < reg_length); i++) + { + p_identity_info->gates_list[i] = reg_value[i]; + } + break; + } + case FULL_VERSION_INDEX : + { + HCI_PRINT_BUFFER("\tVERSION INFO:",reg_value,reg_length); + for(i=0 ;(reg_length <= NXP_FULL_VERSION_LEN)&&(i < reg_length); i++) + { + p_identity_info->full_version[i] = reg_value[i]; + pHwRef->device_info.full_version[i]= reg_value[i]; + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + break; + } /*End of the default Switch Case */ + + } /*End of the Index Switch */ + + } /* End of Context and the Identity information validity check */ + + return status; +} diff --git a/libnfc-nxp/phHciNfc_IDMgmt.h b/libnfc-nxp/phHciNfc_IDMgmt.h new file mode 100644 index 0000000..5e1e7c6 --- /dev/null +++ b/libnfc-nxp/phHciNfc_IDMgmt.h @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_IDMgmt.h * +* \brief HCI Header for the Identity Management Gate. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Aug 14 17:01:26 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.5 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + + +#ifndef PHHCINFC_IDMGMT_H +#define PHHCINFC_IDMGMT_H + +/*@}*/ + + +/** + * \name HCI + * + * File: \ref phHciNfc_IDMgmt.h + * + */ +/*@{*/ +#define PHHCINFC_IDMGMT_FILEREVISION "$Revision: 1.5 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_IDMGMT_FILEALIASES "$Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +/* +******************** Enumeration and Structure Definition ********************** +*/ + + + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_IDMgmt_Initialise function creates and the opens Identity + * Management Gate + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Identity Mgmt Gate Initialisation is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ +extern +NFCSTATUS +phHciNfc_IDMgmt_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_IDMgmt_Info_Sequence function obtains the information + * from the Identity Management Gate + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Identity Mgmt Gate Information is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ +extern +NFCSTATUS +phHciNfc_IDMgmt_Info_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_IDMgmt_Release function closes the opened pipes between + * the Host Controller Device and the NFC Device. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Release of the Identity Management gate + * resources are pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ +extern +NFCSTATUS +phHciNfc_IDMgmt_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_IDMgmt_Update_PipeInfo function updates the pipe_id of the Idetity + * Gate Managment Struction. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pipeID pipeID of the Identity management Gate + * \param[in] pPipeInfo Update the pipe Information of the Identity + * Management Gate. + * + * \retval NFCSTATUS_SUCCESS AdminGate Response received Successfully. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * + */ + +extern +NFCSTATUS +phHciNfc_IDMgmt_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + + +/*! + * \brief Updates the Sequence of Identity Managment Gate. + * + * This function Updates the Sequence of the Identity Management + * gate Information Structure. + * + */ +extern +NFCSTATUS +phHciNfc_IDMgmt_Update_Sequence( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t reader_seq + ); + +/*! + * \brief Allocates the resources of Identity Managment Gate. + * + * This function Allocates the resources of the Identity Management + * gate Information Structure. + * + */ +extern +NFCSTATUS +phHciNfc_IDMgmt_Init_Resources( + phHciNfc_sContext_t *psHciContext + ); + + +/*! + * \brief Get the pipe_id of Identity Managment Gate. + * + * This function Get the pipe_id of Identity Managment Gate. + * + */ + +extern +NFCSTATUS +phHciNfc_IDMgmt_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + + + +#endif + diff --git a/libnfc-nxp/phHciNfc_ISO15693.c b/libnfc-nxp/phHciNfc_ISO15693.c new file mode 100644 index 0000000..99ba86e --- /dev/null +++ b/libnfc-nxp/phHciNfc_ISO15693.c @@ -0,0 +1,769 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_ISO15693.c * +* \brief HCI ISO-15693 management routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Thu Feb 11 18:54:47 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.7 $ * +* $Aliases: $ +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include + +#if defined (TYPE_ISO15693) +#include + +/* +****************************** Macro Definitions ******************************* +*/ +#define ISO_15693_INVENTORY_INDEX 0x01U +#define ISO_15693_AFI_INDEX 0x02U + +#define ISO_15693_INVENTORY_LENGTH 0x0AU +#define ISO_15693_AFI_LENGTH 0x01U + +#define ISO_15693_SINGLE_TAG_FOUND 0x00U +#define ISO_15693_MULTIPLE_TAGS_FOUND 0x03U + +/* +*************************** Structure and Enumeration *************************** +*/ + +/* +*************************** Static Function Declaration ************************** +*/ + +static +NFCSTATUS +phHciNfc_ISO15693_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); + +static +NFCSTATUS +phHciNfc_Recv_ISO15693_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_ISO15693_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +/* +*************************** Function Definitions *************************** +*/ + +NFCSTATUS +phHciNfc_ISO15693_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_ISO15693_Info_t *ps_15693_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if (NULL != psHciContext->p_iso_15693_info) + { + status = NFCSTATUS_SUCCESS; + } + else if(( NULL == psHciContext->p_iso_15693_info ) && + (phHciNfc_Allocate_Resource((void **)(&ps_15693_info), + sizeof(phHciNfc_ISO15693_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_iso_15693_info = ps_15693_info; + ps_15693_info->current_seq = ISO15693_INVENTORY; + ps_15693_info->next_seq = ISO15693_INVENTORY; + ps_15693_info->ps_15693_pipe_info = NULL; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + return status; +} + + +NFCSTATUS +phHciNfc_ISO15693_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_iso_15693_info ) + ) + { + phHciNfc_ISO15693_Info_t *ps_15693_info = NULL; + ps_15693_info = (phHciNfc_ISO15693_Info_t *) + psHciContext->p_iso_15693_info ; + *ppipe_id = ps_15693_info->ps_15693_pipe_info->pipe.pipe_id; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + + +NFCSTATUS +phHciNfc_ISO15693_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if((NULL == psHciContext) || (NULL == pPipeInfo)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_iso_15693_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ISO15693_Info_t *ps_15693_info = NULL; + ps_15693_info = (phHciNfc_ISO15693_Info_t *) + psHciContext->p_iso_15693_info ; + + /* Update the pipe_id of the ISO15693 Gate obtained from + the HCI Response */ + ps_15693_info->ps_15693_pipe_info = pPipeInfo; + ps_15693_info->pipe_id = pipeID; + ps_15693_info->ps_15693_pipe_info->pipe.pipe_id = pipeID; + /* Update the Response Receive routine of the ISO15693 Gate */ + pPipeInfo->recv_resp = &phHciNfc_Recv_ISO15693_Response; + /* Update the event Receive routine of the ISO15693 Gate */ + pPipeInfo->recv_event = &phHciNfc_Recv_ISO15693_Event; + } + return status; +} + + +NFCSTATUS +phHciNfc_ISO15693_Update_Info( + phHciNfc_sContext_t *psHciContext, + uint8_t infotype, + void *iso_15693_info + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if (NULL == psHciContext) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_iso_15693_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ISO15693_Info_t *ps_15693_info = NULL; + ps_15693_info = (phHciNfc_ISO15693_Info_t *) + psHciContext->p_iso_15693_info; + + switch(infotype) + { + case HCI_ISO_15693_ENABLE: + { + if (NULL != iso_15693_info) + { + ps_15693_info->enable_iso_15693_gate = + *((uint8_t *)iso_15693_info); + } + break; + } + case HCI_ISO_15693_INFO_SEQ: + { + ps_15693_info->current_seq = ISO15693_INVENTORY; + ps_15693_info->next_seq = ISO15693_INVENTORY; + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + } + } + return status; +} + + +NFCSTATUS +phHciNfc_ISO15693_Info_Sequence ( + void *psHciHandle, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_iso_15693_info) || + (HCI_ISO_15693_ENABLE != + ((phHciNfc_ISO15693_Info_t *)(psHciContext->p_iso_15693_info))-> + enable_iso_15693_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ISO15693_Info_t *ps_15693_info = NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info = NULL; + uint8_t pipeid = 0; + + ps_15693_info = (phHciNfc_ISO15693_Info_t *) + psHciContext->p_iso_15693_info; + ps_pipe_info = ps_15693_info->ps_15693_pipe_info; + + if(NULL == ps_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + switch(ps_15693_info->current_seq) + { + case ISO15693_INVENTORY: + { + ps_pipe_info->reg_index = ISO_15693_INVENTORY_INDEX; + pipeid = ps_pipe_info->pipe.pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + ps_15693_info->next_seq = ISO15693_AFI; + } + break; + } + case ISO15693_AFI: + { + ps_pipe_info->reg_index = ISO_15693_AFI_INDEX; + pipeid = ps_pipe_info->pipe.pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + ps_15693_info->next_seq = ISO15693_END_SEQUENCE; + } + break; + } + case ISO15693_END_SEQUENCE: + { + phNfc_sCompletionInfo_t CompInfo; + if (ISO_15693_MULTIPLE_TAGS_FOUND == + ps_15693_info->multiple_tgts_found) + { + CompInfo.status = NFCSTATUS_MULTIPLE_TAGS; + } + else + { + CompInfo.status = NFCSTATUS_SUCCESS; + } + + CompInfo.info = &(ps_15693_info->iso15693_info); + + ps_15693_info->iso15693_info.RemDevType = + phHal_eISO15693_PICC; + ps_15693_info->current_seq = ISO15693_INVENTORY; + ps_15693_info->next_seq = ISO15693_INVENTORY; + status = NFCSTATUS_SUCCESS; + /* Notify to the upper layer */ + phHciNfc_Tag_Notify(psHciContext, pHwRef, + NFC_NOTIFY_TARGET_DISCOVERED, + &CompInfo); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_ISO15693_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_ISO15693_Info_t *ps_15693_info = NULL; + uint8_t i = 0; + + ps_15693_info = (phHciNfc_ISO15693_Info_t *) + (psHciContext->p_iso_15693_info); + + + switch(index) + { + case ISO_15693_INVENTORY_INDEX: + { + if (ISO_15693_INVENTORY_LENGTH == reg_length) + { + ps_15693_info->iso15693_info.RemoteDevInfo + .Iso15693_Info.Flags = *(reg_value + i ); + i++; + ps_15693_info->iso15693_info.RemoteDevInfo + .Iso15693_Info.Dsfid = *(reg_value + i ); + i++; + (void)memcpy(ps_15693_info->iso15693_info. + RemoteDevInfo.Iso15693_Info.Uid, + (reg_value+i), (reg_length - i )); + ps_15693_info->iso15693_info.RemoteDevInfo + .Iso15693_Info.UidLength = ( reg_length - i ); + HCI_PRINT_BUFFER("\tISO 15693 inventory", reg_value, reg_length); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case ISO_15693_AFI_INDEX: + { + if (ISO_15693_AFI_LENGTH == reg_length) + { + ps_15693_info->iso15693_info.RemoteDevInfo + .Iso15693_Info.Afi = *(reg_value + i ); + HCI_PRINT_BUFFER("\tISO 15693 AFI", reg_value, reg_length); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + return status; +} + + +static +NFCSTATUS +phHciNfc_Recv_ISO15693_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse) + || (0 == length)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_iso_15693_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ISO15693_Info_t *ps_15693_info = NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info = NULL; + uint8_t prev_cmd = ANY_GET_PARAMETER; + + ps_15693_info = (phHciNfc_ISO15693_Info_t *) + psHciContext->p_iso_15693_info; + + ps_pipe_info = ps_15693_info->ps_15693_pipe_info; + if( NULL == ps_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + prev_cmd = ps_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_GET_PARAMETER: + { + status = phHciNfc_ISO15693_InfoUpdate(psHciContext, + ps_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); +#if 0 + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); +#endif /* #if 0 */ + break; + } + case ANY_SET_PARAMETER: + { + HCI_PRINT("ISO 15693 Parameter Set \n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + ps_15693_info->next_seq = ISO15693_INVENTORY; + break; + } + case ANY_OPEN_PIPE: + { + HCI_PRINT("ISO 15693 open pipe complete\n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + ps_15693_info->next_seq = ISO15693_INVENTORY; + break; + } + case ANY_CLOSE_PIPE: + { + HCI_PRINT("ISO 15693 close pipe complete\n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + break; + } + + case NXP_ISO15693_CMD: + { + if (length >= HCP_HEADER_LEN) + { + HCI_PRINT("ISO 15693 packet received \n"); + /* Copy buffer to the receive buffer */ + phHciNfc_Append_HCPFrame(psHciContext->recv_buffer, + 0, pResponse, length); + psHciContext->rx_total = length; + psHciContext->rx_index = HCP_HEADER_LEN; + HCI_PRINT_BUFFER("ISO 15693 Bytes received", + pResponse, length); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + }/* End of switch(prev_cmd) */ + + if( NFCSTATUS_SUCCESS == status ) + { + ps_pipe_info->prev_status = NFCSTATUS_SUCCESS; + ps_15693_info->current_seq = ps_15693_info->next_seq; + } + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_ISO15693_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_iso_15693_info) || + (HCI_ISO_15693_ENABLE != + ((phHciNfc_ISO15693_Info_t *)(psHciContext->p_iso_15693_info))-> + enable_iso_15693_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_ISO15693_Info_t *ps_15693_info=NULL; + phHciNfc_HCP_Message_t *message = NULL; + uint8_t instruction=0, + i = 0; + + ps_15693_info = (phHciNfc_ISO15693_Info_t *) + psHciContext->p_iso_15693_info; + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &p_packet->msg.message; + /* Get the instruction bits from the Message Header */ + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + + if ((EVT_TARGET_DISCOVERED == instruction) + && ((ISO_15693_MULTIPLE_TAGS_FOUND == message->payload[i]) + || (ISO_15693_SINGLE_TAG_FOUND == message->payload[i])) + ) + { + phNfc_sCompletionInfo_t pCompInfo; + +/* #define NFC_ISO_15693_MULTIPLE_TAGS_SUPPORT 0x00 */ +#if (NFC_ISO_15693_MULTIPLE_TAGS_SUPPORT >= 0x01) + + if (ISO_15693_MULTIPLE_TAGS_FOUND == message->payload[i]) + { + ps_15693_info->multiple_tgts_found = ISO_15693_MULTIPLE_TAGS_FOUND; + pCompInfo.status = NFCSTATUS_MULTIPLE_TAGS; + } + else +#endif /* #if (NFC_ISO_15693_MULTIPLE_TAGS_SUPPORT <= 0x01) */ + { + ps_15693_info->multiple_tgts_found = FALSE; + pCompInfo.status = NFCSTATUS_SUCCESS; + } + /* CompInfo.info = &(ps_15693_info->iso15693_info); */ + + psHciContext->host_rf_type = phHal_eISO15693_PCD; + ps_15693_info->iso15693_info.RemDevType = phHal_eISO15693_PICC; + ps_15693_info->current_seq = ISO15693_INVENTORY; + /* Notify to the HCI Generic layer To Update the FSM */ + phHciNfc_Notify_Event(psHciContext, pHwRef, + NFC_NOTIFY_TARGET_DISCOVERED, + &pCompInfo); + + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + } + } + return status; +} + +NFCSTATUS +phHciNfc_Send_ISO15693_Command( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_iso_15693_info) || + (HCI_ISO_15693_ENABLE != + ((phHciNfc_ISO15693_Info_t *)(psHciContext->p_iso_15693_info))-> + enable_iso_15693_gate) || + (HCI_UNKNOWN_PIPE_ID == + ((phHciNfc_ISO15693_Info_t *)(psHciContext->p_iso_15693_info))-> + pipe_id) || + (pipe_id != + ((phHciNfc_ISO15693_Info_t *)(psHciContext->p_iso_15693_info))-> + pipe_id)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ISO15693_Info_t *ps_15693_info=NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info=NULL; + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + uint8_t i = 0; + uint16_t length = HCP_HEADER_LEN; + + ps_15693_info = (phHciNfc_ISO15693_Info_t *) + psHciContext->p_iso_15693_info ; + ps_pipe_info = ps_15693_info->ps_15693_pipe_info; + if(NULL == ps_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + psHciContext->tx_total = 0 ; + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + if (NXP_ISO15693_CMD == cmd) + { + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + hcp_message = &(hcp_packet->msg.message); + +#if 0 + /* Command */ + hcp_message->payload[i++] = + psHciContext->p_xchg_info->params.tag_info.cmd_type ; + /* Address */ + hcp_message->payload[i++] = + psHciContext->p_xchg_info->params.tag_info.addr ; +#endif /* #if 0 */ + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, (uint8_t *)ps_pipe_info->param_info, + ps_pipe_info->param_length); + length =(uint16_t)(length + i + ps_pipe_info->param_length); + + ps_pipe_info->sent_msg_type = (uint8_t)HCP_MSG_TYPE_COMMAND; + ps_pipe_info->prev_msg = cmd; + psHciContext->tx_total = length; + psHciContext->response_pending = TRUE; + + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef); + ps_pipe_info->prev_status = status; + } + } + } + return status; +} + +NFCSTATUS +phHciNfc_ISO15693_Set_AFI( + void *psContext, + void *pHwRef, + uint8_t afi_value + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + + if( (NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_iso_15693_info) || + (HCI_ISO_15693_ENABLE != + ((phHciNfc_ISO15693_Info_t *)(psHciContext->p_iso_15693_info))-> + enable_iso_15693_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ISO15693_Info_t *ps_15693_info = NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info = NULL; + uint8_t pipeid = 0; + + ps_15693_info = (phHciNfc_ISO15693_Info_t *) + psHciContext->p_iso_15693_info ; + ps_pipe_info = ps_15693_info->ps_15693_pipe_info; + + if( NULL == ps_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + ps_pipe_info->reg_index = ISO_15693_AFI_INDEX; + ps_pipe_info->param_info = &afi_value; + ps_pipe_info->param_length = sizeof(afi_value); + pipeid = ps_pipe_info->pipe.pipe_id ; + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + } + } + return status; +} + +#endif /* #if defined (TYPE_ISO15693) */ + + diff --git a/libnfc-nxp/phHciNfc_ISO15693.h b/libnfc-nxp/phHciNfc_ISO15693.h new file mode 100644 index 0000000..d6fb849 --- /dev/null +++ b/libnfc-nxp/phHciNfc_ISO15693.h @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_NfcIPMgmt.h * +* \brief HCI NFCIP-1 Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Tue Jun 30 17:09:29 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.1 $ * +* $Aliases: NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + +#ifndef PHHCINFC_ISO15693_H +#define PHHCINFC_ISO15693_H + +/*@}*/ + + +/** +* \name HCI +* +* File: \ref phHciNfc_ISO15693.h +* +*/ +/*@{*/ +#define PHHCINFC_ISO15693_FILEREVISION "$Revision: 1.1 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_ISO15693_FILEALIASES "$Aliases: NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ +/* Enable the ISO 15693 */ +#define HCI_ISO_15693_ENABLE 0x01U +#define HCI_ISO_15693_INFO_SEQ 0x02U + +#define NXP_ISO15693_CMD 0x20U + + +/* +******************** Enumeration and Structure Definition ********************** +*/ + +typedef enum phHciNfc_ISO15693_Seq{ + ISO15693_INVENTORY, + ISO15693_AFI, + ISO15693_END_SEQUENCE, + ISO15693_INVALID_SEQ +} phHciNfc_ISO15693_Seq_t; + +typedef struct phHciNfc_ISO15693_Info{ + phHciNfc_ISO15693_Seq_t current_seq; + phHciNfc_ISO15693_Seq_t next_seq; + phHciNfc_Pipe_Info_t *ps_15693_pipe_info; + uint8_t pipe_id; + uint8_t multiple_tgts_found; + phHal_sRemoteDevInformation_t iso15693_info; + uint8_t enable_iso_15693_gate; +}phHciNfc_ISO15693_Info_t; + + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/*! +* \brief Allocates the resources of ISO15693 management gate. +* +* This function Allocates the resources of the ISO15693 management +* gate Information Structure. +* +*/ +extern +NFCSTATUS +phHciNfc_ISO15693_Init_Resources( + phHciNfc_sContext_t *psHciContext + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ISO15693_Get_PipeID function gives the pipe id of the ISO15693 +* gate +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ISO15693_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ISO15693_Update_PipeInfo function updates the pipe_id of the ISO15693 +* gate management Structure. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pipeID pipeID of the ISO15693 gate +* \param[in] pPipeInfo Update the pipe Information of the ISO15693 +* gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ + +extern +NFCSTATUS +phHciNfc_ISO15693_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ISO15693_Update_Info function stores the data sent by the +* upper layer. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] infotype To enable the ISO 15693 gate +* \param[in] iso_15693_info ISO 15693 gate info +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ISO15693_Update_Info( + phHciNfc_sContext_t *psHciContext, + uint8_t infotype, + void *iso_15693_info + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ISO15693_Sequence function executes the sequence of operations, to +* get the NXP_ISO15693_INVENTORY, NXP_ISO15693_AFI. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ISO15693_Info_Sequence ( + void *psHciHandle, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Send_ISO15693_Command function executes the command sent by the +* upper layer, depending on the commands defined. +* +* \param[in] psContext psContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] pipe_id pipeID of the ISO 15693 gate +* \param[in] cmd command that needs to be sent to the device +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_Send_ISO15693_Command( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ISO15693_Set_AFI function updates the AFI value +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pipeID pipeID of the ISO 15693 gate +* \param[in] pPipeInfo Update the pipe Information of the ISO +* 15693 gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ISO15693_Set_AFI( + void *psContext, + void *pHwRef, + uint8_t afi_value + ); + +#endif /* #ifndef PHHCINFC_ISO15693_H */ + + diff --git a/libnfc-nxp/phHciNfc_Jewel.c b/libnfc-nxp/phHciNfc_Jewel.c new file mode 100644 index 0000000..a6d9c45 --- /dev/null +++ b/libnfc-nxp/phHciNfc_Jewel.c @@ -0,0 +1,839 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_Jewel.c * +* \brief HCI Jewel/Topaz Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Mon Mar 29 17:34:47 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.8 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include + +#if defined(TYPE_JEWEL) +#include + +/* +****************************** Macro Definitions ******************************* +*/ +#define JEWEL_SINGLE_TAG_FOUND 0x00U +#define JEWEL_MULTIPLE_TAGS_FOUND 0x03U +#define NXP_WRA_CONTINUE_ACTIVATION 0x12U + +#define NXP_JEWEL_READID 0x78U +#define NXP_JEWEL_READID_LENGTH 0x06U + +/* +*************************** Structure and Enumeration *************************** +*/ + +/* +*************************** Static Function Declaration ************************** +*/ + +static +NFCSTATUS +phHciNfc_Recv_Jewel_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_Jewel_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Jewel_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); + +static +NFCSTATUS +phHciNfc_Recv_Jewel_Packet( + phHciNfc_sContext_t *psHciContext, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + +NFCSTATUS +phHciNfc_Jewel_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_jewel_info ) + ) + { + phHciNfc_Jewel_Info_t *ps_jewel_info = NULL; + ps_jewel_info = (phHciNfc_Jewel_Info_t *)psHciContext->p_jewel_info; + *ppipe_id = ps_jewel_info->pipe_id; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + +NFCSTATUS +phHciNfc_Jewel_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Jewel_Info_t *ps_jewel_info = NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( + ( NULL == psHciContext->p_jewel_info ) && + (phHciNfc_Allocate_Resource((void **)(&ps_jewel_info), + sizeof(phHciNfc_Jewel_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_jewel_info = ps_jewel_info; + ps_jewel_info->current_seq = JEWEL_INVALID_SEQ; + ps_jewel_info->next_seq = JEWEL_INVALID_SEQ; + ps_jewel_info->pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + return status; +} + +NFCSTATUS +phHciNfc_Jewel_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_jewel_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_Jewel_Info_t *ps_jewel_info=NULL; + ps_jewel_info = (phHciNfc_Jewel_Info_t *)psHciContext->p_jewel_info ; + + /* Update the pipe_id of the Jewel Gate obtained from the HCI + Response */ + ps_jewel_info->pipe_id = pipeID; + ps_jewel_info->p_pipe_info = pPipeInfo; + /* Update the Response Receive routine of the Jewel Gate */ + pPipeInfo->recv_resp = phHciNfc_Recv_Jewel_Response; + /* Update the event Receive routine of the Jewel Gate */ + pPipeInfo->recv_event = phHciNfc_Recv_Jewel_Event; + } + + return status; +} + + +NFCSTATUS +phHciNfc_Jewel_Update_Info( + phHciNfc_sContext_t *psHciContext, + uint8_t infotype, + void *jewel_info + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if (NULL == psHciContext) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_jewel_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_Jewel_Info_t *ps_jewel_info=NULL; + ps_jewel_info = (phHciNfc_Jewel_Info_t *) + psHciContext->p_jewel_info ; + + switch(infotype) + { + case HCI_JEWEL_ENABLE: + { + if (NULL != jewel_info) + { + ps_jewel_info->enable_jewel_gate = + *((uint8_t *)jewel_info); + } + break; + } + case HCI_JEWEL_INFO_SEQ: + { + ps_jewel_info->current_seq = JEWEL_READID_SEQUENCE; + ps_jewel_info->next_seq = JEWEL_READID_SEQUENCE; + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + } + } + return status; +} + +NFCSTATUS +phHciNfc_Jewel_Info_Sequence ( + void *psHciHandle, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + ((phHciNfc_sContext_t *)psHciHandle); + static uint8_t paraminfo[NXP_JEWEL_READID_LENGTH + 1] = {0}; + + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_jewel_info) || + (HCI_JEWEL_ENABLE != + ((phHciNfc_Jewel_Info_t *)(psHciContext->p_jewel_info))-> + enable_jewel_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_Jewel_Info_t *ps_jewel_info=NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info=NULL; + uint8_t pipeid = 0; + + ps_jewel_info = (phHciNfc_Jewel_Info_t *) + psHciContext->p_jewel_info ; + ps_pipe_info = ps_jewel_info->p_pipe_info; + if(NULL == ps_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + switch(ps_jewel_info->current_seq) + { + case JEWEL_READID_SEQUENCE: + { + pipeid = ps_pipe_info->pipe.pipe_id; + ps_pipe_info->reg_index = NXP_JEWEL_READID; + paraminfo[0] = NXP_JEWEL_READID; + + ps_pipe_info->param_info = (void *)¶minfo; + ps_pipe_info->param_length = NXP_JEWEL_READID_LENGTH + 1; + + status = phHciNfc_Send_Jewel_Command(psHciContext, + pHwRef, pipeid, + NXP_JEWEL_RAW); + + if(NFCSTATUS_PENDING == status ) + { + ps_jewel_info->next_seq = JEWEL_END_SEQUENCE; + } + break; + } + case JEWEL_END_SEQUENCE: + { + phNfc_sCompletionInfo_t CompInfo; + + ps_pipe_info->reg_index = JEWEL_END_SEQUENCE; + if (JEWEL_MULTIPLE_TAGS_FOUND == + ps_jewel_info->multiple_tgts_found) + { + CompInfo.status = NFCSTATUS_MULTIPLE_TAGS; + } + else + { + CompInfo.status = NFCSTATUS_SUCCESS; + } + + CompInfo.info = &(ps_jewel_info->s_jewel_info); + + ps_jewel_info->s_jewel_info.RemDevType = phHal_eJewel_PICC; + ps_jewel_info->current_seq = JEWEL_READID_SEQUENCE; + ps_jewel_info->next_seq = JEWEL_READID_SEQUENCE; + status = NFCSTATUS_SUCCESS; + /* Notify to the upper layer */ + phHciNfc_Tag_Notify(psHciContext, pHwRef, + NFC_NOTIFY_TARGET_DISCOVERED, + &CompInfo); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_Jewel_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Jewel_Info_t *ps_jewel_info = NULL; + phHal_sJewelInfo_t *ps_jewel_tag_info = NULL; + + ps_jewel_info = (phHciNfc_Jewel_Info_t *)(psHciContext->p_jewel_info); + ps_jewel_tag_info = &(ps_jewel_info->s_jewel_info.RemoteDevInfo.Jewel_Info); + + switch(index) + { + case NXP_JEWEL_READID: + { + HCI_PRINT_BUFFER("\tJewel ID", reg_value, reg_length); + if(NXP_JEWEL_READID_LENGTH == reg_length) + { + uint8_t i = 0; + ps_jewel_tag_info->HeaderRom0 = reg_value[i++]; + ps_jewel_tag_info->HeaderRom1 = reg_value[i++]; + (void)memcpy(ps_jewel_tag_info->Uid, + &(reg_value[i]), + (reg_length - i)); + + ps_jewel_tag_info->UidLength = (reg_length - i); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_Jewel_Packet( + phHciNfc_sContext_t *psHciContext, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Jewel_Info_t *ps_jewel_info = (phHciNfc_Jewel_Info_t *) + (psHciContext->p_jewel_info); + + if (NXP_JEWEL_READID == ps_jewel_info->p_pipe_info->reg_index) + { + status = phHciNfc_Jewel_InfoUpdate(psHciContext, + ps_jewel_info->p_pipe_info->reg_index, + pResponse, (uint8_t)length); + } + else + { + /* Send Jewel data to the upper layer */ + HCI_PRINT_BUFFER("Jewel Bytes received", pResponse, length); + psHciContext->rx_index = HCP_HEADER_LEN; + } + return status; +} + + +static +NFCSTATUS +phHciNfc_Recv_Jewel_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext; + + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse) + || (0 == length)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_jewel_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_Jewel_Info_t *ps_jewel_info=NULL; + uint8_t prev_cmd = ANY_GET_PARAMETER; + ps_jewel_info = (phHciNfc_Jewel_Info_t *) + psHciContext->p_jewel_info ; + if( NULL == ps_jewel_info->p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + prev_cmd = ps_jewel_info->p_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_GET_PARAMETER: + { + if (length >= HCP_HEADER_LEN) + { + status = phHciNfc_Jewel_InfoUpdate(psHciContext, + ps_jewel_info->p_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case ANY_SET_PARAMETER: + { + HCI_PRINT("Jewel Parameter Set \n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + ps_jewel_info->next_seq = JEWEL_READID_SEQUENCE; + break; + } + case ANY_OPEN_PIPE: + { + HCI_PRINT("Jewel open pipe complete\n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + ps_jewel_info->next_seq = JEWEL_READID_SEQUENCE; + break; + } + case ANY_CLOSE_PIPE: + { + HCI_PRINT("Jewel close pipe complete\n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + break; + } + case NXP_JEWEL_RAW: + { + HCI_PRINT("Jewel packet received \n"); + if (length >= HCP_HEADER_LEN) + { + phHciNfc_Append_HCPFrame(psHciContext->recv_buffer, + 0, pResponse, length); + psHciContext->rx_total = length; + status = phHciNfc_Recv_Jewel_Packet(psHciContext, + &pResponse[HCP_HEADER_LEN], + (length - HCP_HEADER_LEN)); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_WRA_CONTINUE_ACTIVATION: + case NXP_WR_ACTIVATE_ID: + { + HCI_PRINT("Jewel continue activation or "); + HCI_PRINT("reactivation completed \n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + break; + } + case NXP_WR_PRESCHECK: + { + HCI_PRINT("Presence check completed \n"); + break; + } + case NXP_WR_ACTIVATE_NEXT: + { + HCI_PRINT("Activate next completed \n"); + if (length > HCP_HEADER_LEN) + { + if (JEWEL_MULTIPLE_TAGS_FOUND == + pResponse[HCP_HEADER_LEN]) + { + ps_jewel_info->multiple_tgts_found = + JEWEL_MULTIPLE_TAGS_FOUND; + } + else + { + ps_jewel_info->multiple_tgts_found = FALSE; + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_WR_DISPATCH_TO_UICC: + { + switch(length) + { + case HCP_HEADER_LEN: + { + /* Optional error code, if no error code field + in the response, then this command is + successfully completed */ + ps_jewel_info->uicc_activation = + UICC_CARD_ACTIVATION_SUCCESS; + break; + } + case (HCP_HEADER_LEN + 1): + { + ps_jewel_info->uicc_activation = + pResponse[HCP_HEADER_LEN]; + break; + } /* End of case (HCP_HEADER_LEN + index) */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if (NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + ps_jewel_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; + ps_jewel_info->current_seq = ps_jewel_info->next_seq; + } + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_Jewel_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent) + || (0 == length)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_jewel_info) || + (HCI_JEWEL_ENABLE != + ((phHciNfc_Jewel_Info_t *)(psHciContext->p_jewel_info))-> + enable_jewel_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_Jewel_Info_t *ps_jewel_info = NULL; + phHciNfc_HCP_Message_t *message = NULL; + uint8_t instruction=0, + i = 0; + + ps_jewel_info = (phHciNfc_Jewel_Info_t *) + psHciContext->p_jewel_info ; + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &p_packet->msg.message; + /* Get the instruction bits from the Message Header */ + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + + if ((EVT_TARGET_DISCOVERED == instruction) + && ((JEWEL_MULTIPLE_TAGS_FOUND == message->payload[i] ) + || (JEWEL_SINGLE_TAG_FOUND == message->payload[i])) + ) + { + static phNfc_sCompletionInfo_t pCompInfo; + + if (JEWEL_MULTIPLE_TAGS_FOUND == message->payload[i]) + { + ps_jewel_info->multiple_tgts_found = + JEWEL_MULTIPLE_TAGS_FOUND; + pCompInfo.status = NFCSTATUS_MULTIPLE_TAGS; + } + else + { + ps_jewel_info->multiple_tgts_found = FALSE; + pCompInfo.status = NFCSTATUS_SUCCESS; + } + + psHciContext->host_rf_type = phHal_eJewel_PCD; + ps_jewel_info->s_jewel_info.RemDevType = phHal_eJewel_PICC; + ps_jewel_info->current_seq = JEWEL_READID_SEQUENCE; + + /* Notify to the HCI Generic layer To Update the FSM */ + phHciNfc_Notify_Event(psHciContext, pHwRef, + NFC_NOTIFY_TARGET_DISCOVERED, + &pCompInfo); + + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + } + } + return status; +} + +NFCSTATUS +phHciNfc_Send_Jewel_Command( + phHciNfc_sContext_t *psContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_jewel_info) || + (HCI_JEWEL_ENABLE != + ((phHciNfc_Jewel_Info_t *)(psHciContext->p_jewel_info))-> + enable_jewel_gate) || + (HCI_UNKNOWN_PIPE_ID == + ((phHciNfc_Jewel_Info_t *)(psHciContext->p_jewel_info))-> + pipe_id) || + (pipe_id != + ((phHciNfc_Jewel_Info_t *)(psHciContext->p_jewel_info))-> + pipe_id)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_Jewel_Info_t *ps_jewel_info=NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info=NULL; + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + uint8_t i = 0, + length = HCP_HEADER_LEN; + + ps_jewel_info = (phHciNfc_Jewel_Info_t *) + psHciContext->p_jewel_info ; + ps_pipe_info = ps_jewel_info->p_pipe_info; + if(NULL == ps_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + psHciContext->tx_total = 0 ; + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + + if (NXP_JEWEL_RAW == cmd) + { + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + hcp_message = &(hcp_packet->msg.message); + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, (uint8_t *)ps_pipe_info->param_info, + ps_pipe_info->param_length); + length =(uint8_t)(length + i + ps_pipe_info->param_length); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_COMMAND); + } + + if (NFCSTATUS_SUCCESS == status) + { + ps_pipe_info->sent_msg_type = (uint8_t)HCP_MSG_TYPE_COMMAND; + ps_pipe_info->prev_msg = cmd; + psHciContext->tx_total = length; + psHciContext->response_pending = TRUE; + + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef); + ps_pipe_info->prev_status = status; + } + } + } + return status; +} + +NFCSTATUS +phHciNfc_Jewel_GetRID( + phHciNfc_sContext_t *psHciContext, + void *pHwRef) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t reader_id_info[NXP_JEWEL_READID_LENGTH] = {0}; + + if( (NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_jewel_info) || + (HCI_JEWEL_ENABLE != + ((phHciNfc_Jewel_Info_t *)(psHciContext->p_jewel_info))-> + enable_jewel_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_Jewel_Info_t *ps_jewel_info=NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info=NULL; + uint8_t pipeid = 0; + + ps_jewel_info = (phHciNfc_Jewel_Info_t *) + psHciContext->p_jewel_info ; + + ps_pipe_info = ps_jewel_info->p_pipe_info; + if(NULL == ps_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + pipeid = ps_jewel_info->pipe_id ; + reader_id_info[0] = NXP_JEWEL_READID; + + ps_pipe_info->param_info = (void *)&reader_id_info; + ps_pipe_info->param_length = NXP_JEWEL_READID_LENGTH + 1 ; + + status = phHciNfc_Send_Jewel_Command(psHciContext, + pHwRef, pipeid, + NXP_JEWEL_RAW); + } + } + return status; +} + +#endif /* #if defined(TYPE_JEWEL) */ + + diff --git a/libnfc-nxp/phHciNfc_Jewel.h b/libnfc-nxp/phHciNfc_Jewel.h new file mode 100644 index 0000000..e184d27 --- /dev/null +++ b/libnfc-nxp/phHciNfc_Jewel.h @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_Jewel.h * +* \brief HCI Jewel Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Mon Mar 29 17:34:50 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.3 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + +#ifndef PHHCINFC_JEWEL_H +#define PHHCINFC_JEWEL_H + +/*@}*/ + + +/** +* \name HCI +* +* File: \ref phHciNfc_Jewel.h +* +*/ +/*@{*/ +#define PHHCINFC_JEWEL_FILEREVISION "$Revision: 1.3 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_JEWEL_FILEALIASES "$Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +/* Commands exposed to the upper layer */ + +/* Enable the Jewel */ +#define HCI_JEWEL_ENABLE 0x01U +#define HCI_JEWEL_INFO_SEQ 0x02U + +/* Jewel read write commands */ +#define NXP_JEWEL_RAW 0x23U + +/* +******************** Enumeration and Structure Definition ********************** +*/ +typedef enum phHciNfc_Jewel_Seq{ + JEWEL_READID_SEQUENCE, + JEWEL_END_SEQUENCE, + JEWEL_INVALID_SEQ +} phHciNfc_Jewel_Seq_t; + +/* Information structure for the Jewel Gate */ +typedef struct phHciNfc_Jewel_Info{ + /* Current running Sequence of the Jewel Management */ + phHciNfc_Jewel_Seq_t current_seq; + /* Next running Sequence of the Jewel Management */ + phHciNfc_Jewel_Seq_t next_seq; + /* Pointer to the Jewel pipe information */ + phHciNfc_Pipe_Info_t *p_pipe_info; + uint8_t pipe_id; + /* Flag to say about the multiple targets */ + uint8_t multiple_tgts_found; + /* Jewel information */ + phHal_sRemoteDevInformation_t s_jewel_info; + /* Enable or disable reader gate */ + uint8_t enable_jewel_gate; + /* UICC re-activation status */ + uint8_t uicc_activation; +} phHciNfc_Jewel_Info_t; + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/*! +* \brief Allocates the resources of Jewel management gate. +* +* This function Allocates the resources of the Jewel management +* gate Information Structure. +* +*/ +extern +NFCSTATUS +phHciNfc_Jewel_Init_Resources( + phHciNfc_sContext_t *psHciContext + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Jewel_Get_PipeID function gives the pipe id of the Jewel +* gate +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_Jewel_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Jewel_Update_PipeInfo function updates the pipe_id of the Jewel +* gate management Structure. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pipeID pipeID of the Jewel gate +* \param[in] pPipeInfo Update the pipe Information of the reader +* A gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ + +extern +NFCSTATUS +phHciNfc_Jewel_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Jewel_Update_Info function updated the jewel gate info. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] infotype To enable the jewel gate +* \param[in] jewel_info Jewel gate info +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +*/ +extern +NFCSTATUS +phHciNfc_Jewel_Update_Info( + phHciNfc_sContext_t *psHciContext, + uint8_t infotype, + void *jewel_info + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Jewel_Info_Sequence function executes the sequence of operations, to +* get the ID. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_Jewel_Info_Sequence ( + void *psHciHandle, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Send_Jewel_Command function executes the command sent by the +* upper layer, depending on the commands defined. +* +* \param[in] psContext psContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] pipe_id pipeID of the jewel gate +* \param[in] cmd command that needs to be sent to the device +* \param[in] length information length sent by the caller +* \param[in] params information related to the command +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +*/ +extern +NFCSTATUS +phHciNfc_Send_Jewel_Command( + phHciNfc_sContext_t *psContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Jewel_GetRID function executes the command to read the ID +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +*/ +extern +NFCSTATUS +phHciNfc_Jewel_GetRID( + phHciNfc_sContext_t *psHciContext, + void *pHwRef); + +#endif /* #ifndef PHHCINFC_JEWEL_H */ + + diff --git a/libnfc-nxp/phHciNfc_LinkMgmt.c b/libnfc-nxp/phHciNfc_LinkMgmt.c new file mode 100644 index 0000000..3ff0acb --- /dev/null +++ b/libnfc-nxp/phHciNfc_LinkMgmt.c @@ -0,0 +1,478 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_LinkMgmt.c * +* \brief HCI Link Management Gate Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Thu Feb 11 18:52:19 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.11 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +#define REC_ERROR_INDEX 0x01U + +#define REC_RETRY_LEN 0x02U + +/* +*************************** Structure and Enumeration *************************** +*/ + + +/** \defgroup grp_hci_nfc HCI Link Management Component + * + * + */ + +typedef enum phHciNfc_LinkMgmt_Seq{ + LINK_MGMT_PIPE_OPEN = 0x00U, + LINK_MGMT_GET_REC_ERROR, + LINK_MGMT_SET_REC_ERROR, + LINK_MGMT_PIPE_CLOSE +} phHciNfc_LinkMgmt_Seq_t; + +typedef struct phHciNfc_LinkMgmt_Info{ + phHciNfc_LinkMgmt_Seq_t link_cur_seq; + phHciNfc_LinkMgmt_Seq_t link_next_seq; + phHciNfc_Pipe_Info_t *p_pipe_info; + /* Rec Error Count Number from the Host Controller */ + uint16_t hc_rec_error; + /* Rec Error Count Number of the Terminal Host */ + uint16_t rec_error; +} phHciNfc_LinkMgmt_Info_t; + + +/* +*************************** Static Function Declaration ************************** +*/ + +static +NFCSTATUS +phHciNfc_LinkMgmt_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + phHal_sHwReference_t *pHwRef, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); +static +NFCSTATUS +phHciNfc_Recv_LinkMgmt_Response( + void *psHciContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + + +/* +*************************** Function Definitions *************************** +*/ + + + + +/*! + * \brief Initialisation of Link Managment Gate. + * + * This function initialses the Link Management gate and + * populates the Link Management Information Structure + * + */ + +NFCSTATUS +phHciNfc_LinkMgmt_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_LinkMgmt_Info_t *p_link_mgmt_info=NULL; + uint8_t link_pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + + if( ( NULL == psHciContext ) + || (NULL == pHwRef ) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( ( NULL == psHciContext->p_link_mgmt_info ) + && (phHciNfc_Allocate_Resource((void **)(&p_link_mgmt_info), + sizeof(phHciNfc_LinkMgmt_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_link_mgmt_info = p_link_mgmt_info; + p_link_mgmt_info->link_cur_seq = LINK_MGMT_PIPE_OPEN; + p_link_mgmt_info->link_next_seq = LINK_MGMT_PIPE_OPEN; + p_link_mgmt_info->p_pipe_info = NULL; + } + else + { + p_link_mgmt_info = (phHciNfc_LinkMgmt_Info_t *) + psHciContext->p_link_mgmt_info ; + } + + if( NULL == p_link_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } +#ifdef ESTABLISH_SESSION + else if( hciMode_Session == psHciContext->hci_mode ) + { + status = NFCSTATUS_SUCCESS; + } +#endif + else + { + switch(p_link_mgmt_info->link_cur_seq ) + { + /* Link Mgmt pipe open sequence */ + case LINK_MGMT_PIPE_OPEN: + { + if(phHciNfc_Allocate_Resource((void **)(&p_pipe_info), + sizeof(phHciNfc_Pipe_Info_t))!= NFCSTATUS_SUCCESS) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + /* Populate the pipe information in the pipe handle */ + ((phHciNfc_Pipe_Info_t *)p_pipe_info)->pipe.pipe_id = + PIPETYPE_STATIC_LINK; + ((phHciNfc_Pipe_Info_t *)p_pipe_info)->recv_resp = + &phHciNfc_Recv_LinkMgmt_Response; + psHciContext->p_pipe_list[PIPETYPE_STATIC_LINK] = + p_pipe_info ; + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef,p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_link_mgmt_info->p_pipe_info = p_pipe_info ; + p_link_mgmt_info->link_next_seq = + LINK_MGMT_GET_REC_ERROR; + status = NFCSTATUS_PENDING; + } + } + break; + } + case LINK_MGMT_GET_REC_ERROR: + { + p_pipe_info = p_link_mgmt_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + p_pipe_info->reg_index = REC_ERROR_INDEX; + link_pipe_id = PIPETYPE_STATIC_LINK ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + link_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_link_mgmt_info->link_next_seq = + LINK_MGMT_PIPE_CLOSE; + status = NFCSTATUS_SUCCESS; + } + } + break; + } + case LINK_MGMT_SET_REC_ERROR: + { + p_pipe_info = p_link_mgmt_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + p_pipe_info->reg_index = REC_ERROR_INDEX; + link_pipe_id = PIPETYPE_STATIC_LINK ; + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + link_pipe_id, (uint8_t)ANY_GET_PARAMETER ); + if(NFCSTATUS_PENDING == status ) + { + p_link_mgmt_info->link_next_seq = + LINK_MGMT_PIPE_CLOSE; + status = NFCSTATUS_SUCCESS; + } + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + + }/* End of the Sequence Switch */ + + }/* End of the Link Info Memory Check */ + } /* End of Null Context Check */ + + return status; +} + +/*! + * \brief Opens the Link Management Pipe of the Link Management Gate. + * + * This function Opens the Link Management Pipe of the Link Management + * Gate and Confirms that the HCI Link is behaving as expected. + */ + +NFCSTATUS +phHciNfc_LinkMgmt_Open( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + phHciNfc_LinkMgmt_Info_t *p_link_mgmt_info= + (phHciNfc_LinkMgmt_Info_t *)psHciContext->p_link_mgmt_info ; + if(( NULL != p_link_mgmt_info ) && + ( NULL != p_link_mgmt_info->p_pipe_info )) + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_link_mgmt_info->p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + status = NFCSTATUS_PENDING; + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_NOT_ALLOWED); + + }/* End of the Identity Info Memory Check */ + + } /* End of Null Context Check */ + + return status; +} + + +NFCSTATUS +phHciNfc_LinkMgmt_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_LinkMgmt_Info_t *p_link_mgmt_info=NULL; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( NULL != psHciContext->p_link_mgmt_info ) + { + p_link_mgmt_info = (phHciNfc_LinkMgmt_Info_t *) + psHciContext->p_link_mgmt_info ; + status = phHciNfc_Close_Pipe( psHciContext, + pHwRef, p_link_mgmt_info->p_pipe_info ); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_NOT_ALLOWED); + + }/* End of the Identity Info Memory Check */ + + + } /* End of Null Context Check */ + + return status; +} + + +/*! + * \brief Receives the HCI Response from the corresponding peripheral device. + * + * This function receives the HCI Command Response from the connected NFC + * Pheripheral device. + */ +static +NFCSTATUS +phHciNfc_Recv_LinkMgmt_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + phHciNfc_LinkMgmt_Info_t *p_link_mgmt_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t prev_cmd = ANY_GET_PARAMETER; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_link_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + p_link_mgmt_info = (phHciNfc_LinkMgmt_Info_t *) + psHciContext->p_link_mgmt_info ; + prev_cmd = p_link_mgmt_info->p_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_GET_PARAMETER: + { + status = phHciNfc_LinkMgmt_InfoUpdate(psHciContext, + (phHal_sHwReference_t *)pHwRef, + p_link_mgmt_info->p_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); + break; + } + case ANY_SET_PARAMETER: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + case ANY_OPEN_PIPE: + { + break; + } + case ANY_CLOSE_PIPE: + { + phOsalNfc_FreeMemory(p_link_mgmt_info->p_pipe_info); + p_link_mgmt_info->p_pipe_info = NULL; + psHciContext->p_pipe_list[PIPETYPE_STATIC_LINK] = NULL; + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + if( NULL != p_link_mgmt_info->p_pipe_info) + { + p_link_mgmt_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; + } + p_link_mgmt_info->link_cur_seq = p_link_mgmt_info->link_next_seq; + } + + } + return status; +} + + +static +NFCSTATUS +phHciNfc_LinkMgmt_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + phHal_sHwReference_t *pHwRef, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + phHciNfc_LinkMgmt_Info_t *p_link_mgmt_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t i=0; + if( (NULL == psHciContext) + || (NULL == pHwRef) + || (NULL == reg_value) + || (reg_length == 0) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_link_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_link_mgmt_info = (phHciNfc_LinkMgmt_Info_t *) + psHciContext->p_link_mgmt_info ; + if (REC_ERROR_INDEX == index) + { + HCI_PRINT_BUFFER("\tHost Controller REC Error Count :",reg_value,reg_length); + /* p_link_mgmt_info->hc_rec_error = reg_value[i] ; */ + for(i=0 ;(reg_length == REC_RETRY_LEN)&&(i < reg_length); i++) + { + p_link_mgmt_info->hc_rec_error |= + (uint16_t)(reg_value[i] << (BYTE_SIZE * i)); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } /* End of the Index Check */ + + } /* End of Context and the Link information validity check */ + + return status; +} diff --git a/libnfc-nxp/phHciNfc_LinkMgmt.h b/libnfc-nxp/phHciNfc_LinkMgmt.h new file mode 100644 index 0000000..54df378 --- /dev/null +++ b/libnfc-nxp/phHciNfc_LinkMgmt.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_LinkMgmt.h * +* \brief HCI Header for the Link Management Gate. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Tue Mar 30 09:32:13 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.5 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + + +#ifndef PHHCINFC_LINKMGMT_H +#define PHHCINFC_LINKMGMT_H + +/*@}*/ + + +/** + * \name HCI + * + * File: \ref phHciNfc_LinkMgmt.h + * + */ +/*@{*/ +#define PHHCINFC_LINK_MGMT_FILEREVISION "$Revision: 1.5 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_LINK_MGMT_FILEALIASES "$Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +/* +******************** Enumeration and Structure Definition ********************** +*/ + + + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_LinkMgmt_Initialise function creates and the opens Link + * Management Gate + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Link Mgmt Gate Initialisation is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ +extern +NFCSTATUS +phHciNfc_LinkMgmt_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_LinkMgmt_Release function closes the opened pipes between + * the Host Controller Device and the NFC Device. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Release of the Link Management gate + * resources are pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ +extern +NFCSTATUS +phHciNfc_LinkMgmt_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_LinkMgmt_Open function opens Link + * Management Gate + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Link Mgmt Gate open is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_LinkMgmt_Open( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +#endif + diff --git a/libnfc-nxp/phHciNfc_NfcIPMgmt.c b/libnfc-nxp/phHciNfc_NfcIPMgmt.c new file mode 100644 index 0000000..1afdba1 --- /dev/null +++ b/libnfc-nxp/phHciNfc_NfcIPMgmt.c @@ -0,0 +1,2201 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_NfcIPMgmt.c * +* \brief HCI NFCIP-1 management routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Tue Jun 8 09:32:31 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.33 $ * +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include +#include +#include + +#if defined (ENABLE_P2P) +#include +/* +****************************** Macro Definitions ******************************* +*/ +/* RF Error */ +#define NFCIP_RF_NO_ERROR 0x00U +#define NFCIP_STATUS_MAX_VALUE 0x01U + +/* Read and write to the below registry for initiator and target */ +#define NXP_NFCIP_MODE 0x01U +#define NXP_NFCIP_ATR_REQ 0x02U +#define NXP_NFCIP_ATR_RES 0x03U +#define NXP_NFCIP_PSL1 0x04U +#define NXP_NFCIP_PSL2 0x05U +#define NXP_NFCIP_DID 0x06U +#define NXP_NFCIP_NAD 0x07U +#define NXP_NFCIP_OPTIONS 0x08U +#define NXP_NFCIP_STATUS 0x09U +#define NXP_NFCIP_NFCID3I 0x0AU +#define NXP_NFCIP_NFCID3T 0x0BU +#define NXP_NFCIP_PARAM 0x0CU +#define NXP_NFCIP_MERGE 0x0DU + +/* command */ +#define NXP_NFCIP_ATTREQUEST 0x12U +#define NXP_NFCI_CONTINUE_ACTIVATION 0x13U + +/* Event */ +#define NXP_EVT_NFC_SND_DATA 0x01U +#define NXP_EVT_NFC_ACTIVATED 0x02U +#define NXP_EVT_NFC_DEACTIVATED 0x03U +#define NXP_EVT_NFC_RCV_DATA 0x04U +#define NXP_EVT_NFC_CONTINUE_MI 0x05U + +#define NFCIP_DATE_RATE_FACTOR 0x40U +#define NFCIP_DATE_RATE_SHIFT 0x06U +#define NFCIP_DATA_RATE_CALC(val) \ + ((((uint8_t)(val) >> NFCIP_DATE_RATE_SHIFT) + \ + 0x01U) * NFCIP_DATE_RATE_FACTOR) +#define NFCIP_COMM_INITIATOR_SHIFT 0x03 +#define NFCIP_COMM_FACTOR 0x03 +/* +*************************** Structure and Enumeration *************************** +*/ + +/* +*************************** Static Function Declaration ************************** +*/ +static +NFCSTATUS +phHciNfc_NfcIP_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); + +static +NFCSTATUS +phHciNfc_NfcIP_RecvData( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_NfcIP_Response( + phHciNfc_sContext_t *psHciContext, + phHciNfc_Pipe_Info_t *ppipe_info, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_NfcIP_Event( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_Initiator_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_Target_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_Initiator_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_Target_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); +/* +*************************** Function Definitions *************************** +*/ + +NFCSTATUS +phHciNfc_Initiator_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_NfcIP_Info_t *p_init_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if (NULL != psHciContext->p_nfcip_info) + { + status = NFCSTATUS_SUCCESS; + } + else if(( NULL == psHciContext->p_nfcip_info ) && + (phHciNfc_Allocate_Resource((void **)(&p_init_info), + sizeof(phHciNfc_NfcIP_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_nfcip_info = p_init_info; + p_init_info->nfcip_type = NFCIP_INVALID; + p_init_info->current_seq = NFCIP_INVALID_SEQUENCE; + p_init_info->next_seq = NFCIP_INVALID_SEQUENCE; + p_init_info->p_init_pipe_info = NULL; + p_init_info->p_tgt_pipe_info = NULL; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + return status; +} + +NFCSTATUS +phHciNfc_Initiator_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_nfcip_info ) + ) + { + phHciNfc_NfcIP_Info_t *p_init_info=NULL; + p_init_info = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + *ppipe_id = p_init_info->p_init_pipe_info->pipe.pipe_id ; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + +NFCSTATUS +phHciNfc_Initiator_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_init_info=NULL; + p_init_info = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + /* Update the pipe_id of the NFCIP-1 initiator Gate obtained from + the HCI Response */ + p_init_info->p_init_pipe_info = pPipeInfo; + p_init_info->p_init_pipe_info->pipe.pipe_id = pipeID; + /* Update the Response Receive routine of the NFCIP-1 initiator Gate */ + pPipeInfo->recv_resp = &phHciNfc_Recv_Initiator_Response; + /* Update the event Receive routine of the NFCIP-1 initiator Gate */ + pPipeInfo->recv_event = &phHciNfc_Recv_Initiator_Event; + } + return status; +} + +NFCSTATUS +phHciNfc_NfcIP_Presence_Check( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_nfcip_info) || + (NFCIP_INVALID == + ((phHciNfc_NfcIP_Info_t *)(psHciContext->p_nfcip_info))->nfcip_type)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = ((NFCIP_INITIATOR == p_nfcipinfo->nfcip_type)? + p_nfcipinfo->p_init_pipe_info : + p_nfcipinfo->p_tgt_pipe_info); + + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + uint16_t length = HCP_HEADER_LEN; + uint8_t pipeid = 0; + + pipeid = p_pipe_info->pipe.pipe_id; + psHciContext->tx_total = 0 ; + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,(uint8_t)HCP_CHAINBIT_DEFAULT, + (uint8_t) pipeid, (uint8_t)HCP_MSG_TYPE_COMMAND, + (uint8_t)NXP_NFCIP_ATTREQUEST); + + p_pipe_info->sent_msg_type = (uint8_t)HCP_MSG_TYPE_COMMAND; + p_pipe_info->prev_msg = (uint8_t)NXP_NFCIP_ATTREQUEST; + psHciContext->tx_total = length; + psHciContext->response_pending = (uint8_t)TRUE; + + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef); + p_pipe_info->prev_status = status; + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_Initiator_Response( + void *pContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)pContext ; + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse) + || (0 == length)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcip_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + + p_nfcip_info = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = p_nfcip_info->p_init_pipe_info; + if( NULL == p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_Recv_NfcIP_Response(psHciContext, + p_pipe_info, pResponse, + length); + if (NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + } + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_Initiator_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent) + || (0 == length)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_NfcIP_Info_t *p_nfcip_info=NULL; + phHciNfc_HCP_Message_t *message = NULL; + uint8_t instruction=0; + + p_nfcip_info = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &p_packet->msg.message; + /* Get the instruction bits from the Message Header */ + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + if (NXP_EVT_NFC_ACTIVATED == instruction) + { + p_nfcip_info->nfcip_type = NFCIP_INITIATOR; + psHciContext->host_rf_type = phHal_eNfcIP1_Initiator; + p_nfcip_info->rem_nfcip_tgt_info.RemDevType = phHal_eNfcIP1_Target; + } + + status = phHciNfc_Recv_NfcIP_Event(psHciContext, + pHwRef, pEvent, length); + } + return status; +} + +NFCSTATUS +phHciNfc_Target_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_NfcIP_Info_t *p_target_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if (NULL != psHciContext->p_nfcip_info) + { + status = NFCSTATUS_SUCCESS; + } + else if( + ( NULL == psHciContext->p_nfcip_info ) && + (phHciNfc_Allocate_Resource((void **)(&p_target_info), + sizeof(phHciNfc_NfcIP_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_nfcip_info = p_target_info; + p_target_info->nfcip_type = NFCIP_INVALID; + p_target_info->current_seq = NFCIP_INVALID_SEQUENCE; + p_target_info->next_seq = NFCIP_INVALID_SEQUENCE; + p_target_info->p_tgt_pipe_info = NULL; + p_target_info->p_tgt_pipe_info = NULL; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + return status; +} + +NFCSTATUS +phHciNfc_Target_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_nfcip_info ) + ) + { + phHciNfc_NfcIP_Info_t *p_target_info=NULL; + p_target_info = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + *ppipe_id = p_target_info->p_tgt_pipe_info->pipe.pipe_id; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + +NFCSTATUS +phHciNfc_Target_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_target_info=NULL; + p_target_info = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + /* Update the pipe_id of the NFCIP-1 target Gate obtained from + the HCI Response */ + p_target_info->p_tgt_pipe_info = pPipeInfo; + p_target_info->p_tgt_pipe_info->pipe.pipe_id = pipeID; + /* Update the Response Receive routine of the NFCIP-1 target Gate */ + pPipeInfo->recv_resp = &phHciNfc_Recv_Target_Response; + /* Update the event Receive routine of the NFCIP-1 target Gate */ + pPipeInfo->recv_event = &phHciNfc_Recv_Target_Event; + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_Target_Response( + void *pContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)pContext ; + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse) + || (0 == length)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcip_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + + p_nfcip_info = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = p_nfcip_info->p_tgt_pipe_info; + if( NULL == p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + status = phHciNfc_Recv_NfcIP_Response(psHciContext, + p_pipe_info, pResponse, + length); + if (NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_EmuMgmt_Update_Seq(psHciContext, + UPDATE_SEQ); + } + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_Target_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent) + || (0 == length)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_NfcIP_Info_t *p_nfcip_info=NULL; + phHciNfc_HCP_Message_t *message = NULL; + uint8_t instruction=0; + + p_nfcip_info = (phHciNfc_NfcIP_Info_t *)psHciContext->p_nfcip_info ; + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &p_packet->msg.message; + /* Get the instruction bits from the Message Header */ + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + if (NXP_EVT_NFC_ACTIVATED == instruction) + { + p_nfcip_info->nfcip_type = NFCIP_TARGET; + psHciContext->host_rf_type = phHal_eNfcIP1_Target; + p_nfcip_info->rem_nfcip_tgt_info.RemDevType = + phHal_eNfcIP1_Initiator; + } + status = phHciNfc_Recv_NfcIP_Event(psHciContext, + pHwRef, pEvent, length); + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_NfcIP_Response( + phHciNfc_sContext_t *psHciContext, + phHciNfc_Pipe_Info_t *ppipe_info, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + uint8_t prev_cmd = ANY_GET_PARAMETER; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + prev_cmd = ppipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_OPEN_PIPE: + { + HCI_PRINT("NFCIP-1 NFCIP open pipe complete\n"); + p_nfcipinfo->next_seq = NFCIP_NFCID3I; + break; + } + case ANY_CLOSE_PIPE: + { + HCI_PRINT("NFCIP-1 NFCIP close pipe complete\n"); + p_nfcipinfo->next_seq = NFCIP_NFCID3I; + break; + } + case ANY_GET_PARAMETER: + { + HCI_PRINT("NFCIP-1 NFCIP get parameter complete\n"); + if (length >= HCP_HEADER_LEN) + { + status = phHciNfc_NfcIP_InfoUpdate(psHciContext, + ppipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case ANY_SET_PARAMETER: + { + HCI_PRINT("NFCIP-1 NFCIP Parameter Set \n"); + p_nfcipinfo->next_seq = NFCIP_NFCID3I; + break; + } + case NXP_NFCI_CONTINUE_ACTIVATION: + case NXP_NFCIP_ATTREQUEST: + { + p_nfcipinfo->next_seq = NFCIP_NFCID3I; + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + + if( NFCSTATUS_SUCCESS == status ) + { + ppipe_info->prev_status = NFCSTATUS_SUCCESS; + p_nfcipinfo->current_seq = p_nfcipinfo->next_seq; + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_NfcIP_Event( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_HCP_Message_t *message = NULL; + phNfc_sCompletionInfo_t pCompInfo; + uint8_t instruction=0; + uint8_t type = 0; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &p_packet->msg.message; + /* Get the instruction bits from the Message Header */ + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + + switch(instruction) + { + case NXP_EVT_NFC_ACTIVATED: + { + HCI_PRINT("NFCIP-1 device discovered\n"); + + if (NFCIP_INITIATOR == p_nfcipinfo->nfcip_type) + { + pCompInfo.info = &(p_nfcipinfo->rem_nfcip_tgt_info); + type = NFC_NOTIFY_TARGET_DISCOVERED; + } + else + { + type = NFC_NOTIFY_DEVICE_ACTIVATED; + } + + if(length > HCP_HEADER_LEN) + { + HCI_DEBUG("NfcIP-1 activation mode : %d\n", pEvent[HCP_HEADER_LEN]); + /* Mode indicates in which mode the current activation + as be done + - 0x00: Passive mode + - 0x01: Active */ + p_nfcipinfo->activation_mode = pEvent[HCP_HEADER_LEN]; + } + pCompInfo.status = NFCSTATUS_SUCCESS; + /* Notify to the HCI Generic layer To Update the FSM */ + phHciNfc_Notify_Event(psHciContext, pHwRef, + type, &pCompInfo); + break; + } + case NXP_EVT_NFC_DEACTIVATED: + { + static phHal_sEventInfo_t event_info; + + event_info.eventHost = phHal_eHostController; + event_info.eventType = NFC_EVT_DEACTIVATED; + p_nfcipinfo->activation_mode = FALSE; + if (NFCIP_INITIATOR == p_nfcipinfo->nfcip_type) + { + p_nfcipinfo->rem_nfcip_tgt_info.RemDevType = + phHal_eNfcIP1_Target; + event_info.eventSource = phHal_eNfcIP1_Initiator; + } + else + { + p_nfcipinfo->rem_nfcip_tgt_info.RemDevType = + phHal_eNfcIP1_Initiator; + event_info.eventSource = phHal_eNfcIP1_Target; + } + /* Reset the sequence */ + p_nfcipinfo->current_seq = NFCIP_NFCID3I; + p_nfcipinfo->next_seq = NFCIP_NFCID3I; + + HCI_PRINT("NFCIP-1 Target Deactivated\n"); + phHciNfc_Notify_Event(psHciContext, pHwRef, + NFC_NOTIFY_DEVICE_DEACTIVATED, + &event_info); + break; + } + case NXP_EVT_NFC_RCV_DATA: + { + status = phHciNfc_NfcIP_RecvData(psHciContext, + pHwRef, + &pEvent[HCP_HEADER_LEN], + (length - HCP_HEADER_LEN)); + break; + } + case NXP_EVT_NFC_CONTINUE_MI: + { + /* psHciContext->response_pending = FALSE; */ + psHciContext->event_pending = FALSE; + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + } + + return status; +} + +static +NFCSTATUS +phHciNfc_NfcIP_RecvData( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t index = 0; + + if( (NULL == psHciContext) + || (NULL == pHwRef) + || (NULL == pResponse) + || (0 == length)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + phNfc_sTransactionInfo_t transInfo; + phHciNfc_NfcIP_Info_t *p_nfcipinfo = NULL; + uint8_t type = 0; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info; + HCI_PRINT("NFCIP-1 received bytes :"); + if (NFCIP_RF_NO_ERROR == pResponse[index]) + { + HCI_PRINT_BUFFER("device ", &pResponse[index], (length - index)); + transInfo.status = NFCSTATUS_SUCCESS; + index++; + if (TRUE == pResponse[index]) + { + /* Update the more information bit to the upper layer */ + transInfo.status = NFCSTATUS_MORE_INFORMATION; + } + index++; + + + transInfo.buffer = &pResponse[index]; + transInfo.length = (length - index); + type = (uint8_t)NFC_NOTIFY_RECV_EVENT; + } + else + { + HCI_PRINT("NFCIP-1 receive RF ERROR "); + p_nfcipinfo->activation_mode = FALSE; + type = (uint8_t)NFC_NOTIFY_RECV_EVENT; + transInfo.status = NFCSTATUS_RF_TIMEOUT; + transInfo.buffer = NULL; + transInfo.length = 0; + } + status = NFCSTATUS_PENDING; + /* Event NXP_EVT_NFC_RCV_DATA: so give received data to + the upper layer */ + phHciNfc_Notify_Event(psHciContext, pHwRef, + type, + &transInfo ); + } + return status; +} + +NFCSTATUS +phHciNfc_NfcIP_Send_Data ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_XchgInfo_t *sData + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == sData) || + (NULL == sData->tx_buffer) || (0 == sData->tx_length)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_nfcip_info) || + (NFCIP_INVALID == + ((phHciNfc_NfcIP_Info_t *)(psHciContext->p_nfcip_info))->nfcip_type)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = ((NFCIP_INITIATOR == p_nfcipinfo->nfcip_type)? + p_nfcipinfo->p_init_pipe_info : + p_nfcipinfo->p_tgt_pipe_info); + + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + uint16_t length = HCP_HEADER_LEN; + uint8_t pipeid = 0, + i = 0; + + HCI_PRINT_BUFFER("HCI NFCIP-1 Send Data: ", sData->tx_buffer, sData->tx_length); + + psHciContext->tx_total = 0 ; + pipeid = p_pipe_info->pipe.pipe_id; + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + hcp_message = &(hcp_packet->msg.message); + hcp_message->payload[i] = sData->params.nfc_info.more_info; + i++; + + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,(uint8_t)HCP_CHAINBIT_DEFAULT, + (uint8_t) pipeid, (uint8_t)HCP_MSG_TYPE_EVENT, + (uint8_t)NXP_EVT_NFC_SND_DATA); + + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, (uint8_t *)sData->tx_buffer, + (uint8_t)sData->tx_length); + + length =(uint16_t)(length + i + sData->tx_length); + + p_pipe_info->sent_msg_type = (uint8_t)HCP_MSG_TYPE_EVENT; + p_pipe_info->prev_msg = NXP_EVT_NFC_SND_DATA; + psHciContext->tx_total = length; + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef); +#if !defined (ENABLE_CONTINUE_MI) + if ((TRUE == sData->params.nfc_info.more_info) && + (NFCSTATUS_PENDING == status)) + { + /* If more information bit is set, then wait for the event + NXP_EVT_NFC_CONTINUE_MI */ + /* psHciContext->response_pending = TRUE; */ + psHciContext->event_pending = TRUE; + } +#endif /* #if defined (ENABLE_CONTINUE_MI) */ + p_pipe_info->prev_status = status; + } + } + return status; +} + +NFCSTATUS +phHciNfc_NfcIP_Info_Sequence ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef +#ifdef NOTIFY_REQD + , + uint8_t notify_reqd +#endif /* #ifdef NOTIFY_REQD */ + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_nfcip_info) || + (NFCIP_INVALID == + ((phHciNfc_NfcIP_Info_t *)(psHciContext->p_nfcip_info))-> + nfcip_type)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = ((NFCIP_INITIATOR == p_nfcipinfo->nfcip_type)? + p_nfcipinfo->p_init_pipe_info: + p_nfcipinfo->p_tgt_pipe_info); + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + switch(p_nfcipinfo->current_seq) + { + case NFCIP_NFCID3I: + { + p_pipe_info->reg_index = (uint8_t)NXP_NFCIP_NFCID3I; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + p_pipe_info->pipe.pipe_id, + ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_nfcipinfo->next_seq = NFCIP_NFCID3T; + } + break; + } + case NFCIP_NFCID3T: + { + p_pipe_info->reg_index = (uint8_t)NXP_NFCIP_NFCID3T; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + p_pipe_info->pipe.pipe_id, + ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_nfcipinfo->next_seq = NFCIP_PARAM; + } + break; + } + case NFCIP_PARAM: + { + p_pipe_info->reg_index = (uint8_t)NXP_NFCIP_PARAM; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + p_pipe_info->pipe.pipe_id, + ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_nfcipinfo->next_seq = NFCIP_ATR_INFO; + } + break; + } + case NFCIP_ATR_INFO: + { + p_pipe_info->reg_index = (uint8_t)((NFCIP_INITIATOR == + p_nfcipinfo->nfcip_type)? + NXP_NFCIP_ATR_RES : + NXP_NFCIP_ATR_REQ); + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + p_pipe_info->pipe.pipe_id, + ANY_GET_PARAMETER); + + if(NFCSTATUS_PENDING == status ) + { + p_nfcipinfo->next_seq = NFCIP_STATUS; + } + break; + } + case NFCIP_STATUS: + { + p_pipe_info->reg_index = (uint8_t)NXP_NFCIP_STATUS; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + p_pipe_info->pipe.pipe_id, + ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { +#ifdef NOTIFY_REQD + if(FALSE == notify_reqd) +#else /* #ifdef NOTIFY_REQD */ + if (NULL != psHciContext->p_target_info) +#endif /* #ifdef NOTIFY_REQD */ + { + p_nfcipinfo->next_seq = NFCIP_NFCID3I; + status = NFCSTATUS_SUCCESS; + } + else + { + p_nfcipinfo->next_seq = NFCIP_END_SEQUENCE; + } + } + break; + } + case NFCIP_END_SEQUENCE: + { + phHal_uRemoteDevInfo_t *rem_nfcipinfo = NULL; + + if (NULL != psHciContext->p_target_info) + { + /* This is given to user */ + rem_nfcipinfo = + &(psHciContext->p_target_info->RemoteDevInfo); + } + else + { + rem_nfcipinfo = + &(p_nfcipinfo->rem_nfcip_tgt_info.RemoteDevInfo); + } + + /* Update maximum frame length */ + rem_nfcipinfo->NfcIP_Info.MaxFrameLength = + p_nfcipinfo->max_frame_len; + + p_nfcipinfo->current_seq = NFCIP_NFCID3I; + p_nfcipinfo->next_seq = NFCIP_NFCID3I; + + rem_nfcipinfo->NfcIP_Info.Nfcip_Active = + p_nfcipinfo->activation_mode; + + if (NFCIP_INITIATOR == p_nfcipinfo->nfcip_type) + { + phNfc_sCompletionInfo_t CompInfo; + + p_nfcipinfo->rem_nfcip_tgt_info.RemDevType = + phHal_eNfcIP1_Target; + + /* Update initiator speed */ + rem_nfcipinfo->NfcIP_Info.Nfcip_Datarate = + (phHalNfc_eDataRate_t) + (p_nfcipinfo->initiator_speed); + + + /* Update ATR info */ + rem_nfcipinfo->NfcIP_Info.ATRInfo_Length = + p_nfcipinfo->atr_res_length; + (void)memcpy( + (void *)rem_nfcipinfo->NfcIP_Info.ATRInfo, + (void *)p_nfcipinfo->atr_res_info, + rem_nfcipinfo->NfcIP_Info.ATRInfo_Length); + + /* Update NFCID */ + rem_nfcipinfo->NfcIP_Info.NFCID_Length = + p_nfcipinfo->nfcid3i_length; + (void)memcpy( + (void *)rem_nfcipinfo->NfcIP_Info.NFCID, + (void *)p_nfcipinfo->nfcid3i, + rem_nfcipinfo->NfcIP_Info.NFCID_Length); + + CompInfo.status = status = NFCSTATUS_SUCCESS; + if (NULL != psHciContext->p_target_info) + { + CompInfo.info = &(psHciContext->p_target_info); + } + else + { + CompInfo.info = &(p_nfcipinfo->rem_nfcip_tgt_info); + } + /* Notify to the upper layer */ + phHciNfc_Tag_Notify(psHciContext, pHwRef, + NFC_NOTIFY_TARGET_DISCOVERED, + &CompInfo); + } + else + { + static phHal_sEventInfo_t event_info; + + p_nfcipinfo->rem_nfcip_tgt_info.RemDevType = + phHal_eNfcIP1_Initiator; + + /* Update target speed */ + rem_nfcipinfo->NfcIP_Info.Nfcip_Datarate = + (phHalNfc_eDataRate_t) + (p_nfcipinfo->target_speed); + /* Update ATR info */ + rem_nfcipinfo->NfcIP_Info.ATRInfo_Length = + p_nfcipinfo->atr_req_length; + (void)memcpy( + (void *)rem_nfcipinfo->NfcIP_Info.ATRInfo, + (void *)p_nfcipinfo->atr_req_info, + rem_nfcipinfo->NfcIP_Info.ATRInfo_Length); + + /* Update NFCID */ + rem_nfcipinfo->NfcIP_Info.NFCID_Length = + p_nfcipinfo->nfcid3t_length; + (void)memcpy( + (void *)rem_nfcipinfo->NfcIP_Info.NFCID, + (void *)p_nfcipinfo->nfcid3t, + rem_nfcipinfo->NfcIP_Info.NFCID_Length); + + event_info.eventHost = phHal_eHostController; + event_info.eventType = NFC_EVT_ACTIVATED; + event_info.eventSource = phHal_eNfcIP1_Target; + event_info.eventInfo.pRemoteDevInfo = + &(p_nfcipinfo->rem_nfcip_tgt_info); + + phHciNfc_Target_Select_Notify((void *)psHciContext, + pHwRef, + NFC_NOTIFY_EVENT, + &(event_info)); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_NfcIP_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_NfcIP_Info_t *p_nfcipinfo = NULL; + phHal_sNfcIPInfo_t *p_rem_nfcipinfo = NULL; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *)(psHciContext->p_nfcip_info ); + p_rem_nfcipinfo = &(p_nfcipinfo->rem_nfcip_tgt_info.RemoteDevInfo.NfcIP_Info); + + + switch(index) + { + case NXP_NFCIP_ATR_RES: + { + if (reg_length <= NFCIP_ATR_MAX_LENGTH) + { + /* Remote device info provided by the user */ + + HCI_PRINT_BUFFER("\tNFCIP ATR_RES", reg_value, reg_length); + + p_rem_nfcipinfo->ATRInfo_Length = + p_nfcipinfo->atr_res_length = reg_length; + + (void)memcpy((void *)p_rem_nfcipinfo->ATRInfo, + (void *)reg_value, + p_rem_nfcipinfo->ATRInfo_Length); + + (void)memcpy((void *)p_nfcipinfo->atr_res_info, + (void *)reg_value, + p_nfcipinfo->atr_res_length); + if (NULL != psHciContext->p_target_info) + { + phHal_sNfcIPInfo_t *p_remtgt_info = NULL; + /* This is given to user */ + p_remtgt_info = + &(psHciContext->p_target_info->RemoteDevInfo.NfcIP_Info); + p_remtgt_info->ATRInfo_Length = reg_length; + (void)memcpy((void *)p_remtgt_info->ATRInfo, + (void *)reg_value, + p_remtgt_info->ATRInfo_Length); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_NFCIP_STATUS: + { + if (sizeof(*reg_value) == reg_length) +#ifdef STATUS_BUFFER_CHECK + && (*reg_value <= NFCIP_STATUS_MAX_VALUE)) +#endif /* #ifdef STATUS_ERROR */ + { + HCI_PRINT_BUFFER("\tNFCIP STATUS", reg_value, reg_length); + p_nfcipinfo->linkstatus = *reg_value; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_NFCIP_NFCID3I: + { + if (reg_length <= NFCIP_NFCID_LENGTH) + { + HCI_PRINT_BUFFER("\tNFCIP NFCID3I", reg_value, reg_length); + p_nfcipinfo->nfcid3i_length = + p_rem_nfcipinfo->NFCID_Length = reg_length; + (void)memcpy((void *)p_rem_nfcipinfo->NFCID, + (void *)reg_value, + p_rem_nfcipinfo->NFCID_Length); + (void)memcpy((void *)p_nfcipinfo->nfcid3i, + (void *)reg_value, + reg_length); + if ((NULL != psHciContext->p_target_info) && + (NFCIP_INITIATOR == p_nfcipinfo->nfcip_type)) + { + phHal_sNfcIPInfo_t *p_remtgt_info = NULL; + /* This is given to user */ + p_remtgt_info = + &(psHciContext->p_target_info->RemoteDevInfo.NfcIP_Info); + p_remtgt_info->NFCID_Length = reg_length; + (void)memcpy((void *)p_remtgt_info->NFCID, + (void *)reg_value, + p_remtgt_info->NFCID_Length); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_NFCIP_NFCID3T: + { + if (reg_length <= NFCIP_NFCID_LENGTH) + { + HCI_PRINT_BUFFER("\tNFCIP NFCID3T", reg_value, reg_length); + p_nfcipinfo->nfcid3t_length = + p_rem_nfcipinfo->NFCID_Length = reg_length; + (void)memcpy((void *)p_rem_nfcipinfo->NFCID, + (void *)reg_value, + p_rem_nfcipinfo->NFCID_Length); + (void)memcpy((void *)p_nfcipinfo->nfcid3t, + (void *)reg_value, + reg_length); + if ((NULL != psHciContext->p_target_info) && + (NFCIP_TARGET == p_nfcipinfo->nfcip_type)) + { + phHal_sNfcIPInfo_t *p_remtgt_info = NULL; + /* This is given to user */ + p_remtgt_info = + &(psHciContext->p_target_info->RemoteDevInfo.NfcIP_Info); + p_remtgt_info->NFCID_Length = reg_length; + (void)memcpy((void *)p_remtgt_info->NFCID, + (void *)reg_value, + p_remtgt_info->NFCID_Length); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_NFCIP_PARAM: + { + if (sizeof(*reg_value) == reg_length) + { + HCI_PRINT_BUFFER("\tNFCIP PARAMS", reg_value, reg_length); + p_nfcipinfo->initiator_speed = (phHciNfc_eP2PSpeed_t) + ((*reg_value >> NFCIP_COMM_INITIATOR_SHIFT) + & NFCIP_COMM_FACTOR); + if (p_nfcipinfo->nfcip_type == NFCIP_INITIATOR) { + switch(p_nfcipinfo->initiator_speed) { + case phNfc_eDataRate_106: + ALOGI("I'm P2P %s Initiator @ 106 kb/s", p_nfcipinfo->activation_mode ? "Active" : "Passive"); + break; + case phNfc_eDataRate_212: + ALOGI("I'm P2P %s Initiator @ 212 kb/s", p_nfcipinfo->activation_mode ? "Active" : "Passive"); + break; + case phNfc_eDataRate_424: + ALOGI("I'm P2P %s Initiator @ 424 kb/s", p_nfcipinfo->activation_mode ? "Active" : "Passive"); + break; + default: + break; + } + } + p_nfcipinfo->target_speed = (phHciNfc_eP2PSpeed_t) + (*reg_value & NFCIP_COMM_FACTOR); + if (p_nfcipinfo->nfcip_type == NFCIP_TARGET) { + switch(p_nfcipinfo->target_speed) { + case phNfc_eDataRate_106: + ALOGI("I'm P2P %s Target @ 106 kb/s", p_nfcipinfo->activation_mode ? "Active" : "Passive"); + break; + case phNfc_eDataRate_212: + ALOGI("I'm P2P %s Target @ 212 kb/s", p_nfcipinfo->activation_mode ? "Active" : "Passive"); + break; + case phNfc_eDataRate_424: + ALOGI("I'm P2P %s Target @ 424 kb/s", p_nfcipinfo->activation_mode ? "Active" : "Passive"); + break; + default: + break; + } + } + p_nfcipinfo->max_frame_len = NFCIP_DATA_RATE_CALC(*reg_value); + + if (p_nfcipinfo->max_frame_len > NFCIP_MAX_DEP_REQ_HDR_LEN) + { + p_nfcipinfo->max_frame_len -= NFCIP_MAX_DEP_REQ_HDR_LEN; + + if (NULL != psHciContext->p_target_info) + { + phHal_sNfcIPInfo_t *p_remtgt_info = NULL; + /* This is given to user */ + p_remtgt_info = + &(psHciContext->p_target_info->RemoteDevInfo.NfcIP_Info); + p_remtgt_info->MaxFrameLength = p_nfcipinfo->max_frame_len; + p_remtgt_info->Nfcip_Datarate = (phHalNfc_eDataRate_t) + p_nfcipinfo->initiator_speed; + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_NFCIP_MODE: + { + if (sizeof(*reg_value) == reg_length) + { + HCI_PRINT_BUFFER("\tNFCIP MODE", reg_value, reg_length); + p_nfcipinfo->nfcip_mode = *reg_value; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_NFCIP_ATR_REQ: + { + if (reg_length <= NFCIP_ATR_MAX_LENGTH) + { + HCI_PRINT_BUFFER("\tNFCIP ATR_REQ", reg_value, reg_length); + p_rem_nfcipinfo->ATRInfo_Length = + p_nfcipinfo->atr_req_length = reg_length; + (void)memcpy((void *)p_rem_nfcipinfo->ATRInfo, + (void *)reg_value, + p_rem_nfcipinfo->ATRInfo_Length); + (void)memcpy((void *)p_nfcipinfo->atr_req_info, + (void *)reg_value, + p_nfcipinfo->atr_req_length); + if (NULL != psHciContext->p_target_info) + { + phHal_sNfcIPInfo_t *p_remtgt_info = NULL; + /* This is given to user */ + p_remtgt_info = + &(psHciContext->p_target_info->RemoteDevInfo.NfcIP_Info); + p_remtgt_info->NFCID_Length = reg_length; + (void)memcpy((void *)p_remtgt_info->ATRInfo, + (void *)reg_value, + p_remtgt_info->ATRInfo_Length); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_NFCIP_PSL1: + { + if (sizeof(*reg_value) == reg_length) + { + HCI_PRINT_BUFFER("\tNFCIP PSL1", reg_value, reg_length); + p_nfcipinfo->psl1 = *reg_value; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_NFCIP_PSL2: + { + if (sizeof(*reg_value) == reg_length) + { + HCI_PRINT_BUFFER("\tNFCIP PSL2", reg_value, reg_length); + p_nfcipinfo->psl2 = *reg_value; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_NFCIP_DID: + { + if (sizeof(*reg_value) == reg_length) + { + HCI_PRINT_BUFFER("\tNFCIP DID", reg_value, reg_length); + p_nfcipinfo->did = *reg_value; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_NFCIP_NAD: + { + if (sizeof(*reg_value) == reg_length) + { + HCI_PRINT_BUFFER("\tNFCIP NAD", reg_value, reg_length); + p_nfcipinfo->nad = *reg_value; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_NFCIP_OPTIONS: + { + if (sizeof(*reg_value) == reg_length) + { + HCI_PRINT_BUFFER("\tNFCIP OPTIONS", reg_value, reg_length); + p_nfcipinfo->options = *reg_value; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + return status; +} + + +NFCSTATUS +phHciNfc_NfcIP_SetMode( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype, + uint8_t nfcip_mode + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef) || + (nfcip_mode > (uint8_t)NFCIP_MODE_ALL)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if (NFCIP_INVALID == nfciptype) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = ((NFCIP_INITIATOR == nfciptype)? + p_nfcipinfo->p_init_pipe_info: + p_nfcipinfo->p_tgt_pipe_info); + + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + pipeid = p_pipe_info->pipe.pipe_id ; + p_pipe_info->reg_index = (uint8_t)NXP_NFCIP_MODE; + + p_pipe_info->param_info = &nfcip_mode; + p_pipe_info->param_length = sizeof(uint8_t); + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + } + } + return status; +} + +NFCSTATUS +phHciNfc_NfcIP_SetNAD( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype, + uint8_t nad + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if (NFCIP_INVALID == nfciptype) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = ((NFCIP_INITIATOR == nfciptype)? + p_nfcipinfo->p_init_pipe_info: + p_nfcipinfo->p_tgt_pipe_info); + + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + pipeid = p_pipe_info->pipe.pipe_id ; + p_pipe_info->reg_index = (uint8_t)NXP_NFCIP_NAD; + + p_pipe_info->param_info = &nad; + p_pipe_info->param_length = sizeof(uint8_t); + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + } + } + return status; +} + +NFCSTATUS +phHciNfc_NfcIP_SetDID( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t did + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = p_nfcipinfo->p_init_pipe_info; + + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + pipeid = p_pipe_info->pipe.pipe_id ; + p_pipe_info->reg_index = (uint8_t)NXP_NFCIP_DID; + + p_pipe_info->param_info = &did; + p_pipe_info->param_length = sizeof(uint8_t); + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + } + } + return status; +} + +NFCSTATUS +phHciNfc_NfcIP_SetOptions( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype, + uint8_t nfcip_options + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if (NFCIP_INVALID == nfciptype) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = ((NFCIP_INITIATOR == p_nfcipinfo->nfcip_type)? + p_nfcipinfo->p_init_pipe_info: + p_nfcipinfo->p_tgt_pipe_info); + pipeid = p_pipe_info->pipe.pipe_id ; + p_pipe_info->reg_index = (uint8_t)NXP_NFCIP_OPTIONS; + + p_pipe_info->param_info = &nfcip_options; + p_pipe_info->param_length = sizeof(uint8_t); + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + } + return status; +} + +NFCSTATUS +phHciNfc_NfcIP_SetATRInfo( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype, + phHal_sNfcIPCfg_t *atr_info + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == atr_info) || + (atr_info->generalBytesLength > NFCIP_ATR_MAX_LENGTH)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if (NFCIP_INVALID == nfciptype) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = ((NFCIP_INITIATOR == nfciptype)? + p_nfcipinfo->p_init_pipe_info: + p_nfcipinfo->p_tgt_pipe_info); + + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + pipeid = p_pipe_info->pipe.pipe_id ; + p_pipe_info->reg_index = (uint8_t)((NFCIP_INITIATOR == nfciptype)? + NXP_NFCIP_ATR_REQ : + NXP_NFCIP_ATR_RES); + + p_pipe_info->param_info = atr_info->generalBytes; + p_pipe_info->param_length = (uint8_t) + atr_info->generalBytesLength; + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + } + } + return status; +} + +NFCSTATUS +phHciNfc_NfcIP_SetPSL1( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t psl1 + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = p_nfcipinfo->p_init_pipe_info; + + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + pipeid = p_pipe_info->pipe.pipe_id ; + p_pipe_info->reg_index = (uint8_t)NXP_NFCIP_PSL1; + + p_pipe_info->param_info = &psl1; + p_pipe_info->param_length = sizeof(uint8_t); + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + } + } + return status; +} + +NFCSTATUS +phHciNfc_NfcIP_SetPSL2( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t psl2 + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = p_nfcipinfo->p_init_pipe_info; + + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + pipeid = p_pipe_info->pipe.pipe_id ; + p_pipe_info->reg_index = (uint8_t)NXP_NFCIP_PSL2; + + p_pipe_info->param_info = &psl2; + p_pipe_info->param_length = sizeof(uint8_t); + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + } + } + return status; +} + +NFCSTATUS +phHciNfc_NfcIP_GetStatus( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if (NFCIP_INVALID == nfciptype) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = ((NFCIP_INITIATOR == nfciptype)? + p_nfcipinfo->p_init_pipe_info : + p_nfcipinfo->p_tgt_pipe_info); + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + pipeid = p_pipe_info->pipe.pipe_id ; + p_pipe_info->reg_index = (uint8_t)NXP_NFCIP_STATUS; + + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + } + } + return status; +} + +NFCSTATUS +phHciNfc_NfcIP_GetParam( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if (NFCIP_INVALID == nfciptype) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_pipe_info = ((NFCIP_INITIATOR == nfciptype)? + p_nfcipinfo->p_init_pipe_info : + p_nfcipinfo->p_tgt_pipe_info); + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + pipeid = p_pipe_info->pipe.pipe_id ; + p_pipe_info->reg_index = (uint8_t)NXP_NFCIP_PARAM; + + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + } + } + return status; +} + +NFCSTATUS +phHciNfc_Initiator_Cont_Activate ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo = NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + p_nfcipinfo->nfcip_type = NFCIP_INITIATOR; + psHciContext->host_rf_type = phHal_eNfcIP1_Initiator; + p_pipe_info = p_nfcipinfo->p_init_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + uint16_t length = HCP_HEADER_LEN; + uint8_t pipeid = 0; + + pipeid = p_pipe_info->pipe.pipe_id; + psHciContext->tx_total = 0 ; + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,(uint8_t)HCP_CHAINBIT_DEFAULT, + (uint8_t) pipeid, (uint8_t)HCP_MSG_TYPE_COMMAND, + (uint8_t)NXP_NFCI_CONTINUE_ACTIVATION); + + p_pipe_info->sent_msg_type = (uint8_t)HCP_MSG_TYPE_COMMAND; + p_pipe_info->prev_msg = (uint8_t)NXP_NFCI_CONTINUE_ACTIVATION; + psHciContext->tx_total = length; + psHciContext->response_pending = (uint8_t)TRUE; + + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef); + p_pipe_info->prev_status = status; + } + } + return status; +} + + +NFCSTATUS +phHciNfc_NfcIP_GetATRInfo ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if (NFCIP_INVALID == nfciptype) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *p_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + + p_pipe_info = ((NFCIP_INITIATOR == nfciptype)? + p_nfcipinfo->p_init_pipe_info : + p_nfcipinfo->p_tgt_pipe_info); + + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_pipe_info->reg_index = (uint8_t)((NFCIP_INITIATOR == nfciptype)? + NXP_NFCIP_ATR_RES : + NXP_NFCIP_ATR_REQ); + pipeid = p_pipe_info->pipe.pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + } + } + return status; +} + +NFCSTATUS +phHciNfc_NfcIP_SetMergeSak( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t sak_value + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef) || + (sak_value > (uint8_t)TRUE)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_nfcip_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_NfcIP_Info_t *ps_nfcipinfo=NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info=NULL; + uint8_t pipeid = 0; + + ps_nfcipinfo = (phHciNfc_NfcIP_Info_t *) + psHciContext->p_nfcip_info ; + ps_pipe_info = ps_nfcipinfo->p_tgt_pipe_info; + + if(NULL == ps_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + pipeid = ps_pipe_info->pipe.pipe_id ; + ps_pipe_info->reg_index = (uint8_t)NXP_NFCIP_MERGE; + + ps_pipe_info->param_info = &sak_value; + ps_pipe_info->param_length = sizeof(uint8_t); + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + } + } + return status; +} + +#endif /* #if defined (ENABLE_P2P) */ + diff --git a/libnfc-nxp/phHciNfc_NfcIPMgmt.h b/libnfc-nxp/phHciNfc_NfcIPMgmt.h new file mode 100644 index 0000000..00e4b7b --- /dev/null +++ b/libnfc-nxp/phHciNfc_NfcIPMgmt.h @@ -0,0 +1,699 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_NfcIPMgmt.h * +* \brief HCI NFCIP-1 Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Thu Jun 11 18:45:00 2009 $ * +* $Author: ing02260 $ * +* $Revision: 1.14 $ * +* $Aliases: NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + +#ifndef PHHCINFC_NFCIPMGMT_H +#define PHHCINFC_NFCIPMGMT_H + +/*@}*/ + + +/** +* \name HCI +* +* File: \ref phHciNfc_NfcIPMgmt.h +* +*/ +/*@{*/ +#define PHHCINFC_NFCIP1MGMT_FILEREVISION "$Revision: 1.14 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_NFCIP1MGMT_FILEALIASES "$Aliases: NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +/* Commands exposed to the upper layer */ + + +/* +******************** Enumeration and Structure Definition ********************** +*/ +/* LENGTH definition */ +#define NFCIP_ATR_MAX_LENGTH PHHAL_MAX_ATR_LENGTH +#define NFCIP_NFCID_LENGTH PHHAL_MAX_UID_LENGTH +#define NFCIP_MAX_DEP_REQ_HDR_LEN 0x05 + +typedef enum phHciNfc_eNfcIPType{ + NFCIP_INVALID = 0x00U, + NFCIP_INITIATOR, + NFCIP_TARGET +}phHciNfc_eNfcIPType_t; + +typedef enum phHciNfc_NfcIP_Seq{ + NFCIP_INVALID_SEQUENCE = 0x00U, + NFCIP_ATR_INFO, + NFCIP_STATUS, + NFCIP_NFCID3I, + NFCIP_NFCID3T, + NFCIP_PARAM, + NFCIP_END_SEQUENCE +} phHciNfc_NfcIP_Seq_t; + +typedef enum phHciNfc_eP2PSpeed{ + NFCIP_SPEED_106 = 0x00U, + NFCIP_SPEED_212, + NFCIP_SPEED_424, + NFCIP_SPEED_848, + NFCIP_SPEED_1696, + NFCIP_SPEED_3392, + NFCIP_SPEED_6784, + NFCIP_SPEED_RFU +}phHciNfc_eP2PSpeed_t; + +typedef enum phHciNfc_eNfcIPMode{ + NFCIP_MODE_PAS_106 = 0x01U, + NFCIP_MODE_PAS_212 = 0x02U, + NFCIP_MODE_PAS_424 = 0x04U, + NFCIP_MODE_ACT_106 = 0x08U, + NFCIP_MODE_ACT_212 = 0x10U, + NFCIP_MODE_ACT_424 = 0x20U, + NFCIP_MODE_ALL = 0x3FU +}phHciNfc_eNfcIPMode_t; + +typedef struct phHciNfc_NfcIP_Info +{ + phHciNfc_NfcIP_Seq_t current_seq; + phHciNfc_NfcIP_Seq_t next_seq; + phHciNfc_eNfcIPType_t nfcip_type; + phHciNfc_Pipe_Info_t *p_init_pipe_info; + phHciNfc_Pipe_Info_t *p_tgt_pipe_info; + phHal_sRemoteDevInformation_t rem_nfcip_tgt_info; + /* ATR_RES = General bytes length, Max length = 48 bytes for + host = target */ + uint8_t atr_res_info[NFCIP_ATR_MAX_LENGTH]; + uint8_t atr_res_length; + /* ATR_REQ = General bytes length, Max length = 48 bytes for + host = initiator */ + uint8_t atr_req_info[NFCIP_ATR_MAX_LENGTH]; + uint8_t atr_req_length; + /* Contains the current status of the NFCIP-1 link + when communication has been set. + 0x00 -> data is expected from the host + 0x01 -> data is expected from the RF side */ + uint8_t linkstatus; + /* Contains the random NFCID3I conveyed with the ATR_REQ. + always 10 bytes length */ + uint8_t nfcid3i_length; + uint8_t nfcid3i[NFCIP_NFCID_LENGTH]; + /* Contains the random NFCID3T conveyed with the ATR_RES. + always 10 bytes length */ + uint8_t nfcid3t_length; + uint8_t nfcid3t[NFCIP_NFCID_LENGTH]; + /* Contains the current parameters of the NFCIP-1 link when + communication has been set. + - bits 0 to 2: data rate target to initiator + - bits 3 to 5: data rate initiator to target + 0 -> Divisor equal to 1 + 1 -> Divisor equal to 2 + 2 -> Divisor equal to 4 + 3 -> Divisor equal to 8 + 4 -> Divisor equal to 16 + 5 -> Divisor equal to 32 + 6 -> Divisor equal to 64 + 7 -> RFU + - bits 6 to 7: maximum frame length + 0 -> 64 bytes + 1 -> 128 bytes + 2 -> 192 bytes + 3 -> 256 bytes */ + phHciNfc_eP2PSpeed_t initiator_speed; + phHciNfc_eP2PSpeed_t target_speed; + uint16_t max_frame_len; + /* Supported modes */ + uint8_t nfcip_mode; + uint8_t psl1; + uint8_t psl2; + uint8_t nad; + uint8_t did; + uint8_t options; + uint8_t activation_mode; +}phHciNfc_NfcIP_Info_t; + + +/* +*********************** Function Prototype Declaration ************************* +*/ +/*! +* \brief Allocates the resources of NFCIP-1 initiator management gate. +* +* This function Allocates the resources of the NFCIP-1 initiator management +* gate Information Structure. +* +*/ +extern +NFCSTATUS +phHciNfc_Initiator_Init_Resources( + phHciNfc_sContext_t *psHciContext + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Initiator_Get_PipeID function gives the pipe id of the NFCIP-1 +* initiator gate +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_Initiator_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Initiator_Update_PipeInfo function updates the pipe_id of the NFCIP-1 +* initiator gate management Structure. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pipeID pipeID of the NFCIP-1 initiator gate +* \param[in] pPipeInfo Update the pipe Information of the NFCIP-1 +* initiator gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ + +extern +NFCSTATUS +phHciNfc_Initiator_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Send_Initiator_Command function executes the command sent by the +* upper layer, depending on the commands defined. +* +* \param[in] psContext psContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_Presence_Check( + phHciNfc_sContext_t *psContext, + void *pHwRef + ); + +/*! +* \brief Allocates the resources of NFCIP-1 target management gate. +* +* This function Allocates the resources of the NFCIP-1 target management +* gate Information Structure. +* +*/ +extern +NFCSTATUS +phHciNfc_Target_Init_Resources( + phHciNfc_sContext_t *psHciContext + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Target_Get_PipeID function gives the pipe id of the NFCIP-1 +* target gate +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_Target_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Target_Update_PipeInfo function updates the pipe_id of the NFCIP-1 +* target gate management Structure. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pipeID pipeID of the NFCIP-1 target gate +* \param[in] pPipeInfo Update the pipe Information of the NFCIP-1 +* target gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ + +extern +NFCSTATUS +phHciNfc_Target_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_Info_Sequence function executes the sequence of operations, to +* get ATR_RES, NFCID3I, NFCID3T, PARAMS etc. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] notify_reqd if TRUE continue till END_SEQUENCE, else +* stop the sequence +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_Info_Sequence ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef +#ifdef NOTIFY_REQD + , + uint8_t notify_reqd +#endif /* #ifdef NOTIFY_REQD */ + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_SetMode function sets the value for NFCIP-1 modes +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] nfciptype Specifies initiator or target +* \param[in] nfcip_mode nfcip_mode is the supported mode +* information +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_SetMode( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype, + uint8_t nfcip_mode + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_SetNAD function sets the NAD value +* +* \param[in] psHciContext pContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] nfciptype Specifies initiator or target +* \param[in] nad Node address, this will be used as +* logical address of the initiator (b4 to b7) +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_SetNAD( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype, + uint8_t nad + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_SetDID function sets the DID value for the initiator +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] did Device ID +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_SetDID( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t did + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_SetOptions function sets the different options depending on +* the host type (initiator or target) like PSL, NAD and DID +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] nfciptype Specifies initiator or target +* \param[in] nfcip_options specifies enabled options PSL, NAD and DID +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_SetOptions( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype, + uint8_t nfcip_options + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_SetATRInfo function sets the general byte information +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] nfciptype Specifies initiator or target +* \param[in] atr_info contains the general bytes of the ATR_REQ +* (initiator) or ATR_RES (target) (max size = +* 48 bytes) +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_SetATRInfo( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype, + phHal_sNfcIPCfg_t *atr_info + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_SetPSL1 function sets the BRS byte of PSL_REQ +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] psl1 specifies the BRS byte of PSL_REQ +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_SetPSL1( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t psl1 + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_SetPSL2 function sets the BRS byte of PSL_REQ +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] psl2 specifies the FSL byte of PSL_REQ +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_SetPSL2( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t psl2 + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_GetStatus function receives the present status of the +* NFCIP-1 link, when communication has been set. +* If 0x00 is the status, then it means data is expected from the host +* If 0x01 is the status, then it means data is expected from the RF side +* Other status values are error +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] nfciptype Specifies initiator or target +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_GetStatus( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_GetStatus function receives the current parameters of the +* NFCIP-1 link, when communication has been set. +* - bits 0 to 2: data rate target to initiator +* - bits 3 to 5: data rate initiator to target +* 0 -> Divisor equal to 1 +* 1 -> Divisor equal to 2 +* 2 -> Divisor equal to 4 +* 3 -> Divisor equal to 8 +* 4 -> Divisor equal to 16 +* 5 -> Divisor equal to 32 +* 6 -> Divisor equal to 64 +* 7 -> RFU +* - bits 6 to 7: maximum frame length +* 0 -> 64 bytes +* 1 -> 128 bytes +* 2 -> 192 bytes +* 3 -> 256 bytes +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] nfciptype Specifies initiator or target +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_GetParam( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_Send_Data function sends data using the SEND_DATA event +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] sData Data to be sent to the lower layer +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_Send_Data ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_XchgInfo_t *sData + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Initiator_Cont_Activate function to activate the NFCIP initiator +* +* \param[in] pContext pContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_Initiator_Cont_Activate ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_GetATRInfo function is to get ATR information +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] nfciptype Specifies initiator or target +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_GetATRInfo ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_eNfcIPType_t nfciptype + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_NfcIP_SetMergeSak function is to indicate, if the NFCIP-1 +* target feature must be merged with Type A RF card feature in order to +* present only one type A target (set of the related bit in SAK to +* reflect the ISO18092 compliancy). +* 0x00 -> disabled +* 0x01 -> enabled +* Others values are RFU : error code returned as NFCSTATUS_INVALID_PARAMETER +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] sak_value Specifies initiator or target +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_NfcIP_SetMergeSak( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t sak_value + ); +#endif /* #ifndef PHHCINFC_NFCIPMGMT_H */ + + diff --git a/libnfc-nxp/phHciNfc_Pipe.c b/libnfc-nxp/phHciNfc_Pipe.c new file mode 100644 index 0000000..e7edc50 --- /dev/null +++ b/libnfc-nxp/phHciNfc_Pipe.c @@ -0,0 +1,1122 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file hHciNfc_PipeMgmt.c * +* \brief HCI Pipe Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Tue Aug 18 10:12:39 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.42 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + + +/* +***************************** Header File Inclusion **************************** +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef TYPE_B +#include +#endif +#ifdef TYPE_FELICA +#include +#endif +#ifdef TYPE_JEWEL +#include +#endif +#ifdef TYPE_ISO15693 +#include +#endif +#ifdef ENABLE_P2P +#include +#endif +#ifdef HOST_EMULATION +#include +#include +#endif +#include +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +/* +*************************** Structure and Enumeration *************************** +*/ +static phHciNfc_GateID_t host_gate_list[] = { + phHciNfc_IdentityMgmtGate, + phHciNfc_PN544MgmtGate, + phHciNfc_PollingLoopGate, + phHciNfc_RFReaderAGate, +#ifdef TYPE_B + phHciNfc_RFReaderBGate, +#endif + +#ifdef TYPE_FELICA + phHciNfc_RFReaderFGate, +#endif + +#ifdef TYPE_JEWEL + phHciNfc_JewelReaderGate, +#endif + +#ifdef TYPE_ISO15693 + phHciNfc_ISO15693Gate, +#endif + +#ifdef ENABLE_P2P + phHciNfc_NFCIP1InitRFGate, + phHciNfc_NFCIP1TargetRFGate, +#endif + phHciNfc_NfcWIMgmtGate, + phHciNfc_SwpMgmtGate, +#if defined(HOST_EMULATION) && ( NXP_UICC_CE_RIGHTS < 0x01 ) + phHciNfc_CETypeAGate, + phHciNfc_CETypeBGate, +#endif + phHciNfc_UnknownGate +}; + +/* +*************************** Static Function Declaration ************************** +*/ + +static +NFCSTATUS +phHciNfc_Create_Pipe( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_Gate_Info_t *destination, + phHciNfc_Pipe_Info_t **ppPipeHandle + ); + + +/* +*************************** Function Definitions *************************** +*/ + + +/*! + * \brief Creation of the Pipe + * + * This function creates the pipe between a source host's gate and destination + * host's gate + * + */ + +static +NFCSTATUS +phHciNfc_Create_Pipe( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_Gate_Info_t *destination, + phHciNfc_Pipe_Info_t **ppPipeHandle + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + *ppPipeHandle = (phHciNfc_Pipe_Info_t *) + phOsalNfc_GetMemory( sizeof(phHciNfc_Pipe_Info_t) ); + + if(NULL != *ppPipeHandle) + { + /* The Source Host is the Terminal Host */ + (*ppPipeHandle)->pipe.source.host_id = (uint8_t) phHciNfc_TerminalHostID; + + /* The Source Gate is same as the Destination Gate */ + (*ppPipeHandle)->pipe.source.gate_id = + ((phHciNfc_Gate_Info_t *)destination)->gate_id; + (*ppPipeHandle)->pipe.dest.host_id = + ((phHciNfc_Gate_Info_t *)destination)->host_id; + (*ppPipeHandle)->pipe.dest.gate_id = + ((phHciNfc_Gate_Info_t *)destination)->gate_id; + + /* if( hciMode_Override == psHciContext->hci_mode ) */ + { + /* The Pipe ID is unknown until it is assigned */ + (*ppPipeHandle)->pipe.pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + + status = phHciNfc_Send_Admin_Cmd( psHciContext, pHwRef, + ADM_CREATE_PIPE, (PIPEINFO_SIZE-1) + ,*ppPipeHandle ); + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + return status; +} + + +NFCSTATUS +phHciNfc_Update_Pipe( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_PipeMgmt_Seq_t *p_pipe_seq + ) +{ + static uint8_t pipe_index = HCI_DYNAMIC_PIPE_ID; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + + for (pipe_index = 0; + (pipe_index + HCI_DYNAMIC_PIPE_ID) <= + (uint8_t)(sizeof(host_gate_list)/sizeof(phHciNfc_GateID_t) ); + pipe_index++) + { + status = phHciNfc_Allocate_Resource((void **)&p_pipe_info, + sizeof(phHciNfc_Pipe_Info_t)); + + if( (NFCSTATUS_SUCCESS == status) + && (NULL != p_pipe_info)) + { + /* The Source Host is the Terminal Host */ + p_pipe_info->pipe.source.host_id = (uint8_t) phHciNfc_TerminalHostID; + + /* The Source Gate is same as the Destination Gate */ + p_pipe_info->pipe.source.gate_id = + host_gate_list[pipe_index]; + p_pipe_info->pipe.dest.host_id = + phHciNfc_HostControllerID; + p_pipe_info->pipe.dest.gate_id = + host_gate_list[pipe_index]; + /* The Pipe ID is unknown until it is assigned */ + p_pipe_info->pipe.pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + + /* Initialise the Resources for the particular Gate */ + + status = phHciNfc_Create_All_Pipes(psHciContext, + pHwRef, p_pipe_seq ); + + if( NFCSTATUS_SUCCESS == status ) + { + uint8_t pipe_id = (uint8_t)(pipe_index + HCI_DYNAMIC_PIPE_ID); + status = phHciNfc_Update_PipeInfo( psHciContext, p_pipe_seq , + pipe_id, p_pipe_info ); + if( NFCSTATUS_SUCCESS == status ) + { + p_pipe_info->pipe.pipe_id = pipe_id; + psHciContext->p_pipe_list[pipe_id] = p_pipe_info; + } + else + { + phOsalNfc_FreeMemory(p_pipe_info); + } + p_pipe_info = NULL; + } + else + { + phOsalNfc_FreeMemory(p_pipe_info); + p_pipe_info = NULL; + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + } + + if( NFCSTATUS_SUCCESS == status ) + { + status = phHciNfc_LinkMgmt_Initialise( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_ReaderMgmt_Initialise( psHciContext,pHwRef ); + } + if(NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_EmuMgmt_Initialise( psHciContext,pHwRef ); + } + } + + return status; +} + + +/*! + * \brief Deletion of the Pipe + * + * This function Deletes a pipe created between a terminal host's gate and + * destination host's gate + * + */ + +NFCSTATUS +phHciNfc_Delete_Pipe( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_Pipe_Info_t *pPipeHandle + ) +{ + NFCSTATUS status=NFCSTATUS_SUCCESS; + NFCSTATUS cmd_status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || (NULL == pHwRef) + || (NULL == pPipeHandle) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + cmd_status = phHciNfc_Send_Admin_Cmd( psHciContext, pHwRef, + ADM_DELETE_PIPE, PIPEID_LEN, pPipeHandle ); + status = ( (cmd_status == NFCSTATUS_PENDING)? + NFCSTATUS_SUCCESS : cmd_status); + } + + return status; +} + +#ifdef HOST_EMULATION + +NFCSTATUS +phHciNfc_CE_Pipes_OP( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_PipeMgmt_Seq_t *p_pipe_seq + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + /* uint8_t pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; */ + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + switch( *p_pipe_seq ) + { + case PIPE_CARD_A_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_CETypeAGate; + + status = phHciNfc_CE_A_Init_Resources ( psHciContext ); + if(status == NFCSTATUS_SUCCESS) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); + } + break; + } + case PIPE_CARD_B_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_CETypeBGate; + + status = phHciNfc_CE_B_Init_Resources ( psHciContext ); + if(status == NFCSTATUS_SUCCESS) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); + } + break; + } +#if 0 + case PIPE_CARD_F_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_CETypeFGate; + + /* status = phHciNfc_Card_Emulation_Init (psHciContext , TYPE_F); */ + if(status == NFCSTATUS_SUCCESS) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + /* status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); */ + } + break; + } + case PIPE_CARD_A_DELETE: + { + status = phHciNfc_CE_A_Get_PipeID( psHciContext, &pipe_id ); + p_pipe_info = psHciContext->p_pipe_list[pipe_id]; + if(status == NFCSTATUS_SUCCESS) + { + status = phHciNfc_Delete_Pipe( psHciContext, pHwRef, + p_pipe_info); + status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); + } + break; + } + case PIPE_CARD_B_DELETE: + { + status = phHciNfc_CE_B_Get_PipeID( psHciContext, &pipe_id ); + p_pipe_info = psHciContext->p_pipe_list[pipe_id]; + if(status == NFCSTATUS_SUCCESS) + { + status = phHciNfc_Delete_Pipe( psHciContext, pHwRef, + p_pipe_info); + status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); + } + break; + } +#endif + /* case PIPE_MGMT_END : */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + } + } + + return status; +} +#endif + + +/*! + * \brief Creates the Pipes of all the Supported Gates . + * + * This function Creates the pipes for all the supported gates + */ + +NFCSTATUS +phHciNfc_Create_All_Pipes( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_PipeMgmt_Seq_t *p_pipe_seq + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + + if( (NULL == psHciContext) || (NULL == pHwRef) + || (NULL == p_pipe_seq) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + + switch( *p_pipe_seq ) + { + /* Admin pipe close sequence */ + case PIPE_IDMGMT_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_IdentityMgmtGate; + + status = phHciNfc_IDMgmt_Init_Resources (psHciContext); + if((status == NFCSTATUS_SUCCESS) +#ifdef ESTABLISH_SESSION + && (hciMode_Session != psHciContext->hci_mode) +#endif + ) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + /* status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); */ + } + break; + } + case PIPE_PN544MGMT_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_PN544MgmtGate; + + status = phHciNfc_DevMgmt_Init_Resources (psHciContext); + if((status == NFCSTATUS_SUCCESS) +#ifdef ESTABLISH_SESSION + && (hciMode_Session != psHciContext->hci_mode) +#endif + ) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + if(HCI_SELF_TEST == psHciContext->init_mode) + { + status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); + } + } + break; + } + case PIPE_POLLINGLOOP_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_PollingLoopGate; + + status = phHciNfc_PollLoop_Init_Resources (psHciContext); + if((status == NFCSTATUS_SUCCESS) +#ifdef ESTABLISH_SESSION + && (hciMode_Session != psHciContext->hci_mode) +#endif + ) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + /* status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); */ + } + break; + } + case PIPE_READER_A_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_RFReaderAGate; + + status = phHciNfc_ReaderA_Init_Resources (psHciContext); + if((status == NFCSTATUS_SUCCESS) +#ifdef ESTABLISH_SESSION + && (hciMode_Session != psHciContext->hci_mode) +#endif + ) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + /* status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); */ + } + break; + } +#ifdef TYPE_B + case PIPE_READER_B_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_RFReaderBGate; + + status = phHciNfc_ReaderB_Init_Resources (psHciContext); + if((status == NFCSTATUS_SUCCESS) +#ifdef ESTABLISH_SESSION + && (hciMode_Session != psHciContext->hci_mode) +#endif + ) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + /* status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); */ + } + break; + } +/* #ifdef TYPE_B*/ +#endif +#ifdef TYPE_FELICA + case PIPE_READER_F_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_RFReaderFGate; + + status = phHciNfc_Felica_Init_Resources (psHciContext); + if((status == NFCSTATUS_SUCCESS) +#ifdef ESTABLISH_SESSION + && (hciMode_Session != psHciContext->hci_mode) +#endif + ) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + /* status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); */ + } + break; + } +#endif +#ifdef TYPE_JEWEL + case PIPE_READER_JWL_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_JewelReaderGate; + + status = phHciNfc_Jewel_Init_Resources (psHciContext); + if((status == NFCSTATUS_SUCCESS) +#ifdef ESTABLISH_SESSION + && (hciMode_Session != psHciContext->hci_mode) +#endif + ) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + /* status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); */ + } + break; + } +#endif /* #ifdef TYPE_JEWEL */ +#ifdef TYPE_ISO15693 + case PIPE_READER_ISO15693_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_ISO15693Gate; + + status = phHciNfc_ISO15693_Init_Resources (psHciContext); + if((status == NFCSTATUS_SUCCESS) +#ifdef ESTABLISH_SESSION + && (hciMode_Session != psHciContext->hci_mode) +#endif + ) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + /* status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); */ + } + break; + } +#endif /* #ifdef TYPE_ISO15693 */ + case PIPE_NFC_INITIATOR_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_NFCIP1InitRFGate; +#ifdef ENABLE_P2P + status = phHciNfc_Initiator_Init_Resources (psHciContext); + if((status == NFCSTATUS_SUCCESS) +#ifdef ESTABLISH_SESSION + && (hciMode_Session != psHciContext->hci_mode) +#endif + ) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + /* status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); */ + } +#endif + break; + } + case PIPE_NFC_TARGET_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_NFCIP1TargetRFGate; + +#ifdef ENABLE_P2P + status = phHciNfc_Target_Init_Resources (psHciContext); + if((status == NFCSTATUS_SUCCESS) +#ifdef ESTABLISH_SESSION + && (hciMode_Session != psHciContext->hci_mode) +#endif + ) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + /* status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); */ + } +#endif + break; + } + case PIPE_WI_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_NfcWIMgmtGate; + + status = phHciNfc_WI_Init_Resources ( psHciContext ); + if((status == NFCSTATUS_SUCCESS) +#ifdef ESTABLISH_SESSION + && (hciMode_Session != psHciContext->hci_mode) +#endif + ) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + /* status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); */ + } + break; + } + case PIPE_SWP_CREATE: + { + phHciNfc_Gate_Info_t id_dest; + + id_dest.host_id = (uint8_t)phHciNfc_HostControllerID; + id_dest.gate_id = (uint8_t)phHciNfc_SwpMgmtGate; + + status = phHciNfc_SWP_Init_Resources ( psHciContext ); + + if((status == NFCSTATUS_SUCCESS) +#ifdef ESTABLISH_SESSION + && (hciMode_Session != psHciContext->hci_mode) +#endif + ) + { + status = phHciNfc_Create_Pipe( psHciContext, pHwRef, + &id_dest, &p_pipe_info); + status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); + } + break; + } + /* case PIPE_MGMT_END : */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + + } /* End of Pipe Seq Switch */ + + } /* End of Null Check for the Context */ + + return status; +} + +/*! + * \brief Deletes the Pipes of all the Supported Gates . + * + * This function Deletes the pipes for all the supported gates + */ + +NFCSTATUS +phHciNfc_Delete_All_Pipes( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_PipeMgmt_Seq_t pipeSeq + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t length = 0; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* pipeSeq = PIPE_DELETE_ALL; */ + + if ( PIPE_DELETE_ALL == pipeSeq ) + { + /* Admin pipe close sequence */ + p_pipe_info = psHciContext->p_pipe_list[PIPETYPE_STATIC_ADMIN]; + status = phHciNfc_Send_Admin_Cmd( psHciContext, + pHwRef, ADM_CLEAR_ALL_PIPE, + length, p_pipe_info); + status = ((NFCSTATUS_PENDING == status)? + NFCSTATUS_SUCCESS : status); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + } + + + } /* End of Null Check for the Context */ + + return status; +} + + + +NFCSTATUS +phHciNfc_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + phHciNfc_PipeMgmt_Seq_t *pPipeSeq, + uint8_t pipe_id, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + phHciNfc_GateID_t gate_id = phHciNfc_UnknownGate; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( + (NULL == psHciContext) || (NULL == pPipeSeq) + || ( NULL == pPipeInfo ) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + gate_id = (phHciNfc_GateID_t )pPipeInfo->pipe.dest.gate_id ; + switch( gate_id ) + { + /* Identity Management Pipe Creation */ + case phHciNfc_IdentityMgmtGate: + { + status = phHciNfc_IDMgmt_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { + *pPipeSeq = PIPE_PN544MGMT_CREATE; + } + break; + } + case phHciNfc_PN544MgmtGate: + { + status = phHciNfc_DevMgmt_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { + *pPipeSeq = ( HCI_SELF_TEST != psHciContext->init_mode )? + PIPE_POLLINGLOOP_CREATE:PIPE_DELETE_ALL; + } + break; + } + case phHciNfc_PollingLoopGate: + { + status = phHciNfc_PollLoop_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { + *pPipeSeq = PIPE_READER_A_CREATE; + } + break; + } + case phHciNfc_RFReaderAGate: + { + status = phHciNfc_ReaderA_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { + +#if defined (TYPE_B) + *pPipeSeq = PIPE_READER_B_CREATE; +/* #if defined (TYPE_B) */ +#elif defined (TYPE_FELICA) + *pPipeSeq = PIPE_READER_F_CREATE; +/* #if defined (TYPE_FELICA) */ +#elif defined (TYPE_JEWEL) + *pPipeSeq = PIPE_READER_JWL_CREATE; +/* #if defined (TYPE_JEWEL) */ +#elif defined (TYPE_ISO15693) + *pPipeSeq = PIPE_READER_ISO15693_CREATE; +/* #if defined (TYPE_ISO15693) */ +#elif defined(ENABLE_P2P) + *pPipeSeq = PIPE_NFC_INITIATOR_CREATE; +/* #if defined(ENABLE_P2P) */ + /*lint -e{91} suppress "Line exceeds"*/ +#elif !defined(TYPE_B) && !defined(TYPE_FELICA) && !defined(TYPE_JEWEL) && !defined(TYPE_ISO15693) && !defined(ENABLE_P2P) + *pPipeSeq = PIPE_WI_CREATE; +#endif + } + break; + } +#ifdef TYPE_B + case phHciNfc_RFReaderBGate: + { + status = phHciNfc_ReaderB_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { +#if defined (TYPE_FELICA) + *pPipeSeq = PIPE_READER_F_CREATE; +/* #if defined (TYPE_FELICA) */ +#elif defined (TYPE_JEWEL) + *pPipeSeq = PIPE_READER_JWL_CREATE; +/* #if defined (TYPE_JEWEL) */ +#elif defined (TYPE_ISO15693) + *pPipeSeq = PIPE_READER_ISO15693_CREATE; +/* #if defined (TYPE_ISO15693) */ +#elif defined(ENABLE_P2P) + *pPipeSeq = PIPE_NFC_INITIATOR_CREATE; +/* #if defined(ENABLE_P2P) */ + /*lint -e{91} suppress "Line exceeds"*/ +#elif !defined(TYPE_FELICA) && !defined(TYPE_JEWEL) && !defined(TYPE_ISO15693) && !defined(ENABLE_P2P) + *pPipeSeq = PIPE_WI_CREATE; +#endif + } + break; + } +#endif +#ifdef TYPE_FELICA + case phHciNfc_RFReaderFGate: + { + status = phHciNfc_Felica_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { +#if defined (TYPE_JEWEL) + *pPipeSeq = PIPE_READER_JWL_CREATE; +/* #if defined (TYPE_JEWEL) */ +#elif defined (TYPE_ISO15693) + *pPipeSeq = PIPE_READER_ISO15693_CREATE; +/* #if defined (TYPE_ISO15693) */ +#elif defined(ENABLE_P2P) + *pPipeSeq = PIPE_NFC_INITIATOR_CREATE; +/* #if defined(ENABLE_P2P) */ +#elif !defined(TYPE_JEWEL) && !defined(TYPE_ISO15693) && !defined(ENABLE_P2P) + *pPipeSeq = PIPE_WI_CREATE; +#endif + } + break; + } +#endif +#ifdef TYPE_JEWEL + case phHciNfc_JewelReaderGate: + { + status = phHciNfc_Jewel_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { +#if defined (TYPE_ISO15693) + *pPipeSeq = PIPE_READER_ISO15693_CREATE; +/* #if defined (TYPE_ISO15693) */ +#elif defined(ENABLE_P2P) + *pPipeSeq = PIPE_NFC_INITIATOR_CREATE; +/* #if defined(ENABLE_P2P) */ +#elif !defined(TYPE_ISO15693) && !defined(ENABLE_P2P) + *pPipeSeq = PIPE_WI_CREATE; +#endif + } + break; + } +#endif /* #ifdef TYPE_JEWEL */ +#if defined (TYPE_ISO15693) + case phHciNfc_ISO15693Gate: + { + status = phHciNfc_ISO15693_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { + +#ifdef ENABLE_P2P + *pPipeSeq = PIPE_NFC_INITIATOR_CREATE; +#else + *pPipeSeq = PIPE_WI_CREATE; +#endif /* #ifdef ENABLE_P2P */ + } + break; + } +#endif /* #if defined (TYPE_ISO15693) */ + case phHciNfc_NFCIP1InitRFGate: + { +#ifdef ENABLE_P2P + status = phHciNfc_Initiator_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { + *pPipeSeq = PIPE_NFC_TARGET_CREATE; + } +#endif + break; + } + case phHciNfc_NFCIP1TargetRFGate: + { +#ifdef ENABLE_P2P + status = phHciNfc_Target_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { + *pPipeSeq = PIPE_WI_CREATE; + } +#endif + break; + } + case phHciNfc_NfcWIMgmtGate: + { + status = phHciNfc_WI_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { + *pPipeSeq = PIPE_SWP_CREATE; + } + break; + } + case phHciNfc_SwpMgmtGate: + { + status = phHciNfc_SWP_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { + *pPipeSeq = PIPE_DELETE_ALL; + } + break; + } + case phHciNfc_ConnectivityGate: + { + status = phHciNfc_Uicc_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + break; + } +#ifdef HOST_EMULATION + case phHciNfc_CETypeAGate: + { + status = phHciNfc_CE_A_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { + *pPipeSeq = PIPE_CARD_B_CREATE; + } + break; + } + case phHciNfc_CETypeBGate: + { + status = phHciNfc_CE_B_Update_PipeInfo(psHciContext, + pipe_id, pPipeInfo); + if(NFCSTATUS_SUCCESS == status) + { + *pPipeSeq = PIPE_DELETE_ALL; + } + break; + } +#endif + case phHciNfc_UnknownGate: + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_HCI_GATE_NOT_SUPPORTED ); + break; + } + /*End of the default Switch Case */ + + } /*End of the Index Switch */ + } /* End of Context and the Identity information validity check */ + + return status; +} + + +/*! + * \brief Opening the Pipe + * + * This function opens the the pipe created between a terminal host's gate and + * destination host's gate + * + */ + +NFCSTATUS +phHciNfc_Open_Pipe( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_Pipe_Info_t *pPipeHandle + ) +{ + uint8_t pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + NFCSTATUS status = NFCSTATUS_SUCCESS; + NFCSTATUS cmd_status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || ( NULL == pHwRef ) + || ( NULL == pPipeHandle ) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Obtain the pipe_id from the pipe_handle */ + pipe_id = pPipeHandle->pipe.pipe_id; + + if ( pipe_id <= PHHCINFC_MAX_PIPE) + { + cmd_status = phHciNfc_Send_Generic_Cmd( psHciContext,pHwRef, + pipe_id, ANY_OPEN_PIPE); + status = ( (cmd_status == NFCSTATUS_PENDING)? + NFCSTATUS_SUCCESS : cmd_status); + } + } + return status; +} + + +/*! + * \brief Closing the Pipe + * + * This function Closes the the pipe created between a terminal host's gate and + * destination host's gate + * + */ + +NFCSTATUS +phHciNfc_Close_Pipe( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_Pipe_Info_t *pPipeHandle + ) +{ + uint8_t pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + NFCSTATUS status = NFCSTATUS_SUCCESS; + NFCSTATUS cmd_status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || ( NULL == pHwRef ) + || ( NULL == pPipeHandle ) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Obtain the pipe_id from the pipe_handle */ + pipe_id = pPipeHandle->pipe.pipe_id; + + if( (uint8_t)HCI_UNKNOWN_PIPE_ID > pipe_id) + { + cmd_status = phHciNfc_Send_Generic_Cmd( + psHciContext, pHwRef, pipe_id, + ANY_CLOSE_PIPE ); + + status = ((cmd_status == NFCSTATUS_PENDING)? + NFCSTATUS_SUCCESS : cmd_status); + } + } + return status; +} diff --git a/libnfc-nxp/phHciNfc_Pipe.h b/libnfc-nxp/phHciNfc_Pipe.h new file mode 100644 index 0000000..e011824 --- /dev/null +++ b/libnfc-nxp/phHciNfc_Pipe.h @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_Pipe.h * +* \brief HCI Header for the Pipe Management. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Aug 14 17:01:27 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.17 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/*@{*/ + +#ifndef PHHCINFC_PIPE_H +#define PHHCINFC_PIPE_H + +/*@}*/ + + +/** + * \name HCI + * + * File: \ref phHciNfc_Pipe.h + * + */ +/*@{*/ +#define PHHCINFC_PIPE_FILEREVISION "$Revision: 1.17 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_PIPE_FILEALIASES "$Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +#define PIPEINFO_SIZE 0x04U +#define PIPEID_LEN 0x01U + +#define RESPONSE_GATEID_OFFSET 0x03U +#define RESPONSE_PIPEID_OFFSET 0x04U + + +#define PIPETYPE_STATIC_LINK 0x00U +#define PIPETYPE_STATIC_ADMIN 0x01U +#define PIPETYPE_DYNAMIC 0x02U + +/* +******************** Enumeration and Structure Definition ********************** +*/ + +typedef enum phHciNfc_PipeMgmt_Seq{ + /* Pipe for Identitiy Management */ + PIPE_IDMGMT_CREATE = 0x00U, + /* Pipe for Configuring PN544 Nfc Device */ + PIPE_PN544MGMT_CREATE, + /* Pipe for Configuring Polling Wheel */ + PIPE_POLLINGLOOP_CREATE, + /* Pipes for Configuring the RF Readers */ + PIPE_READER_A_CREATE, + PIPE_READER_B_CREATE, + PIPE_READER_F_CREATE, + PIPE_READER_JWL_CREATE, + PIPE_READER_ISO15693_CREATE, + /* Pipes for configuring the Card Emulation */ + PIPE_CARD_A_CREATE, + PIPE_CARD_A_DELETE, + PIPE_CARD_B_CREATE, + PIPE_CARD_B_DELETE, + PIPE_CARD_F_CREATE, + PIPE_CARD_F_DELETE, + /* Pipes for Peer to Peer Communication */ + PIPE_NFC_INITIATOR_CREATE, + PIPE_NFC_TARGET_CREATE, + /* Secure Element Commands */ + PIPE_WI_CREATE, + PIPE_SWP_CREATE, + /* Connectiviy Gate Pipe */ + PIPE_CONNECTIVITY, + + /* Clearing all the created Pipes */ + PIPE_DELETE_ALL, + PIPE_MGMT_END +} phHciNfc_PipeMgmt_Seq_t; + +/** \defgroup grp_hci_nfc HCI Component + * + * + */ + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/*! + * \brief Creates the Pipes of all the Supported Gates . + * + * This function Creates the pipes for all the supported gates + */ + +extern +NFCSTATUS +phHciNfc_Create_All_Pipes( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_PipeMgmt_Seq_t *p_pipe_seq + ); + +/*! + * \brief Deletes the Pipes of all the Supported Gates . + * + * This function Deletes the pipes for all the supported gates + */ +extern +NFCSTATUS +phHciNfc_Delete_All_Pipes( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_PipeMgmt_Seq_t pipeSeq + ); + +/*! + * \brief Updates the Information of Pipes of all the Supported Gates . + * + * This function Updates the pipe information for all the supported gates + */ + +extern +NFCSTATUS +phHciNfc_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + phHciNfc_PipeMgmt_Seq_t *pPipeSeq, + uint8_t pipe_id, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Open_Pipe function opens + * . + * + * \param[in] psContext psContext is pointer to the context + * Structure of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] pPipeHandle pPipeHandle is the handle used to open + * the Static or Dynamically Created Pipe. + * + * \retval NFCSTATUS_PENDING Pipe Open is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the lower layers + * + */ + + extern + NFCSTATUS + phHciNfc_Open_Pipe ( + phHciNfc_sContext_t *psContext, + void *pHwRef, + phHciNfc_Pipe_Info_t *pPipeHandle + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Close_Pipe function closes + * . + * + * \param[in] psContext psContext is pointer to the context + * Structure of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] pPipeHandle pPipeHandle is the handle used to closes + * the Static or Dynamically Created Pipe. + * + * \retval NFCSTATUS_PENDING Pipe close is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the lower layers + * + */ + + extern + NFCSTATUS + phHciNfc_Close_Pipe ( + phHciNfc_sContext_t *psContext, + void *pHwRef, + phHciNfc_Pipe_Info_t *pPipeHandle + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Delete_Pipe function deletes the dynamically created pipe + * using the supplied pipe handle. + * + * \param[in] psContext psContext is pointer to the context + * Structure of the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] pPipeHandle pPipeHandle is the handle used to delete + * the Dynamically Created Pipe. + * + * \retval NFCSTATUS_PENDING Pipe Deletion is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * + */ + +extern +NFCSTATUS +phHciNfc_Delete_Pipe( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_Pipe_Info_t *pPipeHandle + ); + +/*! + * \brief Creates and Update the Pipes during the Session + * + * This function Creates and Update the Pipes of all the Supported Gates + * for the already initialised session. + */ + +extern +NFCSTATUS +phHciNfc_Update_Pipe( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_PipeMgmt_Seq_t *p_pipe_seq + ); + + +extern +NFCSTATUS +phHciNfc_CE_Pipes_OP( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_PipeMgmt_Seq_t *p_pipe_seq + ); + +#endif + diff --git a/libnfc-nxp/phHciNfc_PollingLoop.c b/libnfc-nxp/phHciNfc_PollingLoop.c new file mode 100644 index 0000000..2142122 --- /dev/null +++ b/libnfc-nxp/phHciNfc_PollingLoop.c @@ -0,0 +1,807 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_PollingLoop.c * +* \brief HCI polling loop Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Mon Mar 29 17:34:48 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.35 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include +#include +/* +****************************** Macro Definitions ******************************* +*/ + +/* Registry index to which command has to be sent */ +#define PL_PAUSE_INDEX 0x08U +#define PL_EMULATION_INDEX 0x07U +#define PL_RD_PHASES_INDEX 0x06U +#define PL_DISABLE_TARGET_INDEX 0x09U + +/* Events */ +#define NXP_EVT_CLK_ACK 0x01U +#define NXP_EVT_CLK_REQUEST 0x02U +#define NXP_EVT_ACTIVATE_RDPHASES 0x03U +#define NXP_EVT_DEACTIVATE_RDPHASES 0x04U + +/* Command length */ +#define PL_DURATION_LENGTH 0x02U +#define PL_BYTE_LEN_1 0x01U + +#define PL_BIT_FIELD_ENABLED 0x01U + + +#define PL_EMULATION_FACTOR 0x0AU +/* Default duration (100 ms * 1000) micro seconds, + always duration shall be less then 3145680 + micro seconds */ +#define PL_DEFAULT_DURATION 100000U +/* Maximum duration */ +#define PL_MAX_DURATION 3145000U +#define PL_DURATION_MIN_VALUE 48U +#define PL_DURATION_CALC(duration) \ + ((uint16_t)((duration)/PL_DURATION_MIN_VALUE)) + +/* +*************************** Structure and Enumeration *************************** +*/ + +typedef enum phHciNfc_Poll_Seq{ + PL_PIPE_OPEN = 0x00U, + PL_PIPE_CLOSE, + PL_SET_DURATION, + PL_GET_DURATION, + PL_GET_RD_PHASES, + PL_SET_RD_PHASES, + PL_GET_DISABLE_TARGET, + PL_SET_DISABLE_TARGET, + PL_END_SEQUENCE +} phHciNfc_Poll_Seq_t; + +/* Information structure for the polling loop Gate */ +typedef struct phHciNfc_PollLoop_Info{ + /* Current running Sequence of the polling loop Management */ + phHciNfc_Poll_Seq_t current_seq; + /* Next running Sequence of the polling loop Management */ + phHciNfc_Poll_Seq_t next_seq; + /* Pointer to the polling loop pipe information */ + phHciNfc_Pipe_Info_t *p_pipe_info; + uint8_t pipe_id; +} phHciNfc_PollLoop_Info_t; + +/* +*************************** Static Function Declaration ************************** +*/ + +static +NFCSTATUS +phHciNfc_PollLoop_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Recv_Pl_Response function interprets the received polling loop + * response from the Host Controller Gate. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in,out] pResponse Response received from the Host Cotroller + * polling loop gate. + * \param[in] length length contains the length of the + * response received from the Host Controller. + * + * \retval NFCSTATUS_PENDING Polling loop gate Response to be received + * is pending. + * \retval NFCSTATUS_SUCCESS Polling loop gate Response received + * Successfully. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +static +NFCSTATUS +phHciNfc_Recv_PollLoop_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_PollLoop_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); +/* +*************************** Function Definitions *************************** +*/ + +NFCSTATUS +phHciNfc_PollLoop_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_poll_loop_info ) + ) + { + phHciNfc_PollLoop_Info_t *p_poll_info=NULL; + p_poll_info = (phHciNfc_PollLoop_Info_t *) + psHciContext->p_poll_loop_info ; + *ppipe_id = p_poll_info->pipe_id ; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + +NFCSTATUS +phHciNfc_PollLoop_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_PollLoop_Info_t *p_poll_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( + ( NULL == psHciContext->p_poll_loop_info ) + && (phHciNfc_Allocate_Resource((void **)(&p_poll_info), + sizeof(phHciNfc_PollLoop_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_poll_loop_info = p_poll_info; + p_poll_info->current_seq = PL_PIPE_OPEN; + p_poll_info->next_seq = PL_PIPE_CLOSE; + p_poll_info->pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + return status; +} + +/*! + * \brief Initialisation of polling loop Gate and Establish the Session . + * + * This function initialses the polling loop Gates and + * all the required pipes and sets the Session ID + * + */ +NFCSTATUS +phHciNfc_PollLoop_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( NULL == psHciContext->p_poll_loop_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_PollLoop_Info_t *p_poll_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + p_poll_info = (phHciNfc_PollLoop_Info_t *) + psHciContext->p_poll_loop_info ; + p_pipe_info = p_poll_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + HCI_PRINT("Polling loop open pipe in progress ...\n"); + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(NFCSTATUS_SUCCESS == status) + { + p_poll_info->next_seq = PL_PIPE_CLOSE; + } + } + } + } + return status; +} + +NFCSTATUS +phHciNfc_PollLoop_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( NULL != psHciContext->p_poll_loop_info ) + { + phHciNfc_PollLoop_Info_t *p_poll_info=NULL; + p_poll_info = (phHciNfc_PollLoop_Info_t *) + psHciContext->p_poll_loop_info ; + if (PL_PIPE_CLOSE == p_poll_info->current_seq) + { + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + p_pipe_info = p_poll_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + HCI_PRINT("Polling loop close pipe in progress ...\n"); + status = phHciNfc_Close_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_poll_info->next_seq = PL_PIPE_OPEN; + } + } + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + } /* End of if (PL_PIPE_CLOSE == p_pl_info->cur_seq) */ + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } /* End of if( NULL != psHciContext->p_poll_loop_info ) */ + } /* End of if( (NULL == psHciContext) || (NULL == pHwRef) ) */ + return status; +} + +NFCSTATUS +phHciNfc_PollLoop_Cfg ( + void *psHciHandle, + void *pHwRef, + uint8_t cfg_type, + void *pcfg_info + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + uint8_t poll_cfg; + static uint16_t pl_duration = 0; + + /* To remove "warning (VS C4100) : unreferenced formal parameter" */ + PHNFC_UNUSED_VARIABLE(pcfg_info); + + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_poll_loop_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_PollLoop_Info_t *p_poll_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + phHal_sADD_Cfg_t *p_poll_cfg = NULL; + uint8_t pipeid = 0; + + p_poll_cfg = (phHal_sADD_Cfg_t*)psHciContext->p_config_params; + p_poll_info = (phHciNfc_PollLoop_Info_t *) + psHciContext->p_poll_loop_info ; + p_pipe_info = p_poll_info->p_pipe_info; + if((NULL == p_pipe_info) || (NULL == p_poll_cfg)) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + switch(cfg_type) + { + case PL_DURATION: + { + /* + Data memory has to be copied to + param_info and also depending on the + CARD_EMULATION or PAUSE, change the + p_pipe_info->reg_index + */ + if(p_poll_cfg->Duration > PL_MAX_DURATION) + { + p_poll_cfg->Duration = PL_MAX_DURATION; + } + + + if (FALSE == + p_poll_cfg->PollDevInfo.PollCfgInfo.DisableCardEmulation) + { + p_poll_cfg->Duration = ((p_poll_cfg->Duration < + PL_DURATION_MIN_VALUE)? + (PL_DEFAULT_DURATION * + PL_EMULATION_FACTOR): + p_poll_cfg->Duration ); + p_pipe_info->reg_index = PL_EMULATION_INDEX; + } + else + { + p_poll_cfg->Duration = ((p_poll_cfg->Duration < + PL_DURATION_MIN_VALUE)? + PL_DEFAULT_DURATION : + p_poll_cfg->Duration); + p_pipe_info->reg_index = PL_PAUSE_INDEX; + } + p_pipe_info->param_length = PL_DURATION_LENGTH; + + /* Calculate duration */ + pl_duration = (uint16_t) + PL_DURATION_CALC(p_poll_cfg->Duration); + + /* Swap the 2 byte value */ + pl_duration = (uint16_t)((pl_duration << BYTE_SIZE) | + ((uint8_t)(pl_duration >> BYTE_SIZE))); + /* Copy the duration from poll config structure, + provided by the upper layer */ + p_pipe_info->param_info = (void *)&(pl_duration); + + pipeid = p_poll_info->pipe_id ; + if (PL_GET_DURATION == p_poll_info->current_seq) + { + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if (NFCSTATUS_PENDING == status) + { + p_poll_info->next_seq = PL_PIPE_CLOSE; + status = NFCSTATUS_SUCCESS; + } + } + else + { + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { +#ifdef ENABLE_VERIFY_PARAM + p_poll_info->next_seq = PL_GET_DURATION; +#else + status = NFCSTATUS_SUCCESS; +#endif /* #ifdef ENABLE_VERIFY_PARAM */ + } + } + break; + } + case PL_RD_PHASES: + { + poll_cfg = (uint8_t) p_poll_cfg->PollDevInfo.PollEnabled; + p_pipe_info->param_length = PL_BYTE_LEN_1; + p_pipe_info->reg_index = PL_RD_PHASES_INDEX; + + /* Data memory has to be copied to + param_info */ + p_pipe_info->param_info = (void *)&(poll_cfg); + pipeid = p_poll_info->pipe_id ; + if (PL_GET_RD_PHASES == p_poll_info->current_seq) + { + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if (NFCSTATUS_PENDING == status) + { + status = NFCSTATUS_SUCCESS; + } + } + else + { + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { +#ifdef ENABLE_VERIFY_PARAM + p_poll_info->next_seq = PL_GET_RD_PHASES; +#else + status = NFCSTATUS_SUCCESS; +#endif /* #ifdef ENABLE_VERIFY_PARAM */ + } + } + break; + } + case PL_DISABLE_TARGET: + { + if (NULL == pcfg_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* poll_cfg = (uint8_t) p_poll_cfg->NfcIP_Tgt_Disable; */ + p_pipe_info->param_length = PL_BYTE_LEN_1; + p_pipe_info->reg_index = PL_DISABLE_TARGET_INDEX; + + /* Data memory has to be copied to + param_info */ + p_pipe_info->param_info = pcfg_info; + pipeid = p_poll_info->pipe_id ; + if (PL_GET_DISABLE_TARGET == p_poll_info->current_seq) + { + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if (NFCSTATUS_PENDING == status) + { + status = NFCSTATUS_SUCCESS; + } + } + else + { + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + if( NFCSTATUS_PENDING == status ) + { +#ifdef ENABLE_VERIFY_PARAM + /* p_poll_info->current_seq = PL_GET_DISABLE_TARGET; */ + p_poll_info->next_seq = PL_GET_DISABLE_TARGET; +#else + status = NFCSTATUS_SUCCESS; +#endif /* #ifdef ENABLE_VERIFY_PARAM */ + } + } + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_PARAMETER); + break; + } + } + } + } + return status; +} + +/* Function to assign pipe ID */ +NFCSTATUS +phHciNfc_PollLoop_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_poll_loop_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_PollLoop_Info_t *p_poll_info=NULL; + p_poll_info = (phHciNfc_PollLoop_Info_t *) + psHciContext->p_poll_loop_info ; + /* Update the pipe_id of the ID Mgmt Gate obtained from the HCI Response */ + p_poll_info->pipe_id = pipeID; + p_poll_info->p_pipe_info = pPipeInfo; + if (NULL != pPipeInfo) + { + /* Update the Response Receive routine of the IDMgmt Gate */ + pPipeInfo->recv_resp = &phHciNfc_Recv_PollLoop_Response; + /* Update the event Receive routine of the IDMgmt Gate */ + pPipeInfo->recv_event = &phHciNfc_Recv_PollLoop_Event; + } + } + + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_PollLoop_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_poll_loop_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_PollLoop_Info_t *p_poll_info=NULL; + uint8_t prev_cmd = ANY_GET_PARAMETER; + p_poll_info = (phHciNfc_PollLoop_Info_t *) + psHciContext->p_poll_loop_info ; + if( NULL == p_poll_info->p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + prev_cmd = p_poll_info->p_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_SET_PARAMETER: + { + HCI_PRINT("Polling loop Set Param complete\n"); + break; + } + case ANY_GET_PARAMETER: + { + status = phHciNfc_PollLoop_InfoUpdate(psHciContext, + p_poll_info->p_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); + break; + } + case ANY_OPEN_PIPE: + { + HCI_PRINT("Polling loop open pipe complete\n"); + break; + } + case ANY_CLOSE_PIPE: + { + HCI_PRINT("Polling loop close pipe complete\n"); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + p_poll_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; + p_poll_info->current_seq = p_poll_info->next_seq; + } + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_PollLoop_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent) + || (length <= HCP_HEADER_LEN)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_poll_loop_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_PollLoop_Info_t *p_poll_info=NULL; + phHciNfc_HCP_Message_t *message = NULL; + static phHal_sEventInfo_t event_info; + uint8_t instruction=0; + + p_poll_info = (phHciNfc_PollLoop_Info_t *) + psHciContext->p_poll_loop_info ; + + PHNFC_UNUSED_VARIABLE(p_poll_info); + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &p_packet->msg.message; + /* Get the instruction bits from the Message Header */ + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + + switch(instruction) + { + case NXP_EVT_CLK_ACK: + { + break; + } + case NXP_EVT_CLK_REQUEST: + { + break; + } + case NXP_EVT_ACTIVATE_RDPHASES: + { + HCI_PRINT("Polling loop activate read phase complete\n"); + event_info.eventHost = phHal_eHostController; + event_info.eventType = NFC_UICC_RDPHASES_ACTIVATE_REQ; + event_info.eventInfo.rd_phases = pEvent[HCP_HEADER_LEN]; + ((phHal_sHwReference_t *)pHwRef)->uicc_rdr_active = TRUE; + phHciNfc_Notify_Event((void *)psHciContext, + pHwRef, + NFC_NOTIFY_EVENT, + &(event_info)); + break; + } + case NXP_EVT_DEACTIVATE_RDPHASES: + { + HCI_PRINT("Polling loop deactivate read phase complete\n"); + event_info.eventHost = phHal_eHostController; + event_info.eventType = NFC_UICC_RDPHASES_DEACTIVATE_REQ; + event_info.eventInfo.rd_phases = pEvent[HCP_HEADER_LEN]; + ((phHal_sHwReference_t *)pHwRef)->uicc_rdr_active = FALSE; + phHciNfc_Notify_Event((void *)psHciContext, + pHwRef, + NFC_NOTIFY_EVENT, + &(event_info)); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + } + return status; +} + + +static +NFCSTATUS +phHciNfc_PollLoop_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_PollLoop_Info_t *p_poll_info=NULL; + p_poll_info = (phHciNfc_PollLoop_Info_t *) + (psHciContext->p_poll_loop_info ); + /* To remove "warning (VS 4100) : unreferenced formal parameter" */ + PHNFC_UNUSED_VARIABLE(reg_value); + PHNFC_UNUSED_VARIABLE(reg_length); + /* Variable was set but never used (ARM warning) */ + PHNFC_UNUSED_VARIABLE(p_poll_info); + switch(index) + { + case PL_EMULATION_INDEX: + case PL_PAUSE_INDEX: + { + HCI_PRINT_BUFFER("\tPoll duration", reg_value, reg_length); + break; + } + case PL_RD_PHASES_INDEX: + { + HCI_PRINT_BUFFER("\tPoll read phase", reg_value, reg_length); + break; + } +#if defined (CLK_REQUEST) + case PL_CLK_REQUEST_INDEX: + { + HCI_PRINT_BUFFER("\tPoll clock request", reg_value, reg_length); + break; + } +#endif /* #if defined (CLK_REQUEST) */ +#if defined (INPUT_CLK) + case PL_INPUT_CLK_INDEX: + { + HCI_PRINT_BUFFER("\tPoll input clock", reg_value, reg_length); + break; + } +#endif/* #if defined (INPUT_CLK) */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + return status; +} + + diff --git a/libnfc-nxp/phHciNfc_PollingLoop.h b/libnfc-nxp/phHciNfc_PollingLoop.h new file mode 100644 index 0000000..6e251e8 --- /dev/null +++ b/libnfc-nxp/phHciNfc_PollingLoop.h @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_PollingLoop.h * +* \brief HCI Header for the Polling loop Management. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Mon Mar 29 17:34:49 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.6 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + + +#ifndef PHHCINFC_POLLINGLOOP_H +#define PHHCINFC_POLLINGLOOP_H + +/*@}*/ + + +/** + * \name HCI + * + * File: \ref phHciNfc_PollingLoop.h + * + */ +/*@{*/ +#define PHHCINFC_POLLINGLOOP_FILEREVISION "$Revision: 1.6 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_POLLINGLOOP_FILEALIASES "$Aliases: NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ +#define PL_DURATION 0x00U +#define PL_RD_PHASES 0x01U +#define PL_DISABLE_TARGET 0x02U + + + +#define PL_RD_PHASES_DISABLE 0x80U + +/* +******************** Enumeration and Structure Definition ********************** +*/ + +/** \defgroup grp_hci_nfc HCI Component + * + * + */ + + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_PollLoop_Initialise function Initialises the polling loop and opens the + * polling loop pipe + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Polling loop gate Initialisation is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_PollLoop_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_PollLoop_Release function closes the polling loop gate pipe + * between the Host Controller Device and the NFC Device. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Release of the Polling loop gate resources are + * pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_PollLoop_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_PollLoop_Update_PipeInfo function updates the pipe_id of the polling + * loop gate Managment Struction. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link + * \param[in] cfg_type Poll configuration type + * + * \param[in] pcfg_info Poll configuration info. + * + * \retval NFCSTATUS_SUCCESS Polling loop gate Response received Successfully. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * + */ +extern +NFCSTATUS +phHciNfc_PollLoop_Cfg ( + void *psHciHandle, + void *pHwRef, + uint8_t cfg_type, + void *pcfg_info + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_PollLoop_Update_PipeInfo function updates the pipe_id of the polling + * loop gate management structure. This function is used by the pipe management to + * update the pipe id + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pipeID pipeID of the polling loop gate + * \param[in] pPipeInfo Update the pipe Information of the polling loop + * gate. + * + * \retval NFCSTATUS_SUCCESS Polling loop gate Response received Successfully. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * + */ + +extern +NFCSTATUS +phHciNfc_PollLoop_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + + +/*! + * \brief Allocates the resources of Polling loop Managment Gate. + * + * This function Allocates the resources of the Polling loop management + * gate Information Structure. + * + */ +extern +NFCSTATUS +phHciNfc_PollLoop_Init_Resources( + phHciNfc_sContext_t *psHciContext + ); + + +/*! + * \brief Get the pipe_id of Polling loop managment Gate. + * + * This function Get the pipe_id of Polling loop managment Gate. + * + */ + +extern +NFCSTATUS +phHciNfc_PollLoop_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + +#endif /* PHHCINFC_POLLINGLOOP_H */ + + diff --git a/libnfc-nxp/phHciNfc_RFReader.c b/libnfc-nxp/phHciNfc_RFReader.c new file mode 100644 index 0000000..919f3fd --- /dev/null +++ b/libnfc-nxp/phHciNfc_RFReader.c @@ -0,0 +1,2390 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_RFReader.c * +* \brief HCI RF Reader Management Gate Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Wed Apr 21 12:21:15 2010 $ * +* $Author: ing07385 $ * +* $Revision: 1.53 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_6 $ * +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include +#include +#ifdef TYPE_B +#include +#endif +#ifdef ENABLE_P2P +#include +#endif +#ifdef TYPE_FELICA +#include +#endif +#ifdef TYPE_JEWEL +#include +#endif +#ifdef TYPE_ISO15693 +#include +#endif /* #ifdef TYPE_ISO15693 */ +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +#define NFCIP_ACTIVATE_DELAY 0x05U + +uint8_t nxp_nfc_isoxchg_timeout = NXP_ISO_XCHG_TIMEOUT; +/* +*************************** Structure and Enumeration *************************** +*/ + + +/** \defgroup grp_hci_nfc HCI Reader RF Management Component + * + * + */ + + +typedef enum phHciNfc_ReaderMgmt_Seq{ + READERA_PIPE_OPEN = 0x00U, + READERB_PIPE_OPEN, + FELICA_PROP_PIPE_OPEN, + JEWEL_PROP_PIPE_OPEN, + ISO15693_PROP_PIPE_OPEN, + NFCIP1_INITIATOR_PIPE_OPEN, + NFCIP1_INITIATOR_MODE_CONFIG, + NFCIP1_INITIATOR_PSL1_CONFIG, + NFCIP1_INITIATOR_PSL2_CONFIG, + READERA_DISABLE_AUTO_ACTIVATE, + + + READERA_PIPE_CLOSE, + READERB_PIPE_CLOSE, + FELICA_PROP_PIPE_CLOSE, + JEWEL_PROP_PIPE_CLOSE, + ISO15693_PROP_PIPE_CLOSE, + NFCIP1_INITIATOR_PIPE_CLOSE, + END_READER_SEQUENCE +} phHciNfc_ReaderMgmt_Seq_t; + +typedef struct phHciNfc_ReaderMgmt_Info{ + phHciNfc_ReaderMgmt_Seq_t rf_gate_cur_seq; + phHciNfc_ReaderMgmt_Seq_t rf_gate_next_seq; +} phHciNfc_ReaderMgmt_Info_t; + + +/* +*************************** Static Function Declaration ************************** +*/ +static +NFCSTATUS +phHciNfc_ReaderMgmt_End_Discovery( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t reader_pipe_id + ); + +static +NFCSTATUS +phHciNfc_ReaderMgmt_Initiate_Discovery( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t reader_pipe_id + ); + +/* +*************************** Function Definitions *************************** +*/ + +#ifdef READER_INIT +/*! + * \brief Allocates the resources of RF Reader Managment Gate. + * + * This function Allocates the resources of the RF Reader Management + * gate Information Structure. + * + */ + +NFCSTATUS +phHciNfc_ReaderMgmt_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_ReaderMgmt_Info_t *p_reader_mgmt_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( ( NULL == psHciContext->p_reader_mgmt_info ) + && (phHciNfc_Allocate_Resource((void **)(&p_reader_mgmt_info), + sizeof(phHciNfc_ReaderMgmt_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_reader_mgmt_info = p_reader_mgmt_info; + p_reader_mgmt_info->rf_gate_cur_seq = READERA_PIPE_OPEN; + p_reader_mgmt_info->rf_gate_next_seq = END_READER_SEQUENCE; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + } + return status; +} + +#endif + +/*! + * \brief Updates the Sequence of RF Reader Managment Gate. + * + * This function Resets/Updates the sequence of the RF Reader Management + * gate. + * + */ + +NFCSTATUS +phHciNfc_ReaderMgmt_Update_Sequence( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t reader_seq + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_ReaderMgmt_Info_t *p_reader_mgmt_info = NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( NULL == psHciContext->p_reader_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_reader_mgmt_info = (phHciNfc_ReaderMgmt_Info_t *) + psHciContext->p_reader_mgmt_info ; + switch(reader_seq) + { + case RESET_SEQ: + case INIT_SEQ: + { + p_reader_mgmt_info->rf_gate_cur_seq = READERA_PIPE_OPEN; + p_reader_mgmt_info->rf_gate_next_seq = END_READER_SEQUENCE; + break; + } + case UPDATE_SEQ: + { + p_reader_mgmt_info->rf_gate_cur_seq = + p_reader_mgmt_info->rf_gate_next_seq; + break; + } + case INFO_SEQ: + { + status = phHciNfc_ReaderA_Update_Info(psHciContext, + HCI_READER_A_INFO_SEQ, NULL); +#if defined( TYPE_B ) + status = phHciNfc_ReaderB_Update_Info(psHciContext, + HCI_READER_B_INFO_SEQ, NULL); +#endif /* end of #if defined(TYPE_B) */ +#if defined( TYPE_FELICA ) + status = phHciNfc_Felica_Update_Info(psHciContext, + HCI_FELICA_INFO_SEQ, NULL); +#endif /* end of #if defined(TYPE_FELICA) */ +#if defined( TYPE_JEWEL ) + status = phHciNfc_Jewel_Update_Info(psHciContext, + HCI_JEWEL_INFO_SEQ, NULL); +#endif /* end of #if defined(TYPE_JEWEL) */ +#if defined( TYPE_ISO15693 ) + status = phHciNfc_ISO15693_Update_Info(psHciContext, + HCI_ISO_15693_INFO_SEQ, NULL); +#endif /* end of #if defined(TYPE_ISO15693) */ + break; + } + case REL_SEQ: + { + p_reader_mgmt_info->rf_gate_cur_seq = READERA_PIPE_CLOSE; + p_reader_mgmt_info->rf_gate_next_seq = END_READER_SEQUENCE; + break; + } + default: + { + break; + } + } + } + } + + return status; + +} + + +/*! + * \brief Initialisation of RF Reader Managment Gate. + * + * This function initialses the RF Reader Management gate and + * populates the Reader Management Information Structure + * + */ + +NFCSTATUS +phHciNfc_ReaderMgmt_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_ReaderMgmt_Info_t *p_reader_mgmt_info=NULL; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + + if( ( NULL == psHciContext->p_reader_mgmt_info ) + && (phHciNfc_Allocate_Resource((void **)(&p_reader_mgmt_info), + sizeof(phHciNfc_ReaderMgmt_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_reader_mgmt_info = p_reader_mgmt_info; + p_reader_mgmt_info->rf_gate_cur_seq = READERA_PIPE_OPEN; + p_reader_mgmt_info->rf_gate_next_seq = END_READER_SEQUENCE; + } + else + { + p_reader_mgmt_info = (phHciNfc_ReaderMgmt_Info_t *) + psHciContext->p_reader_mgmt_info ; + } + + if( NULL == psHciContext->p_reader_mgmt_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INSUFFICIENT_RESOURCES); + } +#ifdef ESTABLISH_SESSION + else if( hciMode_Session == psHciContext->hci_mode ) + { + status = NFCSTATUS_SUCCESS; + } +#endif + else + { + switch(p_reader_mgmt_info->rf_gate_cur_seq ) + { + /* Reader A pipe open sequence */ + case READERA_PIPE_OPEN: + { + p_pipe_info = ((phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + uint8_t rdr_enable = TRUE; + status = phHciNfc_ReaderA_Update_Info( + psHciContext, HCI_READER_A_ENABLE, + &rdr_enable); +#if defined( TYPE_B ) && defined ( ENABLE_AUTO_ACTIVATE ) + p_reader_mgmt_info->rf_gate_next_seq = + READERB_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #ifdef TYPE_B */ +#elif !defined( ENABLE_AUTO_ACTIVATE ) + p_reader_mgmt_info->rf_gate_next_seq = + READERA_DISABLE_AUTO_ACTIVATE; + status = NFCSTATUS_PENDING; +/* #ifdef ENABLE_AUTO_ACTIVATE */ +#elif defined( ENABLE_P2P ) + p_reader_mgmt_info->rf_gate_next_seq = + NFCIP1_INITIATOR_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* #ifdef ENABLE_P2P */ +#else + p_reader_mgmt_info->rf_gate_next_seq = + END_READER_SEQUENCE; + /* status = NFCSTATUS_PENDING; */ +#endif + } + } + break; + } + /* Reader A Auto Activate Disable */ + case READERA_DISABLE_AUTO_ACTIVATE: + { + uint8_t activate_enable = FALSE; + p_pipe_info = ((phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + + status = phHciNfc_ReaderA_Auto_Activate( psHciContext, + pHwRef, activate_enable ); + if(status == NFCSTATUS_SUCCESS) + { +#if defined (TYPE_B) + p_reader_mgmt_info->rf_gate_next_seq = + READERB_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #ifdef TYPE_B */ +#elif defined(TYPE_FELICA) + p_reader_mgmt_info->rf_gate_next_seq = + FELICA_PROP_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #elif defined(TYPE_FELICA) */ +#elif defined(TYPE_JEWEL) + p_reader_mgmt_info->rf_gate_next_seq = + JEWEL_PROP_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #elif defined(TYPE_JEWEL) */ +#elif defined (TYPE_ISO15693) + p_reader_mgmt_info->rf_gate_next_seq = + ISO15693_PROP_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #elif defined(TYPE_ISO15693) */ +#elif defined(ENABLE_P2P) + p_reader_mgmt_info->rf_gate_next_seq = + NFCIP1_INITIATOR_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #ifdef ENABLE_P2P */ +#else + p_reader_mgmt_info->rf_gate_next_seq = + END_READER_SEQUENCE; + /* status = NFCSTATUS_PENDING; */ +#endif /* #if !defined(ENABLE_P2P) && !defined(TYPE_B)*/ + } + } + break; + } +#ifdef TYPE_B + /* Reader B pipe open sequence */ + case READERB_PIPE_OPEN: + { + p_pipe_info = ((phHciNfc_ReaderB_Info_t *) + psHciContext->p_reader_b_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { +#if defined(TYPE_FELICA) + p_reader_mgmt_info->rf_gate_next_seq = + FELICA_PROP_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #ifdef TYPE_FELICA */ +#elif defined(TYPE_JEWEL) + p_reader_mgmt_info->rf_gate_next_seq = + JEWEL_PROP_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #elif defined(TYPE_JEWEL) */ +#elif defined (TYPE_ISO15693) + p_reader_mgmt_info->rf_gate_next_seq = + ISO15693_PROP_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #elif defined(TYPE_ISO15693) */ +#elif defined(ENABLE_P2P) + p_reader_mgmt_info->rf_gate_next_seq = + NFCIP1_INITIATOR_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #ifdef ENABLE_P2P */ +#else + p_reader_mgmt_info->rf_gate_next_seq = + END_READER_SEQUENCE; + /* status = NFCSTATUS_PENDING; */ +#endif /* #if !defined(ENABLE_P2P) && !defined(TYPE_FELICA)*/ + } + } + break; + } +#endif /* #ifdef TYPE_B */ +#ifdef TYPE_FELICA + /* Felica Reader pipe open sequence */ + case FELICA_PROP_PIPE_OPEN: + { + p_pipe_info = ((phHciNfc_Felica_Info_t *) + psHciContext->p_felica_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { +#if defined(TYPE_JEWEL) + p_reader_mgmt_info->rf_gate_next_seq = + JEWEL_PROP_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #if defined(TYPE_JEWEL) */ +#elif defined (TYPE_ISO15693) + p_reader_mgmt_info->rf_gate_next_seq = + ISO15693_PROP_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #elif defined(TYPE_ISO15693) */ +#elif defined(ENABLE_P2P) + p_reader_mgmt_info->rf_gate_next_seq = + NFCIP1_INITIATOR_PIPE_OPEN; + status = NFCSTATUS_PENDING; + /* end of #ifdef ENABLE_P2P */ +#else + p_reader_mgmt_info->rf_gate_next_seq = + END_READER_SEQUENCE; + /* status = NFCSTATUS_PENDING; */ +#endif /* #if !defined(ENABLE_P2P) */ + } + } + break; + } +#endif +#ifdef TYPE_JEWEL + /* Jewel Reader pipe open sequence */ + case JEWEL_PROP_PIPE_OPEN: + { + p_pipe_info = ((phHciNfc_Jewel_Info_t *) + psHciContext->p_jewel_info)->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { +#if defined (TYPE_ISO15693) + p_reader_mgmt_info->rf_gate_next_seq = + ISO15693_PROP_PIPE_OPEN; + status = NFCSTATUS_PENDING; +/* end of #if defined(TYPE_ISO15693) */ +#elif defined (ENABLE_P2P) + p_reader_mgmt_info->rf_gate_next_seq = + NFCIP1_INITIATOR_PIPE_OPEN; + status = NFCSTATUS_PENDING; + /* end of #ifdef ENABLE_P2P */ +#else + p_reader_mgmt_info->rf_gate_next_seq = + END_READER_SEQUENCE; + /* status = NFCSTATUS_PENDING; */ +#endif /* #if !defined(ENABLE_P2P) */ + } + } + break; + } +#endif + +#ifdef TYPE_ISO15693 + /* ISO15693 Reader pipe open sequence */ + case ISO15693_PROP_PIPE_OPEN: + { + p_pipe_info = ((phHciNfc_ISO15693_Info_t *) + psHciContext->p_iso_15693_info)->ps_15693_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { +#ifdef ENABLE_P2P + p_reader_mgmt_info->rf_gate_next_seq = + NFCIP1_INITIATOR_PIPE_OPEN; + status = NFCSTATUS_PENDING; + /* end of #ifdef ENABLE_P2P */ +#else + p_reader_mgmt_info->rf_gate_next_seq = + END_READER_SEQUENCE; + /* status = NFCSTATUS_PENDING; */ +#endif /* #if !defined(ENABLE_P2P) */ + } + } + break; + } + +#endif + +#ifdef ENABLE_P2P + /* NFC-IP1 Initiator pipe open sequence */ + case NFCIP1_INITIATOR_PIPE_OPEN: + { + p_pipe_info = + ((phHciNfc_NfcIP_Info_t *)psHciContext-> + p_nfcip_info)->p_init_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_reader_mgmt_info->rf_gate_next_seq = + NFCIP1_INITIATOR_MODE_CONFIG; + status = NFCSTATUS_PENDING; + } + } + break; + } + case NFCIP1_INITIATOR_MODE_CONFIG: + { + uint8_t mode = DEFAULT_NFCIP_INITIATOR_MODE_SUPPORT; + status = phHciNfc_NfcIP_SetMode( psHciContext, pHwRef, + NFCIP_INITIATOR, mode); + if(status == NFCSTATUS_PENDING ) + { + p_reader_mgmt_info->rf_gate_next_seq = + NFCIP1_INITIATOR_PSL1_CONFIG; + /* status = NFCSTATUS_SUCCESS; */ + } + break; + } + case NFCIP1_INITIATOR_PSL1_CONFIG: + { + uint8_t psl_config = NXP_NFCIP_PSL_BRS_DEFAULT; + status = phHciNfc_NfcIP_SetPSL1( psHciContext, pHwRef, + psl_config); + if(status == NFCSTATUS_PENDING ) + { + p_reader_mgmt_info->rf_gate_next_seq = + END_READER_SEQUENCE; + status = NFCSTATUS_SUCCESS; + } + break; + } +#endif + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + + }/* End of the Sequence Switch */ + + }/* End of the Reader Info Memory Check */ + + } /* End of Null Context Check */ + + return status; +} + + +/*! + * \brief Initiate the Discovery for the RF Reader . + * + * This function starts the Polling Loop and initiates the discovery + * of the Target. + * + */ +static +NFCSTATUS +phHciNfc_ReaderMgmt_Initiate_Discovery( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t reader_pipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( ( NULL == psHciContext ) + || ( NULL == pHwRef ) + || ( HCI_UNKNOWN_PIPE_ID == reader_pipe_id) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + + status = phHciNfc_Send_RFReader_Event ( psHciContext, pHwRef, + reader_pipe_id,(uint8_t) EVT_READER_REQUESTED ); + status = ( (status == NFCSTATUS_PENDING)? + NFCSTATUS_SUCCESS : status); + } + return status; +} + + +/*! + * \brief End the Discovery of the RF Reader . + * + * This function stops the Polling Loop and ends the discovery + * of the Target. + * + */ +static +NFCSTATUS +phHciNfc_ReaderMgmt_End_Discovery( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t reader_pipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( ( NULL == psHciContext ) + || ( NULL == pHwRef ) + || ( HCI_UNKNOWN_PIPE_ID == reader_pipe_id) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + + status = phHciNfc_Send_RFReader_Event ( psHciContext, pHwRef, + reader_pipe_id,(uint8_t) EVT_END_OPERATION ); + status = ( (status == NFCSTATUS_PENDING)? + NFCSTATUS_SUCCESS : status); + } + return status; +} + + +/*! + * \brief Enable the Discovery of RF Reader Managment Gate. + * + * This function Enable the discovery of the RF Reader Management + * gate. + * + */ + + +NFCSTATUS +phHciNfc_ReaderMgmt_Enable_Discovery( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_ReaderMgmt_Info_t *p_reader_mgmt_info=NULL; + uint8_t reader_pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + /* phHal_sADD_Cfg_t *p_poll_config = (phHal_sADD_Cfg_t * ) + psHciContext->p_config_params; */ + PHNFC_UNUSED_VARIABLE(p_reader_mgmt_info); + if( NULL != psHciContext->p_reader_mgmt_info ) + { + uint8_t rdr_enable = FALSE; + p_reader_mgmt_info = (phHciNfc_ReaderMgmt_Info_t *) + psHciContext->p_reader_mgmt_info ; +#ifdef TYPE_B + if ( (NULL != psHciContext->p_reader_b_info ) + /* && (FALSE == rdr_enable) */ + ) + { + /* Get the Reader B Pipe ID */ + status = phHciNfc_ReaderB_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( NFCSTATUS_SUCCESS == status ) + { + rdr_enable = (uint8_t)TRUE; + /* rdr_enable = (uint8_t) + p_poll_config->PollDevInfo.PollCfgInfo.EnableIso14443B; */ + status = phHciNfc_ReaderB_Update_Info(psHciContext, + HCI_RDR_ENABLE_TYPE, &rdr_enable); + } + } +#endif +#ifdef TYPE_FELICA + if ( (NULL != psHciContext->p_felica_info ) + /* && (FALSE == rdr_enable) */ + ) + { + /* Get the Reader F Pipe ID */ + status = phHciNfc_Felica_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( NFCSTATUS_SUCCESS == status ) + { + rdr_enable = (uint8_t)TRUE; + /* rdr_enable = (uint8_t) + ( p_poll_config->PollDevInfo.PollCfgInfo.EnableFelica212 + || p_poll_config->PollDevInfo.PollCfgInfo.EnableFelica424 ); */ + status = phHciNfc_Felica_Update_Info(psHciContext, + HCI_RDR_ENABLE_TYPE, &rdr_enable); + } + } +#endif +#ifdef TYPE_JEWEL + if ( (NULL != psHciContext->p_jewel_info ) + /* && (FALSE == rdr_enable) */ + ) + { + /* Get the Reader F Pipe ID */ + status = phHciNfc_Jewel_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( NFCSTATUS_SUCCESS == status ) + { + rdr_enable = (uint8_t)TRUE; + status = phHciNfc_Jewel_Update_Info(psHciContext, + HCI_RDR_ENABLE_TYPE, &rdr_enable); + } + } +#endif /* #ifdef TYPE_JEWEL */ +#if defined(TYPE_ISO15693) + if ( (NULL != psHciContext->p_iso_15693_info ) + /* && (FALSE == rdr_enable) */ + ) + { + /* Get the Reader F Pipe ID */ + status = phHciNfc_ISO15693_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( NFCSTATUS_SUCCESS == status ) + { + rdr_enable = (uint8_t)TRUE; + status = phHciNfc_ISO15693_Update_Info(psHciContext, + HCI_RDR_ENABLE_TYPE, &rdr_enable); + } + } + +/* end of #elif defined(TYPE_ISO15693) */ +#endif + + if(NULL != psHciContext->p_reader_a_info) + { + /* Get the Reader A Pipe ID */ + status = phHciNfc_ReaderA_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( NFCSTATUS_SUCCESS == status ) + { + rdr_enable = (uint8_t)TRUE; + status = phHciNfc_ReaderA_Update_Info(psHciContext, + HCI_RDR_ENABLE_TYPE, &rdr_enable); + } + + } + if( ( NFCSTATUS_SUCCESS == status ) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_ReaderMgmt_Initiate_Discovery( psHciContext, + pHwRef, reader_pipe_id); + } + + }/* End of the Reader Info Memory Check */ + + return status; +} + +/*! + * \brief Disable the Discovery of RF Reader Managment Gate. + * + * This function Disable the discovery of the RF Reader Management + * gate. + * + */ + +NFCSTATUS +phHciNfc_ReaderMgmt_Disable_Discovery( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_FAILED; + phHciNfc_ReaderMgmt_Info_t *p_reader_mgmt_info=NULL; + uint8_t reader_pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + /* phHal_sADD_Cfg_t *p_poll_config = (phHal_sADD_Cfg_t * ) + psHciContext->p_config_params; */ + PHNFC_UNUSED_VARIABLE(p_reader_mgmt_info); + if( NULL != psHciContext->p_reader_mgmt_info ) + { + p_reader_mgmt_info = (phHciNfc_ReaderMgmt_Info_t *) + psHciContext->p_reader_mgmt_info ; + if(NULL != psHciContext->p_reader_a_info) + { + /* Get the Reader A Pipe ID */ + status = phHciNfc_ReaderA_Get_PipeID + (psHciContext, &reader_pipe_id); +#if 0 + if( NFCSTATUS_SUCCESS == status ) + { + uint8_t rdr_enable = (uint8_t) FALSE; + status = phHciNfc_ReaderA_Update_Info(psHciContext, + HCI_RDR_ENABLE_TYPE, &rdr_enable); + } +#endif + + } +#ifdef TYPE_B + else if((NULL != psHciContext->p_reader_b_info ) + /* && (NFCSTATUS_SUCCESS != status) */ + ) + { + /* Get the Reader B Pipe ID */ + status = phHciNfc_ReaderB_Get_PipeID + (psHciContext, &reader_pipe_id); + } +#endif +#ifdef TYPE_FELICA + else if((NULL != psHciContext->p_felica_info ) + /* && (NFCSTATUS_SUCCESS != status) */ + ) + { + /* Get the Reader B Pipe ID */ + status = phHciNfc_Felica_Get_PipeID + (psHciContext, &reader_pipe_id); + } +#endif +#ifdef TYPE_JEWEL + else if((NULL != psHciContext->p_jewel_info ) + /* && (NFCSTATUS_SUCCESS != status) */ + ) + { + /* Get the Reader B Pipe ID */ + status = phHciNfc_Jewel_Get_PipeID + (psHciContext, &reader_pipe_id); + } +#endif /* #ifdef TYPE_JEWEL */ +#ifdef TYPE_ISO15693 + else if((NULL != psHciContext->p_iso_15693_info ) + /* && (NFCSTATUS_SUCCESS != status) */ + ) + { + /* Get the Reader B Pipe ID */ + status = phHciNfc_ISO15693_Get_PipeID + (psHciContext, &reader_pipe_id); + } +#endif /* #ifdef TYPE_ISO15693 */ + + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_NOT_ALLOWED); + } + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_ReaderMgmt_End_Discovery( psHciContext, + pHwRef, reader_pipe_id); + } + + }/* End of the Reader Info Memory Check */ + + return status; +} + + + + +/*! +* \brief Updates the Sequence of RF Reader Managment Gate. +* +* This function Resets/Updates the sequence of the RF Reader Management +* gate. +* +*/ + +NFCSTATUS +phHciNfc_ReaderMgmt_Info_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ +#if defined(NXP_NFCIP_ACTIVATE_DELAY) + static uint8_t nfc_atr_retry = 0; +#endif + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_ReaderMgmt_Info_t *p_reader_mgmt_info=NULL; +#if 0 + uint8_t reader_pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + phHal_eRemDevType_t target_type = phHal_eUnknown_DevType; +#endif + + + PHNFC_UNUSED_VARIABLE(p_reader_mgmt_info); + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( NULL != psHciContext->p_reader_mgmt_info ) + { + p_reader_mgmt_info = (phHciNfc_ReaderMgmt_Info_t *) + psHciContext->p_reader_mgmt_info ; + switch( psHciContext->host_rf_type ) + { + + case phHal_eISO14443_A_PCD: + { + /* If the Target Info is updated then the Target + * is connected. + */ + if(NULL == psHciContext->p_target_info) + { +#if defined(NXP_NFCIP_ACTIVATE_DELAY) + nfc_atr_retry = 0; +#endif + status = phHciNfc_ReaderA_Info_Sequence( + psHciContext, pHwRef ); + } + else + { + status = phHciNfc_ReaderA_App_Data( + psHciContext, pHwRef ); + status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); + } + break; + } +#ifdef ENABLE_P2P + case phHal_eNfcIP1_Initiator: + { + /* If the Target Info is updated then the Target + * is connected. + */ +#ifdef NFCIP_CHECK + if(NULL == psHciContext->p_target_info) +#endif + { + status = phHciNfc_NfcIP_Info_Sequence( + psHciContext, pHwRef +#ifdef NOTIFY_REQD + ,(NULL == psHciContext->p_target_info) +#endif /* #ifdef NOTIFY_REQD */ + ); + } +#ifdef NFCIP_CHECK + else + { + status = phHciNfc_NfcIP_GetATRInfo( + psHciContext, pHwRef, NFCIP_INITIATOR ); +#if defined(NXP_NFCIP_ACTIVATE_DELAY) + if ( + (NFCSTATUS_PENDING == status) + && ( NFCIP_ACTIVATE_DELAY <= nfc_atr_retry) + ) + { + nfc_atr_retry = 0; + status = NFCSTATUS_SUCCESS; + } + else + { + nfc_atr_retry++; + } +#else + status = ((NFCSTATUS_PENDING == status )? + NFCSTATUS_SUCCESS : status); +#endif + } +#endif + break; + } +#endif +#ifdef TYPE_B + case phHal_eISO14443_B_PCD: + { + if(NULL == psHciContext->p_target_info) + { + status = phHciNfc_ReaderB_Info_Sequence( + psHciContext, pHwRef ); + } + break; + } +#endif /* #ifdef TYPE_B */ +#ifdef TYPE_FELICA + case phHal_eFelica_PCD: + { + if(NULL == psHciContext->p_target_info) + { +#if defined(NXP_NFCIP_ACTIVATE_DELAY) + nfc_atr_retry = 0; +#endif + status = phHciNfc_Felica_Info_Sequence( + psHciContext, pHwRef ); + } + break; + } +#endif /* #ifdef TYPE_FELICA */ +#ifdef TYPE_JEWEL + case phHal_eJewel_PCD: + { + if(NULL == psHciContext->p_target_info) + { + status = phHciNfc_Jewel_Info_Sequence( + psHciContext, pHwRef ); + } + break; + } +#endif /* #ifdef TYPE_JEWEL */ +#if defined(TYPE_ISO15693) + case phHal_eISO15693_PCD: + { + if(NULL == psHciContext->p_target_info) + { + status = phHciNfc_ISO15693_Info_Sequence( + psHciContext, pHwRef ); + } + break; + } +#endif + default: + { + break; + } + } + + }/* End of the Reader Info Memory Check */ + + } /* End of Null Context Check */ + + return status; + +} + + +/*! + * \brief Connects the the selected tag via RF Reader Gates. + * + * This function connects the selected tags via RF Reader Gate. + * This function uses the RF Reader gate based on the type of the + * tag specified. + */ + + +NFCSTATUS +phHciNfc_ReaderMgmt_Select( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHal_eRemDevType_t target_type + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t reader_pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + switch (target_type) + { + case phHal_eMifare_PICC: + case phHal_eISO14443_3A_PICC: + { + /* Get the Reader A Pipe ID */ + status = phHciNfc_ReaderA_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_ReaderMgmt_Reactivate( + psHciContext, pHwRef, target_type ); + } + break; + } + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_4A_PICC: + { +#ifdef ENABLE_AUTO_ACTIVATE + /* Get the Reader A Pipe ID */ + status = phHciNfc_ReaderA_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_Send_RFReader_Command (psHciContext, + pHwRef, reader_pipe_id, NXP_WR_PRESCHECK ); + } +#else + status = phHciNfc_ReaderA_Cont_Activate( + psHciContext, pHwRef); +#endif /* #ifdef ENABLE_AUTO_ACTIVATE */ + break; + } +#ifdef TYPE_B + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4B_PICC: + { + /* Get the Reader B Pipe ID */ + status = phHciNfc_ReaderB_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_Send_RFReader_Command (psHciContext, + pHwRef, reader_pipe_id, NXP_WR_PRESCHECK ); + /* status = phHciNfc_ReaderA_Set_DataRateMax( + psHciContext, pHwRef, + DATA_RATE_MAX_DEFAULT_VALUE ); */ + /* status = phHciNfc_ReaderMgmt_Reactivate( + psHciContext, pHwRef, target_type ); */ + } + break; + } +#endif /* #ifdef TYPE_B */ +#ifdef TYPE_FELICA + case phHal_eFelica_PICC: + { + status = phHciNfc_Felica_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + /* Get the Reader Felica Pipe ID */ + /* status = phHciNfc_ReaderA_Set_DataRateMax( + psHciContext, pHwRef, + DATA_RATE_MAX_DEFAULT_VALUE ); */ + status = phHciNfc_ReaderMgmt_Reactivate( + psHciContext, pHwRef, target_type ); + } + break; + } +#endif /* #ifdef TYPE_FELICA */ +#ifdef TYPE_JEWEL + case phHal_eJewel_PICC: + { + /* Get the Reader jewel Pipe ID */ + status = phHciNfc_Jewel_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_Jewel_GetRID( + psHciContext, pHwRef); + } + break; + } +#endif /* #ifdef TYPE_JEWEL */ +#ifdef TYPE_ISO15693 + case phHal_eISO15693_PICC: + { + /* Get the Reader ISO 15693 Pipe ID */ + status = phHciNfc_ISO15693_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + /* TODO */ + status = phHciNfc_ReaderA_Set_DataRateMax( + psHciContext, pHwRef, + DATA_RATE_MAX_DEFAULT_VALUE ); + } + break; + } +#endif /* #ifdef TYPE_ISO15693 */ +#ifdef ENABLE_P2P + case phHal_eNfcIP1_Target: + { + if ( (phHal_eISO14443_A_PCD == + psHciContext->host_rf_type ) + || (phHal_eFelica_PCD == + psHciContext->host_rf_type ) + ) + { + status = phHciNfc_Initiator_Cont_Activate( + psHciContext, pHwRef); + } + else + { + status = phHciNfc_NfcIP_Presence_Check (psHciContext, pHwRef); + } + break; + } +#endif +#if 0 + case phHal_eNfcIP1_Initiator: + { + + break; + } +#endif + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + + } /* End of the tag_type Switch */ + } + + return status; +} + +NFCSTATUS +phHciNfc_ReaderMgmt_UICC_Dispatch( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHal_eRemDevType_t target_type + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t reader_pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if (NULL == psHciContext->p_target_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + switch (target_type) + { + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_4A_PICC: + { + /* Get the Reader A Pipe ID */ + status = phHciNfc_ReaderA_Get_PipeID( + psHciContext, &reader_pipe_id); + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + p_pipe_info->param_info = &psHciContext->p_target_info-> + RemoteDevInfo.Iso14443A_Info.Uid; + p_pipe_info->param_length = psHciContext->p_target_info-> + RemoteDevInfo.Iso14443A_Info.UidLength; + + break; + } +#ifdef TYPE_B + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4B_PICC: + { + /* Get the Reader B Pipe ID */ + status = phHciNfc_ReaderB_Get_PipeID + (psHciContext, &reader_pipe_id); + + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + p_pipe_info->param_info = &psHciContext->p_target_info-> + RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.Pupi; + p_pipe_info->param_length = PHHAL_PUPI_LENGTH; + break; + } +#endif /* #ifdef TYPE_B */ + case phHal_eMifare_PICC: + case phHal_eISO14443_3A_PICC: + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + + } /* End of the tag_type Switch */ + } + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_Send_RFReader_Command (psHciContext, + pHwRef, reader_pipe_id, NXP_WR_DISPATCH_TO_UICC ); + } + + return status; +} + + +NFCSTATUS +phHciNfc_ReaderMgmt_Reactivate( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHal_eRemDevType_t target_type + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t reader_pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if (NULL == psHciContext->p_target_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + switch (target_type) + { + case phHal_eISO14443_A_PICC: + case phHal_eMifare_PICC: + case phHal_eISO14443_4A_PICC: + case phHal_eISO14443_3A_PICC: + { + /* Get the Reader A Pipe ID */ + status = phHciNfc_ReaderA_Get_PipeID( + psHciContext, &reader_pipe_id); + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + p_pipe_info->param_info = &psHciContext->p_target_info-> + RemoteDevInfo.Iso14443A_Info.Uid; + p_pipe_info->param_length = psHciContext->p_target_info-> + RemoteDevInfo.Iso14443A_Info.UidLength; + + break; + } +#ifdef TYPE_B + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4B_PICC: + { + /* Get the Reader B Pipe ID */ + status = phHciNfc_ReaderB_Get_PipeID + (psHciContext, &reader_pipe_id); + + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + p_pipe_info->param_info = &psHciContext->p_target_info-> + RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.Pupi; + p_pipe_info->param_length = PHHAL_PUPI_LENGTH; + break; + } +#endif /* #ifdef TYPE_B */ +#ifdef TYPE_FELICA + case phHal_eFelica_PICC: + { + /* Get the Felica Reader Pipe ID */ + status = phHciNfc_Felica_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + p_pipe_info->param_info = &psHciContext->p_target_info-> + RemoteDevInfo.Felica_Info.IDm; + p_pipe_info->param_length = PHHAL_FEL_ID_LEN; + } + break; + } +#endif /* #ifdef TYPE_FELICA */ +#ifdef ENABLE_P2P + case phHal_eNfcIP1_Target: + { + /* Get the Initiator Pipe ID */ + status = phHciNfc_Initiator_Get_PipeID( + psHciContext, &reader_pipe_id); + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + p_pipe_info->param_info = &psHciContext->p_target_info-> + RemoteDevInfo.NfcIP_Info.NFCID; + p_pipe_info->param_length = psHciContext->p_target_info-> + RemoteDevInfo.NfcIP_Info.NFCID_Length; + break; + } + case phHal_eNfcIP1_Initiator: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } +#endif /* #ifdef ENABLE_P2P */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + + } /* End of the tag_type Switch */ + } + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_Send_RFReader_Command (psHciContext, + pHwRef, reader_pipe_id, NXP_WR_ACTIVATE_ID ); + } + + return status; +} + + +/*! +* \brief Activates the next Remote Target in the field. +* +* This function selects and activates the next tag present in the field. +*/ + + +NFCSTATUS +phHciNfc_ReaderMgmt_Activate_Next( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + /* phHciNfc_Pipe_Info_t *p_pipe_info = NULL; */ + uint8_t reader_pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + switch ( psHciContext->host_rf_type ) + { + case phHal_eISO14443_A_PCD: + { + /* Get the Reader A Pipe ID */ + status = phHciNfc_ReaderA_Get_PipeID + (psHciContext, &reader_pipe_id); + + break; + } +#ifdef TYPE_B + case phHal_eISO14443_B_PCD: + { + /* Get the Reader B Pipe ID */ + status = phHciNfc_ReaderB_Get_PipeID + (psHciContext, &reader_pipe_id); + + break; + } +#endif /* #ifdef TYPE_B */ +#ifdef TYPE_FELICA + case phHal_eFelica_PCD: + { + /* Get the Felica Reader Pipe ID */ + status = phHciNfc_Felica_Get_PipeID + (psHciContext, &reader_pipe_id); + + break; + } +#endif /* #ifdef TYPE_FELICA */ +#ifdef TYPE_ISO15693 + case phHal_eISO15693_PCD: + { + /* Get the ISO 15693 Reader Pipe ID */ + status = phHciNfc_ISO15693_Get_PipeID + (psHciContext, &reader_pipe_id); + + break; + } +#endif /* #ifdef TYPE_ISO15693 */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + + } /* End of the reader_type Switch */ + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_Send_RFReader_Command (psHciContext, + pHwRef, reader_pipe_id, NXP_WR_ACTIVATE_NEXT ); + } + + } + + return status; + +} + +/*! +* \brief Checks the presence of the Remote Target in the field. +* +* This function checks the presence of the tag present in the field. +*/ + + +NFCSTATUS +phHciNfc_ReaderMgmt_Presence_Check( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + /* phHciNfc_Pipe_Info_t *p_pipe_info = NULL; */ + uint8_t reader_pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + phHal_eRemDevType_t target_type = phHal_eUnknown_DevType; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + target_type = psHciContext->p_target_info->RemDevType; + switch (target_type) + { + case phHal_eMifare_PICC: + case phHal_eISO14443_3A_PICC: + { + /* Get the Reader A Pipe ID */ + status = phHciNfc_ReaderA_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_ReaderMgmt_Reactivate( + psHciContext, pHwRef, target_type ); + } + break; + } + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_4A_PICC: + { + /* Get the Reader A Pipe ID */ + status = phHciNfc_ReaderA_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_Send_RFReader_Command (psHciContext, + pHwRef, reader_pipe_id, NXP_WR_PRESCHECK ); + } + break; + } +#ifdef ENABLE_P2P + case phHal_eNfcIP1_Target: + { + status = phHciNfc_NfcIP_Presence_Check (psHciContext, pHwRef); + break; + } +#endif +#ifdef TYPE_B + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4B_PICC: + { + /* Get the Reader B Pipe ID */ + status = phHciNfc_ReaderB_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_Send_RFReader_Command (psHciContext, + pHwRef, reader_pipe_id, NXP_WR_PRESCHECK ); + } + break; + } +#endif /* #ifdef TYPE_B */ +#ifdef TYPE_FELICA + case phHal_eFelica_PICC: + { + /* Get the Felica Reader Pipe ID */ + status = phHciNfc_Felica_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + status = phHciNfc_Felica_Request_Mode(psHciContext, pHwRef); + } + break; + } +#endif /* #ifdef TYPE_FELICA */ +#ifdef TYPE_JEWEL + case phHal_eJewel_PICC: + { + /* Get the Jewel Reader Pipe ID */ + status = phHciNfc_Jewel_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + /* status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_FEATURE_NOT_SUPPORTED); */ + status = phHciNfc_Jewel_GetRID( + psHciContext, pHwRef); + } + break; + } +#endif /* #ifdef TYPE_JEWEL */ +#ifdef TYPE_ISO15693 + case phHal_eISO15693_PICC: + { + /* Get the Reader ISO 15693 Pipe ID */ + status = phHciNfc_ISO15693_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + uint8_t cmd[11]; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + p_pipe_info->param_info = &cmd; + p_pipe_info->param_length = 11; + // masked inventory command: + // set #slots to 1 to use mask without padding, + // need to set inventory flag to enable setting #slots + cmd[0] = 0x04 | 0x20; // FLAG_INVENTORY | FLAG_SLOTS + cmd[1] = 0x01; // CMD_INVENTORY + cmd[2] = 64; // mask bit-length + memcpy(cmd + 3, &(psHciContext->p_target_info->RemoteDevInfo.Iso15693_Info.Uid), 8); + status = phHciNfc_Send_ISO15693_Command( + psHciContext, pHwRef + ,reader_pipe_id, NXP_ISO15693_CMD ); + + } + break; + } +#endif /* #ifdef TYPE_ISO15693 */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + + } /* End of the tag_type Switch */ + } + + return status; + +} + + +/*! + * \brief Disconnects the the selected tag. + * + * This function disconnects the selected tags via RF Reader Gate. + * This function uses the RF Reader gate based on the type of the + * tag specified. + */ + + +NFCSTATUS +phHciNfc_ReaderMgmt_Deselect( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHal_eRemDevType_t target_type, + uint8_t re_poll + ) +{ + static uint8_t rls_param = FALSE; + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t reader_pipe_id = + (uint8_t) HCI_UNKNOWN_PIPE_ID; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + + + + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + rls_param = re_poll; + + switch (target_type) + { + case phHal_eMifare_PICC: + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_3A_PICC: + case phHal_eISO14443_4A_PICC: + { + /* Get the Reader A Pipe ID */ + status = phHciNfc_ReaderA_Get_PipeID + (psHciContext, &reader_pipe_id); + break; + } +#ifdef TYPE_B + case phHal_eISO14443_B_PICC: + case phHal_eISO14443_4B_PICC: + { + /* Get the Reader B Pipe ID */ + status = phHciNfc_ReaderB_Get_PipeID + (psHciContext, &reader_pipe_id); + + break; + } +#endif /* #ifdef TYPE_B */ +#ifdef TYPE_FELICA + case phHal_eFelica_PICC: + { + /* Get the Felica Pipe ID */ + status = phHciNfc_Felica_Get_PipeID + (psHciContext, &reader_pipe_id); + + break; + } +#endif /* #ifdef TYPE_FELICA */ +#ifdef TYPE_JEWEL + case phHal_eJewel_PICC: + { + /* Get the Jewel Pipe ID */ + status = phHciNfc_Jewel_Get_PipeID + (psHciContext, &reader_pipe_id); + + break; + } +#endif /* #ifdef TYPE_JEWEL */ +#ifdef TYPE_ISO15693 + case phHal_eISO15693_PICC: + { + /* Get the ISO 15693 Pipe ID */ + status = phHciNfc_ISO15693_Get_PipeID + (psHciContext, &reader_pipe_id); + + break; + } +#endif /* #ifdef TYPE_ISO15693 */ +#ifdef ENABLE_P2P + case phHal_eNfcIP1_Target: + { + /* Get the Reader A Pipe ID */ + status = phHciNfc_Initiator_Get_PipeID + (psHciContext, &reader_pipe_id); + + break; + } +#endif + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + + } /* End of the tag_type Switch */ + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + && ( NULL != p_pipe_info ) ) + { + if (TRUE == rls_param) + { + p_pipe_info->param_info = &rls_param; + p_pipe_info->param_length = sizeof(rls_param); + } + status = phHciNfc_Send_RFReader_Event ( psHciContext, pHwRef, + reader_pipe_id,(uint8_t) NXP_EVT_RELEASE_TARGET ); + } + } + + return status; +} + + +/*! + * \brief Exchanges the data to/from the selected tags via RF Reader Gates. + * + * This function Exchanges the data to/from the selected tags + * via RF Reader Gates. This function uses the RF Reader gate based on the + * type of the selected tag and the type of the Reader gate specified. + */ + + +NFCSTATUS +phHciNfc_ReaderMgmt_Exchange_Data( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_XchgInfo_t *p_xchg_info + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t reader_pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID; + phHal_eRemDevType_t target_type = phHal_eUnknown_DevType; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if (NULL == psHciContext->p_xchg_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + + } + else + { + switch (psHciContext->host_rf_type) + { + case phHal_eISO14443_A_PCD: + { + /* Get the Reader A Pipe ID */ + status = phHciNfc_ReaderA_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + p_pipe_info->param_info = p_xchg_info->tx_buffer; + p_pipe_info->param_length = p_xchg_info->tx_length; + target_type = psHciContext->p_target_info->RemDevType; + switch (target_type) + { + case phHal_eMifare_PICC: + case phHal_eISO14443_3A_PICC: + { + if ((uint8_t)phHal_eMifareRaw == + p_xchg_info->params.tag_info.cmd_type) + { + status = phHciNfc_Send_ReaderA_Command( + psHciContext, pHwRef + ,reader_pipe_id, NXP_MIFARE_RAW ); + } + else + { + status = phHciNfc_Send_ReaderA_Command( + psHciContext, pHwRef, + reader_pipe_id, NXP_MIFARE_CMD ); + } + break; + } + case phHal_eISO14443_A_PICC: + case phHal_eISO14443_4A_PICC: + { + status = phHciNfc_Send_RFReader_Command( + psHciContext, pHwRef, + reader_pipe_id, WR_XCHGDATA ); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + } /* End of the tag_type Switch */ + } /* End of Pipe ID Check */ + break; + } +#ifdef TYPE_B + case phHal_eISO14443_B_PCD: + { + /* Get the Reader B Pipe ID */ + status = phHciNfc_ReaderB_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + p_pipe_info->param_info = p_xchg_info->tx_buffer; + p_pipe_info->param_length = p_xchg_info->tx_length; + status = phHciNfc_Send_RFReader_Command( + psHciContext, pHwRef, + reader_pipe_id, WR_XCHGDATA ); + } + break; + } +#endif /* #ifdef TYPE_B */ +#ifdef TYPE_FELICA + case phHal_eFelica_PCD: + { + /* Get the Felica Reader Pipe ID */ + status = phHciNfc_Felica_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + p_pipe_info->param_info = p_xchg_info->tx_buffer; + p_pipe_info->param_length = p_xchg_info->tx_length; + if ((uint8_t)phHal_eFelica_Raw == + p_xchg_info->params.tag_info.cmd_type) + { + status = phHciNfc_Send_Felica_Command( + psHciContext, pHwRef + ,reader_pipe_id, NXP_FELICA_RAW ); + } + else + { + status = phHciNfc_Send_Felica_Command( + psHciContext, pHwRef, + reader_pipe_id, NXP_FELICA_CMD ); + } + } + break; + } +#endif /* #ifdef TYPE_FELICA */ +#if defined(TYPE_ISO15693) + case phHal_eISO15693_PCD: + { + /* Get the ISO15693 Reader Pipe ID */ + status = phHciNfc_ISO15693_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + p_pipe_info->param_info = p_xchg_info->tx_buffer; + p_pipe_info->param_length = p_xchg_info->tx_length; + if (((uint8_t)phHal_eIso15693_Cmd == + p_xchg_info->params.tag_info.cmd_type) +#if defined(SUPPORT_ISO15693_RAW) + || ((uint8_t) phHal_eIso15693_Raw == + p_xchg_info->params.tag_info.cmd_type) +#endif + ) + { + status = phHciNfc_Send_ISO15693_Command( + psHciContext, pHwRef + ,reader_pipe_id, NXP_ISO15693_CMD ); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_PARAMETER); + } + } + break; + } +#endif +#ifdef TYPE_JEWEL + case phHal_eJewel_PCD: + { + /* Get the Jewel Reader Pipe ID */ + status = phHciNfc_Jewel_Get_PipeID + (psHciContext, &reader_pipe_id); + + if( (NFCSTATUS_SUCCESS == status) + && (reader_pipe_id != HCI_UNKNOWN_PIPE_ID ) + ) + { + uint8_t transact_type = 0; + p_pipe_info = psHciContext->p_pipe_list[reader_pipe_id]; + p_pipe_info->param_info = p_xchg_info->tx_buffer; + p_pipe_info->param_length = p_xchg_info->tx_length; + switch(p_xchg_info->params.tag_info.cmd_type) + { + case phHal_eJewel_Raw: + { + transact_type = NXP_JEWEL_RAW; + break; + } + case phHal_eJewel_Invalid: + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_PARAMETER); + break; + } + } + if(0 != transact_type) + { + status = phHciNfc_Send_Jewel_Command( + psHciContext, pHwRef, + reader_pipe_id, transact_type ); + } + } + break; + } +#endif /* #ifdef TYPE_JEWEL */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + }/* End of Reader Type Switch */ + } + + return status; +} + + + +/*! + * \brief Releases the resources allocated the RF Reader Management. + * + * This function Releases the resources allocated the RF Reader Management. + */ + +NFCSTATUS +phHciNfc_ReaderMgmt_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + phHciNfc_ReaderMgmt_Info_t *p_reader_mgmt_info=NULL; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( NULL != psHciContext->p_reader_mgmt_info ) + { + p_reader_mgmt_info = (phHciNfc_ReaderMgmt_Info_t *) + psHciContext->p_reader_mgmt_info ; + switch(p_reader_mgmt_info->rf_gate_cur_seq) + { + /* Reader A pipe close sequence */ + case READERA_PIPE_CLOSE: + { + p_pipe_info = ((phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info)->p_pipe_info; + + status = phHciNfc_Close_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_reader_mgmt_info->rf_gate_next_seq = + READERB_PIPE_CLOSE; + /* status = NFCSTATUS_PENDING; */ + } + break; + } +#ifdef TYPE_B + /* Reader B pipe close sequence */ + case READERB_PIPE_CLOSE: + { + p_pipe_info = ((phHciNfc_ReaderB_Info_t *) + psHciContext->p_reader_b_info)->p_pipe_info; + + status = phHciNfc_Close_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_reader_mgmt_info->rf_gate_next_seq = + FELICA_PROP_PIPE_CLOSE; + status = NFCSTATUS_PENDING; + } + break; + } +#endif /* #ifdef TYPE_B */ +#ifdef TYPE_FELICA + /* Felica Reader pipe close sequence */ + case FELICA_PROP_PIPE_CLOSE: + { + p_pipe_info = ((phHciNfc_Felica_Info_t *) + psHciContext->p_felica_info)->p_pipe_info; + + status = phHciNfc_Close_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_reader_mgmt_info->rf_gate_next_seq = + NFCIP1_INITIATOR_PIPE_CLOSE; + /* status = NFCSTATUS_PENDING; */ + } + break; + } +#endif /* #ifdef TYPE_FELICA */ +#ifdef ENABLE_P2P + /* NFC-IP1 Initiator pipe Close sequence */ + case NFCIP1_INITIATOR_PIPE_CLOSE: + { + p_pipe_info = + ((phHciNfc_NfcIP_Info_t *)psHciContext-> + p_nfcip_info)->p_init_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + status = phHciNfc_Open_Pipe( psHciContext, + pHwRef, p_pipe_info ); + if(status == NFCSTATUS_SUCCESS) + { + p_reader_mgmt_info->rf_gate_next_seq = READERA_PIPE_CLOSE; + status = NFCSTATUS_PENDING; + } + } + break; + } +#endif /* #ifdef ENABLE_P2P */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + + }/* End of the Sequence Switch */ + + }/* End of the Reader Info Memory Check */ + + } /* End of Null Context Check */ + + return status; +} + + +/*! + * \brief Sends the RF Reader HCI Events to the connected reader device. + * + * This function Sends the RF Reader HCI Event frames in the HCP packet format to the + * connected reader device. + */ + + NFCSTATUS + phHciNfc_Send_RFReader_Event ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t event + ) + { + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t length = 0; + uint8_t i = 0; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || ( pipe_id > PHHCINFC_MAX_PIPE) + ||(NULL == psHciContext->p_pipe_list[pipe_id]) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + HCI_DEBUG("%s: Invalid Arguments passed \n", + "phHciNfc_Send_RFReader_Event"); + } + else + { + p_pipe_info = (phHciNfc_Pipe_Info_t *) + psHciContext->p_pipe_list[pipe_id]; + psHciContext->tx_total = 0 ; + length += HCP_HEADER_LEN ; + switch( event ) + { + case EVT_READER_REQUESTED: + case EVT_END_OPERATION: + { + + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_EVENT, event); + break; + } + case NXP_EVT_RELEASE_TARGET: + { + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_EVENT, event); + hcp_message = &(hcp_packet->msg.message); + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, p_pipe_info->param_info, + p_pipe_info->param_length); + length =(uint16_t)(length + i + p_pipe_info->param_length); + break; + } + default: + { + status = PHNFCSTVAL( CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED ); + HCI_DEBUG("%s: Statement Should Not Occur \n", + "phHciNfc_Send_RFReader_Event"); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + p_pipe_info->sent_msg_type = HCP_MSG_TYPE_EVENT ; + p_pipe_info->prev_msg = event ; + psHciContext->tx_total = length; + + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef ); + p_pipe_info->prev_status = NFCSTATUS_PENDING; + } + } + + return status; +} + +/*! + * \brief Sends the RF Reader HCI Additonal Commands to the connected + * reader device. + * + * This function Sends the RF Reader HCI Command frames in the HCP packet + * format to the connected reader device. + */ + + NFCSTATUS + phHciNfc_Send_RFReader_Command ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ) + { + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t i = 0; + uint16_t length=0; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || ( pipe_id > PHHCINFC_MAX_PIPE) + ||(NULL == psHciContext->p_pipe_list[pipe_id]) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + HCI_DEBUG("%s: Invalid Arguments passed \n", + "phHciNfc_Send_RFReader_Command"); + } + else + { + p_pipe_info = (phHciNfc_Pipe_Info_t *) + psHciContext->p_pipe_list[pipe_id]; + psHciContext->tx_total = 0 ; + length += HCP_HEADER_LEN ; + switch( cmd ) + { + case WR_XCHGDATA: + { + + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + hcp_message = &(hcp_packet->msg.message); + /* Frame Wait Timeout */ + hcp_message->payload[i++] = nxp_nfc_isoxchg_timeout ; + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, p_pipe_info->param_info, + p_pipe_info->param_length); + length =(uint16_t)(length + i + p_pipe_info->param_length); + break; + } + case NXP_WR_PRESCHECK: + case NXP_WR_ACTIVATE_NEXT: + { + + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + break; + } + case NXP_WR_DISPATCH_TO_UICC: + case NXP_WR_ACTIVATE_ID: + { + + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + hcp_message = &(hcp_packet->msg.message); + /* UID of the Card */ + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, p_pipe_info->param_info, + p_pipe_info->param_length); + length =(uint16_t)(length + i + p_pipe_info->param_length); + break; + } + default: + { + status = PHNFCSTVAL( CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED ); + HCI_DEBUG("%s: Statement Should Not Occur \n", + "phHciNfc_Send_RFReader_Command"); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + p_pipe_info->sent_msg_type = HCP_MSG_TYPE_COMMAND; + p_pipe_info->prev_msg = cmd; + psHciContext->tx_total = length; + psHciContext->response_pending = TRUE ; + + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef ); + p_pipe_info->prev_status = NFCSTATUS_PENDING; + } + } + + return status; +} + + + diff --git a/libnfc-nxp/phHciNfc_RFReader.h b/libnfc-nxp/phHciNfc_RFReader.h new file mode 100644 index 0000000..751fbbb --- /dev/null +++ b/libnfc-nxp/phHciNfc_RFReader.h @@ -0,0 +1,558 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_RFReader.h * +* \brief HCI Header for the RF Reader Management Gate. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Aug 14 17:01:28 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.17 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + + +#ifndef PHHCINFC_RFREADER_H +#define PHHCINFC_RFREADER_H + +/*@}*/ + + +/** + * \name HCI + * + * File: \ref phHciNfc_RFReader.h + * + */ +/*@{*/ +#define PHHCINFC_RF_READER_FILEREVISION "$Revision: 1.17 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_RF_READER_FILEALIASES "$Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ +/* Events Requested by the Reader Application Gates */ +#define EVT_READER_REQUESTED 0x10U +#define EVT_END_OPERATION 0x11U + +/* Events Triggered by the Reader RF Gates */ +#define EVT_TARGET_DISCOVERED 0x10U + +/* Commands from ETSI HCI Specification */ +#define WR_XCHGDATA 0x10U + +/* NXP Additional Commands apart from ETSI HCI Specification */ +/* Command to Check the presence of the card */ +#define NXP_WR_PRESCHECK 0x30U + +/* Command to Activate the next card present in the field */ +#define NXP_WR_ACTIVATE_NEXT 0x31U + +/* Command to Activate a card with its UID */ +#define NXP_WR_ACTIVATE_ID 0x32U + +/* Command to Dispatch the card to UICC */ +#define NXP_WR_DISPATCH_TO_UICC 0x33U + +/* NXP Additional Events apart from ETSI HCI Specification */ +/* Event to Release the Target and Restart The Wheel */ +#define NXP_EVT_RELEASE_TARGET 0x35U + + +/* Type Macro to Update the RF Reader Information */ + +#define HCI_RDR_ENABLE_TYPE 0x01U + +#define UICC_CARD_ACTIVATION_SUCCESS 0x00U +#define UICC_CARD_ACTIVATION_ERROR 0x01U +#define UICC_RDR_NOT_INTERESTED 0x02U + + +/* +******************** Enumeration and Structure Definition ********************** +*/ + + + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_ReaderMgmt_Initialise function creates and the opens RF Reader + * Management Gate + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Reader RF Mgmt Gate Initialisation is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ +extern +NFCSTATUS +phHciNfc_ReaderMgmt_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_ReaderMgmt_Release function closes the opened RF Reader pipes + * between the Host Controller Device and the NFC Device. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Release of the Reader RF Management gate + * resources are pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ +extern +NFCSTATUS +phHciNfc_ReaderMgmt_Release( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_ReaderMgmt_Update_Sequence function Resets/Updates the sequence + * to the Specified RF Reader Sequence . + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] reader_seq reader_seq is the Type of sequence update + * required to reset . + * + * \retval NFCSTATUS_SUCCESS Updates/Resets the Sequence of the Reader + * RF Management gate Successsfully. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval + * NFCSTATUS_INVALID_HCI_INFORMATION The RF Reader Management information is + * invalid. + * + */ + +extern +NFCSTATUS +phHciNfc_ReaderMgmt_Update_Sequence( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t reader_seq + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_ReaderMgmt_Enable_Discovery function Enables the RF Reader + * Gates to discover the corresponding PICC Tags . + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Enable of the Reader RF Management gate + * Discovery is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_ReaderMgmt_Enable_Discovery( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_ReaderMgmt_Discovery function Enables/Disables/Restart/Continue + * the RF Reader Gates to discover the corresponding PICC Tags . + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Enable of the Reader RF Management gate + * Discovery is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_ReaderMgmt_Disable_Discovery function Disables the RF Reader + * Gates discovery . + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Disable of the Reader RF Management gate + * Discovery is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_ReaderMgmt_Disable_Discovery( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_ReaderMgmt_Info_Sequence function Gets the information + * of the Tag discovered . + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_PENDING Reception the information of the discoverd + * tag is ongoing. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_ReaderMgmt_Info_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_ReaderMgmt_Select function connects the + * the selected tag by performing certain operation. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] target_type target_type is the type of the + * Target Device to be connected . + * + * \retval NFCSTATUS_PENDING The selected tag initialisation for + * transaction ongoing. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_ReaderMgmt_Select( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHal_eRemDevType_t target_type + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_ReaderMgmt_Reactivate function reactivates the + * the tag by performing reactivate operation. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] target_type target_type is the type of the + * Target Device to be reactivated . + * + * \retval NFCSTATUS_PENDING The tag reactivation ongoing. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + + +extern +NFCSTATUS +phHciNfc_ReaderMgmt_Reactivate( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHal_eRemDevType_t target_type + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderMgmt_Presence_Check function performs presence on ISO +* cards. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link . +* +* \retval NFCSTATUS_PENDING The presence check for tag is ongoing. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* \retval Other errors Errors related to the other layers +* +*/ + +extern +NFCSTATUS +phHciNfc_ReaderMgmt_Presence_Check( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderMgmt_Activate_Next function activates and selects next +* tag or target present in the RF Field . +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link . +* +* \retval NFCSTATUS_PENDING The activation of the next tag is ongoing. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* \retval Other errors Errors related to the other layers +* +*/ + +extern +NFCSTATUS +phHciNfc_ReaderMgmt_Activate_Next( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_ReaderMgmt_UICC_Dispatch function de-activates the + * the selected tag by de-selecting the tag and dispatch the Card to UICC. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] target_type target_type is the type of the + * Target Device to be de-selected . + * \param[in] re_poll If True: Start re-polling of the target + * after the Target Device is de-activated + * or else - continue discovery with next + * technology. + * + * + * \retval NFCSTATUS_PENDING Dispatching the selected tag to UICC + * is ongoing. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_ReaderMgmt_UICC_Dispatch( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHal_eRemDevType_t target_type + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_ReaderMgmt_Deselect function de-activates the + * the selected tag by de-selecting the tag and restarting the discovery. + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] target_type target_type is the type of the + * Target Device to be de-selected . + * + * \retval NFCSTATUS_PENDING Terminating the operations between selected + * tag is ongoing. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_ReaderMgmt_Deselect( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHal_eRemDevType_t target_type, + uint8_t re_poll + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_ReaderMgmt_Exchange_Data function exchanges the + * data to/from the selected tag . + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * context Structure. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] p_xchg_info The tag exchange info contains the command type, + * addr and data to be sent to the connected + * remote target device. + * + * \retval NFCSTATUS_PENDING Exchange of the data between the selected + * tag is ongoing. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS +phHciNfc_ReaderMgmt_Exchange_Data( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHciNfc_XchgInfo_t *p_xchg_info + ); + + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Send_RFReader_Command function sends the HCI Reader Gate + * Specific Commands to the HCI Controller device. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] pipe_id The Reader pipe to which the + * command is being sent. + * \param[in] cmd The HCI Reader Gate specific command + * sent to a Reader pipe . + * + * + * \retval NFCSTATUS_PENDING ETSI HCI RF Reader gate Command + * to be sent is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS + phHciNfc_Send_RFReader_Command ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Send_RFReader_Event function sends the HCI Reader Gate + * Specific Events to the HCI Controller device. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] pipe_id The Reader pipe to which the + * command is being sent. + * \param[in] event The HCI Reader Gate specific event + * sent to a Reader pipe . + * + * + * \retval NFCSTATUS_PENDING ETSI HCI RF Reader gate Event + * to be sent is pending. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Errors related to the other layers + * + */ + +extern +NFCSTATUS + phHciNfc_Send_RFReader_Event ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t event + ); + +#endif /* PHHCINFC_RFREADER_H */ + diff --git a/libnfc-nxp/phHciNfc_RFReaderA.c b/libnfc-nxp/phHciNfc_RFReaderA.c new file mode 100644 index 0000000..1b1280a --- /dev/null +++ b/libnfc-nxp/phHciNfc_RFReaderA.c @@ -0,0 +1,1294 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_RFReaderA.c * +* \brief HCI Reader A Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Wed Feb 17 16:19:04 2010 $ * +* $Author: ing02260 $ * +* $Revision: 1.57 $ * +* $Aliases: NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include +#include +/* +****************************** Macro Definitions ******************************* +*/ + +/* Registry used for getting the data */ +#define RDR_A_DATA_RATE_MAX_INDEX 0x01U +#define RDR_A_UID_INDEX 0x02U +#define RDR_A_SAK_INDEX 0x03U +#define RDR_A_ATQA_INDEX 0x04U +#define RDR_A_APP_DATA_INDEX 0x05U +#define RDR_A_FWI_SFGT_INDEX 0x06U + +/* Registry index for auto activation */ +#define NXP_AUTO_ACTIVATION_INDEX 0x10U + +#define RDR_A_SAK_FWI_SFGT_LENGTH 0x01U + +#define RDR_A_SINGLE_TAG_FOUND 0x00U +#define RDR_A_MULTIPLE_TAGS_FOUND 0x03U + +#define RDR_A_MAX_APP_DATA_LEN 0x30U + +/* Time out */ +#define RDR_A_MIFARE_STATUS 0x00U + +#define RDR_A_MIFARE_RAW_LENGTH 0x03U + +uint8_t nxp_nfc_mifareraw_timeout = NXP_MIFARE_XCHG_TIMEOUT; +/* +*************************** Structure and Enumeration *************************** +*/ + + +/* +*************************** Static Function Declaration ************************** +*/ + +static +NFCSTATUS +phHciNfc_Recv_ReaderA_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_ReaderA_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_ReaderA_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); + +static +NFCSTATUS +phHciNfc_Recv_Mifare_Packet( + phHciNfc_sContext_t *psHciContext, + uint8_t cmd, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_Iso_A_Packet( + phHciNfc_sContext_t *psHciContext, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); +/* +*************************** Function Definitions *************************** +*/ +NFCSTATUS +phHciNfc_ReaderA_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_reader_a_info ) + ) + { + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info ; + *ppipe_id = p_rdr_a_info->pipe_id ; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + + +NFCSTATUS +phHciNfc_ReaderA_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( + ( NULL == psHciContext->p_reader_a_info ) && + (phHciNfc_Allocate_Resource((void **)(&p_rdr_a_info), + sizeof(phHciNfc_ReaderA_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_reader_a_info = p_rdr_a_info; + p_rdr_a_info->current_seq = RDR_A_INVALID_SEQ; + p_rdr_a_info->next_seq = RDR_A_INVALID_SEQ; + p_rdr_a_info->pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + return status; +} + +NFCSTATUS +phHciNfc_ReaderA_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_reader_a_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info ; + /* Update the pipe_id of the reader A Gate obtained from the HCI Response */ + p_rdr_a_info->pipe_id = pipeID; + p_rdr_a_info->p_pipe_info = pPipeInfo; + if (NULL != pPipeInfo) + { + /* Update the Response Receive routine of the reader A Gate */ + pPipeInfo->recv_resp = &phHciNfc_Recv_ReaderA_Response; + /* Update the event Receive routine of the reader A Gate */ + pPipeInfo->recv_event = &phHciNfc_Recv_ReaderA_Event; + } + } + + return status; +} + +NFCSTATUS +phHciNfc_ReaderA_Info_Sequence ( + void *psHciHandle, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + + HCI_PRINT ("HCI : phHciNfc_ReaderA_Info_Sequence called... \n"); + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_reader_a_info) || + (HCI_READER_A_ENABLE != + ((phHciNfc_ReaderA_Info_t *)(psHciContext->p_reader_a_info))-> + enable_rdr_a_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info ; + p_pipe_info = p_rdr_a_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + HCI_DEBUG ("HCI : p_rdr_a_info->current_seq : %02X\n", p_rdr_a_info->current_seq); + switch(p_rdr_a_info->current_seq) + { + case RDR_A_UID: + { + p_pipe_info->reg_index = RDR_A_UID_INDEX; + pipeid = p_rdr_a_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_rdr_a_info->next_seq = RDR_A_SAK; + } + break; + } + case RDR_A_SAK: + { + p_pipe_info->reg_index = RDR_A_SAK_INDEX; + pipeid = p_rdr_a_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_rdr_a_info->next_seq = RDR_A_ATQA; + } + break; + } + case RDR_A_ATQA: + { + p_pipe_info->reg_index = RDR_A_ATQA_INDEX; + pipeid = p_rdr_a_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_rdr_a_info->next_seq = RDR_A_END_SEQUENCE; + } + break; + } + case RDR_A_END_SEQUENCE: + { + phNfc_sCompletionInfo_t CompInfo; + if (RDR_A_MULTIPLE_TAGS_FOUND == + p_rdr_a_info->multiple_tgts_found) + { + CompInfo.status = NFCSTATUS_MULTIPLE_TAGS; + } + else + { + CompInfo.status = NFCSTATUS_SUCCESS; + } + + CompInfo.info = &(p_rdr_a_info->reader_a_info); + + p_rdr_a_info->reader_a_info.RemDevType = phHal_eISO14443_A_PICC; + p_rdr_a_info->current_seq = RDR_A_UID; + p_rdr_a_info->next_seq = RDR_A_UID; + status = NFCSTATUS_SUCCESS; + HCI_DEBUG ("HCI : p_rdr_a_info->reader_a_info.RemDevType : %02X\n", p_rdr_a_info->reader_a_info.RemDevType); + HCI_DEBUG ("HCI : status notified: %02X\n", CompInfo.status); + /* Notify to the upper layer */ + phHciNfc_Tag_Notify(psHciContext, + pHwRef, + NFC_NOTIFY_TARGET_DISCOVERED, + &CompInfo); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + HCI_DEBUG ("HCI : p_rdr_a_info->current_seq after : %02X\n", p_rdr_a_info->current_seq); + HCI_DEBUG ("HCI : p_rdr_a_info->next_seq : %02X\n", p_rdr_a_info->next_seq); + } + } + + HCI_PRINT ("HCI : phHciNfc_ReaderA_Info_Sequence end \n"); + return status; +} + + +static +NFCSTATUS +phHciNfc_ReaderA_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + phHal_sIso14443AInfo_t *p_tag_a_info = NULL; + + p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + (psHciContext->p_reader_a_info ); + p_tag_a_info = &(p_rdr_a_info->reader_a_info.RemoteDevInfo.Iso14443A_Info); + + switch(index) + { + case RDR_A_UID_INDEX: + { + /* Maximum UID length can go upto 10 bytes */ + if (reg_length <= PHHAL_MAX_UID_LENGTH) + { + HCI_PRINT_BUFFER("\tReader A UID", reg_value, reg_length); + /* Update UID buffer and length */ + p_tag_a_info->UidLength = reg_length; + (void)memcpy( + p_tag_a_info->Uid, + reg_value, + p_tag_a_info->UidLength); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case RDR_A_SAK_INDEX: + { + /* SAK length is 1 byte */ + if (RDR_A_SAK_FWI_SFGT_LENGTH == reg_length) + { + HCI_PRINT_BUFFER("\tReader A SAK", reg_value, reg_length); + /* Copy SAK byte */ + p_tag_a_info->Sak = *reg_value; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case RDR_A_ATQA_INDEX: + { + /* ATQA length shall be 2 bytes */ + if (PHHAL_ATQA_LENGTH == reg_length) + { + HCI_PRINT_BUFFER("\tReader A ATQA", reg_value, reg_length); + /* Copy ATQA */ + (void)memcpy(p_tag_a_info->AtqA, + reg_value, + reg_length); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case RDR_A_APP_DATA_INDEX: + { + /* Remote device info provided by the user */ + p_tag_a_info = + &(psHciContext->p_target_info->RemoteDevInfo.Iso14443A_Info); + /* Historical bytes length shall be 2 bytes */ + if (reg_length <= RDR_A_MAX_APP_DATA_LEN) + { + HCI_PRINT_BUFFER("\tReader A APP DATA", reg_value, reg_length); + p_tag_a_info->AppDataLength = reg_length; + /* Historical bytes */ + (void)memcpy(p_tag_a_info->AppData, + reg_value, + reg_length); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case RDR_A_FWI_SFGT_INDEX: + { + if (RDR_A_SAK_FWI_SFGT_LENGTH == reg_length) + { + HCI_PRINT_BUFFER("\tReader A FWI SFGT", reg_value, reg_length); + p_tag_a_info->Fwi_Sfgt = *reg_value; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + return status; +} + + +static +NFCSTATUS +phHciNfc_Recv_ReaderA_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_reader_a_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + uint8_t prev_cmd = ANY_GET_PARAMETER; + p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info ; + if( NULL == p_rdr_a_info->p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + prev_cmd = p_rdr_a_info->p_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_GET_PARAMETER: + { + status = phHciNfc_ReaderA_InfoUpdate(psHciContext, + p_rdr_a_info->p_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); +#if 0 + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); +#endif + break; + } + case ANY_SET_PARAMETER: + { + HCI_PRINT("Reader A Parameter Set \n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + p_rdr_a_info->next_seq = RDR_A_UID; + break; + } + case ANY_OPEN_PIPE: + { + HCI_PRINT("Reader A open pipe complete\n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + p_rdr_a_info->next_seq = RDR_A_UID; + break; + } + case ANY_CLOSE_PIPE: + { + HCI_PRINT("Reader A close pipe complete\n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + break; + } + case NXP_WRA_CONTINUE_ACTIVATION: + case NXP_WR_ACTIVATE_ID: + { + HCI_PRINT("Reader A continue activation or "); + HCI_PRINT("reactivation completed \n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + break; + } + case NXP_MIFARE_RAW: + case NXP_MIFARE_CMD: + { + if (length > HCP_HEADER_LEN) + { + HCI_PRINT("Mifare packet received \n"); + /* Copy buffer to the receive buffer */ + phHciNfc_Append_HCPFrame(psHciContext->recv_buffer, + 0, pResponse, length); + psHciContext->rx_total = length; + status = phHciNfc_Recv_Mifare_Packet(psHciContext, + prev_cmd, + &pResponse[HCP_HEADER_LEN], + (length - HCP_HEADER_LEN)); + + } + else if (length == HCP_HEADER_LEN) + { + psHciContext->rx_total = length; + psHciContext->rx_index = HCP_HEADER_LEN; + + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case WR_XCHGDATA: + { + if (length >= HCP_HEADER_LEN) + { + uint8_t i = 1; + HCI_PRINT("ISO 14443-4A received \n"); + /* Copy buffer to the receive buffer */ + phHciNfc_Append_HCPFrame(psHciContext->recv_buffer, + 0, pResponse, (length - i)); + psHciContext->rx_total = (length - i); + status = phHciNfc_Recv_Iso_A_Packet(psHciContext, + &pResponse[HCP_HEADER_LEN], + (length - HCP_HEADER_LEN)); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_WR_PRESCHECK: + { + HCI_PRINT("Presence check completed \n"); + break; + } + case NXP_WR_ACTIVATE_NEXT: + { + if (length > HCP_HEADER_LEN) + { + if (RDR_A_MULTIPLE_TAGS_FOUND == pResponse[HCP_HEADER_LEN]) + { + p_rdr_a_info->multiple_tgts_found = + RDR_A_MULTIPLE_TAGS_FOUND; + } + else + { + p_rdr_a_info->multiple_tgts_found = FALSE; + } + HCI_PRINT("Activate next completed \n"); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_WR_DISPATCH_TO_UICC: + { + switch(length) + { + case HCP_HEADER_LEN: + { + /* Optional error code, if no error code field + in the response, then this command is + successfully completed */ + p_rdr_a_info->uicc_activation = + UICC_CARD_ACTIVATION_SUCCESS; + break; + } + case (HCP_HEADER_LEN + 1): + { + p_rdr_a_info->uicc_activation = + pResponse[HCP_HEADER_LEN]; + break; + } /* End of case (HCP_HEADER_LEN + index) */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } /* End of switch(length) */ + if (NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } /* End of switch(prev_cmd) */ + if( NFCSTATUS_SUCCESS == status ) + { + p_rdr_a_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; + p_rdr_a_info->current_seq = p_rdr_a_info->next_seq; + } + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_Iso_A_Packet( + phHciNfc_sContext_t *psHciContext, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t i = 1; + + psHciContext->rx_index = HCP_HEADER_LEN; + /* command WRA_XCHG_DATA: so give ISO 14443-4A data to the upper layer */ + if(FALSE != pResponse[(length - i)]) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_RF_ERROR); + } + HCI_PRINT_BUFFER("ISO 14443- 4A Bytes received", pResponse, length); + + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_Mifare_Packet( + phHciNfc_sContext_t *psHciContext, + uint8_t cmd, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + /* To remove "warning (VS C4100) : unreferenced formal parameter" */ + PHNFC_UNUSED_VARIABLE(pResponse); + PHNFC_UNUSED_VARIABLE(length); + + if (NXP_MIFARE_RAW == cmd) + { +#ifdef ENABLE_MIFARE_RAW + uint8_t index = 0; +#ifndef HAL_SW_3A_STATUS + if(phHal_eISO14443_3A_PICC == psHciContext->p_target_info->RemDevType) + { + index++; + psHciContext->rx_index = (index + HCP_HEADER_LEN); + HCI_PRINT_BUFFER("Mifare Bytes received", &pResponse[index], (length - index)); + } + else +#endif + if (RDR_A_MIFARE_STATUS == pResponse[index]) /* Status byte */ + { + index++; + psHciContext->rx_index = (index + HCP_HEADER_LEN); + HCI_PRINT_BUFFER("Mifare Bytes received", &pResponse[index], (length - index)); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } +#else + psHciContext->rx_index = HCP_HEADER_LEN; + /* Give Mifare data to the upper layer */ + HCI_PRINT_BUFFER("Mifare Bytes received", pResponse, length); +#endif /* #ifdef ENABLE_MIFARE_RAW */ + } + else + { + psHciContext->rx_index = HCP_HEADER_LEN; + /* command NXP_MIFARE_CMD: so give Mifare data to the upper layer */ + HCI_PRINT_BUFFER("Mifare Bytes received", pResponse, length); + } + + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_ReaderA_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + + HCI_PRINT ("HCI : phHciNfc_Recv_ReaderA_Event called...\n"); + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_reader_a_info) || + (HCI_READER_A_ENABLE != + ((phHciNfc_ReaderA_Info_t *)(psHciContext->p_reader_a_info))-> + enable_rdr_a_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + phHciNfc_HCP_Message_t *message = NULL; + uint8_t instruction=0, + i = 0; + + p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info ; + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &p_packet->msg.message; + /* Get the instruction bits from the Message Header */ + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + + HCI_DEBUG ("HCI : instruction : %02X\n", instruction); + HCI_DEBUG ("HCI : Multiple tag found : %02X\n", message->payload[i]); + + if ((EVT_TARGET_DISCOVERED == instruction) + && ((RDR_A_MULTIPLE_TAGS_FOUND == message->payload[i] ) + || (RDR_A_SINGLE_TAG_FOUND == message->payload[i])) + ) + { + phNfc_sCompletionInfo_t pCompInfo; + + if (RDR_A_MULTIPLE_TAGS_FOUND == message->payload[i]) + { + p_rdr_a_info->multiple_tgts_found = RDR_A_MULTIPLE_TAGS_FOUND; + pCompInfo.status = NFCSTATUS_MULTIPLE_TAGS; + } + else + { + p_rdr_a_info->multiple_tgts_found = FALSE; + pCompInfo.status = NFCSTATUS_SUCCESS; + } + + psHciContext->host_rf_type = phHal_eISO14443_A_PCD; + p_rdr_a_info->reader_a_info.RemDevType = phHal_eISO14443_A_PICC; + p_rdr_a_info->current_seq = RDR_A_UID; + + HCI_DEBUG ("HCI : psHciContext->host_rf_type : %02X\n", psHciContext->host_rf_type); + HCI_DEBUG ("HCI : p_rdr_a_info->reader_a_info.RemDevType : %02X\n", p_rdr_a_info->reader_a_info.RemDevType); + HCI_DEBUG ("HCI : p_rdr_a_info->current_seq : %02X\n", p_rdr_a_info->current_seq); + + /* Notify to the HCI Generic layer To Update the FSM */ + phHciNfc_Notify_Event(psHciContext, pHwRef, + NFC_NOTIFY_TARGET_DISCOVERED, + &pCompInfo); + + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + } + } + HCI_PRINT ("HCI : phHciNfc_Recv_ReaderA_Event end\n"); + return status; +} + +NFCSTATUS +phHciNfc_ReaderA_Auto_Activate( + void *psContext, + void *pHwRef, + uint8_t activate_enable + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_reader_a_info) || + (HCI_READER_A_ENABLE != + ((phHciNfc_ReaderA_Info_t *)(psHciContext->p_reader_a_info))-> + enable_rdr_a_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info ; + p_pipe_info = p_rdr_a_info->p_pipe_info; + p_pipe_info->reg_index = NXP_AUTO_ACTIVATION_INDEX; + p_pipe_info->param_info = &activate_enable; + p_pipe_info->param_length = sizeof(activate_enable); + pipeid = p_rdr_a_info->pipe_id ; + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + status = NFCSTATUS_SUCCESS; + } + } + return status; +} + +NFCSTATUS +phHciNfc_ReaderA_Set_DataRateMax( + void *psContext, + void *pHwRef, + uint8_t data_rate_value + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_reader_a_info) || + (HCI_READER_A_ENABLE != + ((phHciNfc_ReaderA_Info_t *)(psHciContext->p_reader_a_info))-> + enable_rdr_a_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info ; + p_pipe_info = p_rdr_a_info->p_pipe_info; + p_pipe_info->reg_index = RDR_A_DATA_RATE_MAX_INDEX; + p_pipe_info->param_info = &data_rate_value; + p_pipe_info->param_length = sizeof(data_rate_value); + pipeid = p_rdr_a_info->pipe_id ; + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + } + return status; +} + + +NFCSTATUS +phHciNfc_Send_ReaderA_Command( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_reader_a_info) || + (HCI_READER_A_ENABLE != + ((phHciNfc_ReaderA_Info_t *)(psHciContext->p_reader_a_info))-> + enable_rdr_a_gate) || + (HCI_UNKNOWN_PIPE_ID == + ((phHciNfc_ReaderA_Info_t *)(psHciContext->p_reader_a_info))-> + pipe_id) || + (pipe_id != + ((phHciNfc_ReaderA_Info_t *)(psHciContext->p_reader_a_info))-> + pipe_id)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + uint8_t i = 0; + uint16_t length = HCP_HEADER_LEN; + + p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info ; + p_pipe_info = p_rdr_a_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + psHciContext->tx_total = 0 ; + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + switch(cmd) + { + case NXP_WRA_CONTINUE_ACTIVATION: + case NXP_WR_ACTIVATE_ID: + { + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + break; + } + + case NXP_MIFARE_RAW: + { + if (p_pipe_info->param_length < RDR_A_MIFARE_RAW_LENGTH) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* + Buffer shall be updated with + TO - Time out (1 byte) + Status - b0 to b2 indicate valid bits (1 byte) + Data (with CRC) - params received from this function + */ + hcp_message = &(hcp_packet->msg.message); +#ifdef ENABLE_MIFARE_RAW + /* Time out */ + hcp_message->payload[i++] = nxp_nfc_mifareraw_timeout; + /* Status */ + hcp_message->payload[i++] = RDR_A_MIFARE_STATUS; +#else + cmd = NXP_MIFARE_CMD; +#endif /* #ifdef ENABLE_MIFARE_RAW */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, (uint8_t *)p_pipe_info->param_info, +#ifdef ENABLE_MIFARE_RAW + p_pipe_info->param_length); +#else + (p_pipe_info->param_length - 2)); +#endif /* #ifdef ENABLE_MIFARE_RAW */ + +#ifdef ENABLE_MIFARE_RAW + length =(uint16_t)(length + i + p_pipe_info->param_length); +#else + length =(uint16_t)(length + i + p_pipe_info->param_length - 2); +#endif /* #ifdef ENABLE_MIFARE_RAW */ + } + break; + } + case NXP_MIFARE_CMD: + { + /* + Buffer shall be updated with + Cmd - Authentication A/B, read/write + (1 byte) + Addr - Address associated with Mifare cmd + (1 byte) + Data - params received from this function + */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_COMMAND, cmd); + hcp_message = &(hcp_packet->msg.message); + + /* Command */ + hcp_message->payload[i++] = + psHciContext->p_xchg_info->params.tag_info.cmd_type ; + /* Address */ + hcp_message->payload[i++] = + psHciContext->p_xchg_info->params.tag_info.addr ; + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, (uint8_t *)p_pipe_info->param_info, + p_pipe_info->param_length); + length =(uint16_t)(length + i + p_pipe_info->param_length); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_COMMAND); + break; + } + } + if (NFCSTATUS_SUCCESS == status) + { + p_pipe_info->sent_msg_type = (uint8_t)HCP_MSG_TYPE_COMMAND; + p_pipe_info->prev_msg = cmd; + psHciContext->tx_total = length; + psHciContext->response_pending = TRUE; + + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef); + p_pipe_info->prev_status = status; + } + } + } + return status; +} + +NFCSTATUS +phHciNfc_ReaderA_Cont_Activate ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) || (NULL == pHwRef) ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_reader_a_info) || + (HCI_READER_A_ENABLE != + ((phHciNfc_ReaderA_Info_t *)(psHciContext->p_reader_a_info))-> + enable_rdr_a_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderA_Info_t *p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info; + /* + NXP_WRA_CONTINUE_ACTIVATION: + for activation command */ + status = phHciNfc_Send_ReaderA_Command(psHciContext, + pHwRef, (uint8_t)p_rdr_a_info->pipe_id, + (uint8_t)NXP_WRA_CONTINUE_ACTIVATION); + } + return status; +} + +NFCSTATUS +phHciNfc_ReaderA_Update_Info( + phHciNfc_sContext_t *psHciContext, + uint8_t infotype, + void *rdr_a_info + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if (NULL == psHciContext) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_reader_a_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info ; + + switch(infotype) + { + case HCI_READER_A_ENABLE: + { + if(NULL != rdr_a_info) + { + p_rdr_a_info->enable_rdr_a_gate = + *((uint8_t *)rdr_a_info); + } + break; + } + case HCI_READER_A_INFO_SEQ: + { + p_rdr_a_info->current_seq = RDR_A_UID; + p_rdr_a_info->next_seq = RDR_A_UID; + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + } + } + return status; +} + +NFCSTATUS +phHciNfc_ReaderA_App_Data ( + void *psHciHandle, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_reader_a_info) || + (HCI_READER_A_ENABLE != + ((phHciNfc_ReaderA_Info_t *)(psHciContext->p_reader_a_info))-> + enable_rdr_a_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info ; + p_pipe_info = p_rdr_a_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + p_pipe_info->reg_index = RDR_A_APP_DATA_INDEX; + pipeid = p_rdr_a_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + } + } + return status; +} + +NFCSTATUS +phHciNfc_ReaderA_Fwi_Sfgt ( + void *psHciHandle, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_reader_a_info) || + (HCI_READER_A_ENABLE != + ((phHciNfc_ReaderA_Info_t *)(psHciContext->p_reader_a_info))-> + enable_rdr_a_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderA_Info_t *p_rdr_a_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_rdr_a_info = (phHciNfc_ReaderA_Info_t *) + psHciContext->p_reader_a_info ; + p_pipe_info = p_rdr_a_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + p_pipe_info->reg_index = RDR_A_FWI_SFGT_INDEX; + pipeid = p_rdr_a_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + } + } + return status; +} + diff --git a/libnfc-nxp/phHciNfc_RFReaderA.h b/libnfc-nxp/phHciNfc_RFReaderA.h new file mode 100644 index 0000000..7743186 --- /dev/null +++ b/libnfc-nxp/phHciNfc_RFReaderA.h @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_RFReaderA.h * +* \brief HCI Reader A Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Aug 14 17:01:27 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.17 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + + +#ifndef PHHCINFC_RFREADERA_H +#define PHHCINFC_RFREADERA_H + +/*@}*/ + + +/** + * \name HCI + * + * File: \ref phHciNfc_ReaderA.h + * + */ +/*@{*/ +#define PHHCINFC_RFREADERA_FILEREVISION "$Revision: 1.17 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_RFREADERA_FILEALIASES "$Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +/* Commands exposed to the upper layer */ +#define NXP_WRA_CONTINUE_ACTIVATION 0x12U +#define NXP_MIFARE_RAW 0x20U +#define NXP_MIFARE_CMD 0x21U +#define DATA_RATE_MAX_DEFAULT_VALUE 0x00U + +/* Enable the reader A */ +#define HCI_READER_A_ENABLE 0x01U +#define HCI_READER_A_INFO_SEQ 0x02U + +#define RDR_A_TIMEOUT_MIN 0x00U +#define RDR_A_TIMEOUT_MAX 0x15U +/* +******************** Enumeration and Structure Definition ********************** +*/ +typedef enum phHciNfc_ReaderA_Seq{ + RDR_A_DATA_RATE_MAX, + RDR_A_UID, + RDR_A_SAK, + RDR_A_ATQA, + RDR_A_APP_DATA, + RDR_A_FWI_SFGT, + RDR_A_END_SEQUENCE, + RDR_A_INVALID_SEQ +} phHciNfc_ReaderA_Seq_t; + +/* Information structure for the polling loop Gate */ +typedef struct phHciNfc_ReaderA_Info{ + /* Current running Sequence of the reader A Management */ + phHciNfc_ReaderA_Seq_t current_seq; + /* Next running Sequence of the reader A Management */ + phHciNfc_ReaderA_Seq_t next_seq; + /* Pointer to the reader A pipe information */ + phHciNfc_Pipe_Info_t *p_pipe_info; + uint8_t pipe_id; + /* Flag to say about the multiple targets */ + uint8_t multiple_tgts_found; + /* Reader A information */ + phHal_sRemoteDevInformation_t reader_a_info; + /* Enable or disable reader gate */ + uint8_t enable_rdr_a_gate; + /* UICC re-activation status */ + uint8_t uicc_activation; +} phHciNfc_ReaderA_Info_t; + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/*! + * \brief Allocates the resources of reader A management gate. + * + * This function Allocates the resources of the reader A management + * gate Information Structure. + * + */ +extern +NFCSTATUS +phHciNfc_ReaderA_Init_Resources( + phHciNfc_sContext_t *psHciContext + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderA_Get_PipeID function gives the pipe id of the reader A +* gate +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderA_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderA_Sequence function executes the sequence of operations, to +* get the UID, SAK, ATQA etc. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderA_Info_Sequence ( + void *psHciHandle, + void *pHwRef + ); + + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderA_App_Data function is to get the application data information. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderA_App_Data ( + void *psHciHandle, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderA_Fwi_Sfgt function is to get the frame waiting time +* information. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderA_Fwi_Sfgt ( + void *psHciHandle, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderA_Update_PipeInfo function updates the pipe_id of the reader A +* gate management Structure. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pipeID pipeID of the reader A gate +* \param[in] pPipeInfo Update the pipe Information of the reader +* A gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ + +extern +NFCSTATUS +phHciNfc_ReaderA_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Send_ReaderA_Command function executes the command sent by the +* upper layer, depending on the commands defined. +* +* \param[in] psContext psContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] pipe_id pipeID of the reader A gate +* \param[in] cmd command that needs to be sent to the device +* \param[in] length information length sent by the caller +* \param[in] params information related to the command +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_Send_ReaderA_Command( + phHciNfc_sContext_t *psContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t cmd + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderA_Auto_Activate function updates auto activate register +* +* \param[in] psContext psContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] activate_enable to enable or disable auto activation +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderA_Auto_Activate( + void *psContext, + void *pHwRef, + uint8_t activate_enable + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_Send_ReaderA_Command function executes the command sent by the +* upper layer, depending on the commands defined. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] infotype To enable the reader A gate +* \param[in] rdr_a_info reader A gate info +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderA_Update_Info( + phHciNfc_sContext_t *psHciContext, + uint8_t infotype, + void *rdr_a_info + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderA_Cont_Active function executes NXP_WRA_CONTINUE_ACTIVATION +* command to inform the CLF Controller after having received the event +* EVT_TARGET_DISCOVERED to continue activation in case activation has +* been stopped after successful SAK response. The response to this command, sent +* as soon as the activation is finished, indicates the result of the +* activation procedure +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] pipeID pipeID of the reader A gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderA_Cont_Activate ( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderA_Set_DataRateMax function updates the data rate max value +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pipeID pipeID of the reader A gate +* \param[in] pPipeInfo Update the pipe Information of the reader +* A gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderA_Set_DataRateMax( + void *psContext, + void *pHwRef, + uint8_t data_rate_value + ); + +#endif /* #ifndef PHHCINFC_RFREADERA_H */ + diff --git a/libnfc-nxp/phHciNfc_RFReaderB.c b/libnfc-nxp/phHciNfc_RFReaderB.c new file mode 100644 index 0000000..4ddd4bf --- /dev/null +++ b/libnfc-nxp/phHciNfc_RFReaderB.c @@ -0,0 +1,918 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_RFReaderB.c * +* \brief HCI Reader B Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Mon Aug 17 15:17:07 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.7 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include + +#if defined (TYPE_B) +#include +/* +****************************** Macro Definitions ******************************* +*/ + +#define RDR_B_SINGLE_TAG_FOUND 0x00U +#define RDR_B_MULTIPLE_TAGS_FOUND 0x03U +/* Commands exposed to the upper layer */ +#define NXP_WRA_CONTINUE_ACTIVATION 0x12U + +#define RDR_B_PUPI_INDEX 0x03U +#define RDR_B_APP_DATA_INDEX 0x04U +#define RDR_B_AFI_INDEX 0x02U +#define RDR_B_HIGHER_LAYER_RESP_INDEX 0x01U +#define RDR_B_HIGHER_LAYER_DATA_INDEX 0x05U + + +/* +*************************** Structure and Enumeration *************************** +*/ + + +/* +*************************** Static Function Declaration ************************** +*/ + +static +NFCSTATUS +phHciNfc_Recv_ReaderB_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_ReaderB_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_ReaderB_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); + +static +NFCSTATUS +phHciNfc_Recv_Iso_B_Packet( + phHciNfc_sContext_t *psHciContext, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); +/* +*************************** Function Definitions *************************** +*/ + +NFCSTATUS +phHciNfc_ReaderB_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_reader_b_info ) + ) + { + phHciNfc_ReaderB_Info_t *p_rdr_b_info=NULL; + p_rdr_b_info = (phHciNfc_ReaderB_Info_t *) + psHciContext->p_reader_b_info ; + *ppipe_id = p_rdr_b_info->pipe_id ; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + +NFCSTATUS +phHciNfc_ReaderB_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_ReaderB_Info_t *p_rdr_b_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if( + ( NULL == psHciContext->p_reader_b_info ) && + (phHciNfc_Allocate_Resource((void **)(&p_rdr_b_info), + sizeof(phHciNfc_ReaderB_Info_t))== NFCSTATUS_SUCCESS) + ) + { + psHciContext->p_reader_b_info = p_rdr_b_info; + p_rdr_b_info->current_seq = RDR_B_INVALID_SEQ; + p_rdr_b_info->next_seq = RDR_B_INVALID_SEQ; + p_rdr_b_info->pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + return status; +} + +NFCSTATUS +phHciNfc_ReaderB_Update_Info( + phHciNfc_sContext_t *psHciContext, + uint8_t infotype, + void *rdr_b_info + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if (NULL == psHciContext) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_reader_b_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderB_Info_t *ps_rdr_b_info=NULL; + ps_rdr_b_info = (phHciNfc_ReaderB_Info_t *) + psHciContext->p_reader_b_info ; + + switch(infotype) + { + case HCI_READER_B_ENABLE: + { + if(NULL != rdr_b_info) + { + ps_rdr_b_info->enable_rdr_b_gate = + *((uint8_t *)rdr_b_info); + } + break; + } + case HCI_READER_B_INFO_SEQ: + { + ps_rdr_b_info->current_seq = RDR_B_PUPI; + ps_rdr_b_info->next_seq = RDR_B_PUPI; + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + } + } + return status; +} + + +NFCSTATUS +phHciNfc_ReaderB_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_reader_b_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderB_Info_t *p_rdr_b_info=NULL; + p_rdr_b_info = (phHciNfc_ReaderB_Info_t *) + psHciContext->p_reader_b_info ; + /* Update the pipe_id of the reader B Gate obtained from the HCI Response */ + p_rdr_b_info->pipe_id = pipeID; + p_rdr_b_info->p_pipe_info = pPipeInfo; + /* Update the Response Receive routine of the reader B Gate */ + pPipeInfo->recv_resp = &phHciNfc_Recv_ReaderB_Response; + /* Update the event Receive routine of the reader B Gate */ + pPipeInfo->recv_event = &phHciNfc_Recv_ReaderB_Event; + } + + return status; +} + +NFCSTATUS +phHciNfc_ReaderB_Info_Sequence ( + void *psHciHandle, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + if( (NULL == psHciContext) + || (NULL == pHwRef) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_reader_b_info) || + (HCI_READER_B_ENABLE != + ((phHciNfc_ReaderB_Info_t *)(psHciContext->p_reader_b_info))-> + enable_rdr_b_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderB_Info_t *p_rdr_b_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + p_rdr_b_info = (phHciNfc_ReaderB_Info_t *) + psHciContext->p_reader_b_info ; + p_pipe_info = p_rdr_b_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + switch(p_rdr_b_info->current_seq) + { + case RDR_B_PUPI: + { + p_pipe_info->reg_index = RDR_B_PUPI_INDEX; + pipeid = p_rdr_b_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_rdr_b_info->next_seq = RDR_B_APP_DATA; + } + break; + } + case RDR_B_APP_DATA: + { + p_pipe_info->reg_index = RDR_B_APP_DATA_INDEX; + pipeid = p_rdr_b_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_rdr_b_info->next_seq = RDR_B_AFI; + } + break; + } + case RDR_B_AFI: + { + /* RW to the registry */ + p_pipe_info->reg_index = RDR_B_AFI_INDEX; + pipeid = p_rdr_b_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_rdr_b_info->next_seq = RDR_B_HIGHER_LAYER_RESP; + } + break; + } + + case RDR_B_HIGHER_LAYER_RESP: + { + p_pipe_info->reg_index = RDR_B_HIGHER_LAYER_RESP_INDEX; + pipeid = p_rdr_b_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_rdr_b_info->next_seq = RDR_B_HIGHER_LAYER_DATA; + } + break; + } + + case RDR_B_HIGHER_LAYER_DATA: + { + /* RW to the registry */ + p_pipe_info->reg_index = RDR_B_HIGHER_LAYER_DATA_INDEX; + pipeid = p_rdr_b_info->pipe_id ; + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_GET_PARAMETER); + if(NFCSTATUS_PENDING == status ) + { + p_rdr_b_info->next_seq = RDR_B_END_SEQUENCE; + } + break; + } + case RDR_B_END_SEQUENCE: + { + phNfc_sCompletionInfo_t CompInfo; + if (RDR_B_MULTIPLE_TAGS_FOUND == + p_rdr_b_info->multiple_tgts_found) + { + CompInfo.status = NFCSTATUS_MULTIPLE_TAGS; + } + else + { + CompInfo.status = NFCSTATUS_SUCCESS; + } + + CompInfo.info = &(p_rdr_b_info->reader_b_info); + + p_rdr_b_info->reader_b_info.RemDevType = phHal_eISO14443_B_PICC; + p_rdr_b_info->current_seq = RDR_B_PUPI; + p_rdr_b_info->next_seq = RDR_B_PUPI; + status = NFCSTATUS_SUCCESS; + /* Notify to the upper layer */ + phHciNfc_Tag_Notify(psHciContext, + pHwRef, + NFC_NOTIFY_TARGET_DISCOVERED, + &CompInfo); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_ReaderB_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_reader_b_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderB_Info_t *p_rdr_b_info=NULL; + uint8_t prev_cmd = ANY_GET_PARAMETER; + + p_rdr_b_info = (phHciNfc_ReaderB_Info_t *) + psHciContext->p_reader_b_info ; + if( NULL == p_rdr_b_info->p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + prev_cmd = p_rdr_b_info->p_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_GET_PARAMETER: + { + status = phHciNfc_ReaderB_InfoUpdate(psHciContext, + p_rdr_b_info->p_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); + break; + } + case ANY_SET_PARAMETER: + { + HCI_PRINT("Reader B Parameter Set \n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + p_rdr_b_info->next_seq = RDR_B_PUPI; + break; + } + case ANY_OPEN_PIPE: + { + HCI_PRINT("Reader B open pipe complete\n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + p_rdr_b_info->next_seq = RDR_B_PUPI; + break; + } + case ANY_CLOSE_PIPE: + { + HCI_PRINT("Reader B close pipe complete\n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + break; + } + case NXP_WRA_CONTINUE_ACTIVATION: + case NXP_WR_ACTIVATE_ID: + { + HCI_PRINT("Reader B continue activation or "); + HCI_PRINT("reactivation completed \n"); + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + break; + } + case WR_XCHGDATA: + { + if (length >= HCP_HEADER_LEN) + { + uint8_t i = 1; + HCI_PRINT("ISO 14443-4B received \n"); + /* Copy buffer to the receive buffer */ + phHciNfc_Append_HCPFrame(psHciContext->recv_buffer, + 0, pResponse, length); + psHciContext->rx_total = (length - i); + status = phHciNfc_Recv_Iso_B_Packet(psHciContext, + &pResponse[HCP_HEADER_LEN], + (length - HCP_HEADER_LEN)); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_WR_PRESCHECK: + { + HCI_PRINT("Presence check completed \n"); + break; + } + case NXP_WR_ACTIVATE_NEXT: + { + if (length > HCP_HEADER_LEN) + { + if (RDR_B_MULTIPLE_TAGS_FOUND == pResponse[HCP_HEADER_LEN]) + { + p_rdr_b_info->multiple_tgts_found = + RDR_B_MULTIPLE_TAGS_FOUND; + } + else + { + p_rdr_b_info->multiple_tgts_found = FALSE; + } + HCI_PRINT("Activate next completed \n"); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case NXP_WR_DISPATCH_TO_UICC: + { + switch(length) + { + case HCP_HEADER_LEN: + { + /* Error code field is optional, if no error + code field in the response, then the command + is successfully completed */ + p_rdr_b_info->uicc_activation = + UICC_CARD_ACTIVATION_SUCCESS; + break; + } + case (HCP_HEADER_LEN + 1): + { + p_rdr_b_info->uicc_activation = + pResponse[HCP_HEADER_LEN]; + break; + } /* End of case (HCP_HEADER_LEN + index) */ + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } /* End of switch(length) */ + if (NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_ReaderMgmt_Update_Sequence(psHciContext, + UPDATE_SEQ); + } + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + p_rdr_b_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; + p_rdr_b_info->current_seq = p_rdr_b_info->next_seq; + } + } + } + return status; +} + + +static +NFCSTATUS +phHciNfc_Recv_ReaderB_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_reader_b_info) || + (HCI_READER_B_ENABLE != + ((phHciNfc_ReaderB_Info_t *)(psHciContext->p_reader_b_info))-> + enable_rdr_b_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_ReaderB_Info_t *p_rdr_b_info=NULL; + phHciNfc_HCP_Message_t *message = NULL; + uint8_t instruction=0, + i = 0; + + p_rdr_b_info = (phHciNfc_ReaderB_Info_t *) + psHciContext->p_reader_b_info ; + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &p_packet->msg.message; + /* Get the instruction bits from the Message Header */ + instruction = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + + if ((EVT_TARGET_DISCOVERED == instruction) + && ((RDR_B_MULTIPLE_TAGS_FOUND == message->payload[i] ) + || (RDR_B_SINGLE_TAG_FOUND == message->payload[i])) + ) + { + phNfc_sCompletionInfo_t pCompInfo; + + if (RDR_B_MULTIPLE_TAGS_FOUND == message->payload[i]) + { + p_rdr_b_info->multiple_tgts_found = RDR_B_MULTIPLE_TAGS_FOUND; + pCompInfo.status = NFCSTATUS_MULTIPLE_TAGS; + } + else + { + p_rdr_b_info->multiple_tgts_found = FALSE; + pCompInfo.status = NFCSTATUS_SUCCESS; + } + + psHciContext->host_rf_type = phHal_eISO14443_B_PCD; + p_rdr_b_info->reader_b_info.RemDevType = phHal_eISO14443_B_PICC; + p_rdr_b_info->current_seq = RDR_B_PUPI; + + /* Notify to the HCI Generic layer To Update the FSM */ + phHciNfc_Notify_Event(psHciContext, pHwRef, + NFC_NOTIFY_TARGET_DISCOVERED, + &pCompInfo); + + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_ReaderB_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_ReaderB_Info_t *p_rdr_b_info=NULL; + phHal_sIso14443BInfo_t *p_tag_b_info = NULL; + + p_rdr_b_info = (phHciNfc_ReaderB_Info_t *) + (psHciContext->p_reader_b_info ); + p_tag_b_info = &(p_rdr_b_info->reader_b_info.RemoteDevInfo.Iso14443B_Info); + + switch(index) + { + case RDR_B_PUPI_INDEX: + { + HCI_PRINT_BUFFER("\tReader B PUPI", reg_value, reg_length); + /* Update PUPI buffer and length in the remote device info, + PUPI length is 4 bytes */ + if(PHHAL_PUPI_LENGTH == reg_length) + { + (void)memcpy((void *)p_tag_b_info->AtqB.AtqResInfo.Pupi, + (void *)reg_value, reg_length); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case RDR_B_APP_DATA_INDEX: + { + HCI_PRINT_BUFFER("\tReader B Application data", reg_value, reg_length); + /* Update application data buffer and length, 3 bytes, + this includes CRC_B and number of application + */ + if(PHHAL_APP_DATA_B_LENGTH == reg_length) + { + (void)memcpy((void *)p_tag_b_info->AtqB.AtqResInfo.AppData, + (void *)reg_value, reg_length); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case RDR_B_AFI_INDEX: + { + HCI_PRINT_BUFFER("\tReader B AFI", reg_value, reg_length); + /* Update AFI byte, Only one byte */ + if(sizeof(*reg_value) == reg_length) + { + p_tag_b_info->Afi = *reg_value; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + + case RDR_B_HIGHER_LAYER_RESP_INDEX: + { + HCI_PRINT_BUFFER("\tReader B higher layer response", reg_value, reg_length); + /* Update higher layer response buffer and length */ + if (reg_length <= PHHAL_MAX_ATR_LENGTH) + { + (void)memcpy((void *)p_tag_b_info->HiLayerResp, + (void *)reg_value, reg_length); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + + case RDR_B_HIGHER_LAYER_DATA_INDEX: + { + HCI_PRINT_BUFFER("\tReader B higher layer data", reg_value, reg_length); + /* Update higher layer data buffer and length */ + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + return status; +} + + +static +NFCSTATUS +phHciNfc_Recv_Iso_B_Packet( + phHciNfc_sContext_t *psHciContext, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + uint8_t i = 1; + + psHciContext->rx_index = HCP_HEADER_LEN; + /* command WR_XCHG_DATA: so give ISO 14443-4B data to the upper layer */ + HCI_PRINT_BUFFER("ISO 14443-4B Bytes received", pResponse, length); + if(FALSE != pResponse[(length - i)]) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_RF_ERROR); + } + return status; +} + + +NFCSTATUS +phHciNfc_ReaderB_Set_AFI( + void *psContext, + void *pHwRef, + uint8_t afi_value + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + if( (NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_reader_b_info) || + (HCI_READER_B_ENABLE != + ((phHciNfc_ReaderB_Info_t *)(psHciContext->p_reader_b_info))-> + enable_rdr_b_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderB_Info_t *ps_rdr_b_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + ps_rdr_b_info = (phHciNfc_ReaderB_Info_t *) + psHciContext->p_reader_b_info ; + p_pipe_info = ps_rdr_b_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + pipeid = ps_rdr_b_info->pipe_id ; + p_pipe_info->reg_index = RDR_B_AFI_INDEX; + + p_pipe_info->param_info = &afi_value; + p_pipe_info->param_length = sizeof(uint8_t); + /* Fill the data buffer and send the command to the + device */ + status = + phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + } + } + return status; +} + +NFCSTATUS +phHciNfc_ReaderB_Set_LayerData( + void *psContext, + void *pHwRef, + phNfc_sData_t *layer_data_info + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + + if( (NULL == psHciContext) || (NULL == pHwRef) || + (NULL == layer_data_info) || (NULL == layer_data_info->buffer) + || (0 == layer_data_info->length)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if((NULL == psHciContext->p_reader_b_info) || + (HCI_READER_B_ENABLE != + ((phHciNfc_ReaderB_Info_t *)(psHciContext->p_reader_b_info))-> + enable_rdr_b_gate)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_ReaderB_Info_t *ps_rdr_b_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + uint8_t pipeid = 0; + + ps_rdr_b_info = (phHciNfc_ReaderB_Info_t *) + psHciContext->p_reader_b_info ; + p_pipe_info = ps_rdr_b_info->p_pipe_info; + if(NULL == p_pipe_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + else + { + p_pipe_info->reg_index = RDR_B_HIGHER_LAYER_DATA_INDEX; + pipeid = ps_rdr_b_info->pipe_id ; + p_pipe_info->param_info = (void *)layer_data_info->buffer; + p_pipe_info->param_length = (uint8_t) + layer_data_info->length; + /* Fill the data buffer and send the command to the + device */ + status = phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, + pipeid, (uint8_t)ANY_SET_PARAMETER); + } + } + return status; +} +#endif /* #if defined (TYPE_B) */ + + diff --git a/libnfc-nxp/phHciNfc_RFReaderB.h b/libnfc-nxp/phHciNfc_RFReaderB.h new file mode 100644 index 0000000..4b97da8 --- /dev/null +++ b/libnfc-nxp/phHciNfc_RFReaderB.h @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_RFReaderB.h * +* \brief HCI Reader B Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Aug 14 17:01:26 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.5 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ + +#ifndef PHHCINFC_RFREADERB_H +#define PHHCINFC_RFREADERB_H + +/*@}*/ + + +/** +* \name HCI +* +* File: \ref phHciNfc_ReaderB.h +* +*/ +/*@{*/ +#define PHHCINFC_RFREADERB_FILEREVISION "$Revision: 1.5 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_RFREADERB_FILEALIASES "$Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +***************************** Header File Inclusion **************************** +*/ + +#include + +/* +****************************** Macro Definitions ******************************* +*/ + +/* Enable the reader B */ +#define HCI_READER_B_ENABLE 0x01U +#define HCI_READER_B_INFO_SEQ 0x02U + +/* +******************** Enumeration and Structure Definition ********************** +*/ +typedef enum phHciNfc_ReaderB_Seq{ + RDR_B_PUPI, + RDR_B_APP_DATA, + RDR_B_AFI, + RDR_B_HIGHER_LAYER_RESP, + RDR_B_HIGHER_LAYER_DATA, + RDR_B_END_SEQUENCE, + RDR_B_INVALID_SEQ +} phHciNfc_ReaderB_Seq_t; + +/* Information structure for the reader B Gate */ +typedef struct phHciNfc_ReaderB_Info{ + /* Current running Sequence of the reader B Management */ + phHciNfc_ReaderB_Seq_t current_seq; + /* Next running Sequence of the reader B Management */ + phHciNfc_ReaderB_Seq_t next_seq; + /* Pointer to the reader B pipe information */ + phHciNfc_Pipe_Info_t *p_pipe_info; + uint8_t pipe_id; + /* Flag to say about the multiple targets */ + uint8_t multiple_tgts_found; + /* Reader B information */ + phHal_sRemoteDevInformation_t reader_b_info; + /* Enable or disable reader gate */ + uint8_t enable_rdr_b_gate; + /* UICC re-activation status */ + uint8_t uicc_activation; +} phHciNfc_ReaderB_Info_t; + +/* +*********************** Function Prototype Declaration ************************* +*/ + +/*! +* \brief Allocates the resources of reader B management gate. +* +* This function Allocates the resources of the reader B management +* gate Information Structure. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderB_Init_Resources( + phHciNfc_sContext_t *psHciContext + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderB_Get_PipeID function gives the pipe id of the reader B +* gate +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderB_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderB_Update_PipeInfo function updates the pipe_id of the reader B +* gate management Structure. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pipeID pipeID of the reader B gate +* \param[in] pPipeInfo Update the pipe Information of the reader +* A gate +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ + +extern +NFCSTATUS +phHciNfc_ReaderB_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderB_Info_Sequence function executes the sequence of operations, to +* get the PUPI, AFI, APPLICATION_DATA etc. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderB_Info_Sequence ( + void *psHciHandle, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderB_Update_Info function updates the reader B information. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* context Structure. +* \param[in] infotype To enable the reader B gate +* \param[in] rdr_b_info reader B gate info +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderB_Update_Info( + phHciNfc_sContext_t *psHciContext, + uint8_t infotype, + void *rdr_b_info + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderB_Set_LayerData function updates higher layer data +* registry +* +* \param[in] psContext psContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] layer_data_info layer data information +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderB_Set_LayerData( + void *psContext, + void *pHwRef, + phNfc_sData_t *layer_data_info + ); + +/** +* \ingroup grp_hci_nfc +* +* The phHciNfc_ReaderB_Set_AFI function updates application family +* identifier registry +* +* \param[in] psContext psContext is the pointer to HCI Layer +* context Structure. +* \param[in] pHwRef pHwRef is the Information of +* the Device Interface Link +* \param[in] afi_value to afi value update +* +* \retval NFCSTATUS_SUCCESS Function execution is successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be interpreted properly. +* +*/ +extern +NFCSTATUS +phHciNfc_ReaderB_Set_AFI( + void *psContext, + void *pHwRef, + uint8_t afi_value + ); +#endif /* #ifndef PHHCINFC_RFREADERB_H */ + + diff --git a/libnfc-nxp/phHciNfc_SWP.c b/libnfc-nxp/phHciNfc_SWP.c new file mode 100644 index 0000000..88b877c --- /dev/null +++ b/libnfc-nxp/phHciNfc_SWP.c @@ -0,0 +1,828 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_SWP.c * +* \brief HCI SWP gate Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Tue Aug 18 10:16:36 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.31 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include +#include +#include +/* +****************************** Macro Definitions ******************************* +*/ + +/* SWP Gate regsitry Settings */ +/* set default mode mode as virtual mode */ +#define NXP_SWP_DEFAULT_MODE_INDEX (0x01U) +/* Get the Status of the UICC Connection */ +#define NXP_SWP_STATUS_INDEX (0x02U) + +/* Configure the Secure Element Protected Mode */ +#define NXP_SWP_PROTECTED_INDEX (0x03U) + +/* Switch mode index */ +#define NXP_EVT_SWP_SWITCH_MODE (0x03U) + +/* Protected Event from the Host Controller */ +#define NXP_EVT_SWP_PROTECTED (0x04U) + +/****************** Structure and Enumeration ****************************/ + +/****************** Static Function Declaration **************************/ + +static +NFCSTATUS +phHciNfc_Recv_SWP_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Send_SWP_Event( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t event + ); + + +static +NFCSTATUS +phHciNfc_Recv_SWP_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_SWP_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); + +/* +*************************** Function Definitions *************************** +*/ + +NFCSTATUS +phHciNfc_SWP_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_swp_info ) + ) + { + phHciNfc_SWP_Info_t *p_swp_info=NULL; + p_swp_info = (phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info ; + *ppipe_id = p_swp_info->pipe_id ; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + +NFCSTATUS +phHciNfc_SWP_Init_Resources(phHciNfc_sContext_t *psHciContext) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_SWP_Info_t *ps_swp_info=NULL; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if(( NULL == psHciContext->p_swp_info ) && + (phHciNfc_Allocate_Resource((void **)(&ps_swp_info), + sizeof(phHciNfc_SWP_Info_t))== NFCSTATUS_SUCCESS)) + { + psHciContext->p_swp_info = ps_swp_info; + ps_swp_info->current_seq = SWP_INVALID_SEQUENCE; + ps_swp_info->next_seq = SWP_INVALID_SEQUENCE; + ps_swp_info->pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + return status; +} + + +NFCSTATUS +phHciNfc_SWP_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_swp_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_SWP_Info_t *ps_swp_info=NULL; + ps_swp_info = (phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info ; + /* Update the pipe_id of the SWP Gate obtained from HCI Response */ + ps_swp_info->pipe_id = pipeID; + ps_swp_info->p_pipe_info = pPipeInfo; + if (NULL != pPipeInfo) + { + /* Update the Response Receive routine of the SWP Gate */ + pPipeInfo->recv_resp = &phHciNfc_Recv_SWP_Response; + pPipeInfo->recv_event =&phHciNfc_Recv_SWP_Event; + } + } + return status; +} + + +static +NFCSTATUS +phHciNfc_Recv_SWP_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_swp_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_SWP_Info_t *ps_swp_info=NULL; + uint8_t prev_cmd = ANY_GET_PARAMETER; + + ps_swp_info = (phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info ; + if( NULL == ps_swp_info->p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + prev_cmd = ps_swp_info->p_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_GET_PARAMETER: + { + HCI_PRINT(" Getting the SWP Parameter \n"); + status = phHciNfc_SWP_InfoUpdate(psHciContext, + ps_swp_info->p_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); + + break; + } + case ANY_SET_PARAMETER: + { + HCI_PRINT("SWP Parameter Set \n"); + break; + } + case ANY_OPEN_PIPE: + { + HCI_PRINT("SWP gate open pipe complete\n"); + break; + } + case ANY_CLOSE_PIPE: + { + HCI_PRINT("SWP close pipe complete\n"); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + status = phHciNfc_EmuMgmt_Update_Seq(psHciContext, + UPDATE_SEQ); + ps_swp_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; + ps_swp_info->current_seq = ps_swp_info->next_seq; + } + } + } + return status; +} + + +NFCSTATUS +phHciNfc_SWP_Configure_Default( + void *psHciHandle, + void *pHwRef, + uint8_t enable_type + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t param = 0 ; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + + if((NULL == psHciContext)||(NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_swp_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_SWP_Info_t *ps_swp_info=NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info=NULL; + + ps_swp_info = (phHciNfc_SWP_Info_t*)psHciContext->p_swp_info; + ps_pipe_info = ps_swp_info->p_pipe_info; + + if(NULL == ps_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + ps_pipe_info->reg_index = NXP_SWP_DEFAULT_MODE_INDEX; + /* Enable/Disable SWP link */ + param = (uint8_t)enable_type; + ps_pipe_info->param_info =(void*)¶m ; + ps_pipe_info->param_length = sizeof(param) ; + status = phHciNfc_Send_Generic_Cmd(psHciContext, pHwRef, + ps_swp_info->pipe_id, + (uint8_t)ANY_SET_PARAMETER); + } + + } + return status; +} + + +NFCSTATUS +phHciNfc_SWP_Get_Status( + void *psHciHandle, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + /* static uint8_t param = 0 ; */ + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + + if((NULL == psHciContext)||(NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_swp_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_SWP_Info_t *ps_swp_info=NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info=NULL; + + ps_swp_info = (phHciNfc_SWP_Info_t*)psHciContext->p_swp_info; + ps_pipe_info = ps_swp_info->p_pipe_info; + + if(NULL == ps_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + ps_pipe_info->reg_index = NXP_SWP_STATUS_INDEX; + status = phHciNfc_Send_Generic_Cmd(psHciContext, pHwRef, + ps_swp_info->pipe_id, + (uint8_t)ANY_GET_PARAMETER); + } + } + return status; +} + + +NFCSTATUS +phHciNfc_SWP_Get_Bitrate( + void *psHciHandle, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *) + psHciHandle); + + if((NULL == psHciContext) || (NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_swp_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_SWP_Info_t *ps_swp_info = NULL; + + ps_swp_info = (phHciNfc_SWP_Info_t*)psHciContext->p_swp_info; + + status = phHciNfc_DevMgmt_Get_Info(psHciContext, pHwRef, + NFC_ADDRESS_SWP_BITRATE, &(ps_swp_info->uicc_bitrate)); + + } + return status; +} + + +NFCSTATUS +phHciNfc_SWP_Protection( + void *psHciHandle, + void *pHwRef, + uint8_t mode + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t param = 0 ; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + + if((NULL == psHciContext)||(NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_swp_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_SWP_Info_t *ps_swp_info=NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info=NULL; + + ps_swp_info = (phHciNfc_SWP_Info_t*)psHciContext->p_swp_info; + ps_pipe_info = ps_swp_info->p_pipe_info; + + if(NULL == ps_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + ps_pipe_info->reg_index = NXP_SWP_PROTECTED_INDEX; + /* Enable/Disable SWP Protection */ + param = (uint8_t)mode; + ps_pipe_info->param_info =(void*)¶m ; + ps_pipe_info->param_length = sizeof(param) ; + status = phHciNfc_Send_Generic_Cmd(psHciContext, pHwRef, + ps_swp_info->pipe_id, + (uint8_t)ANY_SET_PARAMETER); + } + + } + return status; +} + + + + +static +NFCSTATUS +phHciNfc_SWP_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + phHciNfc_SWP_Info_t *ps_swp_info=NULL; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + ps_swp_info = (phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info ; + + /* To remove "warning (VS C4100) : unreferenced formal parameter" */ + PHNFC_UNUSED_VARIABLE(reg_length); + switch(index) + { + case NXP_SWP_DEFAULT_MODE_INDEX: + { + HCI_PRINT_BUFFER("\tUICC Enable Register:",reg_value,reg_length); + break; + } + /* Get the Status of the UICC Connection */ + case NXP_SWP_STATUS_INDEX: + { + HCI_PRINT_BUFFER("\tUICC Connection Status:", reg_value, reg_length); + ps_swp_info->uicc_status = (phHciNfc_SWP_Status_t ) *reg_value ; + break; + } + case NXP_SWP_PROTECTED_INDEX: + { + HCI_PRINT_BUFFER("\t UICC Card Emulation Rights :",reg_value,reg_length); + + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + break; + } + } /* End of switch(index) */ + + return status; +} + +NFCSTATUS +phHciNfc_SWP_Configure_Mode( + void *psHciHandle, + void *pHwRef, + uint8_t uicc_mode + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t param = 0; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *) + psHciHandle); + + if( (NULL == psHciContext)||(NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_swp_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_SWP_Info_t *ps_swp_info=NULL; + phHciNfc_Pipe_Info_t *ps_pipe_info=NULL; + + ps_swp_info = (phHciNfc_SWP_Info_t*)psHciContext->p_swp_info; + + ps_pipe_info = ps_swp_info->p_pipe_info; + if(NULL == ps_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + /* Switch the Mode of the SmartMx */ + param = uicc_mode; + ps_pipe_info->param_info =(void*)¶m ; + ps_pipe_info->param_length = sizeof(param) ; + status = phHciNfc_Send_SWP_Event( psHciContext, pHwRef, + ps_swp_info->pipe_id, + NXP_EVT_SWP_SWITCH_MODE ); + + /* Send the Success Status as this is an event */ + status = ((status == NFCSTATUS_PENDING)? + NFCSTATUS_SUCCESS : status); + + }/* End of else part*/ + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_SWP_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext ; + static phHal_sEventInfo_t EventInfo; + + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_swp_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_SWP_Info_t *ps_swp_info=NULL; + + ps_swp_info = (phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info ; + if( NULL == ps_swp_info->p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_HCP_Message_t *message = NULL; + uint8_t EventType = 0; + + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &(p_packet->msg.message); + /* Get the instruction bits from the Message Header */ + EventType = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + + EventInfo.eventHost = phHal_eHostController; + EventInfo.eventSource = phHal_ePICC_DevType; + /* Occurrence of the Protected events for reporting */ + if (NXP_EVT_SWP_PROTECTED == EventType) + { + EventInfo.eventType = NFC_EVT_PROTECTED; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + } + + if (NFCSTATUS_SUCCESS == status ) + { + phHciNfc_Notify_Event( psHciContext, pHwRef, + NFC_NOTIFY_EVENT, (void*)&EventInfo); + } + + } + } + return status; +} + + + +static +NFCSTATUS +phHciNfc_Send_SWP_Event( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t event + ) +{ + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t length = 0; + uint8_t i=0; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + p_pipe_info = (phHciNfc_Pipe_Info_t *) + psHciContext->p_pipe_list[pipe_id]; + psHciContext->tx_total = 0 ; + length = (length + HCP_HEADER_LEN); + + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, + HCP_MSG_TYPE_EVENT, event); + + hcp_message = &(hcp_packet->msg.message); + + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, + (uint8_t *)p_pipe_info->param_info, + p_pipe_info->param_length); + length = (uint8_t)(length + i + p_pipe_info->param_length); + + p_pipe_info->sent_msg_type = HCP_MSG_TYPE_EVENT ; + p_pipe_info->prev_msg = event ; + psHciContext->tx_total = length; + + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef ); + if(NFCSTATUS_PENDING == status) + { + ((phHciNfc_SWP_Info_t *)psHciContext->p_swp_info)->current_seq = + ((phHciNfc_SWP_Info_t *)psHciContext->p_swp_info)->next_seq; + p_pipe_info->prev_status = status; + } + + return status; +} + +NFCSTATUS +phHciNfc_SWP_Update_Sequence( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t SWP_seq + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_SWP_Info_t *ps_swp_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_swp_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + ps_swp_info = (phHciNfc_SWP_Info_t *) + psHciContext->p_swp_info ; + switch(SWP_seq) + { + case RESET_SEQ: + case INIT_SEQ: + { + ps_swp_info->current_seq = SWP_INVALID_SEQUENCE; + ps_swp_info->next_seq = SWP_INVALID_SEQUENCE ; + break; + } + case UPDATE_SEQ: + { + ps_swp_info->current_seq = ps_swp_info->next_seq; + break; + } + case REL_SEQ: + { + ps_swp_info->current_seq = SWP_INVALID_SEQUENCE; + ps_swp_info->next_seq = SWP_INVALID_SEQUENCE; + break; + } + case CONFIG_SEQ: + { + ps_swp_info->current_seq = SWP_STATUS_SEQ; + ps_swp_info->next_seq = SWP_STATUS_SEQ; + break; + } + default: + { + break; + } + } + } + return status; +} + +NFCSTATUS +phHciNfc_SWP_Config_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHal_sEmulationCfg_t *ps_emulation_cfg + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_SWP_Info_t *ps_swp_info=NULL; + + if ((NULL == psHciContext) || (NULL == pHwRef) || + (NULL == ps_emulation_cfg)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if( NULL == psHciContext->p_swp_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_Pipe_Info_t *ps_pipe_info = NULL; + phHal_sUiccEmuCfg_t *uicc_config = + &(ps_emulation_cfg->config.uiccEmuCfg); + + ps_swp_info = (phHciNfc_SWP_Info_t *)psHciContext->p_swp_info; + ps_pipe_info = ps_swp_info->p_pipe_info; + + if (NULL == ps_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + switch(ps_swp_info->current_seq) + { + case SWP_STATUS_SEQ : + { + status = phHciNfc_SWP_Configure_Default( psHciContext, + pHwRef, uicc_config->enableUicc ); + + if(status == NFCSTATUS_PENDING) + { + ps_swp_info->next_seq = SWP_STATUS_SEQ; + status = NFCSTATUS_SUCCESS; + } + break; + } + case SWP_MODE_SEQ : + { + status = phHciNfc_SWP_Configure_Mode( psHciContext, + pHwRef, UICC_SWITCH_MODE_DEFAULT ); + /* UICC_SWITCH_MODE_ON */ + if(status == NFCSTATUS_PENDING) + { + ps_swp_info->next_seq = SWP_STATUS_SEQ; + status = NFCSTATUS_SUCCESS; + } + break; + } + default : + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + break; + } + } + } + } + return status; +} + + + diff --git a/libnfc-nxp/phHciNfc_SWP.h b/libnfc-nxp/phHciNfc_SWP.h new file mode 100644 index 0000000..e397e36 --- /dev/null +++ b/libnfc-nxp/phHciNfc_SWP.h @@ -0,0 +1,355 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_SWP .h * +* \brief HCI wired interface gate Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Aug 14 17:01:28 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.15 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ +#ifndef PHHCINFC_SWP_H +#define PHHCINFC_SWP_H +/*@}*/ +/** + * \name HCI + * + * File: \ref phHciNfc_SWP.h + * + */ +/*@{*/ +#define PHHCINFC_SWPRED_FILEREVISION "$Revision: 1.15 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_SWPREDINTERFACE_FILEALIASES "$Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/****************************** Header File Inclusion *****************************/ +#include + +/******************************* Macro Definitions ********************************/ + +/* Kb/sec */ +#define UICC_REF_BITRATE (106U) +#define UICC_MAX_CONNECT_RETRY (0x02U) + +/* SWP switch mode event parameters */ +#define UICC_SWITCH_MODE_OFF (0x00U) +#define UICC_SWITCH_MODE_DEFAULT (0x01U) +#define UICC_SWITCH_MODE_ON (0x02U) + +/******************** Enumeration and Structure Definition ***********************/ + +typedef enum phHciNfc_SWP_Seq{ + SWP_INVALID_SEQUENCE = 0x00U, + SWP_MODE_SEQ, + SWP_STATUS_SEQ, + SWP_END_SEQ +}phHciNfc_SWP_Seq_t; + +typedef enum phHciNfc_SWP_Status{ + UICC_NOT_CONNECTED = 0x00U, + UICC_CONNECTION_ONGOING, + UICC_CONNECTED, + UICC_CONNECTION_LOST, + UICC_DISCONNECTION_ONGOING, + UICC_CONNECTION_FAILED +}phHciNfc_SWP_Status_t; + + +/* Information structure for SWP Gate */ +typedef struct phHciNfc_SWP_Info{ + + /* Pointer to SWP gate pipe information */ + phHciNfc_Pipe_Info_t *p_pipe_info; + /* SWP gate pipe Identified */ + uint8_t pipe_id; + /*Current internal Sequence type */ + phHciNfc_SWP_Seq_t current_seq; + /*Current next Sequence ID */ + phHciNfc_SWP_Seq_t next_seq; + + phHciNfc_SWP_Status_t uicc_status; + + uint8_t uicc_bitrate; + +} phHciNfc_SWP_Info_t; + +/************************ Function Prototype Declaration *************************/ +/*! + * \brief Allocates the resources required for SWP gate management. + * + * This function Allocates necessary resources as requiered by SWP gate management + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * + * \retval NFCSTATUS_SUCCESS Function execution is successful + * + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid + */ +extern +NFCSTATUS +phHciNfc_SWP_Init_Resources(phHciNfc_sContext_t *psHciContext); + +/** +* \ingroup grp_hci_nfc +* +* \brief Allocates the resources required for SWP gate management. +* +* This function Allocates necessary resources as requiered by SWP gate management +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ + +extern +NFCSTATUS +phHciNfc_SWPMgmt_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* \brief updates SWP gate specific pipe information . +* +* This function intialises gate specific informations like pipe id, +* event handler and response handler etc. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* \param[in] pipeID pipeID of the SWP management Gate +* \param[in] pPipeInfo Update the pipe Information of the SWP +* Management Gate. +* +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ +extern +NFCSTATUS +phHciNfc_SWP_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); +/** +* \ingroup grp_hci_nfc +* +* \brief updates SWP gate specific pipe information . +* +* This function intialises gate specific informations like pipe id, +* event handler and response handler etc. +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ + +extern +NFCSTATUS +phHciNfc_SWP_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + +/** +* \ingroup grp_hci_nfc +* +* \brief Enables /disables SWP mode . +* +* This function enables/disables SWP link associated with UICC. +* +* +* \param[in] psHciContext psHciContext is pointer to HCI Layer +* +* \param[in] pHwRef pHwRef is underlying Hardware context. +* +* \param[in] enable_type 0 means disable ,1 means enable SWP link. +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ +extern +NFCSTATUS +phHciNfc_SWP_Configure_Default( + void *psHciHandle, + void *pHwRef, + uint8_t enable_type + ); + +/** +* \ingroup grp_hci_nfc +* +* \brief Enables /disables SWP mode . +* +* This function enables/disables SWP link associated with UICC. +* +* +* \param[in] psHciContext psHciContext is pointer to HCI Layer +* +* \param[in] pHwRef pHwRef is underlying Hardware context. +* +* \param[in] mode TRUE Enable Protection. +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ +extern +NFCSTATUS +phHciNfc_SWP_Protection( + void *psHciHandle, + void *pHwRef, + uint8_t mode + ); + + +/** +* \ingroup grp_hci_nfc +* +* \brief To send the switch mode event +* +* This function send an event to change the switch mode. +* +* +* \param[in] psHciContext psHciContext is pointer to HCI Layer +* +* \param[in] pHwRef pHwRef is underlying Hardware context. +* +* \param[in] uicc_mode UICC_SWITCH_MODE_OFF +* UICC_SWITCH_MODE_DEFAULT +* UICC_SWITCH_MODE_ON +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ +extern +NFCSTATUS +phHciNfc_SWP_Configure_Mode( + void *psHciHandle, + void *pHwRef, + uint8_t uicc_mode + ); + +/** +* \ingroup grp_hci_nfc +* +* \brief To get the status of the UICC +* +* This function reads the status of the UICC. The status value can be any +* of the values present in the \ref phHciNfc_SWP_Status_t +* +* +* \param[in] psHciContext psHciContext is pointer to HCI Layer +* +* \param[in] pHwRef pHwRef is underlying Hardware context. +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ +extern +NFCSTATUS +phHciNfc_SWP_Get_Status( + void *psHciHandle, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* \brief To get the bitrate +* +* This function reads the bitrate +* +* +* \param[in] psHciContext psHciContext is pointer to HCI Layer +* +* \param[in] pHwRef pHwRef is underlying Hardware context. +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ +extern +NFCSTATUS +phHciNfc_SWP_Get_Bitrate( + void *psHciHandle, + void *pHwRef + ); + +/** +* \ingroup grp_hci_nfc +* +* \brief To update the sequence +* +* This function reads the bitrate +* +* +* \param[in] psHciContext psHciContext is pointer to HCI Layer +* +* \param[in] SWP_seq SWP sequence. +* +* \retval NFCSTATUS_SUCCESS Function execution is successful +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ +extern +NFCSTATUS +phHciNfc_SWP_Update_Sequence( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t SWP_seq + ); + +/** +* \ingroup grp_hci_nfc +* +* \brief To configure default mode and the default status. +* +* This function configures default status and default mode. +* +* +* \param[in] psHciContext psHciContext is pointer to HCI Layer +* \param[in] pHwRef pHwRef is underlying Hardware context. +* \param[in] ps_emulation_cfg emulation configuration info. +* +* +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ +extern +NFCSTATUS +phHciNfc_SWP_Config_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + phHal_sEmulationCfg_t *ps_emulation_cfg + ); + + +#endif /* #ifndef PHHCINFC_SWP_H */ + + diff --git a/libnfc-nxp/phHciNfc_Sequence.c b/libnfc-nxp/phHciNfc_Sequence.c new file mode 100644 index 0000000..6d0bf13 --- /dev/null +++ b/libnfc-nxp/phHciNfc_Sequence.c @@ -0,0 +1,2533 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_Sequence.c * +* \brief State Machine Implementation for the HCI Management and * +* and the Function Sequence for a particular State * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Tue Jun 8 09:33:46 2010 $ * +* $Author: ing04880 $ * +* $Revision: 1.85 $ * +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/* +################################################################################ +***************************** Header File Inclusion **************************** +################################################################################ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef ENABLE_P2P +#include +#endif +#include +#include +#include + +/* +################################################################################ +****************************** Macro Definitions ******************************* +################################################################################ +*/ + +/* Address Definitions for HAL Configuration */ +#define NFC_ADDRESS_HAL_CONF 0x9FD0U + + +/* +################################################################################ +********************** Structure/Enumeration Definitions *********************** +################################################################################ +*/ + + +#ifdef VALIDATE_FSM + +typedef struct phHciNfc_sFsm +{ + phHciNfc_eState_t from_state; + phHciNfc_eState_t to_state; + uint8_t valid; +}phHciNfc_sFsm_t; + +static phHciNfc_sFsm_t phHciNfc_Valid_Fsm[] = { + {hciState_Reset, hciState_Initialise , TRUE}, + /* {hciState_Reset, hciState_Config, FALSE}, */ + {hciState_Initialise, hciState_Config, TRUE}, + {hciState_Initialise, hciState_Release, TRUE}, + {hciState_Config, hciState_Connect, TRUE}, + {hciState_Config, hciState_Release, TRUE}, + {hciState_Connect, hciState_Activate, TRUE}, + {hciState_Connect, hciState_Transact, TRUE}, + {hciState_Connect, hciState_Disconnect, TRUE}, + {hciState_Disconnect, hciState_Config, TRUE}, + /* {hciState_Disconnect, hciState_Release, TRUE}, */ + {hciState_Reset, hciState_Initialise, TRUE}, +}; + +#endif + + +/* +################################################################################ +************************* Function Prototype Declaration *********************** +################################################################################ +*/ + + +static +NFCSTATUS +phHciNfc_Config_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Connect_Sequence function sequence selects the + * discovered target for performing the transaction. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_SUCCESS HCI target selection sequence successful. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + */ + +static +NFCSTATUS +phHciNfc_Transact_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Info_Sequence function sequence selects the + * discovered target for performing the transaction. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_SUCCESS HCI target selection sequence successful. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + */ + +static +NFCSTATUS +phHciNfc_Info_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +static +NFCSTATUS +phHciNfc_Test_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + NFCSTATUS test_status, + uint8_t *pdata, + uint8_t length + ); + +#ifdef HCI_FSM_RESET + +static +void +phHciNfc_FSM_Reset( + phHciNfc_sContext_t *psHciContext + ); + +#endif + +static +NFCSTATUS +phHciNfc_IO_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + NFCSTATUS test_status, + uint8_t *pdata, + uint8_t length + ); + +static +NFCSTATUS +phHciNfc_Pending_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/* +################################################################################ +***************************** Function Definitions ***************************** +################################################################################ +*/ + +NFCSTATUS +phHciNfc_FSM_Validate( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eState_t state, + uint8_t validate_type + ) +{ + NFCSTATUS status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + phHciNfc_eState_t cur_state = (phHciNfc_eState_t) + psHciContext->hci_state.cur_state; + + switch(validate_type) + { + case NFC_FSM_CURRENT: + { + if( cur_state == (uint8_t) state ) + { + status = NFCSTATUS_SUCCESS; + } + break; + } + case NFC_FSM_NEXT: + { + phHciNfc_eState_t next_state = state; + switch (cur_state) + { + case hciState_Reset: + { + switch(next_state) + { + /* Specifies the Starting of the init Sequence */ + case hciState_Initialise: + /* Initialise to Perform Test on + the Antenna/SWP Link */ + case hciState_Test: + { + status = NFCSTATUS_SUCCESS; + break; + } + default: + break; + } + break; + } + case hciState_Initialise: + { + switch(next_state) + { + /* Discovery Resume after connect failure */ + case hciState_Initialise: + /* Configuring the Discovery/Emulation */ + case hciState_Config: + /* Configuring the Memory */ + case hciState_IO: + /* Occurence of the Tag Discovered Event */ + case hciState_Select: + /* Occurence of the Target Activated Event */ + case hciState_Listen: + /* Specifies the Starting of the Release Sequence */ + case hciState_Release: + { + status = NFCSTATUS_SUCCESS; + break; + } + default: + break; + } + break; + } + case hciState_Test: + { + if ((hciState_Test == next_state ) + || (hciState_IO == next_state) + || (hciState_Release == next_state)) + { + /* Next Test/Reset Sequence */ + status = NFCSTATUS_SUCCESS; + } + break; + } + case hciState_Select: + { + switch(next_state) + { + /* Restart the Wheel */ + case hciState_Initialise: + /* Select the next Tag in the Field or + * already Selected Tag Again + */ + /* Configuring the Memory */ + case hciState_IO: + case hciState_Select: + /* Configuring the Discovery/Emulation */ + case hciState_Config: + /* Re-Activate the Target or + * Discover the next target + */ + case hciState_Reactivate: + /* Connect the Discovered Target */ + case hciState_Connect: + /* Specifies the Starting of the Release Sequence */ + case hciState_Release: + { + status = NFCSTATUS_SUCCESS; + break; + } + default: + break; + } + break; + } + case hciState_Connect: + { + switch(next_state) + { + /* Disabling the Tag Discovery */ + case hciState_Initialise: + /* Configuring the Discovery/Emulation */ + /* This should not be allowed if the target + * is connected. + */ + /* Configuring the Memory */ + case hciState_IO: + case hciState_Config: + /* Re-Activate the Target or + * Discover the next target + */ + case hciState_Reactivate: + /* Intermediate Transceive State */ + case hciState_Transact: + /* Intermediate Presence Check State */ + case hciState_Presence: + /* Disconnect the Target Connected */ + case hciState_Disconnect: + /* Specifies the Starting of the Release Sequence */ + case hciState_Release: + { + status = NFCSTATUS_SUCCESS; + break; + } + default: + break; + } + break; + } + case hciState_Listen: + { + switch(next_state) + { + /* Releasing from the Emulation/Target Mode */ + case hciState_Initialise: + /* Occurence of the Tag Discovered Event + * after the Disconnect Operation + */ + case hciState_Select: + /* Configuring the Memory */ + case hciState_IO: + /* Configuring the Discovery/Emulation */ + case hciState_Config: + /* Intermediate Transceive State */ + case hciState_Transact: + /* Specifies the Starting of the Release Sequence */ + case hciState_Release: + { + status = NFCSTATUS_SUCCESS; + break; + } + default: + break; + } + break; + } + case hciState_Reactivate: + { + switch(next_state) + { + /* Restart/Discovery after the Target is removed + * after Reactivation. + */ + /* case hciState_Initialise: */ + /* Re-Connect the Re-Activated Target */ + case hciState_Connect: + /* Configuring the Memory */ + case hciState_IO: + /* Configuring the Discovery/Emulation */ + case hciState_Config: + /* Specifies the Starting of the Release Sequence */ + case hciState_Release: + { + status = NFCSTATUS_SUCCESS; + break; + } + default: + break; + } + break; + } + case hciState_Disconnect: + { + switch(next_state) + { + /* Discovery Resume after connect failure + after the disconnect */ + case hciState_Initialise: + /* Configuring the Memory */ + case hciState_IO: + /* Configuring the Discovery/Emulation */ + case hciState_Config: + /* Occurence of the Tag Discovered Event + * after the Disconnect Operation + */ + case hciState_Select: + /* Occurence of the Target Activated Event */ + case hciState_Listen: + /* Specifies the Starting of the Release Sequence */ + case hciState_Release: + { + status = NFCSTATUS_SUCCESS; + break; + } + default: + { + break; + } + } + break; + } +#ifdef USE_M5 + case hciState_Presence: + case hciState_Transact: + case hciState_Release: + { + break; + } +#endif + /* case phHciNfc_Unknown: */ + default: + { + /* status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); */ + break; + } + } /* End of State Validation Switch */ + if( NFC_FSM_IN_PROGRESS == psHciContext->hci_state.transition ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_BUSY); + } + break; + } + default: + { + HCI_DEBUG("State Validate Type:%x is Unknown/Incorrect \n", + validate_type); + break; + } + } + return status; +} + +NFCSTATUS +phHciNfc_FSM_Update( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eState_t next_state + ) +{ + NFCSTATUS status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + + HCI_DEBUG(" HCI: Current State --> %02u \n", + psHciContext->hci_state.cur_state ); + HCI_DEBUG(" HCI: Transition Before FSM Update --> %02u \n", + psHciContext->hci_state.transition ); + HCI_DEBUG(" HCI: Next State Before FSM Update --> %02u \n", + psHciContext->hci_state.next_state ); + + status = phHciNfc_FSM_Validate(psHciContext, next_state, NFC_FSM_NEXT ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_state.next_state = (uint8_t) next_state; + psHciContext->hci_state.transition = NFC_FSM_IN_PROGRESS; + psHciContext->response_pending = FALSE; + HCI_DEBUG(" HCI: Next State After FSM Update --> %02u \n", + psHciContext->hci_state.next_state ); + } + else + { + HCI_DEBUG(" HCI: FSM - Invalid next state --> %02u \n", + next_state ); + } + + return status; +} + + +NFCSTATUS +phHciNfc_FSM_Complete( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + + HCI_DEBUG("HCI: In Function: %s \n", __FUNCTION__); + + HCI_DEBUG(" HCI: Transition Before FSM Complete --> %02u \n", + psHciContext->hci_state.transition ); + + HCI_DEBUG(" HCI: Current State Before FSM Complete --> %02u \n", + psHciContext->hci_state.cur_state ); + + HCI_DEBUG(" HCI: Next State Before FSM Complete --> %02u \n", + psHciContext->hci_state.next_state ); + + if( (NFC_FSM_IN_PROGRESS == psHciContext->hci_state.transition) + ) + { + psHciContext->hci_state.cur_state = + psHciContext->hci_state.next_state ; + psHciContext->hci_state.transition = NFC_FSM_COMPLETE ; + psHciContext->hci_state.next_state = (uint8_t) hciState_Unknown ; + /* Reset the HCI Sequence */ + psHciContext->response_pending = FALSE; + psHciContext->hci_seq = HCI_INVALID_SEQ; + status = NFCSTATUS_SUCCESS; + } + + HCI_DEBUG(" HCI: Current State After FSM Complete --> %02u \n", + psHciContext->hci_state.cur_state ); + + return status; +} + +void +phHciNfc_FSM_Rollback( + phHciNfc_sContext_t *psHciContext + ) +{ + + HCI_DEBUG("HCI: %s: transition=%02u, cur_state=%02u, next_state=%02u\n", + __func__, + psHciContext->hci_state.transition, + psHciContext->hci_state.cur_state, + psHciContext->hci_state.next_state); + + + + + + + if( (NFC_FSM_IN_PROGRESS == psHciContext->hci_state.transition) + ) + { + psHciContext->hci_state.transition = NFC_FSM_COMPLETE ; + psHciContext->hci_state.next_state = (uint8_t) hciState_Unknown ; + /* Reset the HCI Sequence */ + psHciContext->hci_seq = HCI_INVALID_SEQ; + psHciContext->response_pending = FALSE; + } +} + +#ifdef HCI_FSM_RESET +static +void +phHciNfc_FSM_Reset( + phHciNfc_sContext_t *psHciContext + ) +{ + + if( (hciState_Reset != psHciContext->hci_state.cur_state ) + ) + { + psHciContext->hci_state.cur_state = (uint8_t) hciState_Initialise ; + psHciContext->hci_state.transition = NFC_FSM_COMPLETE ; + psHciContext->hci_state.next_state = (uint8_t) hciState_Unknown ; + /* Reset the HCI Sequence */ + psHciContext->hci_seq = HCI_INVALID_SEQ; + } + +} +#endif + + + +static +NFCSTATUS +phHciNfc_Pending_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + PHNFC_UNUSED_VARIABLE(status); + + HCI_DEBUG("HCI: psHciContext->target_release --> %s \n", + (psHciContext->target_release)?"TRUE":"FALSE"); + if(TRUE == psHciContext->target_release) + { +#ifdef SW_RELEASE_TARGET + status = phHciNfc_ReaderMgmt_Deselect( + psHciContext, pHwRef, phHal_eISO14443_A_PICC, TRUE); + if(NFCSTATUS_PENDING == status ) + { + psHciContext->target_release = FALSE ; + } + } + else + { + status = psHciContext->error_status; +#else + psHciContext->target_release = FALSE ; +#endif + } + + return status; +} + + +void +phHciNfc_Error_Sequence( + void *psContext, + void *pHwRef, + NFCSTATUS error_status, + void *pdata, + uint8_t length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = (phHciNfc_sContext_t *)psContext; + + PHNFC_UNUSED_VARIABLE(status); + + HCI_DEBUG("HCI: In Function: %s \n", + __FUNCTION__); + + HCI_DEBUG ("HCI : Error Status : %04X\n", error_status); + + HCI_DEBUG(" HCI: Current HCI State --> %02u \n", + psHciContext->hci_state.cur_state ); + HCI_DEBUG(" HCI: Next HCI State --> %02u \n", + psHciContext->hci_state.next_state ); + + + if ( NFC_FSM_IN_PROGRESS == psHciContext->hci_state.transition ) + { + switch(psHciContext->hci_state.next_state) + { + case hciState_Initialise: + { + if (hciState_Reset == psHciContext->hci_state.cur_state) + { + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + phHciNfc_Release_Lower( psHciContext, pHwRef ); + /* Release all the resources and + * Notify the Receive Error Scenario to the Upper Layer + */ + comp_info.status = error_status ; + phHciNfc_Release_Notify (psHciContext, pHwRef, + NFC_NOTIFY_INIT_FAILED, &comp_info); + } + else if (hciState_Config == psHciContext->hci_state.cur_state) + { + /* Notify the Poll/Emulation Configure failure to the upper layer */ + + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + comp_info.status = error_status ; + + psHciContext->error_status = error_status; + status = phHciNfc_Pending_Sequence(psHciContext, pHwRef ); + /* Rollback the FSM as the Poll/Emulation configuration Failed */ + phHciNfc_FSM_Rollback(psHciContext); + psHciContext->error_status = NFCSTATUS_SUCCESS; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_CONFIG_ERROR, &comp_info); + } + else + { + + /* Notify the Poll Configure failure to the upper layer */ + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + + psHciContext->error_status = error_status; + status = phHciNfc_Pending_Sequence(psHciContext, pHwRef ); + /* Rollback the FSM as the Poll Disable Failed */ + phHciNfc_FSM_Rollback(psHciContext); + comp_info.status = error_status ; + psHciContext->error_status = NFCSTATUS_SUCCESS; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_ERROR, &comp_info); + } + break; + } + case hciState_Test: + { + status = phHciNfc_Test_Sequence( psHciContext, pHwRef , error_status, + (uint8_t *)pdata, length ); + break; + } + case hciState_IO: + { + status = phHciNfc_IO_Sequence( psHciContext, pHwRef , error_status, + (uint8_t *)pdata, length ); + break; + } + case hciState_Config: + { + /* Notify the Configure failure to the upper layer */ + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + psHciContext->error_status = error_status; + status = phHciNfc_Pending_Sequence(psHciContext, pHwRef ); + /* Rollback the FSM as the Poll Failed */ + phHciNfc_FSM_Rollback(psHciContext); + comp_info.status = psHciContext->error_status ; + psHciContext->error_status = NFCSTATUS_SUCCESS; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_CONFIG_ERROR, &comp_info); + break; + } + case hciState_Select: + { + /* Notify the Configure failure to the upper layer */ + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + /* Rollback the FSM as the Target Discovery Failed */ + phHciNfc_FSM_Rollback(psHciContext); + status = phHciNfc_ReaderMgmt_Update_Sequence( + psHciContext, INFO_SEQ ); + comp_info.status = error_status ; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_DISCOVERY_ERROR, &comp_info); + +#if 0 + /* Polling Wheel will be restarted by the upper layer + * to Rediscover again */ + if(NFCSTATUS_SUCCESS == status) + { + status = phHciNfc_ReaderMgmt_Deselect( + psHciContext, pHwRef, phHal_eISO14443_A_PICC, FALSE); + } + phHciNfc_FSM_Rollback(psHciContext); +#endif + break; + } + case hciState_Transact: + /* Notify the Transceive failure to the upper layer */ + { + phNfc_sTransactionInfo_t transact_info={FALSE,0,NULL,NULL,0}; + + /* Rollback the FSM as the Transceive Failed */ + phHciNfc_FSM_Rollback(psHciContext); + transact_info.status = error_status; + transact_info.buffer = NULL; + transact_info.length = FALSE; + psHciContext->p_xchg_info = NULL ; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_TRANSCEIVE_ERROR, &transact_info); + break; + + } + case hciState_Connect: + { + /* Notify the General failure to the upper layer */ + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + /* psHciContext->host_rf_type = phHal_eUnknown_DevType; */ + status = phHciNfc_ReaderMgmt_Update_Sequence( + psHciContext, INFO_SEQ ); + psHciContext->p_target_info = NULL; + psHciContext->hci_state.cur_state = hciState_Select; + phHciNfc_FSM_Rollback(psHciContext); + comp_info.status = error_status ; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_CONNECT_FAILED, &comp_info); + break; + } + case hciState_Reactivate: + { + /* Notify the General failure to the upper layer */ + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + /* psHciContext->host_rf_type = phHal_eUnknown_DevType; + status = phHciNfc_ReaderMgmt_Update_Sequence( + psHciContext, INFO_SEQ ); + psHciContext->p_target_info = NULL; + psHciContext->hci_state.cur_state = hciState_Select; */ + phHciNfc_FSM_Rollback(psHciContext); + comp_info.status = error_status ; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_CONNECT_FAILED, &comp_info); + break; + } + case hciState_Presence: + { + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + /* Roll Back to Connect State as Presence Check is Complete */ + phHciNfc_FSM_Rollback(psHciContext); + + /* Initialisation Complete Notification to the Upper Layer */ + comp_info.status = error_status; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_ERROR, &comp_info); + HCI_PRINT(" HCI Remote Target Removed from the Field. \n"); + break; + } + /* Notify the Connect or Disconnect failure to the upper layer */ + case hciState_Disconnect: + { + /* Notify the General failure to the upper layer */ + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + phHciNfc_FSM_Rollback(psHciContext); + comp_info.status = error_status ; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_DISCONNECT_FAILED, &comp_info); + break; + } + case hciState_Release: + { +#ifdef NXP_HCI_SHUTDOWN_OVERRIDE + status = phHciNfc_Release_Sequence(psHciContext ,pHwRef); +#else + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + phHciNfc_Release_Lower( psHciContext, pHwRef ); + /* Release all the resources and + * Notify the Receive Error Scenario to the Upper Layer + */ + comp_info.status = error_status ; + phHciNfc_Release_Notify (psHciContext, pHwRef, + NFC_NOTIFY_DEINIT_FAILED, &comp_info); +#endif + break; + } + default: + { + /* Notify the General failure to the upper layer */ + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + phHciNfc_FSM_Rollback(psHciContext); + comp_info.status = error_status ; + psHciContext->error_status = error_status; + status = phHciNfc_Pending_Sequence(psHciContext, pHwRef ); + if (NFCSTATUS_PENDING != status) + { + psHciContext->error_status = NFCSTATUS_SUCCESS; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_ERROR, &comp_info); + } + break; + } + + } /* End of the Processing of HCI State*/ + } + else + { + /* Notify the General failure to the upper layer */ + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + phHciNfc_FSM_Rollback(psHciContext); + comp_info.status = error_status ; + /* Disable the Notification to the Upper Layer */ + if(NFCSTATUS_BOARD_COMMUNICATION_ERROR + == PHNFCSTATUS(error_status)) + { + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_ERROR, &comp_info); + } + else + { + psHciContext->error_status = error_status; + status = phHciNfc_Pending_Sequence(psHciContext, pHwRef ); + if (NFCSTATUS_PENDING != status) + { + psHciContext->error_status = NFCSTATUS_SUCCESS; + } + } + } + return; +} + + + +NFCSTATUS +phHciNfc_Resume_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + HCI_DEBUG("HCI: %s: cur_state=%02u, next_state=%02u", + __FUNCTION__, + psHciContext->hci_state.cur_state, + psHciContext->hci_state.next_state); + + + + + switch(psHciContext->hci_state.next_state) + { + /* Process the Admin Gate Response based on the HCI State */ + case hciState_Initialise: + { + switch (psHciContext->hci_state.cur_state) + { + /* Initialise State after Power on */ + case hciState_Reset: + { + status = phHciNfc_Initialise_Sequence(psHciContext ,pHwRef); + break; + } + /* Initialise State after Power on */ + case hciState_Config: + { + status = phHciNfc_Config_Sequence(psHciContext ,pHwRef); + break; + } + /* Discovery Resume after connect failure */ + case hciState_Initialise: + case hciState_Select: + case hciState_Connect: + { + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + /* Update to the Intialise state as the discovery wheel is + * restarted. + */ + status = phHciNfc_FSM_Complete(psHciContext); + + psHciContext->host_rf_type = phHal_eUnknown_DevType; + psHciContext->p_target_info = NULL; + psHciContext->p_xchg_info = NULL; + + /* Initialisation Complete Notification to the Upper Layer */ + comp_info.status = status; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_POLL_RESTARTED , &comp_info); + HCI_PRINT(" HCI Remote Target Still Present in the Field. \n"); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + break; + } + } + break; + } + case hciState_Release: + { + status = phHciNfc_Release_Sequence(psHciContext ,pHwRef); + break; + } + case hciState_Config: + { + status = phHciNfc_Config_Sequence(psHciContext ,pHwRef); + break; + } + case hciState_Listen: + case hciState_Select: + { + status = phHciNfc_Info_Sequence( psHciContext, pHwRef ); + break; + } + case hciState_Reactivate: + case hciState_Connect: + { + status = phHciNfc_Connect_Sequence( psHciContext, pHwRef ); + break; + } + case hciState_Transact: + { + status = phHciNfc_Transact_Sequence( + psHciContext, pHwRef ); + break; + } + case hciState_Presence: + { + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + /* Roll Back to Connect State as Presence Check is Complete */ + phHciNfc_FSM_Rollback(psHciContext); + + /* Initialisation Complete Notification to the Upper Layer */ + comp_info.status = NFCSTATUS_SUCCESS; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_TARGET_PRESENT , &comp_info); + HCI_PRINT(" HCI Remote Target Still Present in the Field. \n"); + break; + } + case hciState_Disconnect: + { + status = phHciNfc_Disconnect_Sequence( psHciContext, pHwRef ); + break; + } + case hciState_Test: + { + status = phHciNfc_Test_Sequence( psHciContext, pHwRef , status, NULL, 0 ); + break; + } + case hciState_IO: + { + status = phHciNfc_IO_Sequence( psHciContext, pHwRef , status, NULL, 0 ); + break; + } + case hciState_Unknown: + { + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_STATE); + break; + } + } /* End of the Processing of HCI State*/ + + return status; +} + + +NFCSTATUS +phHciNfc_Initialise_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t config = 0; + + PHNFC_UNUSED_VARIABLE(config); + + switch(psHciContext->hci_seq) + { + case ADMIN_INIT_SEQ: + { + status = phHciNfc_Admin_Initialise( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { +#ifdef ESTABLISH_SESSION + if( hciMode_Session == psHciContext->hci_mode) + { + /* TODO: Initialise Link Management + Gate Resources */ + NFCSTATUS info_status = NFCSTATUS_SUCCESS; + PHNFC_UNUSED_VARIABLE(info_status); + info_status = phHciNfc_IDMgmt_Update_Sequence( + psHciContext, INFO_SEQ ); + + if(NFCSTATUS_SUCCESS == info_status) + { + psHciContext->hci_seq = PL_STOP_SEQ; + } + else + { + psHciContext->hci_seq = HCI_END_SEQ; + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } + } + else +#endif + { + psHciContext->hci_seq = LINK_MGMT_INIT_SEQ; + } + } + break; + } + case LINK_MGMT_INIT_SEQ: + { + status = phHciNfc_LinkMgmt_Initialise( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = IDENTITY_INIT_SEQ; + } + break; + } + case IDENTITY_INIT_SEQ: + { + status = phHciNfc_IDMgmt_Initialise( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = DEV_INIT_SEQ; + } + break; + } + case DEV_INIT_SEQ: + { + status = phHciNfc_DevMgmt_Initialise( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + if (HCI_SELF_TEST != psHciContext->init_mode) + { + psHciContext->hci_seq = PL_INIT_SEQ; + } + else + { +#if defined( ESTABLISH_SESSION ) + NFCSTATUS info_status = NFCSTATUS_SUCCESS; + PHNFC_UNUSED_VARIABLE(info_status); + info_status = phHciNfc_IDMgmt_Update_Sequence( + psHciContext, INFO_SEQ ); + + if(NFCSTATUS_SUCCESS == info_status) + { +#if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) + psHciContext->hci_seq = DEV_HAL_INFO_SEQ; +#else + psHciContext->hci_seq = IDENTITY_INFO_SEQ; +#endif /* #if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) */ + } + else + { + psHciContext->hci_seq = HCI_END_SEQ; + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_SEQUENCE); + } +#elif ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) + psHciContext->hci_seq = DEV_HAL_INFO_SEQ; +#else + psHciContext->hci_seq = HCI_END_SEQ; +#endif /* #ifdef ESTABLISH_SESSION */ + } + + } + break; + } + case PL_INIT_SEQ: + { + status = phHciNfc_PollLoop_Initialise( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + NFCSTATUS reset_status = NFCSTATUS_SUCCESS; + PHNFC_UNUSED_VARIABLE(reset_status); + reset_status = phHciNfc_ReaderMgmt_Update_Sequence( + psHciContext, RESET_SEQ ); + psHciContext->hci_seq = READER_MGMT_INIT_SEQ; + } + break; + } + case READER_MGMT_INIT_SEQ: + { + status = phHciNfc_ReaderMgmt_Initialise( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + NFCSTATUS reset_status = NFCSTATUS_SUCCESS; + PHNFC_UNUSED_VARIABLE(reset_status); + reset_status = phHciNfc_EmuMgmt_Update_Seq( + psHciContext, RESET_SEQ ); + psHciContext->hci_seq = EMULATION_INIT_SEQ; + } + break; + } + case EMULATION_INIT_SEQ: + { + status = phHciNfc_EmuMgmt_Initialise( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { +#if defined( ESTABLISH_SESSION ) + psHciContext->hci_seq = ADMIN_SESSION_SEQ; +#elif ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) + psHciContext->hci_seq = DEV_HAL_INFO_SEQ; +#else + psHciContext->hci_seq = HCI_END_SEQ; +#endif + } + break; + } +#ifdef ESTABLISH_SESSION + case ADMIN_SESSION_SEQ: + { + status = phHciNfc_Admin_Initialise( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { +#if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) + psHciContext->hci_seq = DEV_HAL_INFO_SEQ; +#else + psHciContext->hci_seq = IDENTITY_INFO_SEQ; +#endif /* #if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) */ + } + break; + } + case PL_STOP_SEQ: + { + status = phHciNfc_ReaderMgmt_Disable_Discovery( + psHciContext, pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { +#if defined( SW_AUTO_ACTIVATION ) + psHciContext->hci_seq = READER_SW_AUTO_SEQ; +#elif ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) + psHciContext->hci_seq = DEV_HAL_INFO_SEQ; +#else + psHciContext->hci_seq = IDENTITY_INFO_SEQ; +#endif /* #if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) */ + } + break; + } +#ifdef SW_AUTO_ACTIVATION + case READER_SW_AUTO_SEQ: + { + uint8_t activate_enable = FALSE; + uint8_t rdr_enable = TRUE; + + status = phHciNfc_ReaderA_Update_Info( + psHciContext, HCI_READER_A_ENABLE, + &rdr_enable); + if(status == NFCSTATUS_SUCCESS) + { + status = phHciNfc_ReaderA_Auto_Activate( psHciContext, + pHwRef, activate_enable ); + if(status == NFCSTATUS_SUCCESS) + { + psHciContext->hci_seq = IDENTITY_INFO_SEQ; + } + } + break; + } +#endif + /* fall through */ + case IDENTITY_INFO_SEQ: + { + status = phHciNfc_IDMgmt_Info_Sequence( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + if ((HCI_SELF_TEST != psHciContext->init_mode) + /* && ( TRUE == ((phHal_sHwReference_t *)pHwRef)->se_detect ) */ + && (HCI_CUSTOM_INIT != psHciContext->init_mode) + && (HCI_NFC_DEVICE_TEST != psHciContext->init_mode)) + { + NFCSTATUS info_status = NFCSTATUS_SUCCESS; + PHNFC_UNUSED_VARIABLE(info_status); + info_status = phHciNfc_EmuMgmt_Update_Seq( + psHciContext, INFO_SEQ ); + + if(NFCSTATUS_SUCCESS == info_status) + { + psHciContext->hci_seq = EMULATION_SWP_SEQ; + } + } + else + { + psHciContext->hci_seq = HCI_END_SEQ; + } + } + break; + } + case EMULATION_SWP_SEQ: + { + status = phHciNfc_EmuMgmt_Initialise( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = HCI_END_SEQ; + } + break; + } +#endif /* #ifdef ESTABLISH_SESSION */ + +#if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) + case DEV_HAL_INFO_SEQ: + { + static uint8_t mem_index = 0; + status = phHciNfc_DevMgmt_Get_Info(psHciContext, pHwRef, + (NFC_ADDRESS_HAL_CONF + mem_index), + (psHciContext->hal_mem_info + mem_index)); + if(NFCSTATUS_PENDING == status) + { + mem_index++; + if (NXP_HAL_MEM_INFO_SIZE <= mem_index ) + { + NFCSTATUS info_status = NFCSTATUS_SUCCESS; + PHNFC_UNUSED_VARIABLE(info_status); + info_status = phHciNfc_IDMgmt_Update_Sequence( + psHciContext, INFO_SEQ ); + mem_index = 0; + psHciContext->hci_seq = IDENTITY_INFO_SEQ; + /* psHciContext->hci_seq = + (HCI_SELF_TEST != psHciContext->init_mode)? + IDENTITY_INFO_SEQ : HCI_END_SEQ; */ + } + } + break; + } +#endif /* #if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) */ + case HCI_END_SEQ: + { + phHal_sMemInfo_t *p_mem_info = + (phHal_sMemInfo_t *) ( psHciContext->hal_mem_info ); + if ( + (HCI_SELF_TEST == psHciContext->init_mode ) + || (HCI_NFC_DEVICE_TEST == psHciContext->init_mode ) + ) + { + psHciContext->hci_state.next_state + = (uint8_t) hciState_Test; + } + status = phHciNfc_FSM_Complete ( psHciContext ); +#ifdef UICC_CONNECTIVITY_PATCH + phHciNfc_Uicc_Connectivity( psHciContext, pHwRef ); +#endif /* #ifdef UICC_CONNECTIVITY_PATCH */ + +#if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) + if(NXP_FW_UPLOAD_SUCCESS != p_mem_info->fw_magic ) + { + status = PHNFCSTVAL( CID_NFC_HCI, NFCSTATUS_FAILED ); + } +#endif /* #if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) */ + + /* Initialisation Complete Notification to the Upper Layer */ + if(NFCSTATUS_SUCCESS == status) + { + phNfc_sCompletionInfo_t comp_info={FALSE,0, NULL}; + + comp_info.status = status; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_INIT_COMPLETED, &comp_info); + HCI_PRINT("HCI Initialisation Completed \n"); + } + else + { + pphNfcIF_Notification_CB_t p_upper_notify = psHciContext->p_upper_notify; + void *pcontext = psHciContext->p_upper_context; + phNfc_sCompletionInfo_t comp_info; + + + phHciNfc_Release_Lower( psHciContext, pHwRef ); + phHciNfc_Release_Resources( &psHciContext ); + /* Notify the Failure to the Upper Layer */ + comp_info.status = status; + phHciNfc_Notify( p_upper_notify, pcontext, pHwRef, + NFC_NOTIFY_INIT_FAILED, &comp_info); + HCI_PRINT("HCI FSM Initialisation Error \n"); + } + break; + } + default: + break; + } + + return status; +} + + +NFCSTATUS +phHciNfc_Release_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + switch(psHciContext->hci_seq) + { + case PL_STOP_SEQ: + { + status = phHciNfc_ReaderMgmt_Disable_Discovery( + psHciContext, pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + (void)phHciNfc_EmuMgmt_Update_Seq( + psHciContext, REL_SEQ ); + psHciContext->hci_seq = EMULATION_REL_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + case EMULATION_REL_SEQ: + { + status = phHciNfc_EmuMgmt_Release( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + (void)phHciNfc_DevMgmt_Update_Sequence( + psHciContext, REL_SEQ ); + psHciContext->hci_seq = ADMIN_REL_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + case DEV_REL_SEQ: + { + NFCSTATUS info_status = NFCSTATUS_SUCCESS; + PHNFC_UNUSED_VARIABLE(info_status); + info_status = phHciNfc_DevMgmt_Update_Sequence( + psHciContext, REL_SEQ ); + status = phHciNfc_DevMgmt_Release( psHciContext, pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = HCI_END_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + case READER_MGMT_REL_SEQ: + { + status = phHciNfc_ReaderMgmt_Release( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = PL_REL_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + case PL_REL_SEQ: + { + status = phHciNfc_PollLoop_Release( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = IDENTITY_REL_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + case IDENTITY_REL_SEQ: + { + status = phHciNfc_IDMgmt_Release( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = LINK_MGMT_REL_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + case LINK_MGMT_REL_SEQ: + { + status = phHciNfc_LinkMgmt_Release( psHciContext,pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = ADMIN_REL_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + case ADMIN_REL_SEQ: + { + /* Admin Management Release Sequence */ + status = phHciNfc_Admin_Release( psHciContext,pHwRef, phHciNfc_TerminalHostID ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = DEV_REL_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + case HCI_END_SEQ: + { + pphNfcIF_Notification_CB_t p_upper_notify = + psHciContext->p_upper_notify; + phNfc_sLowerIF_t *plower_if = + &(psHciContext->lower_interface); + void *pcontext = + psHciContext->p_upper_context; + phNfc_sCompletionInfo_t comp_info; + + + status = plower_if->release((void *)plower_if->pcontext, + (void *)pHwRef); + + phHciNfc_Release_Resources( &psHciContext ); + /* De-Initialisation Complete Notification to the Upper Layer */ + comp_info.status = status; + phHciNfc_Notify(p_upper_notify, pcontext, pHwRef, + NFC_NOTIFY_DEINIT_COMPLETED, &comp_info); + + HCI_PRINT("HCI Release Completed \n"); + break; + } + default: + { + /* psHciContext->hci_seq = HCI_END_SEQ; */ + break; + } + } + + return status; +} + + +static +NFCSTATUS +phHciNfc_Config_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phNfc_sCompletionInfo_t comp_info = {FALSE,0,NULL}; + + switch(psHciContext->config_type) + { + case POLL_LOOP_CFG: + { + status = phHciNfc_PollLoop_Sequence( psHciContext, pHwRef ); + break; + } + case SMX_WI_MODE: + { + status = phHciNfc_SmartMx_Mode_Sequence( psHciContext, pHwRef ); + break; + } +#ifdef ENABLE_P2P + case NFC_GENERAL_CFG: + { + if(TARGET_GENERAL_SEQ == psHciContext->hci_seq) + { + status = phHciNfc_NfcIP_SetATRInfo( psHciContext, + pHwRef, NFCIP_TARGET, + psHciContext->p_config_params); + if( NFCSTATUS_PENDING != status ) + { + /* Roll Back the State Machine to its Original State */ + phHciNfc_FSM_Rollback ( psHciContext ); + } + else + { + psHciContext->hci_seq = HCI_END_SEQ; + } + } + else + { + status = phHciNfc_Pending_Sequence(psHciContext, pHwRef ); + if (NFCSTATUS_PENDING != status) + { + /* Roll Back to its Current State as Configuration is Complete */ + phHciNfc_FSM_Rollback(psHciContext); + + HCI_PRINT(" NFC-IP(P2P) Configuration Completed. \n"); + comp_info.status = status; + psHciContext->error_status = NFCSTATUS_SUCCESS; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_CONFIG_SUCCESS , &comp_info); + } + } + break; + } +#endif + case SWP_PROTECT_CFG: + case SWP_EVT_CFG: + case SMX_WI_CFG: + { + /* Roll Back to its Current State as Configuration is Complete */ + phHciNfc_FSM_Rollback(psHciContext); + + HCI_DEBUG(" %s Configuration Completed. \n", + ((SMX_WI_CFG == psHciContext->config_type)? + "SmartMX" : "SWP Event/Protection")); + + comp_info.status = status; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_CONFIG_SUCCESS, &comp_info); + break; + } + case NFC_TARGET_CFG: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + break; + } + case UICC_SWP_CFG: +#if 0 + { + phHal_sEmulationCfg_t *p_emulation_cfg = + (phHal_sEmulationCfg_t * ) + psHciContext->p_config_params; + if (NULL != p_emulation_cfg) + { + phHal_sUiccEmuCfg_t *uicc_config = + &p_emulation_cfg->config.uiccEmuCfg; + if( TRUE == uicc_config->enableUicc ) + { + status = phHciNfc_Uicc_Connect_Status(psHciContext,pHwRef); + if( NFCSTATUS_PENDING == status ) + { + break; + } /* Or Else Fall through to notify the above layer */ + } + } + } +#endif + /* fall through */ + case NFC_CE_A_CFG: + case NFC_CE_B_CFG: + { + status = phHciNfc_EmulationCfg_Sequence( psHciContext, pHwRef ); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); + break; + } + } + + return status; +} + + +NFCSTATUS +phHciNfc_PollLoop_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHal_sADD_Cfg_t *p_poll_config = (phHal_sADD_Cfg_t * ) + psHciContext->p_config_params; + if (NULL != p_poll_config) + { + uint8_t speed = + p_poll_config->NfcIP_Mode; + uint8_t targetSpeed = + p_poll_config->NfcIP_Target_Mode; + switch(psHciContext->hci_seq) + { + case PL_DURATION_SEQ: + { + status = phHciNfc_PollLoop_Cfg( psHciContext, pHwRef, + (uint8_t)PL_DURATION , NULL); + if(NFCSTATUS_SUCCESS == status) + { +#if defined (ENABLE_P2P) && defined (TARGET_SPEED) + psHciContext->hci_seq = TARGET_SPEED_SEQ; +#elif defined (ENABLE_P2P) && defined (INITIATOR_SPEED) + psHciContext->hci_seq = INITIATOR_SPEED_SEQ; +#elif defined (ENABLE_P2P) && defined (NFCIP_TGT_DISABLE_CFG) + psHciContext->hci_seq = PL_TGT_DISABLE_SEQ; +#else + psHciContext->hci_seq = PL_CONFIG_PHASE_SEQ; +#endif + + status = NFCSTATUS_PENDING; + } + break; + } +#if defined (ENABLE_P2P) && defined (TARGET_SPEED) + case TARGET_SPEED_SEQ: + { +#define NFCIP_ACTIVE_SHIFT 0x03U +#define NFCIP_PASSIVE_MASK 0x07U + uint8_t mode = targetSpeed; + HCI_DEBUG("Setting target mode to 0x%02X", mode); + status = + phHciNfc_NfcIP_SetMode( psHciContext, pHwRef, NFCIP_TARGET, + (uint8_t) mode ); + if(NFCSTATUS_PENDING == status) + { +#if defined (INITIATOR_SPEED) + psHciContext->hci_seq = INITIATOR_SPEED_SEQ; +#elif defined (NFCIP_TGT_DISABLE_CFG) + psHciContext->hci_seq = PL_TGT_DISABLE_SEQ; +#else + psHciContext->hci_seq = PL_CONFIG_PHASE_SEQ; +#endif + status = NFCSTATUS_PENDING; + } + break; + } +#endif +#if defined (ENABLE_P2P) && defined (INITIATOR_SPEED) + case INITIATOR_SPEED_SEQ: + { + HCI_DEBUG("Setting initiator mode to 0x%02X", speed); + status = + phHciNfc_NfcIP_SetMode( psHciContext, pHwRef, NFCIP_INITIATOR, + (uint8_t) (speed & DEFAULT_NFCIP_INITIATOR_MODE_SUPPORT)); + if(NFCSTATUS_PENDING == status) + { +#if defined (NFCIP_TGT_DISABLE_CFG) + psHciContext->hci_seq = PL_TGT_DISABLE_SEQ; +#else + psHciContext->hci_seq = PL_CONFIG_PHASE_SEQ; +#endif + status = NFCSTATUS_PENDING; + } + break; + } +#endif +#if defined (ENABLE_P2P) && defined (NFCIP_TGT_DISABLE_CFG) + case PL_TGT_DISABLE_SEQ: + { + /* Configure the Polling Loop Target Disable Parameter */ + status = phHciNfc_PollLoop_Cfg( psHciContext, pHwRef, + (uint8_t)PL_DISABLE_TARGET, &p_poll_config->NfcIP_Tgt_Disable ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = PL_CONFIG_PHASE_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } +#endif + case PL_CONFIG_PHASE_SEQ: + { + phHal_sPollDevInfo_t *p_poll_info = + &(p_poll_config->PollDevInfo.PollCfgInfo); + + p_poll_info->EnableIso14443A = + ( (p_poll_info->EnableIso14443A) + || ( speed & (uint8_t)phHal_ePassive106 ) + ); + p_poll_info->EnableFelica212 = + ( (p_poll_info->EnableFelica212) + || ( speed & (uint8_t)phHal_ePassive212 ) + ); + p_poll_info->EnableFelica424 = + ( (p_poll_info->EnableFelica424) + || ( speed & (uint8_t)phHal_ePassive424 ) + ); + /* Configure the Polling Loop Gate Parameters */ + status = phHciNfc_PollLoop_Cfg( psHciContext, pHwRef, + (uint8_t)PL_RD_PHASES, NULL ); + if(NFCSTATUS_SUCCESS == status) + { + if(((~(PL_RD_PHASES_DISABLE)) & + p_poll_config->PollDevInfo.PollEnabled)!= 0) + { + psHciContext->hci_seq = READER_ENABLE_SEQ; + } + else + { + /* psHciContext->hci_seq = READER_DISABLE_SEQ; */ + psHciContext->hci_seq = HCI_END_SEQ; + } + status = NFCSTATUS_PENDING; + } + break; + } + case READER_ENABLE_SEQ: + { + status = + phHciNfc_ReaderMgmt_Enable_Discovery( + psHciContext, pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + /* psHciContext->hci_seq = PL_CONFIG_PHASE_SEQ; */ + psHciContext->hci_seq = HCI_END_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + case READER_DISABLE_SEQ: + { + status = phHciNfc_ReaderMgmt_Disable_Discovery( + psHciContext, pHwRef ); + + if(NFCSTATUS_SUCCESS == status) + { + if((~(PL_RD_PHASES_DISABLE) & + p_poll_config->PollDevInfo.PollEnabled)!= 0) + { + psHciContext->hci_seq = PL_DURATION_SEQ; + } + else + { +#if defined (ENABLE_P2P) && defined (INITIATOR_SPEED) + psHciContext->hci_seq = INITIATOR_SPEED_SEQ; +#elif defined (ENABLE_P2P) && defined (NFCIP_TGT_DISABLE_CFG) + psHciContext->hci_seq = PL_TGT_DISABLE_SEQ; +#else + psHciContext->hci_seq = PL_CONFIG_PHASE_SEQ; +#endif + /* psHciContext->hci_seq = HCI_END_SEQ; */ + } + status = NFCSTATUS_PENDING; + } + break; + } + case HCI_END_SEQ: + { + phNfc_sCompletionInfo_t comp_info; + status = phHciNfc_Pending_Sequence(psHciContext, pHwRef ); + if (NFCSTATUS_PENDING != status) + { + /* status = phHciNfc_FSM_Complete ( psHciContext );*/ + phHciNfc_FSM_Rollback ( psHciContext ); + /* Poll Configuration Notification to the Upper Layer */ + if((~(PL_RD_PHASES_DISABLE) & + p_poll_config->PollDevInfo.PollEnabled)!= 0) + { + comp_info.status = status; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_POLL_ENABLED, &comp_info); + } + else + { + comp_info.status = status; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_POLL_DISABLED, &comp_info); + } + HCI_PRINT("HCI Discovery Configuration Completed \n"); + } + break; + } + default: + { + /* psHciContext->hci_seq = HCI_END_SEQ; */ + break; + } + }/* End of the Poll Sequence Switch */ + }/* End of the Poll Config info Check */ + + return status; +} + + +NFCSTATUS +phHciNfc_EmulationCfg_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static phNfc_sCompletionInfo_t comp_info = {FALSE,0,NULL}; +#if defined(HOST_EMULATION) + phHciNfc_GateID_t ce_gate = phHciNfc_UnknownGate; +#endif /* #ifdef HOST_EMULATION */ + phHal_sEmulationCfg_t *p_emulation_cfg = (phHal_sEmulationCfg_t * ) + psHciContext->p_config_params; +#ifdef UICC_SESSION_RESET + uint8_t uicc_clear_pipes = FALSE; +#endif + + + if (NULL != p_emulation_cfg) + { +#if defined(HOST_EMULATION) + if(NFC_HOST_CE_A_EMULATION == p_emulation_cfg->emuType) + { + psHciContext->config_type = NFC_CE_A_CFG; + if (NULL == psHciContext->p_ce_a_info) + { + ce_gate = phHciNfc_CETypeAGate; + } + } + else if (NFC_HOST_CE_B_EMULATION == p_emulation_cfg->emuType) + { + psHciContext->config_type = NFC_CE_B_CFG; + if (NULL == psHciContext->p_ce_b_info) + { + ce_gate = phHciNfc_CETypeBGate; + } + } +#ifdef UICC_SESSION_RESET + else if ((NFC_UICC_EMULATION == p_emulation_cfg->emuType) + &&(FALSE == p_emulation_cfg->config.uiccEmuCfg.enableUicc) + ) + { + uicc_clear_pipes = TRUE; + } +#endif + else + { + ; + } +#endif /* #ifdef HOST_EMULATION */ + + switch(psHciContext->hci_seq) + { +#if defined(HOST_EMULATION) + case ADMIN_CE_SEQ: + { + if(phHciNfc_UnknownGate != ce_gate) + { + status = phHciNfc_Admin_CE_Init(psHciContext, pHwRef, ce_gate); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_NOT_ALLOWED); + } + + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = EMULATION_CONFIG_SEQ; + /* psHciContext->hci_seq = HCI_END_SEQ; */ + status = NFCSTATUS_PENDING; + } + break; + } +#endif + case EMULATION_CONFIG_SEQ: + { + status = phHciNfc_Emulation_Cfg(psHciContext, pHwRef, + psHciContext->config_type); + if(NFCSTATUS_SUCCESS == status) + { + /* psHciContext->hci_seq = PL_CONFIG_PHASE_SEQ; */ +#ifdef UICC_SESSION_RESET + if(UICC_SWP_CFG == psHciContext->config_type) + { + psHciContext->hci_seq = ADMIN_REL_SEQ; + } + else +#endif /* UICC_SESSION_RESET */ + { + psHciContext->hci_seq = HCI_END_SEQ; + } + status = NFCSTATUS_PENDING; + } + break; + } +#ifdef UICC_SESSION_RESET + case ADMIN_REL_SEQ: + { + if (TRUE == uicc_clear_pipes) + { + /* Admin Management UICC Release Sequence */ + status = phHciNfc_Admin_Release( psHciContext,pHwRef, phHciNfc_UICCHostID ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = HCI_END_SEQ; + if (UICC_SWP_CFG == psHciContext->config_type) + { + (void)phHciNfc_SWP_Update_Sequence(psHciContext, + CONFIG_SEQ ); + } + status = NFCSTATUS_PENDING; + } + break; + } + } +#endif /* UICC_SESSION_RESET */ + /* fall through */ + case HCI_END_SEQ: + { + phHciNfc_FSM_Rollback(psHciContext); + + HCI_PRINT(" Emulation Configuration Completed. \n"); + + comp_info.status = status; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_CONFIG_SUCCESS, &comp_info); + break; + } + default: + { + /* psHciContext->hci_seq = HCI_END_SEQ; */ + break; + } + } + /* + NFC_CE_A_CFG; + NFC_CE_B_CFG; */ + + }/* End of the Emulation Config info Check */ + + return status; +} + + +NFCSTATUS +phHciNfc_SmartMx_Mode_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHal_sADD_Cfg_t *p_poll_config = (phHal_sADD_Cfg_t * ) + psHciContext->p_config_params; + phNfc_sCompletionInfo_t comp_info = {FALSE,0,NULL}; + if (NULL != p_poll_config) + { + switch(psHciContext->hci_seq) + { + case READER_DISABLE_SEQ: + { + status = phHciNfc_ReaderMgmt_Disable_Discovery( + psHciContext, pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = EMULATION_CONFIG_SEQ; + /* psHciContext->hci_seq = HCI_END_SEQ; */ + status = NFCSTATUS_PENDING; + } + break; + } + case EMULATION_CONFIG_SEQ: + { + status = phHciNfc_WI_Configure_Mode( + psHciContext, pHwRef,psHciContext->smx_mode ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = PL_CONFIG_PHASE_SEQ; + /* psHciContext->hci_seq = HCI_END_SEQ; */ + status = NFCSTATUS_PENDING; + } + break; + } + case PL_CONFIG_PHASE_SEQ: + { + /* Configure the Polling Loop Gate Parameters */ + status = phHciNfc_PollLoop_Cfg( psHciContext, pHwRef, + (uint8_t)PL_RD_PHASES, NULL ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = READER_ENABLE_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + case READER_ENABLE_SEQ: + { + status = + phHciNfc_ReaderMgmt_Enable_Discovery( + psHciContext, pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + /* psHciContext->hci_seq = PL_CONFIG_PHASE_SEQ; */ + psHciContext->hci_seq = HCI_END_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + case HCI_END_SEQ: + { + status = phHciNfc_Pending_Sequence(psHciContext, pHwRef ); + if (NFCSTATUS_PENDING != status) + { + /* status = phHciNfc_FSM_Complete ( psHciContext );*/ + phHciNfc_FSM_Rollback ( psHciContext ); + if( hciState_Disconnect == psHciContext->hci_state.cur_state) + { + psHciContext->host_rf_type = phHal_eUnknown_DevType; + psHciContext->p_target_info = NULL; + psHciContext->p_xchg_info = NULL; + } + /* Poll Configuration Notification to the Upper Layer */ + if((~(PL_RD_PHASES_DISABLE) & + p_poll_config->PollDevInfo.PollEnabled)!= 0) + { + comp_info.status = status; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_POLL_ENABLED, &comp_info); + } + else + { + comp_info.status = status; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_POLL_DISABLED, &comp_info); + } + HCI_PRINT("HCI Discovery Configuration Completed \n"); + } + break; + } + default: + { + /* psHciContext->hci_seq = HCI_END_SEQ; */ + break; + } + }/* End of the Poll Sequence Switch */ + }/* End of the Poll Config info Check */ + + return status; +} + + +NFCSTATUS +phHciNfc_Connect_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static phNfc_sCompletionInfo_t comp_info = {FALSE,0,NULL}; + phHal_eRemDevType_t target_type = phHal_eUnknown_DevType; + + if( NULL != psHciContext->p_target_info ) + { + + target_type = psHciContext->p_target_info->RemDevType; + switch(psHciContext->hci_seq) + { + case READER_REACTIVATE_SEQ: + { + /* Complete the Reactivate Sequence and notify the HAL */ + status = phHciNfc_FSM_Complete ( psHciContext ); + /* Reactivate Complete Notification to the Upper Layer */ + if(NFCSTATUS_SUCCESS == status) + { + comp_info.status = status; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_TARGET_REACTIVATED , &comp_info); + HCI_PRINT(" HCI Remote Target Reactivated. \n"); + } + else + { + comp_info.status = status; + phHciNfc_FSM_Rollback ( psHciContext ); + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_ERROR , &comp_info); + HCI_PRINT("HCI FSM Invalid Selection State \n"); + HCI_PRINT("HCI Remote Target Reactivation Failed \n"); + } + break; + } + case READER_SELECT_SEQ: + { + /* If the Target is Mifare then it should fall through */ + if(( phHal_eMifare_PICC != target_type ) + &&(phHal_eISO14443_3A_PICC != target_type) +#ifdef TYPE_B + && ( phHal_eISO14443_B_PICC != target_type ) + && ( phHal_eISO14443_4B_PICC != target_type ) +#endif +#ifdef TYPE_FELICA + && ( phHal_eFelica_PICC != target_type ) +#endif +#ifdef TYPE_JEWEL + && ( phHal_eJewel_PICC != target_type ) +#endif /* #ifdef TYPE_JEWEL */ +#ifdef TYPE_ISO15693 + && ( phHal_eISO15693_PICC != target_type ) +#endif /* #ifdef TYPE_ISO15693 */ + + ) + { + status = phHciNfc_ReaderMgmt_Info_Sequence( psHciContext, pHwRef ); + if(NFCSTATUS_SUCCESS == status) + { + psHciContext->hci_seq = HCI_END_SEQ; + status = NFCSTATUS_PENDING; + } + break; + } + } + /* fall through */ + case HCI_END_SEQ: + { + /* Complete the Connect Sequence and notify the HAL */ + status = phHciNfc_FSM_Complete ( psHciContext ); + /* Connection Complete Notification to the Upper Layer */ + if(NFCSTATUS_SUCCESS == status) + { + /* Invalidate the previously polled RF Reader Type */ + /* psHciContext->host_rf_type = phHal_eInvalidRFType;*/ + comp_info.status = status; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_TARGET_CONNECTED , &comp_info); + HCI_PRINT(" HCI Remote Target Selected for Transaction. \n"); + } + else + { + comp_info.status = status; + /* phHciNfc_FSM_Rollback ( psHciContext ); */ + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_ERROR , &comp_info); + HCI_PRINT("HCI FSM Invalid Selection State \n"); + HCI_PRINT("HCI Remote Target Selection Failed \n"); + } + break; + } + default: + { + HCI_PRINT("\t Invalid HCI Connect Sequence \n"); + /* psHciContext->hci_seq = HCI_END_SEQ; */ + break; + } + }/* End of the Connect Sequence Switch */ + } + + return status; +} + + +NFCSTATUS +phHciNfc_Disconnect_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static phNfc_sCompletionInfo_t comp_info = {FALSE, 0 , NULL}; + phHal_eRemDevType_t target_type = phHal_eUnknown_DevType; + uint8_t re_poll = 0; + + if( NULL != psHciContext->p_target_info ) + { + + target_type = psHciContext->p_target_info->RemDevType; + switch(psHciContext->hci_seq) + { + case READER_UICC_DISPATCH_SEQ: + { + status = phHciNfc_ReaderMgmt_UICC_Dispatch( + psHciContext, pHwRef, target_type ); + psHciContext->hci_seq = READER_DESELECT_SEQ; + if(NFCSTATUS_PENDING == status) + { + break; + } + } + /* fall through */ + case READER_DESELECT_SEQ: + { + re_poll = (uint8_t) ( NULL != psHciContext->p_config_params )? + *((uint8_t *)psHciContext->p_config_params):FALSE; + status = phHciNfc_ReaderMgmt_Deselect( + psHciContext, pHwRef, target_type, re_poll); + if(NFCSTATUS_PENDING == status) + { + psHciContext->hci_seq = HCI_END_SEQ; + psHciContext->p_config_params = NULL; + } + break; + } + case HCI_END_SEQ: + { + /* Complete the Disconnect Sequence and notify the HAL */ + status = phHciNfc_FSM_Complete ( psHciContext ); + /* Disconnect Notification to the Upper Layer */ + if(NFCSTATUS_SUCCESS == status) + { + /* Invalidate the previously polled RF Reader Type */ + psHciContext->host_rf_type = phHal_eUnknown_DevType; + psHciContext->p_target_info = NULL; + psHciContext->p_xchg_info = NULL; + comp_info.status = status; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_TARGET_DISCONNECTED , &comp_info); + HCI_PRINT(" HCI Remote Target De-Selected. \n"); + } + else + { + comp_info.status = status; + /* phHciNfc_FSM_Rollback ( psHciContext ); */ + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_ERROR , &comp_info); + HCI_PRINT("HCI FSM Invalid De-Selection State \n"); + HCI_PRINT("HCI Remote Target De-Selection Failed \n"); + } + + break; + } + default: + { + HCI_PRINT("\t Invalid HCI Connect Sequence \n"); + /* psHciContext->hci_seq = HCI_END_SEQ; */ + break; + } + }/* End of the Connect Sequence Switch */ + } + + return status; +} + + +static +NFCSTATUS +phHciNfc_Transact_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + static phNfc_sTransactionInfo_t transact_info = {FALSE,0,NULL,NULL,0}; + + pphNfcIF_Notification_CB_t p_upper_notify = psHciContext->p_upper_notify; + void *pcontext = psHciContext->p_upper_context; + uint8_t transact_result = NFC_NOTIFY_ERROR; + + /* Roll Back to Connect State as Transceive is Complete */ + phHciNfc_FSM_Rollback(psHciContext); + + switch (psHciContext->host_rf_type) + { + case phHal_eISO14443_A_PCD: +#ifdef TYPE_B + case phHal_eISO14443_B_PCD: +#endif + case phHal_eISO14443_BPrime_PCD: +#ifdef TYPE_FELICA + case phHal_eFelica_PCD: +#endif +#ifdef TYPE_ISO15693 + case phHal_eISO15693_PCD: +#endif + { + if(ZERO != psHciContext->rx_index) + { + transact_info.status = NFCSTATUS_SUCCESS; + transact_info.buffer = + &psHciContext->recv_buffer[psHciContext->rx_index]; + transact_info.length = + psHciContext->rx_total - psHciContext->rx_index; + transact_result = NFC_NOTIFY_TRANSCEIVE_COMPLETED; + } + else + { + transact_info.status = NFCSTATUS_FAILED; + transact_result = NFC_NOTIFY_TRANSCEIVE_ERROR; + } + HCI_PRINT(" HCI Transceive operation Completed. \n"); + psHciContext->p_xchg_info = NULL ; + break; + } +#ifdef TYPE_JEWEL + /* fall through */ + case phHal_eJewel_PCD: +#endif + { + transact_info.status = NFCSTATUS_SUCCESS; + transact_info.buffer = + &psHciContext->recv_buffer[psHciContext->rx_index]; + transact_info.length = + psHciContext->rx_total - psHciContext->rx_index; + transact_result = NFC_NOTIFY_TRANSCEIVE_COMPLETED; + HCI_PRINT(" HCI Transceive operation Completed. \n"); + psHciContext->p_xchg_info = NULL ; + break; + } +#if defined(ENABLE_P2P) + case phHal_eNfcIP1_Initiator: + case phHal_eNfcIP1_Target: +#endif + { + HCI_PRINT(" HCI Send operation Completed. \n"); + transact_info.status = NFCSTATUS_SUCCESS; + transact_result = NFC_NOTIFY_SEND_COMPLETED; + break; + } + case phHal_eUnknown_DevType: + default: + { + transact_info.status = + PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + + } + /* Notify the Transceive Completion to the Upper layer */ + phHciNfc_Notify( p_upper_notify, pcontext , pHwRef, + transact_result, &transact_info); + + return (NFCSTATUS)NFCSTATUS_SUCCESS; +} + +static +NFCSTATUS +phHciNfc_Info_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + HCI_DEBUG(" HCI: Info Sequence Entry --> Reader Type : %02X \n", + psHciContext->host_rf_type); + switch (psHciContext->host_rf_type) + { + case phHal_eISO14443_A_PCD: +#ifdef TYPE_B + case phHal_eISO14443_B_PCD: +#endif + case phHal_eISO14443_BPrime_PCD: +#ifdef TYPE_FELICA + case phHal_eFelica_PCD: +#endif +#ifdef TYPE_JEWEL + case phHal_eJewel_PCD: +#endif +#ifdef TYPE_ISO15693 + case phHal_eISO15693_PCD: +#endif + { + /* To update the select sequence to retrieve + * the target information using the reader type. + */ + status = phHciNfc_ReaderMgmt_Info_Sequence( psHciContext, pHwRef ); + break; + } +#if defined(ENABLE_P2P) + case phHal_eNfcIP1_Initiator: + case phHal_eNfcIP1_Target: + { + status = phHciNfc_NfcIP_Info_Sequence( psHciContext, pHwRef ); + break; + } +#endif + case phHal_eUnknown_DevType: + default: + { + status = + PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + break; + } + + } + return status; +} + +static +NFCSTATUS +phHciNfc_Test_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + NFCSTATUS test_status, + uint8_t *pdata, + uint8_t length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static phNfc_sCompletionInfo_t comp_info = {0}; + static phNfc_sData_t test_result= {NULL,0}; + + /* Complete the Test Sequence and notify the HAL */ + status = phHciNfc_FSM_Complete ( psHciContext ); + /* Test Results to the Upper Layer */ + if(NFCSTATUS_SUCCESS == status) + { + comp_info.status = test_status; + if ( (NULL != pdata) && (length >= HCP_HEADER_LEN) ) + { + test_result.buffer = ( pdata + HCP_HEADER_LEN); + test_result.length = length - HCP_HEADER_LEN; + } + else + { + status = phHciNfc_DevMgmt_Get_Test_Result( + psHciContext, &test_result ); + } + comp_info.info = &test_result; + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_RESULT , &comp_info); + HCI_DEBUG(" HCI System Test Completed : Status = %u\n", test_status); + } + else + { + comp_info.status = status; + phHciNfc_FSM_Rollback ( psHciContext ); + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_NOTIFY_ERROR , &comp_info); + HCI_PRINT("HCI FSM Invalid Test State \n"); + } + + return status; +} + +static +NFCSTATUS +phHciNfc_IO_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + NFCSTATUS io_status, + uint8_t *pdata, + uint8_t length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static phNfc_sCompletionInfo_t comp_info = {0}; + + /* To remove "warning (VS 4100) : unreferenced formal parameter" */ + PHNFC_UNUSED_VARIABLE(pdata); + PHNFC_UNUSED_VARIABLE(length); + /* Complete the Test Sequence and notify the HAL */ + phHciNfc_FSM_Rollback ( psHciContext ); + /* Test Results to the Upper Layer */ + comp_info.status = io_status; + status = phHciNfc_Pending_Sequence(psHciContext, pHwRef ); + if(NFCSTATUS_SUCCESS == io_status) + { + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_IO_SUCCESS , &comp_info); + HCI_PRINT(" HCI System IO Successful. \n"); + } + else + { + phHciNfc_Notify(psHciContext->p_upper_notify, + psHciContext->p_upper_context, pHwRef, + NFC_IO_ERROR , &comp_info); + HCI_PRINT("HCI IO Error \n"); + } + return status; +} + + + +#ifdef OTHER_TAGS + +NFCSTATUS +phHciNfc_Activate_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + return status; +} + + +#endif + + diff --git a/libnfc-nxp/phHciNfc_Sequence.h b/libnfc-nxp/phHciNfc_Sequence.h new file mode 100644 index 0000000..e3c714f --- /dev/null +++ b/libnfc-nxp/phHciNfc_Sequence.h @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_Sequence.h * +* \brief State Machine Management for the HCI and the Function Sequence * +* for a particular State. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Aug 14 17:01:28 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.12 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* * +* =========================================================================== * +*/ + +/*@{*/ +#ifndef PHHCINFC_SEQUENCE_H +#define PHHCINFC_SEQUENCE_H + +/*@}*/ + + +/** + * \name HCI + * + * File: \ref phHciNfc_Sequence.h + * + */ + +/*@{*/ +#define PHHCINFC_SEQUENCE_FILEREVISION "$Revision: 1.12 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_SEQUENCE_FILEALIASES "$Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + + +/* +################################################################################ +***************************** Header File Inclusion **************************** +################################################################################ +*/ + +#include + +/* +################################################################################ +****************************** Macro Definitions ******************************* +################################################################################ +*/ + +/* +################################################################################ +************************* Function Prototype Declaration *********************** +################################################################################ +*/ + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_FSM_Update function Validates the HCI State to + * the next operation ongoing. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] state state is the state to which the + * current HCI Layer state is validated. + * \param[in] validate_type validate the state by the type of the + * validation required. + * + * \retval NFCSTATUS_SUCCESS FSM Validated successfully . + * \retval NFCSTATUS_INVALID_STATE The supplied state parameter is invalid. + * + */ + +extern +NFCSTATUS +phHciNfc_FSM_Validate( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eState_t state, + uint8_t validate_type + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_FSM_Update function Checks and Updates the HCI State to + * the next valid State. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] next_state next_state is the state to which + * we the HCI Layer. + * \param[in] transition transiton of the state whether + * ongoing or complete . + * + * \retval NFCSTATUS_SUCCESS FSM Updated successfully . + * \retval NFCSTATUS_INVALID_STATE The supplied state parameter is invalid. + * + */ + +extern +NFCSTATUS +phHciNfc_FSM_Update( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eState_t next_state + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_FSM_Complete function completes the ongoing state transition + * from the current state to the next state. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * + * \retval NFCSTATUS_SUCCESS FSM Updated successfully . + * \retval NFCSTATUS_INVALID_STATE The supplied state parameter is invalid. + * + */ + +extern +NFCSTATUS +phHciNfc_FSM_Complete( + phHciNfc_sContext_t *psHciContext + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_FSM_Rollback function rolls back to previous valid state + * and abort the ongoing state transition. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * + * \retval NONE. + * + */ + +extern +void +phHciNfc_FSM_Rollback( + phHciNfc_sContext_t *psHciContext + ); + + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Initialise_Sequence function sequence initialises the + * HCI layer and the remote device by performing the operations required + * setup the reader and discovery functionality. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_SUCCESS HCI current initialise sequence successful. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + */ + + +extern +NFCSTATUS +phHciNfc_Initialise_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_PollLoop_Sequence function sequence starts the + * discovery sequence of device. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_SUCCESS HCI Discovery Configuration sequence successful. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + */ + +extern +NFCSTATUS +phHciNfc_PollLoop_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_EmulationCfg_Sequence function sequence configures the + * device for different types of emulation supported. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_SUCCESS HCI Emulation Configuration + * sequence successful. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + */ + +extern +NFCSTATUS +phHciNfc_EmulationCfg_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_SmartMx_Mode_Sequence function sequence configures the + * SmartMx device for different modes by enabling and disabling polling. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_SUCCESS HCI SmartMX Mode Configuration + * sequence successful. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + */ + +extern +NFCSTATUS +phHciNfc_SmartMx_Mode_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Connect_Sequence function sequence selects the + * discovered target for performing the transaction. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_SUCCESS HCI target selection sequence successful. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + */ + +extern +NFCSTATUS +phHciNfc_Connect_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Disconnect_Sequence function sequence de-selects the + * selected target . + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_SUCCESS HCI target de-selection sequence successful. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + */ + +extern +NFCSTATUS +phHciNfc_Disconnect_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Error_Sequence function sequence notifies the + * error in the HCI sequence to the upper layer . + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * \param[in] status Notify status information from the + * HCI layer to the Upper Layer. + * + * + * \retval NFCSTATUS_SUCCESS HCI Error sequence Notification successful. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + */ +extern +void +phHciNfc_Error_Sequence( + void *psContext, + void *pHwRef, + NFCSTATUS error_status, + void *pdata, + uint8_t length + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Resume_Sequence function sequence resumes the + * previous pending sequence of HCI . + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_SUCCESS HCI sequence resume successful. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + */ + +extern +NFCSTATUS +phHciNfc_Resume_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/** + * \ingroup grp_hci_nfc + * + * The phHciNfc_Release_Sequence function sequence releases the + * HCI layer and the remote device by performing the operations required + * release the reader and discovery functionality. + * + * \param[in] psHciContext psHciContext is the context of + * the HCI Layer. + * \param[in] pHwRef pHwRef is the Information of + * the Device Interface Link . + * + * \retval NFCSTATUS_SUCCESS HCI current release sequence successful. + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters + * could not be interpreted properly. + * \retval Other errors Other related errors + * + */ + + +extern +NFCSTATUS +phHciNfc_Release_Sequence( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); + + +/* +################################################################################ +***************************** Function Definitions ***************************** +################################################################################ +*/ + +#endif + diff --git a/libnfc-nxp/phHciNfc_WI.c b/libnfc-nxp/phHciNfc_WI.c new file mode 100644 index 0000000..e1310a4 --- /dev/null +++ b/libnfc-nxp/phHciNfc_WI.c @@ -0,0 +1,778 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_WI.c * +* \brief HCI WI gate Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Tue Aug 18 10:22:34 2009 $ * +* $Author: ing04880 $ * +* $Revision: 1.33 $ * +* $Aliases: NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * * +* =========================================================================== * +*/ + +/* +***************************** Header File Inclusion **************************** +*/ +#include +#include +#include +#include +#include +/* +****************************** Macro Definitions ******************************* +*/ +/* WI gate specific Events definition */ +#define NXP_EVT_SE_START_OF_TRANSACTION (0x01U) +#define NXP_EVT_SE_END_OF_TRANSACTION (0x02U) +#define NXP_EVT_SE_SWITCH_MODE (0x03U) +#define NXP_EVT_SE_TRANSACTION (0x04U) + +/* WI Gate registry Settings */ +/* set default mode mode as virtual mode */ +#define NXP_SE_DEFAULTMODE_INDEX (0x01) +#define NXP_SE_EVENTS_INDEX (0x05) + +/* Set Bit 0 and Bit 1 to report Start of transaction and End of transaction*/ +#define WI_ENABLE_EVENTS (0x04) +#define WI_VIRTUALMODE (0x01) +#define WI_OFFMODE (0x00) +#define AID_SIZE (0x20) +/****************** Structure and Enumeration ****************************/ + + +/****************** Static Function Declaration **************************/ + +static uint8_t paypass_removal[2] = {0x50, 0x00}; +static uint8_t mifare_access = 0x60; + +static +NFCSTATUS +phHciNfc_Recv_WI_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Recv_WI_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ); + +static +NFCSTATUS +phHciNfc_Send_WI_Event( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t event + ); + +static +NFCSTATUS +phHciNfc_WI_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ); + + +#if defined (WI_UPDATE_SEQ) +static +NFCSTATUS +phHciNfc_WI_Update_Sequence( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t WI_seq + ); +#endif /* #if defined (WI_UPDATE_SEQ) */ + +/* +*************************** Function Definitions *************************** +*/ + + + +NFCSTATUS +phHciNfc_WI_Init_Resources( + phHciNfc_sContext_t *psHciContext + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_WI_Info_t *p_WI_info=NULL; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else + { + if(( NULL == psHciContext->p_wi_info ) && + (phHciNfc_Allocate_Resource((void **)(&p_WI_info), + sizeof(phHciNfc_WI_Info_t))== NFCSTATUS_SUCCESS)) + { + psHciContext->p_wi_info = p_WI_info; + p_WI_info->current_seq = eWI_PipeOpen; + p_WI_info->next_seq = eWI_PipeOpen; + p_WI_info->pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES); + } + + } + return status; +} + +NFCSTATUS +phHciNfc_WI_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL != psHciContext) + && ( NULL != ppipe_id ) + && ( NULL != psHciContext->p_wi_info ) + ) + { + phHciNfc_WI_Info_t *p_wi_info=NULL; + p_wi_info = (phHciNfc_WI_Info_t *) + psHciContext->p_wi_info ; + *ppipe_id = p_wi_info->pipe_id ; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + return status; +} + + +NFCSTATUS +phHciNfc_WI_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_wi_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_WI_Info_t *p_WI_info=NULL; + p_WI_info = (phHciNfc_WI_Info_t *) + psHciContext->p_wi_info ; + /* Update the pipe_id of the WI Gate obtained from HCI Response */ + p_WI_info->pipe_id = pipeID; + p_WI_info->p_pipe_info = pPipeInfo; + if ( NULL != pPipeInfo) + { + /* Update the Response Receive routine of the WI Gate */ + pPipeInfo->recv_resp = &phHciNfc_Recv_WI_Response; + /* Update the event Receive routine of the WI Gate */ + pPipeInfo->recv_event = &phHciNfc_Recv_WI_Event; + } + } + + return status; +} + +#if defined (WI_UPDATE_SEQ) +static +NFCSTATUS +phHciNfc_WI_Update_Sequence( + phHciNfc_sContext_t *psHciContext, + phHciNfc_eSeqType_t WI_seq + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_WI_Info_t *p_WI_info=NULL; + if( NULL == psHciContext ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_wi_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_WI_info = (phHciNfc_WI_Info_t *) + psHciContext->p_wi_info ; + switch(WI_seq) + { + case RESET_SEQ: + case INIT_SEQ: + { + p_WI_info->current_seq = eWI_PipeOpen; + p_WI_info->next_seq = eWI_SetDefaultMode ; + }break; + case UPDATE_SEQ: + { + p_WI_info->current_seq = p_WI_info->next_seq; + + }break; + case REL_SEQ: + { + p_WI_info->current_seq = eWI_PipeOpen; + p_WI_info->next_seq = eWI_PipeClose ; + }break; + default: + { + break; + } + }/* End of Update Sequence Switch */ + } + return status; + +} +#endif /* #if defined (WI_UPDATE_SEQ) */ + +NFCSTATUS +phHciNfc_WI_Configure_Default( + void *psHciHandle, + void *pHwRef, + uint8_t enable_type + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t param = 0; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + + if( (NULL == psHciContext)||(NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_wi_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_WI_Info_t *p_wi_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + + p_wi_info = (phHciNfc_WI_Info_t*)psHciContext->p_wi_info; + + p_pipe_info = p_wi_info->p_pipe_info; + if(NULL == p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_pipe_info->reg_index = NXP_SE_DEFAULTMODE_INDEX; + /* Enable/Disable Default Virtual Mode for SmartMx */ + param = (uint8_t)enable_type; + p_pipe_info->param_info =(void*)¶m ; + p_pipe_info->param_length = sizeof(param) ; + status = phHciNfc_Send_Generic_Cmd(psHciContext,pHwRef, + p_wi_info->pipe_id,(uint8_t)ANY_SET_PARAMETER); + + }/* End of else part*/ + } + return status; +} + +NFCSTATUS +phHciNfc_WI_Get_Default( + void *psHciHandle, + void *pHwRef + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + + if( (NULL == psHciContext)||(NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_wi_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_WI_Info_t *p_wiinfo=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + + p_wiinfo = (phHciNfc_WI_Info_t*)psHciContext->p_wi_info; + + p_pipe_info = p_wiinfo->p_pipe_info; + if(NULL == p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + p_pipe_info->reg_index = NXP_SE_DEFAULTMODE_INDEX; + + status = phHciNfc_Send_Generic_Cmd(psHciContext,pHwRef, + p_wiinfo->pipe_id, + (uint8_t)ANY_GET_PARAMETER); + + }/* End of else part*/ + } + return status; +} + + +NFCSTATUS +phHciNfc_WI_Configure_Mode( + void *psHciHandle, + void *pHwRef, + phHal_eSmartMX_Mode_t e_smx_mode + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t param = 0; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + + if( (NULL == psHciContext)||(NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_wi_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_WI_Info_t *p_wi_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + + p_wi_info = (phHciNfc_WI_Info_t*)psHciContext->p_wi_info; + + p_pipe_info = p_wi_info->p_pipe_info; + if(NULL == p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + /* Switch the Mode of the SmartMx */ + param = (uint8_t)e_smx_mode; + p_pipe_info->param_info =(void*)¶m ; + p_pipe_info->param_length = sizeof(param) ; + status = phHciNfc_Send_WI_Event( psHciContext, pHwRef, + p_wi_info->pipe_id, NXP_EVT_SE_SWITCH_MODE ); + /* Send the Success Status as this is an event */ + status = ( (status == NFCSTATUS_PENDING)? + NFCSTATUS_SUCCESS : status); + + }/* End of else part*/ + } + return status; +} + + +NFCSTATUS +phHciNfc_WI_Configure_Notifications( + void *psHciHandle, + void *pHwRef, + phHciNfc_WI_Events_t eNotification + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + static uint8_t param = 0; + phHciNfc_sContext_t *psHciContext = ((phHciNfc_sContext_t *)psHciHandle); + + if( (NULL == psHciContext)||(NULL == pHwRef)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if ( NULL == psHciContext->p_wi_info ) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_WI_Info_t *p_wi_info=NULL; + phHciNfc_Pipe_Info_t *p_pipe_info=NULL; + + + p_wi_info = (phHciNfc_WI_Info_t*)psHciContext->p_wi_info; + p_pipe_info = p_wi_info->p_pipe_info; + if(NULL == p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + if(eEnableEvents == eNotification) + { + /* Enable start and end of transaction events*/ + param = WI_ENABLE_EVENTS; + } + else + { + /* Disable Events*/ + param = FALSE ; + } + p_pipe_info->reg_index = NXP_SE_EVENTS_INDEX; + p_pipe_info->param_info =(void*)¶m ; + p_pipe_info->param_length = sizeof(param) ; + + status = phHciNfc_Send_Generic_Cmd(psHciContext,pHwRef, + p_wi_info->pipe_id,(uint8_t)ANY_SET_PARAMETER); + } + } + return status; +} + + +/*! +* \brief Sends WI gate specfic HCI Events to the connected reader device. +* This function Sends the WI mode specific HCI Event frames in the HCP packet format to the +* connected reader device. +*/ + +static +NFCSTATUS +phHciNfc_Send_WI_Event( + phHciNfc_sContext_t *psHciContext, + void *pHwRef, + uint8_t pipe_id, + uint8_t event + ) +{ + phHciNfc_HCP_Packet_t *hcp_packet = NULL; + phHciNfc_HCP_Message_t *hcp_message = NULL; + phHciNfc_Pipe_Info_t *p_pipe_info = NULL; + uint8_t length = 0; + uint8_t i=0; + NFCSTATUS status = NFCSTATUS_SUCCESS; + + if( (NULL == psHciContext) + || ( pipe_id > PHHCINFC_MAX_PIPE) + ||(NULL == psHciContext->p_pipe_list[pipe_id]) + ) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + HCI_DEBUG("%s: Invalid Arguments passed \n", + "phHciNfc_Send_WI_Event"); + } + else + { + p_pipe_info = (phHciNfc_Pipe_Info_t *) + psHciContext->p_pipe_list[pipe_id]; + psHciContext->tx_total = 0 ; + length =length+HCP_HEADER_LEN ; + + if( NXP_EVT_SE_SWITCH_MODE == event) + { + hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer; + /* Construct the HCP Frame */ + phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT, + (uint8_t) pipe_id, HCP_MSG_TYPE_EVENT, event); + hcp_message = &(hcp_packet->msg.message); + phHciNfc_Append_HCPFrame((uint8_t *)hcp_message->payload, + i, (uint8_t *)p_pipe_info->param_info, + p_pipe_info->param_length); + length =(uint8_t)(length + i + p_pipe_info->param_length); + } + else + { + status = PHNFCSTVAL( CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INSTRUCTION ); + HCI_DEBUG("%s: Invalid Send Event Request \n","phHciNfc_Send_WI_Event"); + } + + if( NFCSTATUS_SUCCESS == status ) + { + p_pipe_info->sent_msg_type = HCP_MSG_TYPE_EVENT ; + p_pipe_info->prev_msg = event ; + psHciContext->tx_total = length; + + /* Send the Constructed HCP packet to the lower layer */ + status = phHciNfc_Send_HCP( psHciContext, pHwRef ); + p_pipe_info->prev_status = NFCSTATUS_PENDING; + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_WI_Response( + void *psContext, + void *pHwRef, + uint8_t *pResponse, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_sContext_t *psHciContext = + (phHciNfc_sContext_t *)psContext; + + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pResponse) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_wi_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); + } + else + { + phHciNfc_WI_Info_t *p_wiinfo=NULL; + uint8_t prev_cmd = ANY_GET_PARAMETER; + p_wiinfo = (phHciNfc_WI_Info_t *)psHciContext->p_wi_info ; + + if( NULL == p_wiinfo->p_pipe_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + prev_cmd = p_wiinfo->p_pipe_info->prev_msg ; + switch(prev_cmd) + { + case ANY_GET_PARAMETER: + { + if (length > HCP_HEADER_LEN) + { + status = phHciNfc_WI_InfoUpdate (psHciContext, + p_wiinfo->p_pipe_info->reg_index, + &pResponse[HCP_HEADER_LEN], + (uint8_t)(length - HCP_HEADER_LEN)); + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + break; + } + case ANY_SET_PARAMETER: + { + HCI_PRINT("WI Parameter Set \n"); + status = phHciNfc_EmuMgmt_Update_Seq(psHciContext, + UPDATE_SEQ); + break; + } + case ANY_OPEN_PIPE: + { + HCI_PRINT("WI gate open pipe complete\n"); + status = phHciNfc_EmuMgmt_Update_Seq(psHciContext, + UPDATE_SEQ); + break; + } + case ANY_CLOSE_PIPE: + { + HCI_PRINT("WI close pipe complete\n"); + status = phHciNfc_EmuMgmt_Update_Seq(psHciContext, + UPDATE_SEQ); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE); + break; + } + } + if( NFCSTATUS_SUCCESS == status ) + { + p_wiinfo->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; + p_wiinfo->current_seq = p_wiinfo->next_seq; + } + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_Recv_WI_Event( + void *psContext, + void *pHwRef, + uint8_t *pEvent, +#ifdef ONE_BYTE_LEN + uint8_t length +#else + uint16_t length +#endif + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHal_sEventInfo_t EventInfo; + /* phNfc_sNotificationInfo_t NotificationInfo; */ + phHciNfc_sContext_t *psHciContext =(phHciNfc_sContext_t *)psContext; + + + if( (NULL == psHciContext) || (NULL == pHwRef) || (NULL == pEvent) + || (length == 0)) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); + } + else if(NULL == psHciContext->p_wi_info) + { + status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); + } + else + { + phHciNfc_HCP_Packet_t *p_packet = NULL; + phHciNfc_HCP_Message_t *message = NULL; + phHciNfc_WI_Info_t *p_wi_info = NULL; + uint8_t EventType = 0; + + p_wi_info = (phHciNfc_WI_Info_t *)psHciContext->p_wi_info ; + + p_packet = (phHciNfc_HCP_Packet_t *)pEvent; + message = &(p_packet->msg.message); + /* Get the instruction bits from the Message Header */ + EventType = (uint8_t) GET_BITS8( message->msg_header, + HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN); + + EventInfo.eventHost = phHal_eHostController; + EventInfo.eventSource = phHal_ePICC_DevType; + /* Now check for possible Transaction events for reporting */ + switch(EventType) + { + case NXP_EVT_SE_START_OF_TRANSACTION: + { + EventInfo.eventType = NFC_EVT_START_OF_TRANSACTION; + break; + } + case NXP_EVT_SE_END_OF_TRANSACTION: + { + EventInfo.eventType = NFC_EVT_END_OF_TRANSACTION; + break; + } + case NXP_EVT_SE_TRANSACTION: + { + EventInfo.eventType = NFC_EVT_TRANSACTION; + EventInfo.eventInfo.aid.buffer = (uint8_t *)p_wi_info->aid; + /* check for AID data is at least 1 byte is their */ + if (length > HCP_HEADER_LEN) + { + EventInfo.eventInfo.aid.length = length - HCP_HEADER_LEN; + memcpy((void *)p_wi_info->aid, message->payload, + EventInfo.eventInfo.aid.length ); + } + + /* Filter Transaction event */ + if (EventInfo.eventInfo.aid.length == 4) + { + EventInfo.eventType = NFC_EVT_APDU_RECEIVED; + } + else if (EventInfo.eventInfo.aid.length == 2) + { + if (!memcmp(paypass_removal, EventInfo.eventInfo.aid.buffer, EventInfo.eventInfo.aid.length)) + { + EventInfo.eventType = NFC_EVT_EMV_CARD_REMOVAL; + } + else if(mifare_access == EventInfo.eventInfo.aid.buffer[0]) + { + EventInfo.eventType = NFC_EVT_MIFARE_ACCESS; + } + } + + EventInfo.eventInfo.aid.buffer = (uint8_t *)p_wi_info->aid; + (void) memcpy((void *)p_wi_info->aid,message->payload, + EventInfo.eventInfo.aid.length ); + break; + } + default: + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_INSTRUCTION); + break; + } + } + if (NFCSTATUS_SUCCESS == status ) + { + phHciNfc_Notify_Event( psHciContext, pHwRef, + NFC_NOTIFY_EVENT, (void*)&EventInfo); + } + } + return status; +} + +static +NFCSTATUS +phHciNfc_WI_InfoUpdate( + phHciNfc_sContext_t *psHciContext, + uint8_t index, + uint8_t *reg_value, + uint8_t reg_length + ) +{ + NFCSTATUS status = NFCSTATUS_SUCCESS; + phHciNfc_WI_Info_t *p_wiinfo = NULL; + + p_wiinfo = psHciContext->p_wi_info; + + if ((NXP_SE_DEFAULTMODE_INDEX == index) && + (sizeof(*reg_value) == reg_length)) + { + p_wiinfo->default_type = *reg_value; + } + else + { + status = PHNFCSTVAL(CID_NFC_HCI, + NFCSTATUS_INVALID_HCI_RESPONSE); + } + + return status; +} + diff --git a/libnfc-nxp/phHciNfc_WI.h b/libnfc-nxp/phHciNfc_WI.h new file mode 100644 index 0000000..6ab2f5c --- /dev/null +++ b/libnfc-nxp/phHciNfc_WI.h @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* =========================================================================== * +* * +* * +* \file phHciNfc_WI .h * +* \brief HCI wired interface gate Management Routines. * +* * +* * +* Project: NFC-FRI-1.1 * +* * +* $Date: Fri Jan 16 10:33:47 2009 $ * +* $Author: ravindrau $ * +* $Revision: 1.11 $ * +* $Aliases: NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * +* * +* =========================================================================== * +*/ +#ifndef PHHCINFC_WI_H +#define PHHCINFC_WI_H +/*@}*/ +/** + * \name HCI + * + * File: \ref phHciNfc_WI.h + * + */ +/*@{*/ +#define PHHCINFC_WIRED_FILEREVISION "$Revision: 1.11 $" /**< \ingroup grp_file_attributes */ +#define PHHCINFC_WIREDINTERFACE_FILEALIASES "$Aliases: NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/****************************** Header File Inclusion *****************************/ +#include +#include + +/******************************* Macro Definitions ********************************/ + +/******************** Enumeration and Structure Definition ***********************/ + + +/* enable /disable notifications */ +typedef enum phHciNfc_WI_Events{ + eDisableEvents, + eEnableEvents +} phHciNfc_WI_Events_t; + +typedef enum phHciNfc_WI_Seq{ + eWI_PipeOpen = 0x00U, + eWI_SetDefaultMode, + eWI_PipeClose +} phHciNfc_WI_Seq_t; + +/* Information structure for WI Gate */ +typedef struct phHciNfc_WI_Info{ + + /* Pointer to WI gate pipe information */ + phHciNfc_Pipe_Info_t *p_pipe_info; + /* WI gate pipe Identifier */ + uint8_t pipe_id; + /* Application ID of the Transaction performed */ + uint8_t aid[MAX_AID_LEN]; + /* Default info */ + uint8_t default_type; + /* Current WI gate Internal Sequence type */ + phHciNfc_WI_Seq_t current_seq; + /*Current WI gate next Sequence ID */ + phHciNfc_WI_Seq_t next_seq; + +} phHciNfc_WI_Info_t; + +/************************ Function Prototype Declaration *************************/ +/*! + * \brief Allocates the resources required for WI gate management. + * + * This function Allocates necessary resources as requiered by WI gate management + * + * \param[in] psHciContext psHciContext is the pointer to HCI Layer + * + * \retval NFCSTATUS_SUCCESS Function execution is successful + * + * \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid + */ +extern +NFCSTATUS +phHciNfc_WI_Init_Resources(phHciNfc_sContext_t *psHciContext); + +/** +* \ingroup grp_hci_nfc +* +* \brief Allocates the resources required for WI gate management. +* +* This function Allocates necessary resources as requiered by WI gate management +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ + +extern +NFCSTATUS +phHciNfc_WIMgmt_Initialise( + phHciNfc_sContext_t *psHciContext, + void *pHwRef + ); +/** +* \ingroup grp_hci_nfc +* +* \brief Allocates the resources required for WI gate management. +* +* This function Allocates necessary resources as requiered by WI gate management +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ +extern +NFCSTATUS +phHciNfc_WI_Update_PipeInfo( + phHciNfc_sContext_t *psHciContext, + uint8_t pipeID, + phHciNfc_Pipe_Info_t *pPipeInfo + ); + +/** +* \ingroup grp_hci_nfc +* +* \brief Allocates the resources required for WI gate management. +* +* This function Allocates necessary resources as requiered by WI gate management +* +* \param[in] psHciContext psHciContext is the pointer to HCI Layer +* +* \retval NFCSTATUS_SUCCESS Function execution is successful +* +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the given inputs are not valid +*/ +extern +NFCSTATUS +phHciNfc_WI_Configure_Mode( + void *psHciHandle, + void *pHwRef, + phHal_eSmartMX_Mode_t cfg_Mode + ); + +extern +NFCSTATUS +phHciNfc_WI_Configure_Notifications( + void *psHciHandle, + void *pHwRef, + phHciNfc_WI_Events_t eNotification + ); + +extern +NFCSTATUS +phHciNfc_WI_Get_PipeID( + phHciNfc_sContext_t *psHciContext, + uint8_t *ppipe_id + ); + +extern +NFCSTATUS +phHciNfc_WI_Configure_Default( + void *psHciHandle, + void *pHwRef, + uint8_t enable_type + ); + +extern +NFCSTATUS +phHciNfc_WI_Get_Default( + void *psHciHandle, + void *pHwRef + ); + + +#endif /* #ifndef PHHCINFC_WI_H */ + diff --git a/libnfc-nxp/phLibNfc.c b/libnfc-nxp/phLibNfc.c new file mode 100644 index 0000000..b22f9ee --- /dev/null +++ b/libnfc-nxp/phLibNfc.c @@ -0,0 +1,1008 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phLibNfc.c + + * Project: NFC FRI / HALDL + * + * $Date: Tue Jun 1 14:53:48 2010 $ + * $Author: ing07385 $ + * $Revision: 1.89 $ + * $Aliases: NFC_FRI1.1_WK1024_SDK $ + * + */ + + +/* +************************* Header Files **************************************** +*/ + +#define LOG_TAG "NFC" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* +*************************** Macro's ****************************************** +*/ + +extern int dlopen_firmware(); + +#ifndef STATIC_DISABLE +#define STATIC static +#else +#define STATIC +#endif + + +/* +*************************** Global Variables ********************************** +*/ + + +pphLibNfc_LibContext_t gpphLibContext=NULL; + +/* +*************************** Static Function Declaration *********************** +*/ + +/* Init callback */ +STATIC void phLibNfc_InitCb(void *pContext,NFCSTATUS status); + +/* Shutdown callback */ +STATIC void phLibNfc_ShutdownCb(void *pContext,NFCSTATUS status); + +/**Default notification handler registered with lower layer immediately after + successful initialization*/ +STATIC void phLibNfc_DefaultHandler( + void *context, + phHal_eNotificationType_t type, + phHal4Nfc_NotificationInfo_t info, + NFCSTATUS status + ); +/* +*************************** Function Definitions ****************************** +*/ + +NFCSTATUS phLibNfc_Mgt_ConfigureDriver (pphLibNfc_sConfig_t psConfig, + void ** ppDriverHandle) +{ + if(NULL != gpphLibContext) + { + return NFCSTATUS_ALREADY_INITIALISED; + } + + return phDal4Nfc_Config(psConfig, ppDriverHandle); +} + +NFCSTATUS phLibNfc_Mgt_UnConfigureDriver (void * pDriverHandle) +{ + if(NULL != gpphLibContext) + { + return NFCSTATUS_ALREADY_INITIALISED; + } + + return phDal4Nfc_ConfigRelease(pDriverHandle); +} + +NFCSTATUS phLibNfc_HW_Reset () +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + + Status = phDal4Nfc_Reset(1); + Status = phDal4Nfc_Reset(0); + Status = phDal4Nfc_Reset(1); + + return Status; +} + +NFCSTATUS phLibNfc_Download_Mode () +{ + return phDal4Nfc_Download(); +} + +int phLibNfc_Load_Firmware_Image () +{ + int status; + status = dlopen_firmware(); + return status; +} + +// Function for delay the recovery in case wired mode is set +// to complete the possible pending transaction with SE +void phLibNfc_Mgt_Recovery () +{ + /* Wait before recovery if wired mode */ + if (gpphLibContext->sSeContext.eActivatedMode == phLibNfc_SE_ActModeWired) + { + usleep (12000000); + } + + return; +} + +extern uint8_t nxp_nfc_isoxchg_timeout; +NFCSTATUS phLibNfc_SetIsoXchgTimeout(uint8_t timeout) { + nxp_nfc_isoxchg_timeout = timeout; + return NFCSTATUS_SUCCESS; +} + +int phLibNfc_GetIsoXchgTimeout() { + return nxp_nfc_isoxchg_timeout; +} + +extern uint32_t nxp_nfc_hci_response_timeout; +NFCSTATUS phLibNfc_SetHciTimeout(uint32_t timeout_in_ms) { + nxp_nfc_hci_response_timeout = timeout_in_ms; + return NFCSTATUS_SUCCESS; +} + +int phLibNfc_GetHciTimeout() { + return nxp_nfc_hci_response_timeout; +} + +extern uint8_t nxp_nfc_felica_timeout; +NFCSTATUS phLibNfc_SetFelicaTimeout(uint8_t timeout_in_ms) { + nxp_nfc_felica_timeout = timeout_in_ms; + return NFCSTATUS_SUCCESS; +} + +int phLibNfc_GetFelicaTimeout() { + return nxp_nfc_felica_timeout; +} + +extern uint8_t nxp_nfc_mifareraw_timeout; +NFCSTATUS phLibNfc_SetMifareRawTimeout(uint8_t timeout) { + nxp_nfc_mifareraw_timeout = timeout; + return NFCSTATUS_SUCCESS; +} + +int phLibNfc_GetMifareRawTimeout() { + return nxp_nfc_mifareraw_timeout; +} + +/** +* Initialize the phLibNfc interface. +*/ + +NFCSTATUS phLibNfc_Mgt_Initialize(void *pDriverHandle, + pphLibNfc_RspCb_t pInitCb, + void *pContext) +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + if((NULL == pDriverHandle)||(NULL == pInitCb)) + { + Status = NFCSTATUS_INVALID_PARAMETER; + } + else if(NULL == gpphLibContext) + { + /* Initialize the Lib context */ + gpphLibContext=(pphLibNfc_LibContext_t)phOsalNfc_GetMemory( + (uint32_t)sizeof(phLibNfc_LibContext_t)); + if(NULL == gpphLibContext) + { + Status=NFCSTATUS_INSUFFICIENT_RESOURCES; + } + else + { + (void)memset((void *)gpphLibContext,0,( + (uint32_t)sizeof(phLibNfc_LibContext_t))); + + /* Store the Callback and context in LibContext structure*/ + gpphLibContext->CBInfo.pClientInitCb=pInitCb; + gpphLibContext->CBInfo.pClientInitCntx=pContext; + /* Initialize the HwReferece structure */ + gpphLibContext->psHwReference=(phHal_sHwReference_t *) + phOsalNfc_GetMemory((uint32_t)sizeof(phHal_sHwReference_t)); + (void)memset((void *)gpphLibContext->psHwReference,0, + ((uint32_t)sizeof(phHal_sHwReference_t))); + /* Allocate the Memory for the Transceive info */ + if( gpphLibContext->psHwReference!=NULL) + { + gpphLibContext->psHwReference->p_board_driver = pDriverHandle; + Status = phLibNfc_UpdateNextState(gpphLibContext, + eLibNfcHalStateInitandIdle); + if(Status==NFCSTATUS_SUCCESS) + { + Status=phHal4Nfc_Open( + gpphLibContext->psHwReference, + eInitDefault, + phLibNfc_InitCb, + (void *)gpphLibContext); + } + } + else + { + Status = NFCSTATUS_INSUFFICIENT_RESOURCES; + } + phLibNfc_Ndef_Init(); + } + } + else if(gpphLibContext->LibNfcState.next_state==eLibNfcHalStateShutdown) + { + Status = NFCSTATUS_SHUTDOWN; + } + else + { + Status=NFCSTATUS_ALREADY_INITIALISED; + } + return Status; +} + +/* + * This function called by the HAL4 when the initialization seq is completed. + */ +STATIC void phLibNfc_InitCb(void *pContext,NFCSTATUS status) +{ + pphLibNfc_LibContext_t pLibContext=NULL; + pphLibNfc_RspCb_t pClientCb=NULL; + void *pUpperLayerContext=NULL; + + + /* Initialize the local variable */ + pLibContext = (pphLibNfc_LibContext_t)pContext; + + pClientCb =pLibContext->CBInfo.pClientInitCb; + pUpperLayerContext=pLibContext->CBInfo.pClientInitCntx; + if(status == NFCSTATUS_SUCCESS) + { + /* Get the Lib context */ + pLibContext=(pphLibNfc_LibContext_t)gpphLibContext; + gpphLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeOff; + if(pLibContext->psHwReference->uicc_connected==TRUE) + { + /* populate state of the secured element */ + gpphLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeDefault; + sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].eSE_CurrentState=phLibNfc_SE_Active; + pLibContext->sSeContext.uUiccActivate=TRUE; + } + if(pLibContext->psHwReference->smx_connected==TRUE) + { + /* populate state of the secured element */ + gpphLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeDefault; + sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].eSE_CurrentState=phLibNfc_SE_Inactive; + pLibContext->sSeContext.uSmxActivate =FALSE; + } + + phLibNfc_UpdateCurState(status,pLibContext); + (void)phHal4Nfc_RegisterNotification( + pLibContext->psHwReference, + eRegisterDefault, + phLibNfc_DefaultHandler, + (void*)pLibContext + ); + /* call the upper layer register function */ + (*pClientCb)(pUpperLayerContext,status); + + } + else + { + /*Change the status code failed*/ + status = NFCSTATUS_FAILED; + /* Get the Lib context */ + pLibContext=(pphLibNfc_LibContext_t)gpphLibContext; + + phLibNfc_UpdateCurState(status,pLibContext); + + + + /* Allocate the Memory for the Transceive info */ + if(pLibContext->psHwReference!= NULL) + { + phOsalNfc_FreeMemory(pLibContext->psHwReference); + pLibContext->psHwReference = NULL; + } + (*pClientCb)(pUpperLayerContext, status); + + phOsalNfc_FreeMemory(pLibContext); + pLibContext= NULL; + gpphLibContext = NULL; + + } + return; +} + +/**Default notification handler registered with lower layer immediately after + successful initialization*/ +STATIC void phLibNfc_DefaultHandler( + void *context, + phHal_eNotificationType_t type, + phHal4Nfc_NotificationInfo_t info, + NFCSTATUS status + ) +{ + if(context != (void *)gpphLibContext) + { + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + if((NFC_EVENT_NOTIFICATION == type) && + (NFCSTATUS_BOARD_COMMUNICATION_ERROR == status)) + { + phLibNfc_UpdateCurState(NFCSTATUS_FAILED,gpphLibContext); + phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); + } + } + return; +} +/** +* De-Initialize the LIB NFC. +*/ +NFCSTATUS phLibNfc_Mgt_DeInitialize(void * pDriverHandle, + pphLibNfc_RspCb_t pDeInitCb, + void* pContext + ) +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + pphLibNfc_LibContext_t pLibContext = gpphLibContext; + if(NULL==pDriverHandle) + { + /*Check for valid parameters */ + Status = NFCSTATUS_INVALID_PARAMETER; + } + else if((pLibContext==NULL) + || (pLibContext->LibNfcState.cur_state + == eLibNfcHalStateShutdown)) + { /*Lib Nfc not initlized*/ + Status = NFCSTATUS_NOT_INITIALISED; + } + else + { + if(pDeInitCb==NULL) + { + phHal4Nfc_Hal4Reset(pLibContext->psHwReference,(void *)pLibContext); + if(pLibContext->psHwReference!=NULL) + { + phOsalNfc_FreeMemory(pLibContext->psHwReference); + pLibContext->psHwReference = NULL; + } + /*Free the memory allocated during NDEF read,write + and NDEF formatting*/ + phLibNfc_Ndef_DeInit(); + phOsalNfc_FreeMemory(pLibContext); + gpphLibContext=NULL; + pLibContext= NULL; + } + else + { + if (NULL!= pLibContext->CBInfo.pClientShutdownCb) + { + /* Previous callback pending */ + Status = NFCSTATUS_BUSY; + } + Status = NFCSTATUS_PENDING; + if(TRUE != pLibContext->status.GenCb_pending_status) + { + Status = phHal4Nfc_Close(pLibContext->psHwReference, + phLibNfc_ShutdownCb, + (void *)pLibContext); + } + if(Status== NFCSTATUS_PENDING) + { + pLibContext->CBInfo.pClientShutdownCb = pDeInitCb; + pLibContext->CBInfo.pClientShtdwnCntx = pContext; + pLibContext->status.GenCb_pending_status=TRUE; + pLibContext->LibNfcState.next_state= eLibNfcHalStateShutdown; + } + else + { + Status =NFCSTATUS_FAILED; + } + } + } + return Status; +} +/* shutdown callback - + Free the allocated memory here */ +STATIC void phLibNfc_ShutdownCb(void *pContext,NFCSTATUS status) +{ + pphLibNfc_RspCb_t pClientCb=NULL; + void *pUpperLayerContext=NULL; + pphLibNfc_LibContext_t pLibContext=NULL; + + PHNFC_UNUSED_VARIABLE(pContext); + /* Get the Lib context */ + pLibContext=(pphLibNfc_LibContext_t)gpphLibContext; + + if(pLibContext == NULL) + { + status = NFCSTATUS_FAILED; + } + else + { + /* Initialize the local variable */ + pClientCb =pLibContext->CBInfo.pClientShutdownCb; + pUpperLayerContext=pLibContext->CBInfo.pClientShtdwnCntx; + if(status == NFCSTATUS_SUCCESS) + { + pLibContext->LibNfcState.cur_state = eLibNfcHalStateShutdown; + phLibNfc_UpdateCurState(status,pLibContext); + + pLibContext->status.GenCb_pending_status=FALSE; + + /* Allocate the Memory for the Transceive info */ + if(pClientCb!=NULL) + { + (*pClientCb)(pUpperLayerContext, status); + } + if(pLibContext->psHwReference!=NULL) + { + phOsalNfc_FreeMemory(pLibContext->psHwReference); + pLibContext->psHwReference = NULL; + } + if(NULL != gpphLibContext->psBufferedAuth) + { + if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sRecvData.buffer); + } + if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sSendData.buffer); + } + phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth); + gpphLibContext->psBufferedAuth = NULL; + } + /*Free the memory allocated during NDEF read,write + and NDEF formatting*/ + phLibNfc_Ndef_DeInit(); + phOsalNfc_FreeMemory(pLibContext); + gpphLibContext=NULL; + pLibContext= NULL; + + } + else + { + /* shutdown sequence failed by HAL 4 */ + status= NFCSTATUS_FAILED; + pLibContext=(pphLibNfc_LibContext_t)gpphLibContext; + phLibNfc_UpdateCurState(status,pLibContext); + pLibContext->status.GenCb_pending_status=FALSE; + if(pClientCb!=NULL) + { + (*pClientCb)(pUpperLayerContext,status); + } + } + } +} +/** +* Pending shutdown call. +*/ + + +void phLibNfc_Pending_Shutdown(void) +{ + NFCSTATUS RetStatus = NFCSTATUS_SUCCESS ; + gpphLibContext->status.GenCb_pending_status = FALSE; + RetStatus = phHal4Nfc_Close( + gpphLibContext->psHwReference, + phLibNfc_ShutdownCb, + (void *)gpphLibContext); + PHNFC_UNUSED_VARIABLE(RetStatus); + return; +} + + +/** +* Reset the LIB NFC. +*/ +NFCSTATUS phLibNfc_Mgt_Reset(void *pContext) +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)pContext; + + if((pLibNfc_Ctxt == NULL) + || (gpphLibContext->LibNfcState.cur_state + == eLibNfcHalStateShutdown)) + { /*Lib Nfc not initlized*/ + Status = NFCSTATUS_NOT_INITIALISED; + } + else if(NULL == pContext) + { + Status = NFCSTATUS_INVALID_PARAMETER; + } + /* Check for valid state,If De initialize is called then + return NFCSTATUS_SHUTDOWN */ + else if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + Status = NFCSTATUS_SHUTDOWN; + } + else + { + /*Reset all callback status*/ + (void) memset(&(gpphLibContext->RegNtfType),0, + sizeof(phLibNfc_Registry_Info_t)); + (void) memset(&(gpphLibContext->sADDconfig),0, + sizeof(phLibNfc_sADD_Cfg_t)); + (void) memset(&(gpphLibContext->ndef_cntx),0, + sizeof(phLibNfc_NdefInfo_t)); + (void) memset(&(gpphLibContext->sNfcIp_Context),0, + sizeof(phLibNfc_NfcIpInfo_t)); + (void) memset(&(gpphLibContext->sCardEmulCfg),0, + sizeof(phHal_sEmulationCfg_t)); + (void) memset(&(gpphLibContext->Discov_handle),0, + MAX_REMOTE_DEVICES); + + /*Free memory allocated for NDEF records*/ + if(NULL != gpphLibContext->psBufferedAuth) + { + if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sRecvData.buffer); + gpphLibContext->psBufferedAuth->sRecvData.buffer = NULL; + } + if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sSendData.buffer); + gpphLibContext->psBufferedAuth->sSendData.buffer = NULL; + } + phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth); + gpphLibContext->psBufferedAuth = NULL; + } + if(NULL != gpphLibContext->psTransInfo) + { + phOsalNfc_FreeMemory(gpphLibContext->psTransInfo); + gpphLibContext->psTransInfo = NULL; + } + if(NULL != gpphLibContext->ndef_cntx.psNdefMap) + { + if(NULL != gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf) + { + phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf); + gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf = NULL; + } + phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.psNdefMap); + gpphLibContext->ndef_cntx.psNdefMap = NULL; + } + if(NULL != gpphLibContext->psOverHalCtxt) + { + phOsalNfc_FreeMemory(gpphLibContext->psOverHalCtxt); + gpphLibContext->psTransInfo = NULL; + } + if(NULL != gpphLibContext->psDevInputParam) + { + phOsalNfc_FreeMemory(gpphLibContext->psDevInputParam); + gpphLibContext->psDevInputParam = NULL; + } + if(NULL != gpphLibContext->ndef_cntx.ndef_fmt) + { + phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.ndef_fmt); + gpphLibContext->ndef_cntx.ndef_fmt = NULL; + } + if(NULL != pNdefRecord) + { + if(NULL != pNdefRecord->Id) + { + phOsalNfc_FreeMemory(pNdefRecord->Id); + pNdefRecord->Id = NULL; + } + if(NULL != pNdefRecord->Type) + { + phOsalNfc_FreeMemory(pNdefRecord->Type); + pNdefRecord->Type = NULL; + } + if(NULL != pNdefRecord->PayloadData) + { + phOsalNfc_FreeMemory(pNdefRecord->PayloadData); + pNdefRecord->PayloadData = NULL; + } + } + if(NULL != NdefInfo.pNdefRecord) + { + phOsalNfc_FreeMemory(NdefInfo.pNdefRecord); + NdefInfo.pNdefRecord = NULL; + } + if(NULL != gpphLibContext->phLib_NdefRecCntx.NdefCb) + { + phOsalNfc_FreeMemory(gpphLibContext->phLib_NdefRecCntx.NdefCb); + gpphLibContext->phLib_NdefRecCntx.NdefCb = NULL; + } + if(NULL != gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer) + { + phOsalNfc_FreeMemory(gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer); + gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer = NULL; + } + /* No device is connected */ + gpphLibContext->Connected_handle = 0x00; + gpphLibContext->Prev_Connected_handle = 0x00; + gpphLibContext->ReleaseType = NFC_INVALID_RELEASE_TYPE; + gpphLibContext->eLibNfcCfgMode = NFC_DISCOVERY_STOP; + /*Lib Nfc Stack is initilized and in idle state*/ + gpphLibContext->LibNfcState.cur_state = eLibNfcHalStateInitandIdle; + + /* Reset all callback status */ + gpphLibContext->CBInfo.pClientCkNdefCb = NULL; + gpphLibContext->CBInfo.pClientCkNdefCntx = NULL; + gpphLibContext->CBInfo.pClientConCntx = NULL; + gpphLibContext->CBInfo.pClientConnectCb = NULL; + gpphLibContext->CBInfo.pClientDConCntx = NULL; + gpphLibContext->CBInfo.pClientDisCfgCntx = NULL; + gpphLibContext->CBInfo.pClientDisConfigCb = NULL; + gpphLibContext->CBInfo.pClientInitCb = NULL; + gpphLibContext->CBInfo.pClientInitCntx = gpphLibContext; + gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL; + gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL; + gpphLibContext->CBInfo.pClientNtfRegRespCB = NULL; + gpphLibContext->CBInfo.pClientNtfRegRespCntx = NULL; + gpphLibContext->CBInfo.pClientPresChkCb = NULL; + gpphLibContext->CBInfo.pClientPresChkCntx = NULL; + gpphLibContext->CBInfo.pClientRdNdefCb = NULL; + gpphLibContext->CBInfo.pClientRdNdefCntx = NULL; + gpphLibContext->CBInfo.pClientShtdwnCntx = NULL; + gpphLibContext->CBInfo.pClientShutdownCb = NULL; + gpphLibContext->CBInfo.pClientTransceiveCb = NULL; + gpphLibContext->CBInfo.pClientTranseCntx = NULL; + gpphLibContext->CBInfo.pClientWrNdefCb = NULL; + gpphLibContext->CBInfo.pClientWrNdefCntx = NULL; + gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCb = NULL; + gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCntx = NULL; + gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb = NULL; + gpphLibContext->sNfcIp_Context.pClientNfcIpRxCntx = NULL; + gpphLibContext->sNfcIp_Context.pClientNfcIpTxCb = NULL; + gpphLibContext->sNfcIp_Context.pClientNfcIpTxCntx = NULL; + gpphLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb = NULL; + gpphLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt = NULL; + gpphLibContext->sSeContext.sSeCallabackInfo.pSEsetModeCb = NULL; + gpphLibContext->sSeContext.sSeCallabackInfo.pSEsetModeCtxt = NULL; + /*No callback is pending*/ + gpphLibContext->status.GenCb_pending_status = FALSE; + + } + return Status; +} +/** +* LibNfc state machine next state update. +*/ + +NFCSTATUS +phLibNfc_UpdateNextState( + pphLibNfc_LibContext_t pLibContext, + phLibNfc_State_t next_state + ) +{ + NFCSTATUS status = NFCSTATUS_INVALID_STATE; + switch(pLibContext->LibNfcState.cur_state) + { + case eLibNfcHalStateShutdown: + { + switch(next_state) + { + case eLibNfcHalStateShutdown: + case eLibNfcHalStateInitandIdle: + status = NFCSTATUS_SUCCESS; + break; + default: + break; + } + } + break; + case eLibNfcHalStateConfigReady: + { + switch(next_state) + { + case eLibNfcHalStateShutdown: + case eLibNfcHalStateConfigReady: + case eLibNfcHalStateInitandIdle: + case eLibNfcHalStateConnect: + status = NFCSTATUS_SUCCESS; + break; + default: + break; + } + } + break; + case eLibNfcHalStateConnect: + { + switch(next_state) + { + case eLibNfcHalStateShutdown: + case eLibNfcHalStateRelease: + case eLibNfcHalStateTransaction: + case eLibNfcHalStatePresenceChk: + status = NFCSTATUS_SUCCESS; + break; + default: + break; + } + } + break; + case eLibNfcHalStatePresenceChk: + { + switch(next_state) + { + case eLibNfcHalStateShutdown: + case eLibNfcHalStateConfigReady: + case eLibNfcHalStateRelease: + case eLibNfcHalStateTransaction: + case eLibNfcHalStatePresenceChk: + status = NFCSTATUS_SUCCESS; + break; + default: + break; + } + } + break; + case eLibNfcHalStateInitandIdle: + { + switch(next_state) + { + case eLibNfcHalStateShutdown: + case eLibNfcHalStateConfigReady: + status = NFCSTATUS_SUCCESS; + break; + default: + break; + } + } + break; + default: + break; + } + pLibContext->LibNfcState.next_state = + (uint8_t)((NFCSTATUS_SUCCESS == status)?next_state:pLibContext->LibNfcState.next_state); + + return status; +} + +/** +* LibNfc state machine current state update. +*/ + +void +phLibNfc_UpdateCurState( + NFCSTATUS status, + pphLibNfc_LibContext_t psLibContext + ) +{ + switch(psLibContext->LibNfcState.next_state) + { + case eLibNfcHalStateTransaction: + psLibContext->LibNfcState.cur_state = (uint8_t)eLibNfcHalStateConnect; + break; + case eLibNfcHalStateRelease: + psLibContext->LibNfcState.cur_state + = (uint8_t)(psLibContext->status.DiscEnbl_status == TRUE? + eLibNfcHalStateInitandIdle:eLibNfcHalStateConfigReady); + break; + case eLibNfcHalStateInvalid: + break; + default: + psLibContext->LibNfcState.cur_state + = (uint8_t)((NFCSTATUS_SUCCESS == status)? + psLibContext->LibNfcState.next_state: + psLibContext->LibNfcState.cur_state); + } + psLibContext->LibNfcState.next_state = (uint8_t)eLibNfcHalStateInvalid; + return; +} +/* Interface to stack capabilities */ + +NFCSTATUS phLibNfc_Mgt_GetstackCapabilities( + phLibNfc_StackCapabilities_t *phLibNfc_StackCapabilities, + void *pContext) +{ + NFCSTATUS RetVal = NFCSTATUS_FAILED; + /*Check Lib Nfc stack is initilized*/ + if((NULL == gpphLibContext)|| + (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) + { + RetVal = NFCSTATUS_NOT_INITIALISED; + } + /*Check application has sent the valid parameters*/ + else if((NULL == phLibNfc_StackCapabilities) + || (NULL == pContext)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + RetVal = NFCSTATUS_SHUTDOWN; + } + else if(TRUE == gpphLibContext->status.GenCb_pending_status) + { + /*Previous operation is pending */ + RetVal = NFCSTATUS_BUSY; + } + else + { + /* Tag Format Capabilities*/ + phLibNfc_StackCapabilities->psFormatCapabilities.Desfire = TRUE; + phLibNfc_StackCapabilities->psFormatCapabilities.MifareStd = TRUE; + phLibNfc_StackCapabilities->psFormatCapabilities.MifareUL = TRUE; + phLibNfc_StackCapabilities->psFormatCapabilities.FeliCa = FALSE; + phLibNfc_StackCapabilities->psFormatCapabilities.Jewel = FALSE; + phLibNfc_StackCapabilities->psFormatCapabilities.ISO14443_4A = FALSE; + phLibNfc_StackCapabilities->psFormatCapabilities.ISO14443_4B = FALSE; + phLibNfc_StackCapabilities->psFormatCapabilities.MifareULC = TRUE; + phLibNfc_StackCapabilities->psFormatCapabilities.ISO15693 = FALSE; + + /* Tag Mapping Capabilities */ + phLibNfc_StackCapabilities->psMappingCapabilities.FeliCa = TRUE; + phLibNfc_StackCapabilities->psMappingCapabilities.Desfire = TRUE; + phLibNfc_StackCapabilities->psMappingCapabilities.ISO14443_4A = TRUE; + phLibNfc_StackCapabilities->psMappingCapabilities.ISO14443_4B = TRUE; + phLibNfc_StackCapabilities->psMappingCapabilities.MifareStd = TRUE; + phLibNfc_StackCapabilities->psMappingCapabilities.MifareUL = TRUE; + phLibNfc_StackCapabilities->psMappingCapabilities.MifareULC = TRUE; + phLibNfc_StackCapabilities->psMappingCapabilities.Jewel = TRUE; + phLibNfc_StackCapabilities->psMappingCapabilities.ISO15693 = FALSE; + + /*Call Hal4 Get Dev Capabilities to get info about protocols supported + by Lib Nfc*/ + PHDBG_INFO("LibNfc:Get Stack capabilities "); + RetVal= phHal4Nfc_GetDeviceCapabilities( + gpphLibContext->psHwReference, + &(phLibNfc_StackCapabilities->psDevCapabilities), + (void *)gpphLibContext); + + LIB_NFC_VERSION_SET(phLibNfc_StackCapabilities->psDevCapabilities.hal_version, + PH_HAL4NFC_VERSION, + PH_HAL4NFC_REVISION, + PH_HAL4NFC_PATCH, + PH_HAL4NFC_BUILD); + + phLibNfc_StackCapabilities->psDevCapabilities.fw_version= + gpphLibContext->psHwReference->device_info.fw_version; + phLibNfc_StackCapabilities->psDevCapabilities.hci_version= + gpphLibContext->psHwReference->device_info.hci_version; + phLibNfc_StackCapabilities->psDevCapabilities.hw_version= + gpphLibContext->psHwReference->device_info.hw_version; + phLibNfc_StackCapabilities->psDevCapabilities.model_id= + gpphLibContext->psHwReference->device_info.model_id; + (void)memcpy(phLibNfc_StackCapabilities->psDevCapabilities.full_version, + gpphLibContext->psHwReference->device_info.full_version,NXP_FULL_VERSION_LEN); + /* Check the firmware version */ + if (nxp_nfc_full_version == NULL) { + // Couldn't load firmware, just pretend we're up to date. + ALOGW("Firmware image not available: this device might be running old NFC firmware!"); + phLibNfc_StackCapabilities->psDevCapabilities.firmware_update_info = 0; + } else { + phLibNfc_StackCapabilities->psDevCapabilities.firmware_update_info = memcmp(phLibNfc_StackCapabilities->psDevCapabilities.full_version, nxp_nfc_full_version, + NXP_FULL_VERSION_LEN); + } + + if(NFCSTATUS_SUCCESS != RetVal) + { + RetVal = NFCSTATUS_FAILED; + } + } + return RetVal; +} + + + + + + +NFCSTATUS phLibNfc_Mgt_ConfigureTestMode(void *pDriverHandle, + pphLibNfc_RspCb_t pTestModeCb, + phLibNfc_Cfg_Testmode_t eTstmode, + void *pContext) +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + phHal4Nfc_InitType_t eInitType=eInitDefault; + + if((NULL == pDriverHandle)||(NULL == pTestModeCb)) + { + Status = NFCSTATUS_INVALID_PARAMETER; + } + else if((NULL != gpphLibContext) && \ + (gpphLibContext->LibNfcState.next_state==eLibNfcHalStateShutdown)) + { + Status = NFCSTATUS_SHUTDOWN; + } + else if( (eTstmode == phLibNfc_TstMode_On) && (NULL != gpphLibContext)) + { + Status=NFCSTATUS_ALREADY_INITIALISED; + } + else if( (eTstmode == phLibNfc_TstMode_Off) && (NULL == gpphLibContext)) + { + Status = NFCSTATUS_NOT_INITIALISED; + } + else if( (eTstmode == phLibNfc_TstMode_Off) && (NULL != gpphLibContext)) + { + if (NULL!= gpphLibContext->CBInfo.pClientShutdownCb) + { /* Previous callback pending */ + Status = NFCSTATUS_BUSY; + } + else + { + Status = NFCSTATUS_PENDING; + if(TRUE != gpphLibContext->status.GenCb_pending_status) + { + Status = phHal4Nfc_Close(gpphLibContext->psHwReference, + phLibNfc_ShutdownCb, + (void *)gpphLibContext); + } + if(Status== NFCSTATUS_PENDING) + { + gpphLibContext->CBInfo.pClientShutdownCb = pTestModeCb; + gpphLibContext->CBInfo.pClientShtdwnCntx = pContext; + gpphLibContext->status.GenCb_pending_status=TRUE; + gpphLibContext->LibNfcState.next_state= eLibNfcHalStateShutdown; + } + else + { + Status =NFCSTATUS_FAILED; + } + } + } + else + { + /* Initialize the Lib context */ + gpphLibContext=(pphLibNfc_LibContext_t)phOsalNfc_GetMemory( + (uint32_t)sizeof(phLibNfc_LibContext_t)); + if(NULL == gpphLibContext) + { + Status=NFCSTATUS_INSUFFICIENT_RESOURCES; + } + else + { + (void)memset((void *)gpphLibContext,0,( + (uint32_t)sizeof(phLibNfc_LibContext_t))); + + /* Store the Callback and context in LibContext structure*/ + gpphLibContext->CBInfo.pClientInitCb=pTestModeCb; + gpphLibContext->CBInfo.pClientInitCntx=pContext; + /* Initialize the HwReferece structure */ + gpphLibContext->psHwReference=(phHal_sHwReference_t *) + phOsalNfc_GetMemory((uint32_t)sizeof(phHal_sHwReference_t)); + (void)memset((void *)gpphLibContext->psHwReference,0, + ((uint32_t)sizeof(phHal_sHwReference_t))); + /* Allocate the Memory for the Transceive info */ + if( gpphLibContext->psHwReference!=NULL) + { + gpphLibContext->psHwReference->p_board_driver = pDriverHandle; + Status = phLibNfc_UpdateNextState(gpphLibContext, + eLibNfcHalStateInitandIdle); + if(Status==NFCSTATUS_SUCCESS) + { + if(eTstmode == phLibNfc_TstMode_On) + eInitType = eInitTestModeOn; + if(eTstmode == phLibNfc_TstMode_Off) + eInitType = eInitDefault; + Status=phHal4Nfc_Open( + gpphLibContext->psHwReference, + eInitType, + phLibNfc_InitCb, + (void *)gpphLibContext); + } + } + else + { + Status = NFCSTATUS_INSUFFICIENT_RESOURCES; + } + phLibNfc_Ndef_Init(); + } + } + + return Status; +} + diff --git a/libnfc-nxp/phLibNfc.h b/libnfc-nxp/phLibNfc.h new file mode 100644 index 0000000..ddce262 --- /dev/null +++ b/libnfc-nxp/phLibNfc.h @@ -0,0 +1,3152 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +*\file phLibNfc_1.1.h +*\brief Contains FRI1.1 API details. +*Project: NFC-FRI 1.1 +* $Workfile:: phLibNfc_1.1.h $ +* $Modtime:: $ +* $Author: ing07385 $ +* $Revision: 1.80 $ +* $Aliases: NFC_FRI1.1_WK1014_SDK,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1024_SDK $ +*\defgroup grp_lib_nfc LIBNFC Component +*/ +/* \page LibNfc_release_label FRI1.1 API Release Label +* $Aliases: NFC_FRI1.1_WK1014_SDK,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1024_SDK $ +*\note This is the TAG (label, alias) of the FRI1.1. +*If the string is empty, the current documentation +* has not been generated for official release. +*/ +#ifndef PHLIBNFC_H +#define PHLIBNFC_H +#include +#include +#include +#include +#include +#ifdef ANDROID +#include +#endif + +/*! +*\def PHLIBNFC_MAXNO_OF_SE +*Defines maximum no of secured elements supported by PN544. +*/ +#define LIBNFC_READONLY_NDEF +#define PHLIBNFC_MAXNO_OF_SE (0x02) + +typedef uintptr_t phLibNfc_Handle; + +extern const unsigned char *nxp_nfc_full_version; + + +/** +*\ingroup grp_lib_nfc +* +*\brief Defines Testmode Init configuration values +*/ + +typedef enum +{ + phLibNfc_TstMode_Off = 0x00, /**< Test mode is off */ + phLibNfc_TstMode_On /**< Testmode is on */ + +} phLibNfc_Cfg_Testmode_t; + + +/** +*\ingroup grp_lib_nfc +* +*\brief Defines Secure Element configurable states +*/ + +typedef enum +{ + phLibNfc_SE_Active = 0x00, /**< state of the SE is active */ + phLibNfc_SE_Inactive= 0x01 /**< state of the SE is In active*/ + +} phLibNfc_SE_State_t; + +/** +*\ingroup grp_lib_nfc +* +*\brief Defines Secure Element types. +*/ +typedef enum +{ + phLibNfc_SE_Type_Invalid=0x00,/**< Indicates SE type is Invalid */ + phLibNfc_SE_Type_SmartMX=0x01,/**< Indicates SE type is SmartMX */ + phLibNfc_SE_Type_UICC =0x02,/**LibNfc[label="phLibNfc_Mgt_ConfigureDriver()",URL="\ref phLibNfc_Mgt_ConfigureDriver"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_ConfigureDriver()",URL="\ref phLibNfc_Mgt_ConfigureDriver"]; + *LibNfcClient<LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; + *LibNfcClient<LibNfc [label="phLibNfc_Mgt_DeInitialize()",URL="\ref phLibNfc_Mgt_DeInitialize"]; + *LibNfcClient<LibNfc [label="phLibNfc_Mgt_UnConfigureDriver()",URL="\ref phLibNfc_Mgt_UnConfigureDriver"]; + *LibNfcClient< timeout value, (256*16/13.56*10^6) * 2^value +// [0] -> 0.0003s +// .. +// [14] -> 4.9s +// [15] -> not allowed +// bit [4] => timeout enable +// bit [5..7] => unused +NFCSTATUS phLibNfc_SetIsoXchgTimeout(uint8_t timeout); +int phLibNfc_GetIsoXchgTimeout(); + +NFCSTATUS phLibNfc_SetHciTimeout(uint32_t timeout_in_ms); +int phLibNfc_GetHciTimeout(); + +// Felica timeout +// [0] -> timeout disabled +// [1..255] -> timeout in ms +NFCSTATUS phLibNfc_SetFelicaTimeout(uint8_t timeout_in_ms); +int phLibNfc_GetFelicaTimeout(); + +// MIFARE RAW timeout (ISO14443-3A / NfcA timeout) +// timeout is 8 bits +// bits [0..3] => timeout value, (256*16/13.56*10^6) * 2^value +// [0] -> 0.0003s +// .. +// [14] -> 4.9s +// [15] -> not allowed +// bits [4..7] => 0 +NFCSTATUS phLibNfc_SetMifareRawTimeout(uint8_t timeout); +int phLibNfc_GetMifareRawTimeout(); + +/** +* \ingroup grp_lib_nfc +* +* \brief Initializes the NFC library . +* +* +*\brief This function initializes NFC library and its underlying layers. +* As part of this interface underlying modules gets initialized. +* A session with NFC hardware will be established. +* Once initialization is successful ,NFC library ready for use. +*\note It is must to initialize prior usage of the stack . +* +* \param[in] pDriverHandle Driver Handle currently application is using. +* \param[in] pInitCb The init callback is called by the LibNfc when init is +* completed or there is an error in initialization. +* +* \param[in] pContext Client context which will be included in +* callback when the request is completed. +* +* \retval NFCSTATUS_ALREADY_INITIALISED Stack is already initialized. +* \retval NFCSTATUS_PENDING Init sequence has been successfully +* started and result will be conveyed via +* callback notification. +* \retval NFCSTATUS_INVALID_PARAMETER The parameter could not be properly +* interpreted. +*\retval NFCSTATUS_INSUFFICIENT_RESOURCES Insufficient resource.(Ex: insufficient memory) +* +*\msc +*LibNfcClient,LibNfc; +*--- [label="Before initializing Nfc LIB,Configure Driver layer"]; +*LibNfcClient=>LibNfc[label="phLibNfc_Mgt_ConfigureDriver()",URL="\ref phLibNfc_Mgt_ConfigureDriver"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_DeInitialize()",URL="\ref phLibNfc_Mgt_DeInitialize"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<LibNfc [label="phLibNfc_SE_GetSecureElementList()",URL="\ref phLibNfc_SE_GetSecureElementList"]; +*LibNfcClient<LibNfc [label="phLibNfc_SE_SetMode(hSE_Handle,)",URL="\ref phLibNfc_SE_SetMode"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<LibNfc [label="phLibNfc_SE_NtfRegister()",URL="\ref phLibNfc_SE_NtfRegister"]; +LibNfcClient<LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<LibNfc [label="phLibNfc_SE_NtfRegister()",URL="\ref phLibNfc_SE_NtfRegister"]; +LibNfcClient<LibNfc [label="phLibNfc_SE_NtfUnregister()",URL="\ref phLibNfc_SE_NtfUnregister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_IoCtl(pDriverHandle,)",URL="\ref phLibNfc_Mgt_IoCtl"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*--- [label="Register for technology type.Ex: MIFARE UL"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<
a)Enabling/disabling of Reader phases for A,B and F technologies. +*
b)Configuring NFC-IP1 Initiator Speed and duration of the Emulation phase . +* +*Discovery wheel configuration based on discovery mode selected is as below. +*

1.If discovery Mode is set as \ref NFC_DISCOVERY_CONFIG then previous configurations +* over written by new configurations passed in \ref phLibNfc_sADD_Cfg_t and Discovery wheel +*restarts with new configurations. +*

2.If discovery Mode is set as \ref NFC_DISCOVERY_START or \ref NFC_DISCOVERY_STOP then +* discovery parameters passed in \ref phLibNfc_sADD_Cfg_t will not be considered and previous +*configurations still holds good. +*

3.If discovery Mode is set as \ref NFC_DISCOVERY_RESUME discovery mode starts the discovery +*wheel from where it is stopped previously. +* +*\b Note: Config types \b NFC_DISCOVERY_START, \b NFC_DISCOVERY_STOP and \b NFC_DISCOVERY_RESUME +* are not supported currently. It is for future use. +* +* \param[in] DiscoveryMode Discovery Mode allows to choose between: +* discovery configuration and start, stop +* discovery and start discovery (with last +* set configuration).For mode details refer to +\ref phNfc_eDiscoveryConfigMode_t. +* \param[in] sADDSetup Includes Enable/Disable discovery for +* each protocol A,B and F. +* Details refer to \ref phNfc_sADD_Cfg_t. +* \param[in] pConfigDiscovery_RspCb is called once the discovery wheel +* configuration is complete. +* \param[in] pContext Client context which will be included in +* callback when the request is completed. +* +* +*\retval NFCSTATUS_PENDING Discovery request is in progress and result +* will be notified via callback later. +*\retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +*\retval NFCSTATUS_NOT_INITIALISED Indicates stack is not initialized. +*\retval NFCSTATUS_INSUFFICIENT_RESOURCES Insufficient resource.(Ex: insufficient memory) +*\retval NFCSTATUS_BUSY already discovery in progress +* or it is already discovered Target and +* connected. +*\retval NFSCSTATUS_SHUTDOWN Shutdown in progress. +*\retval NFCSTATUS_FAILED Request failed. + +* +* \note : During Reader/Initiator mode it is mandatory +* to call \ref phLibNfc_RemoteDev_Connect before any transaction can be performed +* with the discovered target. Even if the LibNfc client is not +* interested in using any of the discovered targets \ref phLibNfc_RemoteDev_Connect +* and \ref phLibNfc_RemoteDev_Disconnect should be called to restart the Discovery +* wheel. +* \sa \ref phLibNfc_RemoteDev_Connect, phLibNfc_RemoteDev_Disconnect. + +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref +phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_ConfigureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*LibNfcClient<-LibNfc [label="pConfigDiscovery_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Now discovery wheel configured as requested"]; +* +*\endmsc +* +*\note Response callback parameters details for this interface are as listed below. +* +* \param[in] pContext LibNfc client context passed in the corresponding request before. +* \param[in] status Status of the response callback. +* +* \param NFCSTATUS_SUCCESS Discovery Configuration successful. +* \param NFCSTATUS_SHUTDOWN Shutdown in progress. +* \param NFCSTATUS_FAILED Request failed. +*/ + +NFCSTATUS phLibNfc_Mgt_ConfigureDiscovery (phLibNfc_eDiscoveryConfigMode_t DiscoveryMode, + phLibNfc_sADD_Cfg_t sADDSetup, + pphLibNfc_RspCb_t pConfigDiscovery_RspCb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief This function is used to to connect to a single Remote Device. +* +* This function is called to connect to discovered target. +* Once notification handler notified sucessfully discovered targets will be available in +* \ref phLibNfc_RemoteDevList_t .Remote device list contains valid handles for discovered +* targets .Using this interface LibNfc client can connect to one out of 'n' discovered targets. +* A new session is started after connect operation is successful.The session ends with a +* successful disconnect operation.Connect operation on an already connected tag Reactivates +* the Tag.This Feature is not Valid for Jewel/Topaz Tags ,and hence a second connect if issued +* without disconnecting a Jewel/Topaz tag always Fails. +* +* \note :In case multiple targets discovered LibNfc client can connect to only one target. +* +* \param[in] hRemoteDevice Handle of the target device obtained during discovery process. +* +* \param[in] pNotifyConnect_RspCb Client response callback to be to be +* notified to indicate status of the request. +* +* \param[in] pContext Client context which will be included in +* callback when the request is completed. +* +*\retval NFCSTATUS_PENDING Request initiated, result will be informed via +* callback. +*\retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +*\retval NFCSTATUS_TARGET_LOST Indicates target is lost. +*\retval NFSCSTATUS_SHUTDOWN shutdown in progress. +*\retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +*\retval NFCSTATUS_INVALID_HANDLE Target handle is invalid. +* +*\retval NFCSTATUS_FAILED Request failed. +* +* +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_configureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*LibNfcClient<-LibNfc [label="pConfigDiscovery_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Now Present Tag to be discovered"]; +*LibNfcClient<-LibNfc [label="pNotificationHandler",URL="\ref phLibNfc_NtfRegister_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*LibNfcClient<-LibNfc [label="pNotifyConnect_RspCb",URL="\ref pphLibNfc_ConnectCallback_t"]; +* +*\endmsc +*/ + +NFCSTATUS phLibNfc_RemoteDev_Connect(phLibNfc_Handle hRemoteDevice, + pphLibNfc_ConnectCallback_t pNotifyConnect_RspCb, + void* pContext + ); + +#ifdef RECONNECT_SUPPORT + +/** +* \ingroup grp_lib_nfc +* \brief This function is used to to connect to NEXT Remote Device. +* +* This function is called only if there are more than one remote device is detected. +* Once notification handler notified sucessfully discovered targets will be available in +* \ref phLibNfc_RemoteDevList_t .Remote device list contains valid handles for discovered +* targets .Using this interface LibNfc client can connect to one out of 'n' discovered targets. +* A new session is started after connect operation is successful. +* Similarly, if the user wants to connect to another handle. Libnfc client can select the handle and +* the previously connected device is replaced by present handle. The session ends with a +* successful disconnect operation. +* Re-Connect operation on an already connected tag Reactivates the Tag. This Feature is not +* Valid for Jewel/Topaz Tags ,and hence a second re-connect if issued +* without disconnecting a Jewel/Topaz tag always Fails. +* +* \note :In case multiple targets discovered LibNfc client can re-connect to only one target. +* +* \param[in] hRemoteDevice Handle of the target device obtained during discovery process. +* +* \param[in] pNotifyReConnect_RspCb Client response callback to be to be +* notified to indicate status of the request. +* +* \param[in] pContext Client context which will be included in +* callback when the request is completed. +* +*\retval NFCSTATUS_PENDING Request initiated, result will be informed via +* callback. +*\retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +*\retval NFCSTATUS_TARGET_LOST Indicates target is lost. +*\retval NFSCSTATUS_SHUTDOWN shutdown in progress. +*\retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +*\retval NFCSTATUS_INVALID_HANDLE Target handle is invalid. +* +*\retval NFCSTATUS_FAILED Request failed. +* +* +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_configureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*LibNfcClient<-LibNfc [label="pConfigDiscovery_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Now Present multiple protocol Tag to be discovered"]; +*LibNfcClient<-LibNfc [label="pNotificationHandler",URL="\ref phLibNfc_NtfRegister_RspCb_t"]; +*--- [label="TWO remote device information is received, So connect with one handle"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*LibNfcClient<-LibNfc [label="pNotifyConnect_RspCb",URL="\ref pphLibNfc_ConnectCallback_t"]; +*--- [label="Connect is successful, so transact using this handle. Now if user wants to switch to another handle then call Reconnect "]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_ReConnect()",URL="\ref phLibNfc_RemoteDev_ReConnect"]; +*LibNfcClient<-LibNfc [label="pNotifyReConnect_RspCb",URL="\ref pphLibNfc_ConnectCallback_t"]; +* +*\endmsc +*/ +NFCSTATUS +phLibNfc_RemoteDev_ReConnect ( + phLibNfc_Handle hRemoteDevice, + pphLibNfc_ConnectCallback_t pNotifyReConnect_RspCb, + void *pContext); + +#endif /* #ifdef RECONNECT_SUPPORT */ + +/** +* \ingroup grp_lib_nfc +* \brief This interface allows to perform Read/write operation on remote device. +* +* This function allows to send data to and receive data +* from the target selected by libNfc client.It is also used by the +* NFCIP1 Initiator while performing a transaction with the NFCIP1 target. +* The LibNfc client has to provide the handle of the target and the +* command in order to communicate with the selected remote device. +* +* +*\param[in] hRemoteDevice handle of the remote device.This handle to be +* same as as handle obtained for specific remote device +* during device discovery. +* \param[in] psTransceiveInfo Information required by transceive is concealed in +* this structure.It contains send,receive buffers +* and command specific details. +* +* +* \param[in] pTransceive_RspCb Callback function for returning the received response +* or error. +* \param[in] pContext Client context which will be included in +* callback when the request is completed. +* +* \retval NFCSTATUS_PENDING Request initiated, result will be informed through +* the callback. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters could +* not be properly interpreted or invalid. +* \retval NFCSTATUS_COMMAND_NOT_SUPPORTED The command is not supported. +* \retval NFSCSTATUS_SHUTDOWN shutdown in progress. +* \retval NFCSTATUS_TARGET_LOST Indicates target is lost. +* \retval NFCSTATUS_TARGET_NOT_CONNECTED The Remote Device is not connected. +* \retval NFCSTATUS_INVALID_HANDLE Target handle is invalid +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_REJECTED Indicates invalid request. +* \retval NFCSTATUS_FAILED Request failed. +* +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_configureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*LibNfcClient<-LibNfc [label="pConfigDiscovery_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Now Present Tag to be discovered"]; +*LibNfcClient<-LibNfc [label="pNotificationHandler",URL="\ref phLibNfc_NtfRegister_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*LibNfcClient<-LibNfc [label="pNotifyConnect_RspCb",URL="\ref pphLibNfc_ConnectCallback_t"]; +*--- [label="Now perform transceive operation"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Transceive()",URL="\ref phLibNfc_RemoteDev_Transceive "]; +*LibNfcClient<-LibNfc [label="pTransceive_RspCb",URL="\ref pphLibNfc_TransceiveCallback_t"]; +* +*\endmsc +*/ + +NFCSTATUS phLibNfc_RemoteDev_Transceive(phLibNfc_Handle hRemoteDevice, + phLibNfc_sTransceiveInfo_t* psTransceiveInfo, + pphLibNfc_TransceiveCallback_t pTransceive_RspCb, + void* pContext + ); + +/** +*\ingroup grp_lib_nfc +*\brief Allows to disconnect from already connected target. +* +* The function allows to disconnect from from already connected target. This +* function closes the session opened during connect operation.The status of discovery +* wheel after disconnection is determined by the \ref phLibNfc_eReleaseType_t parameter. +* it is also used to switch from wired to virtual mode in case the discovered +* device is SmartMX in wired mode. +* +*\param[in] hRemoteDevice handle of the target device.This handle to be +* same as as handle obtained for specific remote device +* during device discovery. +* \param[in] ReleaseType Release mode to be used while +* disconnecting from target.Refer \ref phLibNfc_eReleaseType_t +* for possible release types. +*\param[in] pDscntCallback Client response callback to be to be notified +to indicate status of the request. +* \param[in] pContext Client context which will be included in +* callback when the request is completed. + +*\retval NFCSTATUS_PENDING Request initiated, result will be informed through +the callback. +*\retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters could not be +* properly interpreted. +*\retval NFCSTATUS_TARGET_NOT_CONNECTED The Remote Device is not connected. +*\retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_INVALID_HANDLE Target handle is invalid. +*\retval NFSCSTATUS_SHUTDOWN Shutdown in progress. +*\retval NFCSTATUS_REJECTED Indicates previous disconnect in progress. +* \retval NFCSTATUS_BUSY Indicates can not disconnect due to outstanding transaction in progress. +* \retval NFCSTATUS_FAILED Request failed. + +* +* +* +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_configureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*LibNfcClient<-LibNfc [label="pConfigDiscovery_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Now Present Tag to be discovered"]; +*LibNfcClient<-LibNfc [label="pNotificationHandler",URL="\ref phLibNfc_NtfRegister_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*LibNfcClient<-LibNfc [label="pNotifyConnect_RspCb",URL="\ref pphLibNfc_ConnectCallback_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Transceive()",URL="\ref phLibNfc_RemoteDev_Transceive"]; +*LibNfcClient<-LibNfc [label="pTransceive_RspCb",URL="\ref pphLibNfc_TransceiveCallback_t"]; +*--- [label="Once transceive is completed Now disconnect"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Disconnect()",URL="\ref phLibNfc_RemoteDev_Disconnect"]; +*LibNfcClient<-LibNfc [label="pDscntCallback",URL="\ref pphLibNfc_RspCb_t"]; +* +*\endmsc +*/ +NFCSTATUS phLibNfc_RemoteDev_Disconnect( phLibNfc_Handle hRemoteDevice, + phLibNfc_eReleaseType_t ReleaseType, + pphLibNfc_DisconnectCallback_t pDscntCallback, + void* pContext + ); + + + +/** +* \ingroup grp_lib_nfc +*\brief This interface unregisters notification handler for target discovery. +* +* This function unregisters the listener which has been registered with +* phLibNfc_RemoteDev_NtfUnregister() before. After this call the callback +* function won't be called anymore. If nothing is registered the +* function still succeeds +* \retval NFCSTATUS_SUCCESS callback unregistered. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +*\retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_RemoteDev_NtfUnregister()",URL="\ref phLibNfc_RemoteDev_NtfUnregister"]; +* +*\endmsc +*/ + +NFCSTATUS phLibNfc_RemoteDev_NtfUnregister(void); + +/** +* \ingroup grp_lib_nfc +* \brief Check for target presence. +* This function checks ,given target is present in RF filed or not. +* Client can make use of this API to check periodically discovered +* tag is present in RF field or not. +* +* +*\param[in] hRemoteDevice handle of the target device.This handle to be +* same as as handle obtained for specific remote device +* during device discovery. +* \param[in] pPresenceChk_RspCb callback function called on completion of the +* presence check or in case an error has occurred. +* \param[in] pContext Client context which will be included in +* callback when the request is completed. +* +* \retval NFCSTATUS_PENDING presence check started. Status will be notified +* via callback. +* +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not initialized. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters could +* not be properly interpreted. +* \retval NFCSTATUS_TARGET_NOT_CONNECTED The Remote Device is not connected. +* \retval NFCSTATUS_INVALID_HANDLE Target handle is invalid +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Request failed. +* +* +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_configureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*LibNfcClient<-LibNfc [label="pConfigDiscovery_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Now Present Tag to be discovered"]; +*LibNfcClient<-LibNfc [label="pNotificationHandler",URL="\ref phLibNfc_NtfRegister_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*LibNfcClient<-LibNfc [label="pNotifyConnect_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_CheckPresence()",URL="\ref phLibNfc_RemoteDev_CheckPresence"]; +*LibNfcClient<-LibNfc [label="pPresenceChk_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +* +*\endmsc +* +*\note Response callback parameters details for this interface are as listed below. +* +* \param[in] pContext LibNfc client context passed in the corresponding request before. +* \param[in] status Status of the response callback. +* +* \param NFCSTATUS_SUCCESS Successful,indicates tag is present in RF field. +* \param NFCSTATUS_TARGET_LOST Indicates target is lost. +* \param NFCSTATUS_SHUTDOWN Shutdown in progress. +* \param NFCSTATUS_FAILED Request failed. +* +*/ +NFCSTATUS phLibNfc_RemoteDev_CheckPresence( phLibNfc_Handle hRemoteDevice, + pphLibNfc_RspCb_t pPresenceChk_RspCb, + void* pContext + ); + +/** +* \ingroup grp_lib_nfc +*\brief Allows to check connected tag is NDEF compliant or not. +* This function allows to validate connected tag is NDEF compliant or not. +* +*\param[in] hRemoteDevice handle of the remote device.This handle to be +* same as as handle obtained for specific remote device +* during device discovery. +*\param[in] pCheckNdef_RspCb Response callback defined by the caller. +*\param[in] pContext Client context which will be included in +* callback when the request is completed. +* +* \retval NFCSTATUS_PENDING The action has been successfully triggered. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function +* is invalid. +* \retval NFCSTATUS_TARGET_LOST Indicates target is lost +* \retval NFCSTATUS_TARGET_NOT_CONNECTED The Remote Device is not connected. +* \retval NFCSTATUS_INVALID_HANDLE Target handle is invalid +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Request failed. +* +* +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_configureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*LibNfcClient<-LibNfc [label="pConfigDiscovery_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Now Present NDEF complaint Tag Type"]; +*LibNfcClient<-LibNfc [label="pNotificationHandler",URL="\ref phLibNfc_NtfRegister_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*LibNfcClient<-LibNfc [label="pNotifyConnect_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_Ndef_CheckNdef()",URL="\ref phLibNfc_Ndef_CheckNdef "]; +*LibNfcClient<-LibNfc [label="pCheckNdef_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +* +*\endmsc +* +*\note Response callback parameters details for this interface are as listed below. +* +* \param[in] pContext LibNfc client context passed in the corresponding request before. +* \param[in] status Status of the response callback. +* +* \param NFCSTATUS_SUCCESS Successful and tag is NDEF compliant . +* \param NFCSTATUS_TARGET_LOST NDEF check operation is failed because of target is ** lost. +* \param NFCSTATUS_SHUTDOWN Shutdown in progress. +* \param NFCSTATUS_ABORTED Aborted due to disconnect operation in between. +* \param NFCSTATUS_FAILED Request failed. +*/ + +NFCSTATUS phLibNfc_Ndef_CheckNdef(phLibNfc_Handle hRemoteDevice, + pphLibNfc_ChkNdefRspCb_t pCheckNdef_RspCb, + void* pContext); + +/** +* \ingroup grp_lib_nfc +* \brief Read NDEF message from a Tag. +* This function reads an NDEF message from already connected tag. +* the NDEF message is read starting after the position of the last read operation +* of the same tag during current session. +* If it's FALSE the NDEF message is read from starting of the NDEF message. +* If the call returns with NFCSTATUS_PENDING , a response callback pNdefRead_RspCb is +* called ,when the read operation is complete. +* +*\note Before issuing NDEF read operation LibNfc client should perform NDEF check operation +* using \ref phLibNfc_Ndef_CheckNdef interface. +* If the call back error code is NFCSTATUS_FAILED then the LIBNFC client has to do the +* phLibNfc_RemoteDev_CheckPresence to find , its communication error or target lost. +* +*\param[in] hRemoteDevice handle of the remote device.This handle to be +* same as as handle obtained for specific remote device +* during device discovery. +* \param[in] psRd Pointer to the read buffer info. +* \param[in] Offset Reading Offset : phLibNfc_Ndef_EBegin means from the +* beginning, phLibNfc_Ndef_ECurrent means from the +* current offset. +* \param[in] pNdefRead_RspCb Response callback defined by the caller. +* \param[in] pContext Client context which will be included in +* callback when the request is completed. +* +* \retval NFCSTATUS_SUCCESS NDEF read operation successful. +* \retval NFCSTATUS_PENDING Request accepted and started +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress +* \retval NFCSTATUS_INVALID_HANDLE Target handle is invalid +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters could not +* be properly interpreted. +* \retval NFCSTATUS_TARGET_NOT_CONNECTED The Remote Device is not connected. +* \retval NFCSTATUS_FAILED Read operation failed since tag does not contain NDEF data. +* \retval NFCSTATUS_NON_NDEF_COMPLIANT Tag is not Ndef Compliant. +* \param NFCSTATUS_REJECTED Rejected due to NDEF read issued on non +* ,or Ndef check has not been performed +* before the readNDEF tag. +* +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_configureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*LibNfcClient<-LibNfc [label="pConfigDiscovery_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Now Present NDEF complaint Tag Type"]; +*LibNfcClient<-LibNfc [label="pNotificationHandler",URL="\ref phLibNfc_NtfRegister_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*LibNfcClient<-LibNfc [label="pNotifyConnect_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_Ndef_CheckNdef()",URL="\ref phLibNfc_Ndef_CheckNdef "]; +*LibNfcClient<-LibNfc [label="pCheckNdef_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_Ndef_Read()",URL="\ref phLibNfc_Ndef_Read "]; +*LibNfcClient<-LibNfc [label="pNdefRead_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +* +*\endmsc +* +*\note Response callback parameters details for this interface are as listed below. +* +* \param[in] pContext LibNfc client context passed in the corresponding request before. +* \param[in] status Status of the response callback. +* +* \param NFCSTATUS_SUCCESS NDEF read operation successful. +* \param NFCSTATUS_SHUTDOWN Shutdown in progress. +* \param NFCSTATUS_ABORTED Aborted due to disconnect operation in between. +* \param NFCSTATUS_FAILED Request failed. +*/ +NFCSTATUS phLibNfc_Ndef_Read(phLibNfc_Handle hRemoteDevice, + phNfc_sData_t* psRd, + phLibNfc_Ndef_EOffset_t Offset, + pphLibNfc_RspCb_t pNdefRead_RspCb, + void* pContext + ); +/** +** \ingroup grp_lib_nfc +* +* \brief Write NDEF data to NFC tag. +* +* This function allows the client to write a NDEF data to already connected NFC tag. +* Function writes a complete NDEF message to a tag. If a NDEF message already +* exists in the tag, it will be overwritten. When the transaction is complete, +* a notification callback is notified. +* +*\note Before issuing NDEF write operation LibNfc client should perform NDEF check operation +* using \ref phLibNfc_Ndef_CheckNdef interface. +* +*\param[in] hRemoteDevice handle of the remote device.This handle to be +* same as as handle obtained for specific remote device +* during device discovery. +*\param[in] psWr Ndef Buffer to write. If NdefMessageLen is set to 0 +* and pNdefMessage = NULL, the NFC library will erase +* tag internally. +*\param[in] pNdefWrite_RspCb Response callback defined by the caller. +*\param[in] pContext Client context which will be included in +* callback when the request is completed. +* +*\note If \ref phNfc_sData_t.NdefMessageLen is 0 bytes, this function will erase all +*current NDEF data present in the tag. Any non-zero length buffer size +*will attempt to write NEDF data onto the tag. +* If the call back error code is NFCSTATUS_FAILED then the LIBNFC client has to do the +* phLibNfc_RemoteDev_CheckPresence to find , its communication error or target lost. +* +* +* \retval NFCSTATUS_PENDING Request accepted and started. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_INVALID_HANDLE Target handle is invalid. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters could not +* be properly interpreted. +* \retval NFCSTATUS_NON_NDEF_COMPLIANT Tag is not Ndef Compliant. +* \retval NFCSTATUS_TARGET_NOT_CONNECTED The Remote Device is not connected. +* \retval NFCSTATUS_REJECTED Rejected due to NDEF write issued without +* performing a CheckNdef(). +* \retval NFCSTATUS_FAILED operation failed. +* +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_configureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*LibNfcClient<-LibNfc [label="pConfigDiscovery_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Now Present NDEF Tag "]; +*LibNfcClient<-LibNfc [label="pNotificationHandler",URL="\ref phLibNfc_NtfRegister_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*LibNfcClient<-LibNfc [label="pNotifyConnect_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_Ndef_CheckNdef()",URL="\ref phLibNfc_Ndef_CheckNdef "]; +*LibNfcClient<-LibNfc [label="pCheckNdef_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_Ndef_Write()",URL="\ref phLibNfc_Ndef_Write "]; +*LibNfcClient<-LibNfc [label="pNdefWrite_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +* +*\endmsc +* +*\note Response callback parameters details for this interface are as listed below. +* +* \param[in] pContext LibNfc client context passed in the corresponding request before. +* \param[in] status Status of the response callback. +* +* \param NFCSTATUS_SUCCESS NDEF write operation is successful. +* \param NFCSTATUS_SHUTDOWN Shutdown in progress. +* \param NFCSTATUS_ABORTED, Aborted due to disconnect operation in between. +* \param NFCSTATUS_NOT_ENOUGH_MEMORY Requested no of bytes to be writen exceeds size of the memory available on the tag. +* \param NFCSTATUS_FAILED Request failed. +*/ + +NFCSTATUS phLibNfc_Ndef_Write (phLibNfc_Handle hRemoteDevice, + phNfc_sData_t* psWr, + pphLibNfc_RspCb_t pNdefWrite_RspCb, + void* pContext + ); + + + +/** +* \ingroup grp_lib_nfc +* +* \brief Format target. +* +* This function allows the LibNfc client to perform NDEF formating operation on discovered target. +This function formats given target +* +*\note +*
1. Prior to formating it is recommended to perform NDEF check using \ref phLibNfc_Ndef_CheckNdef interface. +*
2. formatting feature supported only for MIFARE Std,MIFARE UL and Desfire tag types. +* If the call back error code is NFCSTATUS_FAILED then the LIBNFC client has to do the +* phLibNfc_RemoteDev_CheckPresence to find , its communication error or target lost. +* +*\param[in] hRemoteDevice handle of the remote device.This handle to be +* same as as handle obtained for specific remote device +* during device discovery. +*\param[in] pScrtKey info containing the secret key data +* and Secret key buffer length. +* +*\param[in] pNdefformat_RspCb Response callback defined by the caller. +*\param[in] pContext Client context which will be included in +* callback when the request is completed. +* +* +* \retval NFCSTATUS_PENDING Request accepted and started. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_INVALID_HANDLE Target handle is invalid. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters could not +* be properly interpreted. +* \retval NFCSTATUS_TARGET_NOT_CONNECTED The Remote Device is not connected. +* \retval NFCSTATUS_FAILED operation failed. +* \retval NFCSTATUS_REJECTED Tag is already formatted one. +* +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_configureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*LibNfcClient<-LibNfc [label="pConfigDiscovery_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Now Present non NDEF Tag "]; +*LibNfcClient<-LibNfc [label="pNotificationHandler",URL="\ref phLibNfc_NtfRegister_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*LibNfcClient<-LibNfc [label="pNotifyConnect_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_Ndef_CheckNdef()",URL="\ref phLibNfc_Ndef_CheckNdef "]; +*LibNfcClient<-LibNfc [label="pCheckNdef_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Tag found to be non NDEF compliant ,now format it"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_FormatNdef()",URL="\ref phLibNfc_RemoteDev_FormatNdef "]; +*LibNfcClient<-LibNfc [label="pNdefformat_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +* +*\endmsc +* +*\note Response callback parameters details for this interface are as listed below. +* +* \param[in] pContext LibNfc client context passed in the corresponding request before. +* \param[in] status Status of the response callback. +* +* \param NFCSTATUS_SUCCESS NDEF formatting operation is successful. +* \param NFCSTATUS_SHUTDOWN Shutdown in progress. +* \param NFCSTATUS_ABORTED, Aborted due to disconnect operation in between. +* \param NFCSTATUS_FAILED Request failed. +*/ + +NFCSTATUS phLibNfc_RemoteDev_FormatNdef(phLibNfc_Handle hRemoteDevice, + phNfc_sData_t* pScrtKey, + pphLibNfc_RspCb_t pNdefformat_RspCb, + void* pContext + ); + +#ifdef LIBNFC_READONLY_NDEF +/** +* \ingroup grp_lib_nfc +* +* \brief To convert a already formatted NDEF READ WRITE tag to READ ONLY. +* +* This function allows the LibNfc client to convert a already formatted NDEF READ WRITE +* tag to READ ONLY on discovered target. +* +*\note +*
1. Prior to formating it is recommended to perform NDEF check using \ref phLibNfc_Ndef_CheckNdef interface. +*
2. READ ONLY feature supported only for MIFARE UL and Desfire tag types. +* If the call back error code is NFCSTATUS_FAILED then the LIBNFC client has to do the +* phLibNfc_RemoteDev_CheckPresence to find, its communication error or target lost. +* +*\param[in] hRemoteDevice handle of the remote device.This handle to be +* same as as handle obtained for specific remote device +* during device discovery. +*\param[in] pScrtKey Key to be used for making Mifare read only. This parameter is +* unused in case of readonly for other cards. +*\param[in] pNdefReadOnly_RspCb Response callback defined by the caller. +*\param[in] pContext Client context which will be included in +* callback when the request is completed. +* +* +* \retval NFCSTATUS_PENDING Request accepted and started. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_INVALID_HANDLE Target handle is invalid. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters could not +* be properly interpreted. +* \retval NFCSTATUS_TARGET_NOT_CONNECTED The Remote Device is not connected. +* \retval NFCSTATUS_FAILED operation failed. +* \retval NFCSTATUS_REJECTED Tag is already formatted one. +* +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_configureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*LibNfcClient<-LibNfc [label="pConfigDiscovery_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Now Present NDEF Tag "]; +*LibNfcClient<-LibNfc [label="pNotificationHandler",URL="\ref phLibNfc_NtfRegister_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*LibNfcClient<-LibNfc [label="pNotifyConnect_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_Ndef_CheckNdef()",URL="\ref phLibNfc_Ndef_CheckNdef "]; +*LibNfcClient<-LibNfc [label="pCheckNdef_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Tag found to be NDEF compliant ,now convert the tag to read only"]; +*LibNfcClient=>LibNfc [label="phLibNfc_ConvertToReadOnlyNdef()",URL="\ref phLibNfc_ConvertToReadOnlyNdef "]; +*LibNfcClient<-LibNfc [label="pNdefReadOnly_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +* +*\endmsc +* +*\note Response callback parameters details for this interface are as listed below. +* +* \param[in] pContext LibNfc client context passed in the corresponding request before. +* \param[in] status Status of the response callback. +* +* \param NFCSTATUS_SUCCESS Converting the tag to READ ONLY NDEF is successful. +* \param NFCSTATUS_SHUTDOWN Shutdown in progress. +* \param NFCSTATUS_ABORTED, Aborted due to disconnect operation in between. +* \param NFCSTATUS_FAILED Request failed. +*/ + +NFCSTATUS phLibNfc_ConvertToReadOnlyNdef (phLibNfc_Handle hRemoteDevice, + phNfc_sData_t* pScrtKey, + pphLibNfc_RspCb_t pNdefReadOnly_RspCb, + void* pContext + ); +#endif /* #ifdef LIBNFC_READONLY_NDEF */ + +/** +* \ingroup grp_lib_nfc +* \brief Search for NDEF Record type. +* +* This function allows LibNfc client to search NDEF content based on TNF value and type \n +* +*This API allows to find NDEF records based on RTD (Record Type Descriptor) info. +*LibNfc internally parses NDEF content based registration type registered. +*In case there is match LibNfc notifies LibNfc client with NDEF information details. +*LibNfc client can search a new NDEF registration type once the previous call is handled. +* +*\param[in] hRemoteDevice Handle of the remote device.This handle to be +* same as as handle obtained for specific remote device +* during device discovery. +*\param[in] psSrchTypeList List of NDEF records to be looked in based on TNF value and type. +* For NDEF search type refer to \ref phLibNfc_Ndef_SrchType. +* If this set to NULL then it means that libNfc client interested in +* all possible NDEF records. +* +*\param[in] uNoSrchRecords Indicates no of NDEF records in requested list as mentioned +* in psSrchTypeList. +*\param[in] pNdefNtfRspCb Response callback defined by the caller. +*\param[in] pContext Client context which will be included in +* callback when callback is notified. +* +* +* \retval NFCSTATUS_SUCCESS Indicates NDEF notification registration successful. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_INVALID_HANDLE Target handle is invalid. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters could not +* be properly interpreted. +* \retval NFCSTATUS_TARGET_NOT_CONNECTED The Remote Device is not connected. +* \retval NFCSTATUS_FAILED operation failed. +* \retval NFCSTATUS_BUSY Previous request in progress can not accept new request. +* +* \retval NFCSTATUS_ABORTED Aborted due to disconnect request in between. +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_configureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*LibNfcClient<-LibNfc [label="pConfigDiscovery_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*--- [label="Now Present NDEF Tag "]; +*LibNfcClient<-LibNfc [label="pNotificationHandler",URL="\ref phLibNfc_NtfRegister_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*LibNfcClient<-LibNfc [label="pNotifyConnect_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_Ndef_CheckNdef()",URL="\ref phLibNfc_Ndef_CheckNdef "]; +*LibNfcClient<-LibNfc [label="pCheckNdef_RspCb",URL="\ref pphLibNfc_RspCb_t"]; +*LibNfcClient=>LibNfc [label="phLibNfc_Ndef_SearchNdefContent()",URL="\ref phLibNfc_Ndef_SearchNdefContent"]; +*LibNfcClient<-LibNfc [label="pNdefNtfRspCb",URL="\ref pphLibNfc_Ndef_Search_RspCb_t()"]; +*\endmsc +* +*\note Response callback parameters details for this interface are as listed below. +* +* \param[in] pContext LibNfc client context passed in the corresponding request before. +* \param[in] status Status of the response callback. +* +*/ +NFCSTATUS phLibNfc_Ndef_SearchNdefContent( + phLibNfc_Handle hRemoteDevice, + phLibNfc_Ndef_SrchType_t* psSrchTypeList, + uint8_t uNoSrchRecords, + pphLibNfc_Ndef_Search_RspCb_t pNdefNtfRspCb, + void * pContext + ); + + + + +/** +* \ingroup grp_lib_nfc +* \brief Interface used to receive data from initiator at target side during P2P communication. +* +*This function Allows the NFC-IP1 target to retrieve data/commands coming from the +*Initiator.Once this function is called by LibNfc client on target side it waits for +*receiving data from initiator.It is used by libNfc client which acts as target during P2P +*communication. +* +*\note : Once this API is called,its mandatory to wait for receive +*\ref pphLibNfc_Receive_RspCb_t callback notification,before calling any other +*API.Only function allowed is \ref phLibNfc_Mgt_DeInitialize. +* +* \param[in] hRemoteDevice Peer handle obtained during device discovery process. +* +* \param[in] pReceiveRspCb Callback function called after receiving +* the data or in case an error has +* has occurred. +* +* \param[in] pContext Upper layer context to be returned +* in the callback. +* +* \retval NFCSTATUS_PENDING Receive operation is in progress. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_INVALID_DEVICE The device has been disconnected meanwhile. +* \retval NFCSTATUS_DESELECTED Receive operation is not possible due to +* initiator issued disconnect or intiator +* physically removed from the RF field. +* +*\retval NFCSTATUS_REJECTED Indicates invalid request. +*\retval NFCSTATUS_FAILED Request failed. +* +*\msc +*P2PInitiatorClient,InitiatorLibNfc,P2PTargetLibNfc,P2PTargetClient; +*--- [label="stack is intialised and P2P notification handler registered alredy"]; +*P2PTargetClient=>P2PTargetLibNfc [label="phLibNfc_Mgt_SetP2P_ConfigParams()",URL="\ref phLibNfc_Mgt_SetP2P_ConfigParams"]; +*P2PTargetClient<InitiatorLibNfc [label="phLibNfc_Mgt_SetP2P_ConfigParams()",URL="\ref phLibNfc_Mgt_SetP2P_ConfigParams"]; +*P2PInitiatorClient<P2PTargetLibNfc [label="phLibNfc_Mgt_ConfigureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*P2PTargetClient<InitiatorLibNfc [label="phLibNfc_Mgt_ConfigureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*P2PInitiatorClient<InitiatorLibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*P2PInitiatorClient<P2PTargetLibNfc [label="phLibNfc_RemoteDev_Receive()",URL="\ref phLibNfc_RemoteDev_Receive"]; +*--- [label="Now target waits to receive data from intiator"]; +*--- [label="Send data from initiator now"]; +*P2PInitiatorClient=>InitiatorLibNfc [label="phLibNfc_RemoteDev_Transceive()",URL="\ref phLibNfc_RemoteDev_Transceive "]; +*P2PInitiatorClient<-InitiatorLibNfc [label="pTransceive_RspCb",URL="\ref pphLibNfc_TransceiveCallback_t"]; +*--- [label="Now data arrived at target side"]; +*P2PTargetClient<-P2PTargetLibNfc [label="pReceiveRspCb",URL="\ref pphLibNfc_Receive_RspCb_t"]; +\endmsc +*\note Response callback parameters details for this interface are as listed below. +* +* \param[in] pContext LibNfc client context passed in the corresponding request before. +* \param[in] status Status of the response callback. +* +* \param NFCSTATUS_SUCCESS Receive operation successful. +* \param NFCSTATUS_SHUTDOWN Receive operation failed because Shutdown in progress. +* \param NFCSTATUS_ABORTED Aborted due to initiator issued disconnect request. +* or intiator removed physically from the RF field. +* This status code reported,to indicate P2P session +* closed and send and receive requests not allowed +* any more unless new session is started. +* \param NFCSTATUS_DESELECTED Receive operation is not possible due to +* initiator issued disconnect or intiator +* physically removed from the RF field. +*/ +extern +NFCSTATUS +phLibNfc_RemoteDev_Receive( phLibNfc_Handle hRemoteDevice, + pphLibNfc_Receive_RspCb_t pReceiveRspCb, + void* pContext + ); + + + + + +/** +* \ingroup grp_lib_nfc +* \brief Interface used to send data from target to initiator during P2P communication. +* +*This function Allows the NFC-IP1 target to send data to Initiator,in response to packet received +*from initiator during P2P communication.It is must prior to send request target has received +*data from initiator using \ref phLibNfc_RemoteDev_Receive interface. +* +* +* \param[in] hRemoteDevice Peer handle obtained during device discovery process. +* +* \param[in] pTransferData Data and the length of the data to be +* transferred. +* \param[in] pSendRspCb Callback function called on completion +* of the NfcIP sequence or in case an +* error has occurred. +* +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +** \retval NFCSTATUS_PENDING Send operation is in progress. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_INVALID_DEVICE The device has been disconnected meanwhile. +* \retval NFCSTATUS_BUSY Previous request in progress can not accept new request. +* \retval NFCSTATUS_DESELECTED Receive operation is not possible due to +* initiator issued disconnect or intiator +* physically removed from the RF field. +*\retval NFCSTATUS_REJECTED Indicates invalid request. +*\retval NFCSTATUS_FAILED Request failed. +* +*\msc +*P2PInitiatorClient,InitiatorLibNfc,P2PTargetLibNfc,P2PTargetClient; +*--- [label="stack is intialised and P2P notification handler registered alredy"]; +*P2PTargetClient=>P2PTargetLibNfc [label="phLibNfc_Mgt_SetP2P_ConfigParams()",URL="\ref phLibNfc_Mgt_SetP2P_ConfigParams"]; +*P2PTargetClient<InitiatorLibNfc [label="phLibNfc_Mgt_SetP2P_ConfigParams()",URL="\ref phLibNfc_Mgt_SetP2P_ConfigParams"]; +*P2PInitiatorClient<P2PTargetLibNfc [label="phLibNfc_Mgt_ConfigureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*P2PTargetClient<InitiatorLibNfc [label="phLibNfc_Mgt_ConfigureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*P2PInitiatorClient<InitiatorLibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*P2PInitiatorClient<P2PTargetLibNfc [label="phLibNfc_RemoteDev_Receive()",URL="\ref phLibNfc_RemoteDev_Receive"]; +*--- [label="Now target waits to receive data from intiator"]; +*--- [label="Send data from initiator now"]; +*P2PInitiatorClient=>InitiatorLibNfc [label="phLibNfc_RemoteDev_Transceive()",URL="\ref phLibNfc_RemoteDev_Transceive "]; +*--- [label="Now data arrived at target side"]; +*P2PTargetClient<-P2PTargetLibNfc [label="pReceiveRspCb",URL="\ref pphLibNfc_Receive_RspCb_t"]; +*--- [label="Now send data from target"]; +*P2PTargetClient=>P2PTargetLibNfc [label="phLibNfc_RemoteDev_Send()",URL="\ref phLibNfc_RemoteDev_Send"]; +*P2PInitiatorClient<-InitiatorLibNfc [label="pTransceive_RspCb",URL="\ref pphLibNfc_TransceiveCallback_t"]; +*P2PTargetClient<-P2PTargetLibNfc [label="pSendRspCb",URL="\ref pphLibNfc_RspCb_t"]; +*\endmsc +* +*\note Response callback parameters details for this interface are as listed below. +* +* \param[in] pContext LibNfc client context passed in the corresponding request before. +* \param[in] status Status of the response callback. +* +* \param NFCSTATUS_SUCCESS Send operation successful. +* \param NFCSTATUS_SHUTDOWN Send operation failed because Shutdown in progress. +* \param NFCSTATUS_ABORTED Aborted due to initiator issued disconnect request. +* or intiator removed physically from the RF field. +* This status code reported,to indicate P2P session +* closed and send and receive requests not allowed +* any more unless new session is started. +* \param NFCSTATUS_DESELECTED Receive operation is not possible due to +* initiator issued disconnect or intiator +* physically removed from the RF field. +* +* +*/ +extern +NFCSTATUS +phLibNfc_RemoteDev_Send(phLibNfc_Handle hRemoteDevice, + phNfc_sData_t* pTransferData, + pphLibNfc_RspCb_t pSendRspCb, + void* pContext + ); + +/** +* \ingroup grp_lib_nfc +* \brief Interface to configure P2P and intiator mode configurations. +* The setting will be typically take effect for the next cycle of the relevant +* phase of discovery. For optional configuration internal defaults will be +* used in case the configuration is not set. +* +*\note Currently general bytes configuration supported. +* +* \param[in] pConfigInfo Union containing P2P configuration details as +* in \ref phLibNfc_sNfcIPCfg_t. +* +* \param[in] pConfigRspCb This callback has to be called once LibNfc +* completes the Configuration. +* +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* +* \retval NFCSTATUS_PENDING Config operation is in progress. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_BUSY Previous request in progress can not accept new request. +* +*\msc +*P2PInitiatorClient,InitiatorLibNfc,P2PTargetLibNfc,P2PTargetClient; +*--- [label="stack is intialised and P2P notification handler registered alredy"]; +*P2PTargetClient=>P2PTargetLibNfc [label="phLibNfc_Mgt_SetP2P_ConfigParams()",URL="\ref phLibNfc_Mgt_SetP2P_ConfigParams"]; +*P2PTargetClient<InitiatorLibNfc [label="phLibNfc_Mgt_SetP2P_ConfigParams()",URL="\ref phLibNfc_Mgt_SetP2P_ConfigParams"]; +*P2PInitiatorClient<P2PTargetLibNfc [label="phLibNfc_Mgt_ConfigureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*P2PTargetClient<InitiatorLibNfc [label="phLibNfc_Mgt_ConfigureDiscovery()",URL="\ref phLibNfc_Mgt_ConfigureDiscovery"]; +*P2PInitiatorClient<InitiatorLibNfc [label="phLibNfc_RemoteDev_Connect()",URL="\ref phLibNfc_RemoteDev_Connect"]; +*P2PInitiatorClient<Interface to stack capabilities. +* +* LibNfc client can query to retrieve stack capabilities.Stack capabilities contains +*

a).Device capabilities which contains details like protocols supported, +* Hardware,Firmware and model-id version details .For details refer to \ref phNfc_sDeviceCapabilities_t. +*

b).NDEF mapping related info. This info helps in identifying supported tags for NDEF mapping feature. +*

c).NDEF formatting related info. This info helps in identifying supported tags for NDEF formatting feature. +* +* \param[in] phLibNfc_StackCapabilities Contains device capabilities and NDEF mapping and formatting feature + support for different tag types. +* +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* +* \retval NFCSTATUS_SUCCESS Indicates Get stack Capabilities operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED operation failed. +* \retval NFCSTATUS_BUSY Previous request in progress can not accept new request. +* +* +*\msc +*LibNfcClient,LibNfc; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_Initialize()",URL="\ref phLibNfc_Mgt_Initialize"]; +*LibNfcClient<-LibNfc [label="pInitCb()",URL="\ref pphLibNfc_RspCb_t()"]; +*LibNfcClient=>LibNfc [label="phLibNfc_RemoteDev_NtfRegister()",URL="\ref phLibNfc_RemoteDev_NtfRegister"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_GetstackCapabilities()",URL="\ref phLibNfc_Mgt_GetstackCapabilities"]; +*LibNfcClient<Interface to configure local LLCP peer. +* +* This function configures the parameters of the local LLCP peer. This function must be called +* before any other LLCP-related function from this API. +* +* \param[in] pConfigInfo Contains local LLCP link parameters to be applied +* \param[in] pConfigRspCb This callback has to be called once LibNfc +* completes the Configuration. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_PENDING Configuration operation is in progress, + pConfigRspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +* \retval NFCSTATUS_BUSY Previous request in progress can not accept new request. +*/ +extern NFCSTATUS phLibNfc_Mgt_SetLlcp_ConfigParams( phLibNfc_Llcp_sLinkParameters_t* pConfigInfo, + pphLibNfc_RspCb_t pConfigRspCb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Checks if a remote peer is LLCP compliant. +* +* This functions allows to check if a previously detected tag is compliant with the +* LLCP protocol. This step is needed before calling any other LLCP-related function on +* this remote peer, except local LLCP peer configurationn, which is more general. Once +* this checking is done, the caller will be able to receive link status notifications +* until the peer is disconnected. +* +* \param[in] hRemoteDevice Peer handle obtained during device discovery process. +* \param[in] pCheckLlcp_RspCb The callback to be called once LibNfc +* completes the LLCP compliancy check. +* \param[in] pLink_Cb The callback to be called each time the +* LLCP link status changes. +* \param[in] pContext Upper layer context to be returned in +* the callbacks. +* +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_PENDING Check operation is in progress, pCheckLlcp_RspCb will +* be called upon completion. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +* \retval NFCSTATUS_BUSY Previous request in progress can not accept new request. +*/ +extern NFCSTATUS phLibNfc_Llcp_CheckLlcp( phLibNfc_Handle hRemoteDevice, + pphLibNfc_ChkLlcpRspCb_t pCheckLlcp_RspCb, + pphLibNfc_LlcpLinkStatusCb_t pLink_Cb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Activates a LLCP link with a remote device . +* +* This function launches the link activation process on a remote LLCP-compliant peer. The link status +* notification will be sent by the corresponding callback given in the phLibNfc_Llcp_CheckLlcp function. +* If the activation fails, the deactivated status will be notified, even if the link is already in a +* deactivated state. +* +* \param[in] hRemoteDevice Peer handle obtained during device discovery process. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_PENDING Activation operation is in progress, + pLink_Cb will be called upon completion. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +* \retval NFCSTATUS_BUSY Previous request in progress can not accept new request. +*/ +extern NFCSTATUS phLibNfc_Llcp_Activate( phLibNfc_Handle hRemoteDevice ); + + +/** +* \ingroup grp_lib_nfc +* \brief Deactivate a previously activated LLCP link with a remote device. +* +* This function launches the link deactivation process on a remote LLCP-compliant peer. The link status +* notification will be sent by the corresponding callback given in the phLibNfc_Llcp_CheckLlcp function. +* +* \param[in] hRemoteDevice Peer handle obtained during device discovery process. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_PENDING Deactivation operation is in progress, + pLink_Cb will be called upon completion. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +* \retval NFCSTATUS_BUSY Previous request in progress can not accept new request. +*/ +extern NFCSTATUS phLibNfc_Llcp_Deactivate( phLibNfc_Handle hRemoteDevice ); + + +/** +* \ingroup grp_lib_nfc +* \brief Get information on the local LLCP peer. +* +* This function returns the LLCP link parameters of the local peer that were used +* during the link activation. +* +* \param[in] hRemoteDevice Peer handle obtained during device discovery process. +* \param[out] pConfigInfo Pointer on the variable to be filled with the configuration + parameters used during activation. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +* \retval NFCSTATUS_BUSY Previous request in progress can not accept new request. +*/ +extern NFCSTATUS phLibNfc_Llcp_GetLocalInfo( phLibNfc_Handle hRemoteDevice, + phLibNfc_Llcp_sLinkParameters_t* pConfigInfo + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Get information on the remote LLCP peer. +* +* This function returns the LLCP link parameters of the remote peer that were received +* during the link activation. +* +* \param[in] hRemoteDevice Peer handle obtained during device discovery process. +* \param[out] pConfigInfo Pointer on the variable to be filled with the configuration + parameters used during activation. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +* \retval NFCSTATUS_BUSY Previous request in progress can not accept new request. +*/ +extern NFCSTATUS phLibNfc_Llcp_GetRemoteInfo( phLibNfc_Handle hRemoteDevice, + phLibNfc_Llcp_sLinkParameters_t* pConfigInfo + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Create a socket on a LLCP-connected device. +* +* This function creates a socket for a given LLCP link. Sockets can be of two types : +* connection-oriented and connectionless. If the socket is connection-oriented, the caller +* must provide a working buffer to the socket in order to handle incoming data. This buffer +* must be large enough to fit the receive window (RW * MIU), the remaining space being +* used as a linear buffer to store incoming data as a stream. Data will be readable later +* using the phLibNfc_Llcp_Recv function. If the socket is connectionless, the caller may +* provide a working buffer to the socket in order to bufferize as many packets as the buffer +* can contain (each packet needs MIU + 1 bytes). +* The options and working buffer are not required if the socket is used as a listening socket, +* since it cannot be directly used for communication. +* +* \param[in] eType The socket type. +* \param[in] psOptions The options to be used with the socket. +* \param[in] psWorkingBuffer A working buffer to be used by the library. +* \param[out] phSocket A pointer on the variable to be filled with the handle +* on the created socket. +* \param[in] pErr_Cb The callback to be called each time the socket +* is in error. +* \param[in] pContext Upper layer context to be returned in the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_BUFFER_TOO_SMALL The working buffer is too small for the MIU and RW +* declared in the options. +* \retval NFCSTATUS_INSUFFICIENT_RESOURCES No more socket handle available. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_Socket( phLibNfc_Llcp_eSocketType_t eType, + phLibNfc_Llcp_sSocketOptions_t* psOptions, + phNfc_sData_t* psWorkingBuffer, + phLibNfc_Handle* phSocket, + pphLibNfc_LlcpSocketErrCb_t pErr_Cb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Get SAP of remote services using their names. +* +* This function sends SDP queries to the remote peer to get the SAP to address for a given +* service name. The queries are aggregated as much as possible for efficiency, but if all +* the queries cannot fit in a single packet, they will be splitted in multiple packets. +* The callback will be called only when all of the requested services names SAP will be +* gathered. As mentionned in LLCP specification, a SAP of 0 means that the service name +* as not been found. +* +* This feature is available only since LLCP v1.1, both devices must be at least v1.1 in +* order to be able to use this function. +* +* \param[in] hRemoteDevice Peer handle obtained during device discovery process. +* \param[in] psServiceNameList The list of the service names to discover. +* \param[out] pnSapList The list of the corresponding SAP numbers, in the same +* order than the service names list. +* \param[in] nListSize The size of both service names and SAP list. +* \param[in] pDiscover_Cb The callback to be called once LibNfc matched SAP for +* all of the provided service names. +* \param[in] pContext Upper layer context to be returned in the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +* \retval NFCSTATUS_FEATURE_NOT_SUPPORTED Remote peer does not support this feature (e.g.: is v1.0). +* \retval NFCSTATUS_BUSY Previous request in progress can not accept new request. +*/ +extern NFCSTATUS phLibNfc_Llcp_DiscoverServices( phLibNfc_Handle hRemoteDevice, + phNfc_sData_t *psServiceNameList, + uint8_t *pnSapList, + uint8_t nListSize, + pphLibNfc_RspCb_t pDiscover_Cb, + void *pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Close a socket on a LLCP-connected device. +* +* This function closes a LLCP socket previously created using phLibNfc_Llcp_Socket. +* If the socket was connected, it is first disconnected, and then closed. +* +* \param[in] hSocket Socket handle obtained during socket creation. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_Close( phLibNfc_Handle hSocket ); + + +/** +* \ingroup grp_lib_nfc +* \brief Get the local options of a socket. +* +* This function returns the local options (maximum packet size and receive window size) used +* for a given connection-oriented socket. This function shall not be used with connectionless +* sockets. +* +* \param[in] hSocket Socket handle obtained during socket creation. +* \param[in] psLocalOptions A pointer to be filled with the local options of the socket. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_SocketGetLocalOptions( phLibNfc_Handle hSocket, + phLibNfc_Llcp_sSocketOptions_t* psLocalOptions + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Get the local options of a socket. +* +* This function returns the remote options (maximum packet size and receive window size) used +* for a given connection-oriented socket. This function shall not be used with connectionless +* sockets. +* +* \param[in] hSocket Socket handle obtained during socket creation. +* \param[in] psRemoteOptions A pointer to be filled with the remote options of the socket. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_SocketGetRemoteOptions( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + phLibNfc_Llcp_sSocketOptions_t* psRemoteOptions + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Bind a socket to a local SAP. +* +* This function binds the socket to a local Service Access Point. +* +* \param[in] hSocket Peer handle obtained during device discovery process. +* \param TODO (nSap + sn) + +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_ALREADY_REGISTERED The selected SAP is already bound to another + socket. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_Bind( phLibNfc_Handle hSocket, + uint8_t nSap, + phNfc_sData_t * psServiceName + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Listen for incoming connection requests on a socket. +* +* This function switches a socket into a listening state and registers a callback on +* incoming connection requests. In this state, the socket is not able to communicate +* directly. The listening state is only available for connection-oriented sockets +* which are still not connected. The socket keeps listening until it is closed, and +* thus can trigger several times the pListen_Cb callback. The caller can adverise the +* service through SDP by providing a service name. +* +* +* \param[in] hSocket Socket handle obtained during socket creation. +* \param[in] pListen_Cb The callback to be called each time the +* socket receive a connection request. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state to switch +* to listening state. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_Listen( phLibNfc_Handle hSocket, + pphLibNfc_LlcpSocketListenCb_t pListen_Cb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Accept an incoming connection request for a socket. +* +* This functions allows the client to accept an incoming connection request. +* It must be used with the socket provided within the listen callback. The socket +* is implicitly switched to the connected state when the function is called. +* +* \param[in] hSocket Socket handle obtained in the listening callback. +* \param[in] psOptions The options to be used with the socket. +* \param[in] psWorkingBuffer A working buffer to be used by the library. +* \param[in] pErr_Cb The callback to be called each time the accepted socket +* is in error. +* \param[in] pAccept_RspCb The callback to be called when the Accept operation +* is completed. +* \param[in] pContext Upper layer context to be returned in the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_BUFFER_TOO_SMALL The working buffer is too small for the MIU and RW +* declared in the options. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_Accept( phLibNfc_Handle hSocket, + phLibNfc_Llcp_sSocketOptions_t* psOptions, + phNfc_sData_t* psWorkingBuffer, + pphLibNfc_LlcpSocketErrCb_t pErr_Cb, + pphLibNfc_LlcpSocketAcceptCb_t pAccept_RspCb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Reject an incoming connection request for a socket. +* +* This functions allows the client to reject an incoming connection request. +* It must be used with the socket provided within the listen callback. The socket +* is implicitly closed when the function is called. +* +* \param[in] hSocket Socket handle obtained in the listening callback. +* \param[in] pReject_RspCb The callback to be called when the Reject operation +* is completed. +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_Reject( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + pphLibNfc_LlcpSocketAcceptCb_t pReject_RspCb, + void* pContext); + + +/** +* \ingroup grp_lib_nfc +* \brief Try to establish connection with a socket on a remote SAP. +* +* This function tries to connect to a given SAP on the remote peer. If the +* socket is not bound to a local SAP, it is implicitly bound to a free SAP. +* +* \param[in] hSocket Socket handle obtained during socket creation. +* \param[in] nSap The destination SAP to connect to. +* \param[in] pConnect_RspCb The callback to be called when the connection +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Connection operation is in progress, +* pConnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_Connect( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + uint8_t nSap, + pphLibNfc_LlcpSocketConnectCb_t pConnect_RspCb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Try to establish connection with a socket on a remote service, given its URI. +* +* This function tries to connect to a SAP designated by an URI. If the +* socket is not bound to a local SAP, it is implicitly bound to a free SAP. +* +* \param[in] hSocket Socket handle obtained during socket creation. +* \param[in] psUri The URI corresponding to the destination SAP to connect to. +* \param[in] pConnect_RspCb The callback to be called when the connection +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Connection operation is in progress, +* pConnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_ConnectByUri( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + phNfc_sData_t* psUri, + pphLibNfc_LlcpSocketConnectCb_t pConnect_RspCb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Disconnect a currently connected socket. +* +* This function initiates the disconnection of a previously connected socket. +* +* \param[in] hSocket Socket handle obtained during socket creation. +* \param[in] pDisconnect_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Disconnection operation is in progress, +* pDisconnect_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_Disconnect( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + pphLibNfc_LlcpSocketDisconnectCb_t pDisconnect_RspCb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Read data on a socket. +* +* This function is used to read data from a socket. It reads at most the +* size of the reception buffer, but can also return less bytes if less bytes +* are available. If no data is available, the function will be pending until +* more data comes, and the response will be sent by the callback. This function +* can only be called on a connection-oriented socket. +* +* +* \param[in] hSocket Socket handle obtained during socket creation. +* \param[in] psBuffer The buffer receiving the data. +* \param[in] pRecv_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pRecv_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_Recv( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + phNfc_sData_t* psBuffer, + pphLibNfc_LlcpSocketRecvCb_t pRecv_RspCb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Read data on a socket and get the source SAP. +* +* This function is the same as phLibNfc_Llcp_Recv, except that the callback includes +* the source SAP. This functions can only be called on a connectionless socket. +* +* +* \param[in] hSocket Socket handle obtained during socket creation. +* \param[in] psBuffer The buffer receiving the data. +* \param[in] pRecv_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pRecv_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_RecvFrom( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + phNfc_sData_t* psBuffer, + pphLibNfc_LlcpSocketRecvFromCb_t pRecv_Cb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Send data on a socket. +* +* This function is used to write data on a socket. This function +* can only be called on a connection-oriented socket which is already +* in a connected state. +* +* +* \param[in] hSocket Socket handle obtained during socket creation. +* \param[in] psBuffer The buffer containing the data to send. +* \param[in] pSend_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pSend_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_Send( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + phNfc_sData_t* psBuffer, + pphLibNfc_LlcpSocketSendCb_t pSend_RspCb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* \brief Send data on a socket to a given destination SAP. +* +* This function is used to write data on a socket to a given destination SAP. +* This function can only be called on a connectionless socket. +* +* +* \param[in] hSocket Socket handle obtained during socket creation. +* \param[in] nSap The destination SAP. +* \param[in] psBuffer The buffer containing the data to send. +* \param[in] pSend_RspCb The callback to be called when the +* operation is completed. +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_PENDING Reception operation is in progress, +* pSend_RspCb will be called upon completion. +* \retval NFCSTATUS_INVALID_STATE The socket is not in a valid state, or not of +* a valid type to perform the requsted operation. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +* \retval NFCSTATUS_FAILED Operation failed. +*/ +extern NFCSTATUS phLibNfc_Llcp_SendTo( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + uint8_t nSap, + phNfc_sData_t* psBuffer, + pphLibNfc_LlcpSocketSendCb_t pSend_RspCb, + void* pContext + ); + + +/** +* \ingroup grp_lib_nfc +* +* \brief Initializes \ DeInitialize the NFC library for testmode. +* +* +*\brief This function initializes / DeInitialize NFC library and its underlying layers +* in test mode. As part of this interface underlying layers gets configured. +* Once phLibNfc_TstMode_On is successful ,NFC library ready in testmode using IOCTL. +* After using test IOCTLs ,Test mode should be DeInit using phLibNfc_TstMode_Off. +*\note This API should be used only for test IOCTL codes. +* +* \param[in] pDriverHandle Driver Handle currently application is using. +* \param[in] pTestModeCb The init callback is called by the LibNfc when +* Configure test mode completed or there is an error +* in initialization. +* +* \param[in] pContext Client context which will be included in +* callback when the request is completed. +* +* \retval NFCSTATUS_ALREADY_INITIALISED Stack is already initialized. +* \retval NFCSTATUS_PENDING Init sequence has been successfully +* started and result will be conveyed via +* callback notification. +* \retval NFCSTATUS_INVALID_PARAMETER The parameter could not be properly +* interpreted. +*\retval NFCSTATUS_INSUFFICIENT_RESOURCES Insufficient resource.(Ex: insufficient memory) +* +*\msc +*LibNfcClient,LibNfc; +*--- [label="Before initializing Nfc LIB,Setup Driver layer"]; +*LibNfcClient=>LibNfc [label="phLibNfc_Mgt_ConfigureDriver()",URL="\ref phLibNfc_Mgt_ConfigureDriver"]; +*LibNfcClient<LibNfc [label="phLibNfc_Mgt_ConfigureTestMode()",URL="\ref phLibNfc_Mgt_ConfigureTestMode"]; +*LibNfcClient<Interface to LibNfc Reset. +* +* LibNfc client can reset the stack. +* +* \param[in] pContext Upper layer context to be returned in +* the callback. +* +* +* \retval NFCSTATUS_SUCCESS Indicates Get stack Capabilities operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters +* could not be properly interpreted. +* \retval NFCSTATUS_NOT_INITIALISED Indicates stack is not yet initialized. +* \retval NFCSTATUS_SHUTDOWN Shutdown in progress. +*/ + +NFCSTATUS phLibNfc_Mgt_Reset(void *pContext); + +#endif /* PHLIBNFC_H */ + diff --git a/libnfc-nxp/phLibNfcStatus.h b/libnfc-nxp/phLibNfcStatus.h new file mode 100644 index 0000000..c4deb8f --- /dev/null +++ b/libnfc-nxp/phLibNfcStatus.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phLibNfcStatus.h + * \brief NFC Status Values - Function Return Codes + * + * Project: NFC MW / HAL + * + * $Date: Thu Feb 25 19:16:41 2010 $ + * $Author: ing07385 $ + * $Revision: 1.24 $ + * $Aliases: NFC_FRI1.1_WK1008_SDK,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1007_SDK,NFC_FRI1.1_WK1014_SDK,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1024_SDK $ + * + */ +#ifndef PHLIBNFCSTATUS_H /* */ +#define PHLIBNFCSTATUS_H/* */ + +#include + +#define LLCP_CHANGES +#define LLCP_TRANSACT_CHANGES + +#ifdef LLCP_TRANSACT_CHANGES +/* These two macros are defined due to non availibity of the below macros in header files +#define PHFRINFC_LLCP_STATE_RESET_INIT 0 // \internal Initial state +#define PHFRINFC_LLCP_STATE_CHECKED 1 // \internal The tag has been checked for LLCP compliance +*/ +#define LLCP_STATE_RESET_INIT 0x00U +#define LLCP_STATE_CHECKED 0x01U + + +#endif /* #ifdef LLCP_TRANSACT_CHANGES */ +#define LIB_NFC_VERSION_SET(v,major,minor,patch,build) ((v) = \ + ( ((major) << 24) & 0xFF000000 ) | \ + ( ((minor) << 16) & 0x00FF0000 ) | \ + ( ((patch) << 8) & 0x0000FF00 ) | \ + ( (build) & 0x000000FF ) ) + +#define NFCSTATUS_SHUTDOWN (0x0091) +#define NFCSTATUS_TARGET_LOST (0x0092) +#define NFCSTATUS_REJECTED (0x0093) +#define NFCSTATUS_TARGET_NOT_CONNECTED (0x0094) +#define NFCSTATUS_INVALID_HANDLE (0x0095) +#define NFCSTATUS_ABORTED (0x0096) +#define NFCSTATUS_COMMAND_NOT_SUPPORTED (0x0097) +#define NFCSTATUS_NON_NDEF_COMPLIANT (0x0098) +#define NFCSTATUS_OK (0x0000) + +#ifndef NFCSTATUS_NOT_ENOUGH_MEMORY +#define NFCSTATUS_NOT_ENOUGH_MEMORY (0x001F) +#endif + + +#endif /* PHNFCSTATUS_H */ + + + diff --git a/libnfc-nxp/phLibNfc_Internal.h b/libnfc-nxp/phLibNfc_Internal.h new file mode 100644 index 0000000..368c6c9 --- /dev/null +++ b/libnfc-nxp/phLibNfc_Internal.h @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phLibNfc_Internal.h + * + * Project: NFC-FRI 1.1 + * + * $Workfile:: phLibNfc_Internal.h $ + * $Modtime:: $ + * $Author: ing07385 $ + * $Revision: 1.26 $ + * + */ +#ifndef PHLIBNFC_IN_H +#define PHLIBNFC_IN_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/**Maximum number of Records.Presently set to a realistic value of 128 + Configurable upto 1K*/ +#define MAX_NO_OF_RECORDS 128U +#define CHK_NDEF_NOT_DONE 0x02U + +typedef struct phLibNfc_status +{ + unsigned RlsCb_status : 1; + unsigned DiscEnbl_status : 1; + unsigned Connect_status : 1; + unsigned TransProg_status : 1; + unsigned RelsProg_status : 1; + unsigned GenCb_pending_status : 1; + unsigned Shutdown_pending_status : 1; + unsigned Discovery_pending_status : 1; + +}Status_t; +typedef enum phLibNfc_State{ + eLibNfcHalStateShutdown = 0x00, /**< closed*/ + eLibNfcHalInitInProgress, + eLibNfcHalInited, + eLibNfcHalShutdownInProgress, + eLibNfcHalStateInitandIdle, + eLibNfcHalStateConfigReady , + eLibNfcHalStateConnect, + eLibNfcHalStateTransaction, + eLibNfcHalStatePresenceChk, + eLibNfcHalStateRelease, + eLibNfcHalStateInvalid +} phLibNfc_State_t; + + + + +typedef struct phLibNfc_Hal_CB_Info +{ + /*Init call back & its context*/ + pphLibNfc_RspCb_t pClientInitCb; + void *pClientInitCntx; + /*Shutdown call back & its context*/ + pphLibNfc_RspCb_t pClientShutdownCb; + void *pClientShtdwnCntx; + /*Connect call back & its context*/ + pphLibNfc_ConnectCallback_t pClientConnectCb; + void *pClientConCntx; + /*DisConnect call back & its context*/ + pphLibNfc_DisconnectCallback_t pClientDisConnectCb; + void *pClientDConCntx; + + /*Transceive Call back & it's context*/ + pphLibNfc_TransceiveCallback_t pClientTransceiveCb; + void *pClientTranseCntx; + /*Check Ndef Call back & it's context*/ + pphLibNfc_ChkNdefRspCb_t pClientCkNdefCb; + void *pClientCkNdefCntx; + /*Read Ndef Call back & it's context*/ + pphLibNfc_RspCb_t pClientRdNdefCb; + void *pClientRdNdefCntx; + /*Write Ndef Call back & it's context*/ + pphLibNfc_RspCb_t pClientWrNdefCb; + void *pClientWrNdefCntx; + + + /*Discover Call back & it's context*/ + pphLibNfc_RspCb_t pClientDisConfigCb; + void *pClientDisCfgCntx; + + /*Presence check Call back & it's context*/ + pphLibNfc_RspCb_t pClientPresChkCb; + void *pClientPresChkCntx; + + /*Register notification Call back & it's context*/ + phLibNfc_NtfRegister_RspCb_t pClientNtfRegRespCB; + void *pClientNtfRegRespCntx; + + /*Ndef Notification CB*/ + pphLibNfc_Ndef_Search_RspCb_t pClientNdefNtfRespCb; + void *pClientNdefNtfRespCntx; + + /*LLCP Check CB*/ + pphLibNfc_ChkLlcpRspCb_t pClientLlcpCheckRespCb; + void *pClientLlcpCheckRespCntx; + + /*LLCP Link CB*/ + pphLibNfc_LlcpLinkStatusCb_t pClientLlcpLinkCb; + void *pClientLlcpLinkCntx; + + /*LLCP service discovery*/ + pphLibNfc_RspCb_t pClientLlcpDiscoveryCb; + void *pClientLlcpDiscoveryCntx; + +}phLibNfc_Hal_CB_Info_t; + +typedef struct phLibNfc_NdefInfo +{ + bool_t NdefContinueRead; + uint32_t NdefActualSize, + AppWrLength; + phFriNfc_NdefMap_t *psNdefMap; + uint16_t NdefSendRecvLen; + uint16_t NdefDataCount; + phNfc_sData_t *psUpperNdefMsg; + uint32_t NdefReadTimerId, + NdefLength; + uint8_t is_ndef ; + phFriNfc_sNdefSmtCrdFmt_t *ndef_fmt ; + phLibNfc_Last_Call_t eLast_Call; + uint32_t Chk_Ndef_Timer_Id; + + + /*Format Ndef Call back & it's context*/ + pphLibNfc_RspCb_t pClientNdefFmtCb; + void *pClientNdefFmtCntx; + phLibNfc_Ndef_SrchType_t *pNdef_NtfSrch_Type; + +}phLibNfc_NdefInfo_t; + +typedef struct phLibNfc_NdefRecInfo +{ + phFriNfc_NdefReg_CbParam_t CbParam; + phFriNfc_NdefReg_t NdefReg; + uint8_t *NdefTypes_array[100]; + phFriNfc_NdefRecord_t RecordsExtracted; + uint8_t ChunkedRecordsarray[MAX_NO_OF_RECORDS]; + uint32_t NumberOfRecords; + uint8_t IsChunked[MAX_NO_OF_RECORDS]; + uint32_t NumberOfRawRecords; + uint8_t *RawRecords[MAX_NO_OF_RECORDS]; + phFriNfc_NdefReg_Cb_t *NdefCb; + phNfc_sData_t ndef_message; +}phLibNfc_NdefRecInfo_t; + +typedef struct phLibNfc_LlcpInfo +{ + /* Local parameters for LLC, given upon config + * and used upon detection. + */ + phLibNfc_Llcp_sLinkParameters_t sLocalParams; + + /* LLCP compliance flag */ + bool_t bIsLlcp; + + /* Monitor structure for LLCP Transport */ + phFriNfc_LlcpTransport_t sLlcpTransportContext; + + /* Monitor structure for LLCP LLC */ + phFriNfc_Llcp_t sLlcpContext; + + /* LLC Rx buffer */ + uint8_t pRxBuffer[PHFRINFC_LLCP_PDU_HEADER_MAX + PHFRINFC_LLCP_MIU_DEFAULT + PHFRINFC_LLCP_MIUX_MAX]; + + /* LLC Tx buffer */ + uint8_t pTxBuffer[PHFRINFC_LLCP_PDU_HEADER_MAX + PHFRINFC_LLCP_MIU_DEFAULT + PHFRINFC_LLCP_MIUX_MAX]; + +} phLibNfc_LlcpInfo_t; + +typedef struct phLibNfc_LibContext +{ + phHal_sHwReference_t *psHwReference; + Status_t status; + phHal_sEmulationCfg_t sCardEmulCfg; + phLibNfc_SeCtxt_t sSeContext; + phNfc_sState_t LibNfcState; + + phHal_sDevInputParam_t *psDevInputParam; + + phLibNfc_NdefInfo_t ndef_cntx; + phLibNfc_NfcIpInfo_t sNfcIp_Context; + + phFriNfc_OvrHal_t *psOverHalCtxt; + phLibNfc_Registry_Info_t RegNtfType; + uint8_t dev_cnt; + + /*To re configure the discovery wheel*/ + phLibNfc_sADD_Cfg_t sADDconfig; + uintptr_t Connected_handle, + Discov_handle[MAX_REMOTE_DEVICES]; + + /* To store the previous connected handle in case of Multiple protocol tags */ + uintptr_t Prev_Connected_handle; + + /*Call back function pointers */ + + phLibNfc_eDiscoveryConfigMode_t eLibNfcCfgMode; + + phHal4Nfc_DiscoveryInfo_t *psDiscInfo; + + phLibNfc_eReleaseType_t ReleaseType; + /**Transaction Related Info */ + phLibNfc_sTransceiveInfo_t *psTransInfo; + phLibNfc_sTransceiveInfo_t *psBufferedAuth; + uint8_t LastTrancvSuccess; + phLibNfc_RemoteDevList_t psRemoteDevList[MAX_REMOTE_DEVICES]; + /*To Call back function pointers & Client context*/ + phLibNfc_Hal_CB_Info_t CBInfo; + + /*Ndef RTD search Info*/ + phLibNfc_NdefRecInfo_t phLib_NdefRecCntx; + + /*LLCP Info*/ + phLibNfc_LlcpInfo_t llcp_cntx; + + /* Pointer to Lib context */ +} phLibNfc_LibContext_t,*pphLibNfc_LibContext_t; + +extern void phLibNfc_Pending_Shutdown(void); +extern pphLibNfc_LibContext_t gpphLibContext; +extern NFCSTATUS +phLibNfc_UpdateNextState( + pphLibNfc_LibContext_t psNfcHalCtxt, + phLibNfc_State_t next_state + ); + +extern void +phLibNfc_UpdateCurState( + NFCSTATUS status, + pphLibNfc_LibContext_t psNfcHalCtxt + ); + +extern void +phLibNfc_Reconnect_Mifare_Cb ( + void *pContext, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + NFCSTATUS status); + + +#endif + + diff --git a/libnfc-nxp/phLibNfc_Ioctl.c b/libnfc-nxp/phLibNfc_Ioctl.c new file mode 100644 index 0000000..08f34b5 --- /dev/null +++ b/libnfc-nxp/phLibNfc_Ioctl.c @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phLibNfc_Ioctl.c + + * Project: NFC FRI 1.1 + * + * $Date: Mon Mar 1 19:07:05 2010 $ + * $Author: ing07385 $ + * $Revision: 1.35 $ + * $Aliases: NFC_FRI1.1_WK1008_SDK,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1007_SDK,NFC_FRI1.1_WK1014_SDK,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1024_SDK $ + * + */ + +/* +************************* Header Files **************************************** +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +*************************** Macro's **************************************** +*/ + +#ifndef STATIC_DISABLE +#define STATIC static +#else +#define STATIC +#endif + +/* +*************************** Global Variables ********************************** +*/ + +STATIC phLibNfc_Ioctl_Cntx_t phLibNfc_Ioctl_Cntx; + +/* +*************************** Static Function Declaration *********************** +*/ + + +/* Response callback for Ioctl management */ +STATIC void phLibNfc_Ioctl_Mgmt_CB(void *context, + phNfc_sData_t *pOutData, + NFCSTATUS status ); + + +/** Response callback for UICC switch mode*/ +STATIC void phLibNfc_Switch_Swp_Mode_CB( + void *context, + NFCSTATUS status + ); + +/* +*************************** Function Definitions ****************************** +*/ + +/** +* The I/O Control function allows the caller to configure specific +* functionality provided by the lower layer.Each feature is accessible +* via a specific IOCTL Code. +*/ +NFCSTATUS phLibNfc_Mgt_IoCtl (void* pDalHandle, + uint16_t IoctlCode, + phNfc_sData_t* pInParam, + phNfc_sData_t* pOutParam, + pphLibNfc_IoctlCallback_t pIoCtl_Rsp_cb, + void* pContext + ) +{ + NFCSTATUS StatusCode=NFCSTATUS_INVALID_PARAMETER; + + + if((IoctlCode==0)||(NULL==pIoCtl_Rsp_cb) || + (NULL==pContext) ||(NULL==pInParam) || + (NULL==pDalHandle)) + { + StatusCode=NFCSTATUS_INVALID_PARAMETER; + return StatusCode; + } + if(IoctlCode!= NFC_FW_DOWNLOAD) + { + if(pOutParam == NULL) + { + StatusCode = NFCSTATUS_INVALID_PARAMETER; + return StatusCode; + } + if(( gpphLibContext == NULL) || + (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) + { + StatusCode = NFCSTATUS_NOT_INITIALISED; + return StatusCode; + } + else + { + if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + StatusCode = NFCSTATUS_SHUTDOWN; + return StatusCode; + } + } + } + phLibNfc_Ioctl_Cntx.CliRspCb =pIoCtl_Rsp_cb; + phLibNfc_Ioctl_Cntx.pCliCntx = pContext; + phLibNfc_Ioctl_Cntx.pOutParam = pOutParam; + phLibNfc_Ioctl_Cntx.IoctlCode = IoctlCode; + /* Process the IOCTL requests */ + switch(IoctlCode) + { + case NFC_FW_DOWNLOAD: + {/* Set power status */ + phLibNfc_Ioctl_Cntx.psHwReference = phOsalNfc_GetMemory((uint32_t)sizeof(phHal_sHwReference_t)); + if(phLibNfc_Ioctl_Cntx.psHwReference == NULL) + return NFCSTATUS_FAILED; + (void)memset(phLibNfc_Ioctl_Cntx.psHwReference,0,sizeof(phHal_sHwReference_t)); + phLibNfc_Ioctl_Cntx.psHwReference->p_board_driver = pDalHandle; + + StatusCode = phHal4Nfc_Ioctl( phLibNfc_Ioctl_Cntx.psHwReference, + NFC_FW_DOWNLOAD, + pInParam, + pOutParam, + phLibNfc_Ioctl_Mgmt_CB, + &phLibNfc_Ioctl_Cntx ); + }break; + case NFC_MEM_READ: + { + StatusCode = phHal4Nfc_Ioctl(gpphLibContext->psHwReference, + NFC_MEM_READ, + pInParam, + pOutParam, + phLibNfc_Ioctl_Mgmt_CB, + &phLibNfc_Ioctl_Cntx ); + + }break; + case NFC_MEM_WRITE: + { + + StatusCode = phHal4Nfc_Ioctl( gpphLibContext->psHwReference, + NFC_MEM_WRITE, + pInParam, + pOutParam, + phLibNfc_Ioctl_Mgmt_CB, + &phLibNfc_Ioctl_Cntx ); + + }break; + case PHLIBNFC_ANTENNA_TEST: + { + + StatusCode = phHal4Nfc_Ioctl( gpphLibContext->psHwReference, + PHLIBNFC_ANTENNA_TEST, + pInParam, + pOutParam, + phLibNfc_Ioctl_Mgmt_CB, + &phLibNfc_Ioctl_Cntx ); + + }break; + case PHLIBNFC_SWP_TEST: + { + + StatusCode = phHal4Nfc_Ioctl( gpphLibContext->psHwReference, + PHLIBNFC_SWP_TEST, + pInParam, + pOutParam, + phLibNfc_Ioctl_Mgmt_CB, + &phLibNfc_Ioctl_Cntx ); + + }break; + + case PHLIBNFC_PRBS_TEST: + { + StatusCode = phHal4Nfc_Ioctl( gpphLibContext->psHwReference, + PHLIBNFC_PRBS_TEST, + pInParam, + pOutParam, + phLibNfc_Ioctl_Mgmt_CB, + &phLibNfc_Ioctl_Cntx ); + + + }break; + case PHLIBNFC_SWITCH_SWP_MODE: + { + StatusCode = phHal4Nfc_Switch_Swp_Mode( gpphLibContext->psHwReference, + (phHal_eSWP_Mode_t)pInParam->buffer[0], + phLibNfc_Switch_Swp_Mode_CB, + &phLibNfc_Ioctl_Cntx + ); + + + }break; + default : + { + /* don't do any thing*/ + }break; + + } /* End of IOCTL switch */ + if(StatusCode!=NFCSTATUS_PENDING) + { + StatusCode = NFCSTATUS_FAILED; + } + else + { + if(IoctlCode!= NFC_FW_DOWNLOAD) + { + gpphLibContext->status.GenCb_pending_status=TRUE; + } + } + return StatusCode; + +} /* End of IOCTL handler function */ + + + +STATIC void phLibNfc_Ioctl_Mgmt_CB(void *context, + phNfc_sData_t *pOutData, + NFCSTATUS status ) +{ + phLibNfc_Ioctl_Cntx_t *pIoctlCntx=NULL; + if(PHNFCSTATUS(status) == NFCSTATUS_FEATURE_NOT_SUPPORTED) + { + status = NFCSTATUS_FEATURE_NOT_SUPPORTED; + } + else if(PHNFCSTATUS(status)!=NFCSTATUS_SUCCESS) + { + status = NFCSTATUS_FAILED; + } + if(gpphLibContext!= NULL) + { + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { + /*If shutdown called in between allow shutdown to happen*/ + phLibNfc_Pending_Shutdown(); + status = NFCSTATUS_SHUTDOWN; + } + } + pIoctlCntx= (phLibNfc_Ioctl_Cntx_t*)context; + if( pIoctlCntx !=NULL) + { + switch(pIoctlCntx->IoctlCode) + { + case NFC_FW_DOWNLOAD: + { + /*Release the hardware reference memory*/ + phOsalNfc_FreeMemory(pIoctlCntx->psHwReference); + }break; + case NFC_MEM_READ: + { + + }break; + case NFC_MEM_WRITE: + { + + }break; + + case PHLIBNFC_ANTENNA_TEST: + { + + }break; + case PHLIBNFC_SWP_TEST: + { + + }break; + case PHLIBNFC_PRBS_TEST: + { + + }break; + default: + { + } + } + pIoctlCntx->CliRspCb(pIoctlCntx->pCliCntx,pOutData,status); + if(gpphLibContext!= NULL) + { + gpphLibContext->status.GenCb_pending_status=FALSE; + } + } +} + +STATIC void phLibNfc_Switch_Swp_Mode_CB( + void *context, + NFCSTATUS status + ) +{ + if(PHNFCSTATUS(status)!=NFCSTATUS_SUCCESS) + { + status = NFCSTATUS_FAILED; + } + if(gpphLibContext!= NULL) + { + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { + /*If shutdown called in between allow shutdown to happen*/ + phLibNfc_Pending_Shutdown(); + status = NFCSTATUS_SHUTDOWN; + } + } + if((NULL != context)&&(context == (void *)&phLibNfc_Ioctl_Cntx)) + { + if(NULL != phLibNfc_Ioctl_Cntx.CliRspCb) + { + (*phLibNfc_Ioctl_Cntx.CliRspCb)( + phLibNfc_Ioctl_Cntx.pCliCntx, + phLibNfc_Ioctl_Cntx.pOutParam, + status + ); + } + } + return; +} + diff --git a/libnfc-nxp/phLibNfc_SE.c b/libnfc-nxp/phLibNfc_SE.c new file mode 100644 index 0000000..841cf2a --- /dev/null +++ b/libnfc-nxp/phLibNfc_SE.c @@ -0,0 +1,757 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phLibNfc_SE.c + + * Project: NFC FRI / HALDL + * + * $Date: Thu Apr 22 13:59:50 2010 $ + * $Author: ing07385 $ + * $Revision: 1.65 $ + * $Aliases: NFC_FRI1.1_WK1014_SDK,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1024_SDK $ + * + */ + +/* +************************* Header Files *************************************** +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +*************************** Macro's **************************************** +*/ + +#ifndef STATIC_DISABLE +#define STATIC static +#else +#define STATIC +#endif + +/* +*************************** Global Variables ********************************** +*/ + +/*This Structure contains the Secure Element information*/ +phLibNfc_SE_List_t sSecuredElementInfo[PHLIBNFC_MAXNO_OF_SE]; + +/* +*************************** Static Function Declaration *********************** +*/ + +/* Response callback for SE Set Mode*/ +STATIC +void phLibNfc_SE_SetMode_cb(void *context, NFCSTATUS status); + + +/* SE register listner response notification */ +STATIC +void phLibNfc_SeNotification(void *context, + phHal_eNotificationType_t type, + phHal4Nfc_NotificationInfo_t info, + NFCSTATUS status + ); +/* +*************************** Function Definitions ****************************** +*/ + +/** +* Registers notification handler to handle secure element specific events +*/ +NFCSTATUS phLibNfc_SE_NtfRegister ( + pphLibNfc_SE_NotificationCb_t pSE_NotificationCb, + void *pContext + ) +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + pphLibNfc_LibContext_t pLibContext=(pphLibNfc_LibContext_t)gpphLibContext; + + if((NULL == gpphLibContext) || + (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) + { + Status = NFCSTATUS_NOT_INITIALISED; + } + else if((pSE_NotificationCb == NULL) + ||(NULL == pContext)) + { + /*parameters sent by upper layer are not valid*/ + Status = NFCSTATUS_INVALID_PARAMETER; + } + else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + Status = NFCSTATUS_SHUTDOWN; + } + else + { + /*Register SE notification with lower layer. + Any activity on Smx or UICC will be notified */ + Status = phHal4Nfc_RegisterNotification( + pLibContext->psHwReference, + eRegisterSecureElement, + phLibNfc_SeNotification, + (void*)pLibContext); + if(Status == NFCSTATUS_SUCCESS) + { + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb = pSE_NotificationCb; + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt=pContext; + } + else + { + /* Registration failed */ + Status = NFCSTATUS_FAILED; + } + } + return Status; +} +/** +* SE Notification events are notified with this callback +*/ +STATIC void phLibNfc_SeNotification(void *context, + phHal_eNotificationType_t type, + phHal4Nfc_NotificationInfo_t info, + NFCSTATUS status) +{ + pphLibNfc_LibContext_t pLibContext=(pphLibNfc_LibContext_t)context; + phHal_sEventInfo_t *pEvtInfo = NULL; + phLibNfc_uSeEvtInfo_t Se_Trans_Info={{{0,0},{0,0}}}; + phLibNfc_SE_List_t *pSeInfo=NULL; + + if(pLibContext != gpphLibContext) + { + /*wrong context returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + if((status == NFCSTATUS_SUCCESS) && (type == NFC_EVENT_NOTIFICATION)) + { + pEvtInfo = info.psEventInfo; + status = NFCSTATUS_SUCCESS; + if((pEvtInfo->eventSource == phHal_ePICC_DevType ) + && (pEvtInfo->eventHost == phHal_eHostController) ) + { + sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].eSE_Type = phLibNfc_SE_Type_SmartMX; + /* Smartx Mx is Activated */ + pSeInfo = &sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX]; + } + if(pEvtInfo->eventHost == phHal_eUICCHost) + { + /* UICC is Activate */ + sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].eSE_Type = phLibNfc_SE_Type_UICC; + pSeInfo = &sSecuredElementInfo[LIBNFC_SE_UICC_INDEX]; + } + else + { + /*presently Smx event source is not supported */ + } + if(pSeInfo!=NULL) + { + switch(pEvtInfo->eventType) + { + case NFC_EVT_TRANSACTION: + { + if((pEvtInfo->eventInfo.aid.length != 0) && ((pEvtInfo->eventInfo.aid.length <= 16))) // PLG + { + /*copy the Application id on which transaction happened*/ + Se_Trans_Info.UiccEvtInfo.aid.buffer =pEvtInfo->eventInfo.aid.buffer; + Se_Trans_Info.UiccEvtInfo.aid.length =pEvtInfo->eventInfo.aid.length; + } + else + { + // PLG patch + Se_Trans_Info.UiccEvtInfo.aid.buffer = NULL; + Se_Trans_Info.UiccEvtInfo.aid.length = 0; + } + if((pEvtInfo->eventHost == phHal_eUICCHost) + && (info.psEventInfo->eventInfo.uicc_info.param.length + != 0)) + { + /*copy the parameters info on which transaction happened*/ + Se_Trans_Info.UiccEvtInfo.param.buffer = + info.psEventInfo->eventInfo.uicc_info.param.buffer; + Se_Trans_Info.UiccEvtInfo.param.length = + info.psEventInfo->eventInfo.uicc_info.param.length; + } + /*Notify to upper layer that transaction had happened on the + one of the application stored in UICC or Smx*/ + (*pLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb)( + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt, + phLibNfc_eSE_EvtStartTransaction, + pSeInfo->hSecureElement, + &Se_Trans_Info, + status); + break; + } + + case NFC_EVT_APDU_RECEIVED: + { + if ((pEvtInfo->eventInfo.aid.length != 0) && ((pEvtInfo->eventInfo.aid.length <= 16))) + { + /* Copy received APDU to aid buffer. */ + Se_Trans_Info.UiccEvtInfo.aid.buffer = pEvtInfo->eventInfo.aid.buffer; + Se_Trans_Info.UiccEvtInfo.aid.length = pEvtInfo->eventInfo.aid.length; + } + + (*pLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb)( + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt, + phLibNfc_eSE_EvtApduReceived, + pSeInfo->hSecureElement, + &Se_Trans_Info, + status); + break; + } + + case NFC_EVT_MIFARE_ACCESS: + { + /* copy the Block MIFARE accessed */ + Se_Trans_Info.UiccEvtInfo.aid.buffer = pEvtInfo->eventInfo.aid.buffer; + Se_Trans_Info.UiccEvtInfo.aid.length = pEvtInfo->eventInfo.aid.length; + + (*pLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb)( + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt, + phLibNfc_eSE_EvtMifareAccess, + pSeInfo->hSecureElement, + &Se_Trans_Info, + status); + break; + } + + case NFC_EVT_EMV_CARD_REMOVAL: + { + (*pLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb)( + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt, + phLibNfc_eSE_EvtCardRemoval, + pSeInfo->hSecureElement, + &Se_Trans_Info, + status); + break; + } + + case NFC_EVT_END_OF_TRANSACTION: + { + (*pLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb)( + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt, + phLibNfc_eSE_EvtEndTransaction, + pSeInfo->hSecureElement, + &Se_Trans_Info, + status); + break; + } + case NFC_EVT_CONNECTIVITY: + { + (*pLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb)( + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt, + phLibNfc_eSE_EvtConnectivity, + pSeInfo->hSecureElement, + &Se_Trans_Info, + status); + break; + } + case NFC_EVT_START_OF_TRANSACTION: + { + (*pLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb)( + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt, + phLibNfc_eSE_EvtTypeTransaction, + pSeInfo->hSecureElement, + &Se_Trans_Info, + status); + break; + } + case NFC_EVT_FIELD_ON: + { + (*pLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb)( + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt, + phLibNfc_eSE_EvtFieldOn, + pSeInfo->hSecureElement, + &Se_Trans_Info, + status); + break; + } + case NFC_EVT_FIELD_OFF: + { + (*pLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb)( + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt, + phLibNfc_eSE_EvtFieldOff, + pSeInfo->hSecureElement, + &Se_Trans_Info, + status); + break; + } + default: + { + break; + } + } + } + else + { + + } + } + } + return; +} + +/** + * Unregister the Secured Element Notification. + */ +NFCSTATUS phLibNfc_SE_NtfUnregister(void) +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + pphLibNfc_LibContext_t pLibContext=(pphLibNfc_LibContext_t)gpphLibContext; + + if((NULL == gpphLibContext) || + (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) + { + /*Lib Nfc is not initialized*/ + Status = NFCSTATUS_NOT_INITIALISED; + } + else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + Status = NFCSTATUS_SHUTDOWN; + } + else + { + /*Unregister SE event notification with lower layer. + even some transaction happens on UICC or Smx will not + be notified afterworlds */ + Status = phHal4Nfc_UnregisterNotification( + pLibContext->psHwReference, + eRegisterSecureElement, + pLibContext); + if(Status != NFCSTATUS_SUCCESS) + { + /*Unregister failed*/ + Status=NFCSTATUS_FAILED; + } + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerNtfCb=NULL; + pLibContext->sSeContext.sSeCallabackInfo.pSeListenerCtxt=NULL; + } + return Status; +} + +/** +* Get list of available Secure Elements +*/ +NFCSTATUS phLibNfc_SE_GetSecureElementList( + phLibNfc_SE_List_t* pSE_List, + uint8_t* uSE_count + ) +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + uint8_t uNo_Of_SE = 0; + + if((NULL == gpphLibContext) || + (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) + { + Status = NFCSTATUS_NOT_INITIALISED; + } + else if((NULL ==pSE_List) || (NULL ==uSE_count)) + { + Status = NFCSTATUS_INVALID_PARAMETER; + } + else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + Status = NFCSTATUS_SHUTDOWN; + } + else + { + /*Check for which type of Secure Element is available*/ + if(gpphLibContext->psHwReference->uicc_connected==TRUE) + { + /* Populate the UICC type */ + sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].eSE_Type = phLibNfc_SE_Type_UICC; + + /* Populate the UICC handle */ + sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].hSecureElement =(phLibNfc_Handle) + (LIBNFC_SE_UICC_INDEX + LIBNFC_SE_BASE_HANDLE); + +#ifdef NXP_HAL_ENABLE_SMX + + pSE_List[LIBNFC_SE_UICC_INDEX].eSE_Type = + sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].eSE_Type; + pSE_List[LIBNFC_SE_UICC_INDEX].hSecureElement = (phLibNfc_Handle) + (LIBNFC_SE_UICC_INDEX + LIBNFC_SE_BASE_HANDLE); + pSE_List[LIBNFC_SE_UICC_INDEX].eSE_CurrentState = + sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].eSE_CurrentState; +#else + pSE_List->eSE_Type = + sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].eSE_Type; + pSE_List->hSecureElement = (phLibNfc_Handle) + (LIBNFC_SE_UICC_INDEX + LIBNFC_SE_BASE_HANDLE); + pSE_List->eSE_CurrentState = + sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].eSE_CurrentState; +#endif + /* update the No of SE retrieved */ + uNo_Of_SE ++; + + } + if (gpphLibContext->psHwReference->smx_connected ==TRUE) + { + /* if the Smx is also connected to the PN544 */ + /* Populate the SMX type */ + sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].eSE_Type = phLibNfc_SE_Type_SmartMX; + + /* Populate the SMX handle */ + sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].hSecureElement =(phLibNfc_Handle) + (LIBNFC_SE_SMARTMX_INDEX + LIBNFC_SE_BASE_HANDLE); + pSE_List[LIBNFC_SE_SMARTMX_INDEX].eSE_Type = + sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].eSE_Type; + pSE_List[LIBNFC_SE_SMARTMX_INDEX].hSecureElement = (phLibNfc_Handle) + (LIBNFC_SE_SMARTMX_INDEX + LIBNFC_SE_BASE_HANDLE); + pSE_List[LIBNFC_SE_SMARTMX_INDEX].eSE_CurrentState = + sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].eSE_CurrentState; + + /* update the No of SE retrieved */ + uNo_Of_SE ++; + + } + *uSE_count = uNo_Of_SE; + } + return Status; +} + +/** +* Sets secure element mode. +* This function configures SE to specific mode based on activation mode type +*/ + +NFCSTATUS phLibNfc_SE_SetMode ( phLibNfc_Handle hSE_Handle, + phLibNfc_eSE_ActivationMode eActivation_mode, + pphLibNfc_SE_SetModeRspCb_t pSE_SetMode_Rsp_cb, + void * pContext + ) +{ + NFCSTATUS Status = NFCSTATUS_SUCCESS; + phHal_eEmulationType_t eEmulationType = NFC_SMARTMX_EMULATION; + pphLibNfc_LibContext_t pLibContext=(pphLibNfc_LibContext_t)gpphLibContext; + + if((NULL == gpphLibContext) || + (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) + { + Status = NFCSTATUS_NOT_INITIALISED; + } + else if((pSE_SetMode_Rsp_cb ==NULL) + ||(NULL == pContext)||(NULL==(void *)hSE_Handle)) + { + Status=NFCSTATUS_INVALID_PARAMETER; + } + else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + Status = NFCSTATUS_SHUTDOWN; + } + else if((pLibContext->status.GenCb_pending_status == TRUE) + ||(NULL!=pLibContext->sSeContext.sSeCallabackInfo.pSEsetModeCb)) + { + /*previous callback is pending still*/ + Status =NFCSTATUS_REJECTED; + } + else + { + phLibNfc_eSE_ActivationMode originalMode = pLibContext->sSeContext.eActivatedMode; + switch(eActivation_mode) + { + case phLibNfc_SE_ActModeVirtual: + { + if(hSE_Handle == sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].hSecureElement) + { + eEmulationType = NFC_UICC_EMULATION; + /*Enable the UICC -External reader can see it*/ + pLibContext->sCardEmulCfg.config.uiccEmuCfg.enableUicc = TRUE; + } + else if(hSE_Handle == sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].hSecureElement) + { + eEmulationType = NFC_SMARTMX_EMULATION; + /*Enable the SMX -External reader can see it*/ + pLibContext->sCardEmulCfg.config.smartMxCfg.enableEmulation = TRUE; + } + else + { + Status=NFCSTATUS_INVALID_HANDLE; + } + if(Status==NFCSTATUS_SUCCESS) + { + if(pLibContext->sSeContext.eActivatedMode != phLibNfc_SE_ActModeWired) + { + pLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeVirtual; + } + pLibContext->sCardEmulCfg.emuType = eEmulationType; + Status = phHal4Nfc_ConfigParameters( + pLibContext->psHwReference, + NFC_EMULATION_CONFIG, + (phHal_uConfig_t*)&pLibContext->sCardEmulCfg, + phLibNfc_SE_SetMode_cb, + pLibContext); + } + } + break; + case phLibNfc_SE_ActModeVirtualVolatile: + { + if(hSE_Handle == sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].hSecureElement) + { + eEmulationType = NFC_SMARTMX_EMULATION; + /*Enable the SMX -External reader can see it*/ + pLibContext->sCardEmulCfg.config.smartMxCfg.enableEmulation = TRUE; + pLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeVirtualVolatile; + + Status = phHal4Nfc_Switch_SMX_Mode( + pLibContext->psHwReference, + eSmartMx_Virtual, + phLibNfc_SE_SetMode_cb, + pLibContext + ); + } + else if(hSE_Handle == sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].hSecureElement) + { + eEmulationType = NFC_UICC_EMULATION; + /*Enable the UICC -External reader can see it*/ + pLibContext->sCardEmulCfg.config.uiccEmuCfg.enableUicc = TRUE; + pLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeVirtualVolatile; + + Status = phHal4Nfc_Switch_Swp_Mode( + pLibContext->psHwReference, + eSWP_Switch_On, + phLibNfc_SE_SetMode_cb, + pLibContext + ); + } + else + { + Status = NFCSTATUS_INVALID_HANDLE; + } + } + break; + case phLibNfc_SE_ActModeDefault: + { + if(hSE_Handle == sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].hSecureElement) + { + Status = phHal4Nfc_Switch_SMX_Mode( + pLibContext->psHwReference, + eSmartMx_Default, + phLibNfc_SE_SetMode_cb, + pLibContext + ); + } + else if(hSE_Handle == sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].hSecureElement) + { + Status = phHal4Nfc_Switch_Swp_Mode( + pLibContext->psHwReference, + eSWP_Switch_Default, + phLibNfc_SE_SetMode_cb, + pLibContext + ); + } + else + { + Status = NFCSTATUS_INVALID_HANDLE; + } + } + break; + + case phLibNfc_SE_ActModeWired: + { + if(hSE_Handle == sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].hSecureElement) + { + if(pLibContext->CBInfo.pClientNtfRegRespCB!=NULL) + { + /*Disable the SMX -External reader can't see it anymore*/ + pLibContext->sCardEmulCfg.config.smartMxCfg.enableEmulation = FALSE; + pLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeWired; + + Status = phHal4Nfc_Switch_SMX_Mode( + pLibContext->psHwReference, + eSmartMx_Wired, + phLibNfc_SE_SetMode_cb, + pLibContext + ); + } + } + else if(hSE_Handle == sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].hSecureElement) + { + /*This mode is not applicable to UICC*/ + Status = NFCSTATUS_REJECTED; + } + else + { + Status = NFCSTATUS_INVALID_HANDLE; + } + } + break; + + case phLibNfc_SE_ActModeOff: + { + /*UICC emulation deactivate*/ + if(hSE_Handle == sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].hSecureElement) + { + eEmulationType = NFC_UICC_EMULATION; + /*Disable the UICC -External reader can't see it anymore*/ + pLibContext->sCardEmulCfg.config.uiccEmuCfg.enableUicc = FALSE; + + } + else if(hSE_Handle == sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].hSecureElement) + { + eEmulationType = NFC_SMARTMX_EMULATION; + /*Disable the SMX -External reader can't see it anymore*/ + pLibContext->sCardEmulCfg.config.smartMxCfg.enableEmulation=FALSE; + + } + else + { + Status = NFCSTATUS_INVALID_HANDLE; + } + if(Status==NFCSTATUS_SUCCESS) + { + pLibContext->sCardEmulCfg.emuType = eEmulationType; + + if(pLibContext->sSeContext.eActivatedMode != phLibNfc_SE_ActModeWired) + { + pLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeOff; + } + + Status = phHal4Nfc_ConfigParameters(pLibContext->psHwReference, + NFC_EMULATION_CONFIG, + (phHal_uConfig_t*)&pLibContext->sCardEmulCfg, + phLibNfc_SE_SetMode_cb, + pLibContext); + } + } + break; + default: + Status=NFCSTATUS_INVALID_PARAMETER; + break; + + }/*End of eActivation_mode switch */ + if(Status==NFCSTATUS_PENDING) + { + pLibContext->sSeContext.hSetemp=hSE_Handle; + pLibContext->status.GenCb_pending_status = TRUE; + pLibContext->sSeContext.sSeCallabackInfo.pSEsetModeCb = pSE_SetMode_Rsp_cb; + pLibContext->sSeContext.sSeCallabackInfo.pSEsetModeCtxt=pContext; + } + else if(Status != NFCSTATUS_INVALID_HANDLE) + { + // Restore original mode + pLibContext->sSeContext.eActivatedMode = originalMode; + Status = NFCSTATUS_FAILED; + } + } + return Status; +} +/** +* Callback for Se Set mode +*/ +STATIC void phLibNfc_SE_SetMode_cb(void *context, NFCSTATUS status) +{ + /* Note that we don't use the passed in context here; + * the reason is that there are race-conditions around + * the place where this context is stored (mostly in combination + * with LLCP), and we may actually get the wrong context. + * Since this callback always uses the global context + * we don't need the passed in context anyway. + */ + pphLibNfc_LibContext_t pLibContext=gpphLibContext; + pphLibNfc_SE_SetModeRspCb_t pUpperLayerCb=NULL; + void *pUpperContext=NULL; + phLibNfc_Handle hSeHandle=0; + uint8_t TempState=FALSE; + + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { + /*If shutdown is called in between allow shutdown to happen*/ + phLibNfc_Pending_Shutdown(); + status = NFCSTATUS_SHUTDOWN; + } + else + { + if(status == NFCSTATUS_SUCCESS) + { + hSeHandle = pLibContext->sSeContext.hSetemp; + + if(hSeHandle == sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].hSecureElement) + { + if(TRUE==pLibContext->sCardEmulCfg.config.uiccEmuCfg.enableUicc) + { + /*If Activation mode was virtual allow external reader to see it*/ + pLibContext->sSeContext.uUiccActivate = TRUE; + sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].eSE_CurrentState = phLibNfc_SE_Active; + } + else + { + /*If Activation mode was wired don't allow external reader to see it*/ + pLibContext->sSeContext.uUiccActivate = FALSE; + sSecuredElementInfo[LIBNFC_SE_UICC_INDEX].eSE_CurrentState = + phLibNfc_SE_Inactive; + } + status = NFCSTATUS_SUCCESS; + TempState = pLibContext->sSeContext.uUiccActivate; + } + else if (hSeHandle==sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].hSecureElement) + { + if(TRUE==pLibContext->sCardEmulCfg.config.smartMxCfg.enableEmulation) + { + /*If Activation mode was virtual allow external reader to see it*/ + pLibContext->sSeContext.uSmxActivate = TRUE; + sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].eSE_CurrentState = + phLibNfc_SE_Active; + } + else + { + /*If Activation mode was wired don't allow external reader to see it*/ + pLibContext->sSeContext.uSmxActivate = FALSE; + sSecuredElementInfo[LIBNFC_SE_SMARTMX_INDEX].eSE_CurrentState= + phLibNfc_SE_Inactive; + } + status = NFCSTATUS_SUCCESS; + TempState = pLibContext->sSeContext.uSmxActivate; + } + else + { + status = NFCSTATUS_FAILED; + } + } + else + { + status = NFCSTATUS_FAILED; + } + pLibContext->status.GenCb_pending_status = FALSE; + } + + pUpperLayerCb = pLibContext->sSeContext.sSeCallabackInfo.pSEsetModeCb; + pUpperContext = pLibContext->sSeContext.sSeCallabackInfo.pSEsetModeCtxt; + pLibContext->sSeContext.sSeCallabackInfo.pSEsetModeCb = NULL; + pLibContext->sSeContext.sSeCallabackInfo.pSEsetModeCtxt = NULL; + PHNFC_UNUSED_VARIABLE(TempState); + /* Call the upper layer cb */ + if(pUpperLayerCb!= NULL ) + { + (*pUpperLayerCb)(pUpperContext, + hSeHandle, + status); + } + return; +} + + + diff --git a/libnfc-nxp/phLibNfc_SE.h b/libnfc-nxp/phLibNfc_SE.h new file mode 100644 index 0000000..99e3ffe --- /dev/null +++ b/libnfc-nxp/phLibNfc_SE.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phLibNfc_SE.h + * + * Project: NFC-FRI 1.1 + * + * $Workfile:: phLibNfc_1.1.h $ + * $Modtime:: $ + * $Author: ing07299 $ + * $Revision: 1.14 $ + * + */ +#ifndef PHLIBNFC_SE_H +#define PHLIBNFC_SE_H + +#define LIBNFC_SE_INVALID_HANDLE 0 +#define LIBNFC_SE_SUPPORTED 2 +#define LIBNFC_SE_BASE_HANDLE 0xABCDEF + +#define LIBNFC_SE_SMARTMX_INDEX 0 +#define LIBNFC_SE_UICC_INDEX 1 + +#define PAUSE_PHASE 0x0824 /*Indicates the Pause phase duration*/ +#define EMULATION_PHASE 0x5161 /*Indicates the Emulation phase duration*/ + +typedef struct phLibNfc_SeCallbackInfo +{ + /* SE set mode callback and its context */ + pphLibNfc_SE_SetModeRspCb_t pSEsetModeCb; + void *pSEsetModeCtxt; + /* Store SE discovery notification callback and its context */ + pphLibNfc_SE_NotificationCb_t pSeListenerNtfCb; + void *pSeListenerCtxt; + +}phLibNfc_SECallbackInfo_t; + +/*SE State */ +typedef enum { + phLibNfc_eSeInvalid = 0x00, + phLibNfc_eSeInit, + phLibNfc_eSeReady, + phLibNfc_eSeVirtual, + phLibNfc_eSeWired +}phLibNfc_SeState_t; + + +/* Context for secured element */ +typedef struct phLibNfc_SeCtxt +{ + + /* UICC Status in Virtual Mode */ + uint8_t uUiccActivate; + + /* SMX Status in Virtual Mode */ + uint8_t uSmxActivate; + + /* Count of the Secure Elements Present */ + uint8_t uSeCount; + + /* Se Temp handle */ + phLibNfc_Handle hSetemp; + + /*Current SE state*/ + phLibNfc_SeState_t eSE_State; + + /*Current SE Mode */ + + phLibNfc_eSE_ActivationMode eActivatedMode; + + /* SE callback information */ + phLibNfc_SECallbackInfo_t sSeCallabackInfo; + +}phLibNfc_SeCtxt_t; + +extern phLibNfc_SE_List_t sSecuredElementInfo[PHLIBNFC_MAXNO_OF_SE]; + + + +#endif + + diff --git a/libnfc-nxp/phLibNfc_discovery.c b/libnfc-nxp/phLibNfc_discovery.c new file mode 100644 index 0000000..c512f73 --- /dev/null +++ b/libnfc-nxp/phLibNfc_discovery.c @@ -0,0 +1,375 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phLibNfc_discovery.c + + * Project: NFC FRI 1.1 + * + * $Date: Mon Mar 1 19:02:41 2010 $ + * $Author: ing07385 $ + * $Revision: 1.36 $ + * $Aliases: NFC_FRI1.1_WK1008_SDK,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1007_SDK,NFC_FRI1.1_WK1014_SDK,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1024_SDK $ + * + */ + +/* +************************* Header Files **************************************** +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* +*************************** Macro's **************************************** +*/ + +#ifndef STATIC_DISABLE +#define STATIC static +#else +#define STATIC +#endif + +/* +*************************** Global Variables ********************************** +*/ + + + +/* +*************************** Static Function Declaration *********************** +*/ + + +/*Remote device Presence check callback*/ +STATIC void phLibNfc_RemoteDev_CheckPresence_Cb(void *context, + NFCSTATUS status); + +/**Used for presence chk incase of mifare std tags*/ +STATIC void phLibNfc_ChkPresence_Trcv_Cb( + void *context, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phNfc_sData_t *response, + NFCSTATUS status + ); + +/* +*************************** Function Definitions ****************************** +*/ +void phLibNfc_config_discovery_cb(void *context, + NFCSTATUS status) +{ + + if((phLibNfc_LibContext_t *)context == gpphLibContext) + { /*check for same context*/ + + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { + /*If shutdown called in between allow shutdown to happen*/ + phLibNfc_Pending_Shutdown(); + status = NFCSTATUS_SHUTDOWN; + } + else + { + gpphLibContext->status.GenCb_pending_status = FALSE; + gpphLibContext->status.DiscEnbl_status = FALSE; + phLibNfc_UpdateCurState(status,gpphLibContext); +#ifdef RESTART_CFG + if(gpphLibContext->status.Discovery_pending_status == TRUE) + { + NFCSTATUS RetStatus = NFCSTATUS_FAILED; + /* Application has called discovery before receiving this callback, + so NO notification to the upper layer, instead lower layer + discovery is called */ + gpphLibContext->status.Discovery_pending_status = FALSE; + RetStatus = phHal4Nfc_ConfigureDiscovery( + gpphLibContext->psHwReference, + gpphLibContext->eLibNfcCfgMode, + &gpphLibContext->sADDconfig, + (pphLibNfc_RspCb_t) + phLibNfc_config_discovery_cb, + (void *)gpphLibContext); + if (NFCSTATUS_PENDING == RetStatus) + { + (void)phLibNfc_UpdateNextState(gpphLibContext, + eLibNfcHalStateConfigReady); + gpphLibContext->status.GenCb_pending_status = TRUE; + gpphLibContext->status.DiscEnbl_status = TRUE; + } + else + { + status = NFCSTATUS_FAILED; + } + } +#endif /* #ifdef RESTART_CFG */ + } + } /*End of if-context check*/ + else + { /*exception: wrong context pointer returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + status = NFCSTATUS_FAILED; + } + if(gpphLibContext->CBInfo.pClientDisConfigCb!=NULL) + { + gpphLibContext->CBInfo.pClientDisConfigCb(gpphLibContext->CBInfo.pClientDisCfgCntx,status); + gpphLibContext->CBInfo.pClientDisConfigCb=NULL; + } + return; +} +/** +* Configure Discovery Modes. +* This function is used to configure ,start and stop the discovery wheel. +*/ +NFCSTATUS phLibNfc_Mgt_ConfigureDiscovery ( + phLibNfc_eDiscoveryConfigMode_t DiscoveryMode, + phLibNfc_sADD_Cfg_t sADDSetup, + pphLibNfc_RspCb_t pConfigDiscovery_RspCb, + void* pContext + ) + { + NFCSTATUS RetVal = NFCSTATUS_FAILED; + phHal_sADD_Cfg_t *psADDConfig; + psADDConfig = (phHal_sADD_Cfg_t *)&(sADDSetup); + + + if((NULL == gpphLibContext) || + (gpphLibContext->LibNfcState.cur_state + == eLibNfcHalStateShutdown)) + { + /*Lib Nfc not initialized*/ + RetVal = NFCSTATUS_NOT_INITIALISED; + } + /* Check for Valid parameters*/ + else if((NULL == pContext) || (NULL == pConfigDiscovery_RspCb)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + else if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + RetVal= NFCSTATUS_SHUTDOWN; + } + else + { + gpphLibContext->eLibNfcCfgMode =DiscoveryMode; + gpphLibContext->sADDconfig = sADDSetup; + if(gpphLibContext->status.DiscEnbl_status != TRUE) + { + + /* call lower layer config API for the discovery + configuration sent by the application */ + RetVal = phHal4Nfc_ConfigureDiscovery ( gpphLibContext->psHwReference, + DiscoveryMode, + psADDConfig, + (pphLibNfc_RspCb_t) + phLibNfc_config_discovery_cb, + (void*)gpphLibContext); + if(PHNFCSTATUS(RetVal) == NFCSTATUS_PENDING) + { + gpphLibContext->status.DiscEnbl_status = TRUE; + /* Copy discovery callback and its context */ + gpphLibContext->CBInfo.pClientDisConfigCb = pConfigDiscovery_RspCb; + gpphLibContext->CBInfo.pClientDisCfgCntx = pContext; + gpphLibContext->status.GenCb_pending_status = TRUE; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateConfigReady; + } + else + { + if (PHNFCSTATUS(RetVal) == NFCSTATUS_BUSY) + { + RetVal = NFCSTATUS_BUSY; + } + else + { + RetVal=NFCSTATUS_FAILED; + } + } + + } + else + { + RetVal=NFCSTATUS_BUSY; + } + } + return RetVal; + } + +/** +* Check for target presence. +* Checks given target is present in RF filed or not +*/ +NFCSTATUS phLibNfc_RemoteDev_CheckPresence( phLibNfc_Handle hTargetDev, + pphLibNfc_RspCb_t pPresenceChk_RspCb, + void* pRspCbCtx + ) +{ + NFCSTATUS RetVal = NFCSTATUS_FAILED; + phHal_sRemoteDevInformation_t *ps_rem_dev_info = NULL; + /* Check for valid sate */ + if((NULL == gpphLibContext) || + (gpphLibContext->LibNfcState.cur_state + == eLibNfcHalStateShutdown)) + { + RetVal = NFCSTATUS_NOT_INITIALISED; + } + /* Check for valid parameters*/ + else if((NULL == pRspCbCtx) || (NULL == pPresenceChk_RspCb) + || (hTargetDev == 0) ) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + /* Check for DeInit call*/ + else if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + RetVal = NFCSTATUS_SHUTDOWN; + } + /* Check target is connected or not */ + else if( gpphLibContext->Connected_handle == 0) + { + RetVal = NFCSTATUS_TARGET_NOT_CONNECTED; + } + /* Check given handle is valid or not*/ + else if(hTargetDev != gpphLibContext->Connected_handle) + { + RetVal = NFCSTATUS_INVALID_HANDLE; + } +#ifdef LLCP_TRANSACT_CHANGES + else if ((LLCP_STATE_RESET_INIT != gpphLibContext->llcp_cntx.sLlcpContext.state) + && (LLCP_STATE_CHECKED != gpphLibContext->llcp_cntx.sLlcpContext.state)) + { + RetVal= NFCSTATUS_BUSY; + } +#endif /* #ifdef LLCP_TRANSACT_CHANGES */ + else + { + ps_rem_dev_info = (phHal_sRemoteDevInformation_t *) + gpphLibContext->Connected_handle; + if((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType) + &&(0 != ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak) + &&(TRUE == gpphLibContext->LastTrancvSuccess)) + { + /* Call HAL4 API */ + RetVal = phHal4Nfc_Transceive( + gpphLibContext->psHwReference, + gpphLibContext->psBufferedAuth, + (phHal_sRemoteDevInformation_t *) + gpphLibContext->Connected_handle, + (pphHal4Nfc_TransceiveCallback_t ) + phLibNfc_ChkPresence_Trcv_Cb, + (void *)gpphLibContext + ); + + } + else + { + /* Call lower layer PresenceCheck function */ + RetVal = phHal4Nfc_PresenceCheck(gpphLibContext->psHwReference, + phLibNfc_RemoteDev_CheckPresence_Cb, + (void *)gpphLibContext); + } + if( NFCSTATUS_PENDING == PHNFCSTATUS(RetVal)) + { + gpphLibContext->CBInfo.pClientPresChkCb = pPresenceChk_RspCb; + gpphLibContext->CBInfo.pClientPresChkCntx = pRspCbCtx; + /* Mark General callback pending status as TRUE*/ + gpphLibContext->status.GenCb_pending_status = TRUE; + + /* Update the state machine*/ + gpphLibContext->LibNfcState.next_state = eLibNfcHalStatePresenceChk; + } + else /* If return value is internal error(other than pending ) return NFCSTATUS_FAILED*/ + { + RetVal = NFCSTATUS_FAILED; + } + } + return RetVal; +} + +/** +* Response Callback for Remote device Presence Check. +*/ +STATIC +void phLibNfc_RemoteDev_CheckPresence_Cb(void *context, + NFCSTATUS status) +{ + void *pUpperLayerContext=NULL; + pphLibNfc_RspCb_t pClientCb=NULL; + + /*check valid context is returned or not*/ + if((phLibNfc_LibContext_t *)context != gpphLibContext) + { + /*exception: wrong context pointer returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + /* Mark general callback pending status as FALSE*/ + gpphLibContext->status.GenCb_pending_status = FALSE; + pClientCb =gpphLibContext->CBInfo.pClientPresChkCb ; + pUpperLayerContext = gpphLibContext->CBInfo.pClientPresChkCntx; + gpphLibContext->CBInfo.pClientPresChkCntx = NULL; + gpphLibContext->CBInfo.pClientPresChkCb =NULL; + /* Check DeInit call is called, if yes call pending + shutdown and return NFCSTATUS_SHUTDOWN */ + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { + phLibNfc_Pending_Shutdown(); + status = NFCSTATUS_SHUTDOWN; + } + else + { + if (status != NFCSTATUS_SUCCESS) + { + /*If status is other than SUCCESS (Internal error) return + NFCSTATUS_TARGET_LOST */ + status= NFCSTATUS_TARGET_LOST; + } + else + { + status = NFCSTATUS_SUCCESS; + } + } + /* Update the current state */ + phLibNfc_UpdateCurState(status,gpphLibContext); + if(NULL != pClientCb) + { + /* call the upper layer callback */ + pClientCb(pUpperLayerContext,status); + } + return; +} + +/**Used for presence chk incase of mifare std tags*/ +STATIC void phLibNfc_ChkPresence_Trcv_Cb( + void *context, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + phNfc_sData_t *response, + NFCSTATUS status + ) +{ + PHNFC_UNUSED_VARIABLE(psRemoteDevInfo); + PHNFC_UNUSED_VARIABLE(response); + phLibNfc_RemoteDev_CheckPresence_Cb(context,status); + return; +} + + + diff --git a/libnfc-nxp/phLibNfc_discovery.h b/libnfc-nxp/phLibNfc_discovery.h new file mode 100644 index 0000000..a825413 --- /dev/null +++ b/libnfc-nxp/phLibNfc_discovery.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phLibNfc_1.1.h + * + * Project: NFC-FRI 1.1 + * + * $Workfile:: phLibNfc_1.1.h $ + * $Modtime:: $ + * $Author: ing07299 $ + * $Revision: 1.9 $ + * + */ +#ifndef PHLIBNFC_DISCOVERY_H +#define PHLIBNFC_DISCOVERY_H + + + +extern void +phLibNfc_config_discovery_cb(void *context, + NFCSTATUS status + ); + +#endif + diff --git a/libnfc-nxp/phLibNfc_initiator.c b/libnfc-nxp/phLibNfc_initiator.c new file mode 100644 index 0000000..b9796d2 --- /dev/null +++ b/libnfc-nxp/phLibNfc_initiator.c @@ -0,0 +1,1276 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phLibNfc_initiator.c + + * Project: NFC FRI 1.1 + * + * $Date: Fri Apr 23 14:34:08 2010 $ + * $Author: ing07385 $ + * $Revision: 1.53 $ + * $Aliases: NFC_FRI1.1_WK1014_SDK,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1024_SDK $ + * + */ + +/* +************************* Header Files **************************************** +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* +*************************** Macro's **************************************** +*/ + +#ifndef STATIC_DISABLE +#define STATIC static +#else +#define STATIC +#endif + +/* +*************************** Global Variables ********************************** +*/ + +#define PN544_IO_TIMEOUT_RESPONSE 0x89 + +/* +*************************** Static Function Declaration *********************** +*/ + +/* Target discvovery notification callback */ +STATIC void phLibNfc_NotificationRegister_Resp_Cb ( + void *context, + phHal_eNotificationType_t type, + phHal4Nfc_NotificationInfo_t info, + NFCSTATUS status + ); + +/*Remote device connect response callback*/ +STATIC void phLibNfc_RemoteDev_Connect_Cb( + void *pContext, + phHal_sRemoteDevInformation_t *pRmtdev_info, + NFCSTATUS status + ); + +/*Remote device disconnect response callback*/ +STATIC void phLibNfc_RemoteDev_Disconnect_cb( + void *context, + phHal_sRemoteDevInformation_t *reg_handle, + NFCSTATUS status + ); +/*Remote device Transceive response callback*/ +STATIC void phLibNfc_RemoteDev_Transceive_Cb(void *context, + phHal_sRemoteDevInformation_t *pRmtdev_info, + phNfc_sData_t *response, + NFCSTATUS status + ); +/*Set P2P config paramater response callback*/ +STATIC void phLibNfc_Mgt_SetP2P_ConfigParams_Cb( + void *context, + NFCSTATUS status + ); + + +/* +*************************** Function Definitions ****************************** +*/ + +/** +* Response to target discovery. +*/ +STATIC +void phLibNfc_NotificationRegister_Resp_Cb ( + void *context, + phHal_eNotificationType_t type, + phHal4Nfc_NotificationInfo_t info, + NFCSTATUS status + ) +{ + NFCSTATUS RetVal = NFCSTATUS_SUCCESS, + Status = NFCSTATUS_SUCCESS; + uint16_t DeviceIndx, DeviceIndx1; + uint8_t sak_byte=0; + uint8_t tag_disc_flg = 0; + phLibNfc_NtfRegister_RspCb_t pClientCb=NULL; + pClientCb =gpphLibContext->CBInfo.pClientNtfRegRespCB; + PHNFC_UNUSED_VARIABLE(context); + + + if(( type != NFC_DISCOVERY_NOTIFICATION ) + &&(PHNFCSTATUS(status)!=NFCSTATUS_DESELECTED)) + { + Status = NFCSTATUS_FAILED; + } + else if (PHNFCSTATUS(status) == NFCSTATUS_DESELECTED) + { + return; + } + else + { + DeviceIndx=0;DeviceIndx1=0; + while(DeviceIndx < info.psDiscoveryInfo->NumberOfDevices) + { + switch(info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx]->RemDevType) + { + case phHal_eMifare_PICC: + { + /*Mifare Tag discovered*/ + sak_byte = info.psDiscoveryInfo-> + ppRemoteDevInfo[DeviceIndx]->RemoteDevInfo.Iso14443A_Info.Sak; + if((TRUE == gpphLibContext->RegNtfType.MifareUL)&& (sak_byte==0x00)) + { + /*Copy the tag related info*/ + gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo= + info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx]; + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev = + (phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo; + gpphLibContext->Discov_handle[DeviceIndx1] = + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev; + DeviceIndx1++; + tag_disc_flg++; + } + + if((TRUE == gpphLibContext->RegNtfType.MifareStd)&& + (((sak_byte & 0x18)==0x08)||((sak_byte & 0x18)==0x18) || + (sak_byte == 0x01))) + { + /*Copy the tag related info*/ + gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo= + info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx]; + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev = + (phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo; + gpphLibContext->Discov_handle[DeviceIndx1]= + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev; + DeviceIndx1++; + tag_disc_flg++; + } + + }break; + case phHal_eISO14443_A_PICC: + { + /*ISO 14443-A type tag discovered*/ + if(TRUE == gpphLibContext->RegNtfType.ISO14443_4A) + { + /*Copy the ISO type A tag info*/ + gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo= + info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx]; + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev = + (phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo; + gpphLibContext->Discov_handle[DeviceIndx1] = + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev; + DeviceIndx1++; + tag_disc_flg++; + } + }break; + case phHal_eISO14443_3A_PICC: + { + /*ISO 14443-A type tag discovered*/ + if(TRUE == gpphLibContext->RegNtfType.MifareUL) + { + /*Copy the ISO type A tag info*/ + gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo= + info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx]; + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev = + (phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo; + gpphLibContext->Discov_handle[DeviceIndx1] = + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev; + DeviceIndx1++; + tag_disc_flg++; + } + }break; + case phHal_eISO14443_B_PICC: + { + /*ISO 14443-B type tag Discovered */ + if(TRUE == gpphLibContext->RegNtfType.ISO14443_4B) + { + /*Copy the Type B tag info */ + gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo= + info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx]; + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev = + (phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo; + gpphLibContext->Discov_handle[DeviceIndx1] = + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev; + DeviceIndx1++; + tag_disc_flg++; + } + }break; + case phHal_eFelica_PICC: + { + /*Felica Type Tag Discovered */ + if(TRUE == gpphLibContext->RegNtfType.Felica) + { + /*Copy the Felica tag info */ + gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo= + info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx]; + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev = + (phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo; + gpphLibContext->Discov_handle[DeviceIndx1] = + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev; + DeviceIndx1++; + tag_disc_flg++; + } + }break; + case phHal_eJewel_PICC: + { + /*Jewel Type Tag Discovered */ + if(TRUE == gpphLibContext->RegNtfType.Jewel) + { + /*Copy the Felica tag info */ + gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo= + info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx]; + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev = + (phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo; + gpphLibContext->Discov_handle[DeviceIndx1] = + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev; + DeviceIndx1++; + tag_disc_flg++; + } + } + break; + case phHal_eISO15693_PICC: + { + /*Jewel Type Tag Discovered */ + if(TRUE == gpphLibContext->RegNtfType.ISO15693) + { + /*Copy the Felica tag info */ + gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo= + info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx]; + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev = + (phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo; + gpphLibContext->Discov_handle[DeviceIndx1] = + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev; + DeviceIndx1++; + tag_disc_flg++; + } + } + break; + case phHal_eNfcIP1_Target: + { + if(TRUE == gpphLibContext->RegNtfType.NFC) + { + gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo= + info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx]; + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev = + (phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx].psRemoteDevInfo; + gpphLibContext->Discov_handle[DeviceIndx1] = + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev; + DeviceIndx1++; + tag_disc_flg++; + } + } + break; + case phHal_eNfcIP1_Initiator: + { + if(TRUE == gpphLibContext->RegNtfType.NFC) + { + gpphLibContext->LibNfcState.cur_state=eLibNfcHalStateConnect; + gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo= + info.psDiscoveryInfo->ppRemoteDevInfo[DeviceIndx]; + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev = + (phLibNfc_Handle)gpphLibContext->psRemoteDevList[DeviceIndx1].psRemoteDevInfo; + gpphLibContext->sNfcIp_Context.Rem_Initiator_Handle= + gpphLibContext->psRemoteDevList[DeviceIndx1].hTargetDev; + DeviceIndx1++; + tag_disc_flg++; + } + } + break; + default : + { + break; + } + } + DeviceIndx++; + } + } + + if((tag_disc_flg >0 )&&(status != NFCSTATUS_FAILED)) + { + gpphLibContext->dev_cnt = tag_disc_flg; + /* Check for if the discovered tags are multiple or + Multiple protocol tag */ + if ((gpphLibContext->dev_cnt <= 1) || + ((status != NFCSTATUS_MULTIPLE_PROTOCOLS) && + (status != NFCSTATUS_MULTIPLE_TAGS))) + { + status = NFCSTATUS_SUCCESS; + } + /*Notify to upper layer the no of tag discovered and + the protocol */ + if (NULL != pClientCb) + { + pClientCb( + (void*)gpphLibContext->CBInfo.pClientNtfRegRespCntx, + gpphLibContext->psRemoteDevList, + gpphLibContext->dev_cnt, + status + ); + } + + } + else if(PHNFCSTATUS(status)==NFCSTATUS_DESELECTED) + { + info.psDiscoveryInfo->NumberOfDevices = 0; + if (NULL != pClientCb) + { + gpphLibContext->LibNfcState.cur_state=eLibNfcHalStateRelease; + pClientCb((void*)gpphLibContext->CBInfo.pClientNtfRegRespCntx, + NULL, + 0, + status); + } + + } + else /*Reconfigure the discovery wheel*/ + { + RetVal = phHal4Nfc_ConfigureDiscovery ( gpphLibContext->psHwReference, + NFC_DISCOVERY_RESUME, + &(gpphLibContext->sADDconfig), + phLibNfc_config_discovery_cb, + gpphLibContext); + + if((RetVal!=NFCSTATUS_SUCCESS) &&(RetVal!=NFCSTATUS_PENDING)) + { + Status = NFCSTATUS_FAILED; + } + + } + if(Status == NFCSTATUS_FAILED) + { + if (NULL != pClientCb) + { + pClientCb(gpphLibContext->CBInfo.pClientNtfRegRespCntx, + NULL, + 0, + Status); + } + } + return; +} + +/** +* This interface registers notification handler for target discovery. +*/ +NFCSTATUS +phLibNfc_RemoteDev_NtfRegister( + phLibNfc_Registry_Info_t* pRegistryInfo, + phLibNfc_NtfRegister_RspCb_t pNotificationHandler, + void *pContext + ) +{ + NFCSTATUS RetVal = NFCSTATUS_SUCCESS; + + + /*Check for valid parameters*/ + if((NULL == pNotificationHandler) + || (NULL == pContext) + ||(NULL== pRegistryInfo)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + else if((NULL == gpphLibContext) || + (gpphLibContext->LibNfcState.cur_state + == eLibNfcHalStateShutdown)) + { + RetVal = NFCSTATUS_NOT_INITIALISED; + } + else if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + /*Next state is shutdown*/ + RetVal= NFCSTATUS_SHUTDOWN; + } + else + { + + PHDBG_INFO("LibNfc:Registering Notification Handler"); + + + (void) memcpy(&(gpphLibContext->RegNtfType),pRegistryInfo, + sizeof(phLibNfc_Registry_Info_t)); + /* Register Discovery Notification Handler*/ + + /*Register for NFCIP1 target type*/ + RetVal = phHal4Nfc_RegisterNotification( + gpphLibContext->psHwReference, + eRegisterP2PDiscovery, + phLibNfc_NotificationRegister_Resp_Cb, + (void*)gpphLibContext + ); + /*Register for Tag discovery*/ + RetVal = phHal4Nfc_RegisterNotification( + gpphLibContext->psHwReference, + eRegisterTagDiscovery, + phLibNfc_NotificationRegister_Resp_Cb, + (void*)gpphLibContext + ); + gpphLibContext->CBInfo.pClientNtfRegRespCB = pNotificationHandler; + gpphLibContext->CBInfo.pClientNtfRegRespCntx = pContext; + /*Register notification handler with below layer*/ + + } + return RetVal; +} +/** +* This interface unregisters notification handler for target discovery. +*/ +NFCSTATUS phLibNfc_RemoteDev_NtfUnregister(void) +{ + NFCSTATUS RetVal = NFCSTATUS_SUCCESS; + if((NULL == gpphLibContext) || + (gpphLibContext->LibNfcState.cur_state + == eLibNfcHalStateShutdown)) + { + /*Lib Nfc not Initialized*/ + RetVal = NFCSTATUS_NOT_INITIALISED; + } + else if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + /*Lib Nfc Shutdown*/ + RetVal= NFCSTATUS_SHUTDOWN; + } + else + { + /*Unregister notification handler with lower layer */ + RetVal = phHal4Nfc_UnregisterNotification( + gpphLibContext->psHwReference, + eRegisterP2PDiscovery, + gpphLibContext); + + RetVal = phHal4Nfc_UnregisterNotification( + gpphLibContext->psHwReference, + eRegisterTagDiscovery, + gpphLibContext); + + gpphLibContext->CBInfo.pClientNtfRegRespCB = NULL; + gpphLibContext->CBInfo.pClientNtfRegRespCntx =NULL; + PHDBG_INFO("LibNfc:Unregister Notification Handler"); + } + return RetVal; +} + +#ifdef RECONNECT_SUPPORT + +NFCSTATUS +phLibNfc_RemoteDev_ReConnect ( + phLibNfc_Handle hRemoteDevice, + pphLibNfc_ConnectCallback_t pNotifyReConnect_RspCb, + void *pContext) +{ + + NFCSTATUS ret_val = NFCSTATUS_FAILED; + phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo = NULL; + + if ((NULL == gpphLibContext) + || (eLibNfcHalStateShutdown == + gpphLibContext->LibNfcState.cur_state)) + { + ret_val = NFCSTATUS_NOT_INITIALISED; + } + else if ((NULL == pContext) + || (NULL == pNotifyReConnect_RspCb) + || (NULL == (void *)hRemoteDevice)) + { + /* Check valid parameters */ + ret_val = NFCSTATUS_INVALID_PARAMETER; + } + /* Check valid lib nfc State */ + else if (gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + ret_val = NFCSTATUS_SHUTDOWN; + } + else if (0 == gpphLibContext->Connected_handle) + { + ret_val = NFCSTATUS_TARGET_NOT_CONNECTED; + } + else if ((gpphLibContext->Discov_handle[0] != hRemoteDevice) + && (gpphLibContext->Discov_handle[1] != hRemoteDevice) + && (gpphLibContext->Discov_handle[2] != hRemoteDevice) + && (gpphLibContext->Discov_handle[3] != hRemoteDevice) + && (gpphLibContext->Discov_handle[4] != hRemoteDevice) + && (gpphLibContext->Discov_handle[5] != hRemoteDevice) + && (gpphLibContext->Discov_handle[6] != hRemoteDevice) + && (gpphLibContext->Discov_handle[7] != hRemoteDevice) + && (gpphLibContext->Discov_handle[8] != hRemoteDevice) + && (gpphLibContext->Discov_handle[9] != hRemoteDevice)) + { + ret_val = NFCSTATUS_INVALID_HANDLE; + } + else + { + psRemoteDevInfo = (phLibNfc_sRemoteDevInformation_t *)hRemoteDevice; + + /* Call the HAL connect*/ + ret_val = phHal4Nfc_Connect (gpphLibContext->psHwReference, + psRemoteDevInfo, + phLibNfc_RemoteDev_Connect_Cb, + (void *)gpphLibContext); + + if (NFCSTATUS_PENDING == ret_val) + { + /* If HAL Connect is pending update the LibNFC state machine + and store the CB pointer and Context, + mark the General CB pending status is TRUE */ + gpphLibContext->CBInfo.pClientConnectCb = pNotifyReConnect_RspCb; + gpphLibContext->CBInfo.pClientConCntx = pContext; + gpphLibContext->status.GenCb_pending_status = TRUE; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateConnect; + + gpphLibContext->Prev_Connected_handle = gpphLibContext->Connected_handle; + + gpphLibContext->Connected_handle = hRemoteDevice; + } + else if (NFCSTATUS_INVALID_REMOTE_DEVICE == PHNFCSTATUS(ret_val)) + { + /* The Handle given for connect is invalid*/ + ret_val = NFCSTATUS_TARGET_NOT_CONNECTED; + } + else + { + /* Lower layer returns internal error code return NFCSTATUS_FAILED*/ + ret_val = NFCSTATUS_FAILED; + } + } + + return ret_val; +} +#endif /* #ifdef RECONNECT_SUPPORT */ + + +/** +* Connect to a single Remote Device +*/ +NFCSTATUS phLibNfc_RemoteDev_Connect( + phLibNfc_Handle hRemoteDevice, + pphLibNfc_ConnectCallback_t pNotifyConnect_RspCb, + void *pContext + ) +{ + + NFCSTATUS RetVal = NFCSTATUS_FAILED; + phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo; + + if((NULL == gpphLibContext) || + (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) + { + RetVal = NFCSTATUS_NOT_INITIALISED; + }/* Check valid parameters*/ + else if((NULL == pContext) + || (NULL == pNotifyConnect_RspCb) + || (NULL == (void*)hRemoteDevice)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + /* Check valid lib nfc State*/ + else if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + RetVal= NFCSTATUS_SHUTDOWN; + } + else if((gpphLibContext->Discov_handle[0] != hRemoteDevice)&& + (gpphLibContext->Discov_handle[1] != hRemoteDevice)&& + (gpphLibContext->Discov_handle[2] != hRemoteDevice)&& + (gpphLibContext->Discov_handle[3] != hRemoteDevice)&& + (gpphLibContext->Discov_handle[4] != hRemoteDevice)&& + (gpphLibContext->Discov_handle[5] != hRemoteDevice)&& + (gpphLibContext->Discov_handle[6] != hRemoteDevice)&& + (gpphLibContext->Discov_handle[7] != hRemoteDevice)&& + (gpphLibContext->Discov_handle[8] != hRemoteDevice)&& + (gpphLibContext->Discov_handle[9] != hRemoteDevice)) + { + RetVal= NFCSTATUS_INVALID_HANDLE; + } + else if ((hRemoteDevice != gpphLibContext->Connected_handle) + && (0 != gpphLibContext->Connected_handle)) + { + RetVal = NFCSTATUS_FAILED; + } + else + { + psRemoteDevInfo = (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice; + + /* Call the HAL connect*/ + RetVal = phHal4Nfc_Connect(gpphLibContext->psHwReference, + psRemoteDevInfo, + phLibNfc_RemoteDev_Connect_Cb, + (void* )gpphLibContext); + if(RetVal== NFCSTATUS_PENDING) + { + /* If HAL Connect is pending update the LibNFC state machine + and store the CB pointer and Context, + mark the General CB pending status is TRUE*/ + gpphLibContext->CBInfo.pClientConnectCb = pNotifyConnect_RspCb; + gpphLibContext->CBInfo.pClientConCntx = pContext; + gpphLibContext->status.GenCb_pending_status=TRUE; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateConnect; + gpphLibContext->Prev_Connected_handle = gpphLibContext->Connected_handle; + gpphLibContext->Connected_handle = hRemoteDevice; + } + else if(PHNFCSTATUS(RetVal) == NFCSTATUS_INVALID_REMOTE_DEVICE) + { + /* The Handle given for connect is invalid*/ + RetVal= NFCSTATUS_TARGET_NOT_CONNECTED; + } + else + { + /* Lower layer returns internal error code return NFCSTATUS_FAILED*/ + RetVal = NFCSTATUS_FAILED; + } + } + return RetVal; +} + +/** +* Response callback for remote device connect +*/ +STATIC void phLibNfc_RemoteDev_Connect_Cb( + void *pContext, + phHal_sRemoteDevInformation_t *pRmtdev_info, + NFCSTATUS status + ) +{ + NFCSTATUS Connect_status = NFCSTATUS_SUCCESS; + /*Check valid lib nfc context is returned from lower layer*/ + if((phLibNfc_LibContext_t *)pContext == gpphLibContext) + { + gpphLibContext->LastTrancvSuccess = FALSE; + + /* Mark General Callback pending status as false*/ + gpphLibContext->status.GenCb_pending_status = FALSE; + + /* Check the shutdown is called during the lower layer Connect in process, + If yes call shutdown call and return NFCSTATUS_SHUTDOWN */ + if((eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state)) + { + phLibNfc_Pending_Shutdown(); + Connect_status = NFCSTATUS_SHUTDOWN; + + } + else if(PHNFCSTATUS(status)==NFCSTATUS_SUCCESS) + { + /* Copy the Remote device address as connected handle*/ + gpphLibContext->Connected_handle = (uintptr_t)pRmtdev_info; + /* Update the state to connected and return status as SUCCESS*/ + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateConnect; + Connect_status = NFCSTATUS_SUCCESS; + } + else + { /* if(PHNFCSTATUS(status)==NFCSTATUS_INVALID_REMOTE_DEVICE) */ + /* If remote device is invalid return as TARGET LOST to upper layer*/ + /* If error code is other than SUCCESS return NFCSTATUS_TARGET_LOST */ + Connect_status = NFCSTATUS_TARGET_LOST; + gpphLibContext->Connected_handle = gpphLibContext->Prev_Connected_handle ; + } + gpphLibContext->ndef_cntx.is_ndef = CHK_NDEF_NOT_DONE; + /* Update the Current Sate*/ + phLibNfc_UpdateCurState(Connect_status,(phLibNfc_LibContext_t *)pContext); + /* Call the upper layer callback*/ + gpphLibContext->CBInfo.pClientConnectCb( + gpphLibContext->CBInfo.pClientConCntx, + (phLibNfc_Handle)pRmtdev_info, + (phLibNfc_sRemoteDevInformation_t*)pRmtdev_info, + Connect_status); + } + else + { /*exception: wrong context pointer returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + return; +} + +/** +* Allows to disconnect from already connected target. +*/ +NFCSTATUS phLibNfc_RemoteDev_Disconnect( phLibNfc_Handle hRemoteDevice, + phLibNfc_eReleaseType_t ReleaseType, + pphLibNfc_DisconnectCallback_t pDscntCallback, + void* pContext + ) +{ + NFCSTATUS RetVal = NFCSTATUS_SUCCESS; + phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo=NULL; + + /*Check for valid parameter*/ + if((NULL == gpphLibContext) || + (gpphLibContext->LibNfcState.cur_state + == eLibNfcHalStateShutdown)) + { + RetVal = NFCSTATUS_NOT_INITIALISED; + } + else if((NULL == pContext) || + (NULL == pDscntCallback)||(hRemoteDevice == 0)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + /* Check for valid state,If De initialize is called then + return NFCSTATUS_SHUTDOWN */ + else if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + RetVal= NFCSTATUS_SHUTDOWN; + } + else if(gpphLibContext->Connected_handle==0) + { + RetVal=NFCSTATUS_TARGET_NOT_CONNECTED; + } + /* The given handle is not the connected handle return NFCSTATUS_INVALID_HANDLE*/ + else if(hRemoteDevice != gpphLibContext->Connected_handle ) + { + RetVal=NFCSTATUS_INVALID_HANDLE; + } + else + { + if((eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) + ||((gpphLibContext->sSeContext.eActivatedMode == phLibNfc_SE_ActModeWired)&& + (ReleaseType != NFC_SMARTMX_RELEASE)) + ||((gpphLibContext->sSeContext.eActivatedMode != phLibNfc_SE_ActModeWired)&& + (ReleaseType == NFC_SMARTMX_RELEASE))) + { /* Previous disconnect callback is pending */ + RetVal = NFCSTATUS_REJECTED; + } +#ifndef LLCP_CHANGES + else if(eLibNfcHalStateTransaction == gpphLibContext->LibNfcState.next_state) + { /* Previous Transaction is Pending*/ + RetVal = NFCSTATUS_BUSY; + PHDBG_INFO("LibNfc:Transaction is Pending"); + } +#endif /* #ifdef LLCP_CHANGES */ + else + { + gpphLibContext->ReleaseType = ReleaseType; + psRemoteDevInfo = (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice; + RetVal = phHal4Nfc_Disconnect(gpphLibContext->psHwReference, + (phHal_sRemoteDevInformation_t*)psRemoteDevInfo, + gpphLibContext->ReleaseType, + (pphHal4Nfc_DiscntCallback_t) + phLibNfc_RemoteDev_Disconnect_cb, + (void *)gpphLibContext); + if( NFCSTATUS_PENDING == PHNFCSTATUS(RetVal)) + { + /*Copy the upper layer Callback pointer and context*/ + gpphLibContext->CBInfo.pClientDisConnectCb = pDscntCallback; + gpphLibContext->CBInfo.pClientDConCntx = pContext; + /* Mark general callback pending status as TRUE and update the state*/ + gpphLibContext->status.GenCb_pending_status=TRUE; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateRelease; + + } + else + { + /*If lower layer returns other than pending + (internal error codes) return NFCSTATUS_FAILED */ + RetVal = NFCSTATUS_FAILED; + } + } + } + return RetVal; +} +/** +* Response callback for Remote device Disconnect. +*/ +STATIC void phLibNfc_RemoteDev_Disconnect_cb( + void *context, + phHal_sRemoteDevInformation_t *reg_handle, + NFCSTATUS status + ) +{ + NFCSTATUS DisCnct_status = NFCSTATUS_SUCCESS; + pphLibNfc_DisconnectCallback_t pUpper_NtfCb = NULL; + void *pUpper_Context = NULL; + + /* Copy the upper layer Callback and context*/ + pUpper_NtfCb = gpphLibContext->CBInfo.pClientDisConnectCb; + pUpper_Context = gpphLibContext->CBInfo.pClientDConCntx; + + /* Check valid context is returned or not */ + if((phLibNfc_LibContext_t *)context != gpphLibContext) + { + /*exception: wrong context pointer returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + /* Mark the General callback pending status FALSE */ + gpphLibContext->status.GenCb_pending_status = FALSE; + gpphLibContext->CBInfo.pClientDisConnectCb = NULL; + gpphLibContext->CBInfo.pClientDConCntx = NULL; + + gpphLibContext->ndef_cntx.is_ndef = CHK_NDEF_NOT_DONE; + gpphLibContext->LastTrancvSuccess = FALSE; + /*Reset Connected handle */ + gpphLibContext->Connected_handle=0x0000; + /*Reset previous Connected handle */ + gpphLibContext->Prev_Connected_handle = 0x0000; + + if(gpphLibContext->sSeContext.eActivatedMode == phLibNfc_SE_ActModeWired) + { + gpphLibContext->sSeContext.eActivatedMode = phLibNfc_SE_ActModeDefault; + } + if(NULL != gpphLibContext->psBufferedAuth) + { + if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sRecvData.buffer); + } + if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sSendData.buffer); + } + phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth); + gpphLibContext->psBufferedAuth = NULL; + } + } + /* Check DeInit is called or not */ + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { + /*call shutdown and return status as NFCSTATUS_SHUTDOWN */ + phLibNfc_Pending_Shutdown(); + DisCnct_status = NFCSTATUS_SHUTDOWN; + } + else if(NFCSTATUS_SUCCESS == status) + { + DisCnct_status = NFCSTATUS_SUCCESS; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateRelease; + } + else + { + DisCnct_status = NFCSTATUS_FAILED; + phLibNfc_UpdateCurState(DisCnct_status,(phLibNfc_LibContext_t *)context); + } + /* Call the upper layer Callback */ + (*pUpper_NtfCb)(pUpper_Context, + (phLibNfc_Handle)reg_handle, + DisCnct_status); + return; +} + +/** +* This interface allows to perform Read/write operation on remote device. +*/ +NFCSTATUS +phLibNfc_RemoteDev_Transceive(phLibNfc_Handle hRemoteDevice, + phLibNfc_sTransceiveInfo_t* psTransceiveInfo, + pphLibNfc_TransceiveCallback_t pTransceive_RspCb, + void* pContext + ) +{ + NFCSTATUS RetVal = NFCSTATUS_SUCCESS; + + /*Check for valid parameter */ + + if((NULL == gpphLibContext) || + (gpphLibContext->LibNfcState.cur_state + == eLibNfcHalStateShutdown)) + { + RetVal = NFCSTATUS_NOT_INITIALISED; + } + else if((NULL == psTransceiveInfo) + || (NULL == pTransceive_RspCb) + || (NULL == (void *)hRemoteDevice) + || (NULL == psTransceiveInfo->sRecvData.buffer) + || (NULL == psTransceiveInfo->sSendData.buffer) + || (NULL == pContext)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + /* Check the state for DeInit is called or not,if yes return NFCSTATUS_SHUTDOWN*/ + else if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + RetVal= NFCSTATUS_SHUTDOWN; + }/* If there is no handle connected return NFCSTATUS_TARGET_NOT_CONNECTED*/ + else if(gpphLibContext->Connected_handle==0) + { + RetVal=NFCSTATUS_TARGET_NOT_CONNECTED; + }/* If the given handle is not the connected handle return NFCSTATUS_INVALID_HANDLE */ + else if(gpphLibContext->Connected_handle!= hRemoteDevice ) + { + RetVal=NFCSTATUS_INVALID_HANDLE; + } /*If the transceive is called before finishing the previous transceive function + return NFCSTATUS_REJECTED */ + else if((eLibNfcHalStateTransaction == + gpphLibContext->LibNfcState.next_state) + ||(phHal_eNfcIP1_Initiator== + ((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType)) + { + RetVal = NFCSTATUS_REJECTED; + } +#ifdef LLCP_TRANSACT_CHANGES + else if ((LLCP_STATE_RESET_INIT != gpphLibContext->llcp_cntx.sLlcpContext.state) + && (LLCP_STATE_CHECKED != gpphLibContext->llcp_cntx.sLlcpContext.state)) + { + RetVal= NFCSTATUS_BUSY; + } +#endif /* #ifdef LLCP_TRANSACT_CHANGES */ + else + { + gpphLibContext->ndef_cntx.eLast_Call = RawTrans; + (void)memcpy((void *)(gpphLibContext->psTransInfo), + (void *)psTransceiveInfo, + sizeof(phLibNfc_sTransceiveInfo_t)); + /* Check the given Mifare command is supported or not , + If not return NFCSTATUS_COMMAND_NOT_SUPPORTED */ + if( (((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType == + phHal_eMifare_PICC)&& + ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareRaw ) && + ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareAuthentA ) && + ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareAuthentB ) && + ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareRead16 ) && + ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareRead ) && + ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareWrite16 ) && + ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareWrite4 ) && + ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareDec ) && + ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareTransfer ) && + ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareRestore ) && + ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareReadSector ) && + ( gpphLibContext->psTransInfo->cmd.MfCmd != phHal_eMifareWriteSector )) + { + RetVal = NFCSTATUS_COMMAND_NOT_SUPPORTED; + } + if(eLibNfcHalStatePresenceChk != + gpphLibContext->LibNfcState.next_state) + { + PHDBG_INFO("LibNfc:Transceive In Progress"); + if((((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType == + phHal_eMifare_PICC) && (((phHal_sRemoteDevInformation_t*) + hRemoteDevice)->RemoteDevInfo.Iso14443A_Info.Sak != 0)&& + (phHal_eMifareAuthentA == gpphLibContext->psTransInfo->cmd.MfCmd)) + { + if(NULL != gpphLibContext->psBufferedAuth) + { + if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sRecvData.buffer); + } + if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sSendData.buffer); + } + phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth); + } + gpphLibContext->psBufferedAuth + =(phLibNfc_sTransceiveInfo_t *) + phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t)); + gpphLibContext->psBufferedAuth->addr = psTransceiveInfo->addr; + gpphLibContext->psBufferedAuth->cmd = psTransceiveInfo->cmd; + gpphLibContext->psBufferedAuth->sSendData.length + = psTransceiveInfo->sSendData.length; + gpphLibContext->psBufferedAuth->sRecvData.length + = psTransceiveInfo->sRecvData.length; + gpphLibContext->psBufferedAuth->sSendData.buffer + = (uint8_t *) + phOsalNfc_GetMemory( + gpphLibContext->psTransInfo->sSendData.length); + + (void)memcpy((void *) + (gpphLibContext->psBufferedAuth->sSendData.buffer), + (void *)psTransceiveInfo->sSendData.buffer, + psTransceiveInfo->sSendData.length); + + gpphLibContext->psBufferedAuth->sRecvData.buffer + = (uint8_t *) + phOsalNfc_GetMemory( + gpphLibContext->psTransInfo->sRecvData.length); + } + /*Call the lower layer Transceive function */ + RetVal = phHal4Nfc_Transceive( gpphLibContext->psHwReference, + (phHal_sTransceiveInfo_t*)gpphLibContext->psTransInfo, + (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice, + (pphHal4Nfc_TransceiveCallback_t) + phLibNfc_RemoteDev_Transceive_Cb, + (void* )gpphLibContext); + if(PHNFCSTATUS(RetVal) == NFCSTATUS_PENDING) + { + /* Copy the upper layer callback pointer and context */ + gpphLibContext->CBInfo.pClientTransceiveCb = pTransceive_RspCb; + gpphLibContext->CBInfo.pClientTranseCntx = pContext; + /* Mark the General callback pending status is TRUE */ + gpphLibContext->status.GenCb_pending_status = TRUE; + /*Transceive is in Progress-Used in Release API*/ + + /*Update the state machine*/ + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; + } + } + else + { + gpphLibContext->status.GenCb_pending_status = FALSE; + RetVal = NFCSTATUS_FAILED; + } + } + return RetVal; +} +/** +* Response for Remote device transceive. +*/ +STATIC +void phLibNfc_RemoteDev_Transceive_Cb(void *context, + phHal_sRemoteDevInformation_t *pRmtdev_info, + phNfc_sData_t *response, + NFCSTATUS status + ) +{ + NFCSTATUS trans_status = NFCSTATUS_SUCCESS; + phNfc_sData_t *trans_resp= NULL; + void *pUpper_Context = NULL; + pphLibNfc_TransceiveCallback_t pUpper_TagNtfCb = + gpphLibContext->CBInfo.pClientTransceiveCb; + + /*Check valid context is returned or not */ + if((phLibNfc_LibContext_t *)context == gpphLibContext) + { + trans_resp = &gpphLibContext->psTransInfo->sRecvData; + + pUpper_Context = gpphLibContext->CBInfo.pClientTranseCntx; + gpphLibContext->status.GenCb_pending_status = FALSE; + + /*If DeInit is called during the transceive, + call the shutdown and return NFCSTATUS_SHUTDOWN*/ + if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + phLibNfc_Pending_Shutdown(); + trans_status = NFCSTATUS_SHUTDOWN; + } + /* If Disconnect is called return NFCSTATUS_ABORTED */ + else if(eLibNfcHalStateRelease == + gpphLibContext->LibNfcState.next_state) + { + trans_status = NFCSTATUS_ABORTED; + } + /* If the received lower layer status is not SUCCESS return NFCSTATUS_FAILED */ + else if( NFCSTATUS_SUCCESS == status) + { + trans_status = NFCSTATUS_SUCCESS; + } + else if((PHNFCSTATUS(status) != NFCSTATUS_SUCCESS) && + (phHal_eMifare_PICC == pRmtdev_info->RemDevType) && + (0x00 != pRmtdev_info->RemoteDevInfo.Iso14443A_Info.Sak)) + { + gpphLibContext->LastTrancvSuccess = FALSE; + trans_status = NFCSTATUS_FAILED; + /* card type is mifare 1k/4k, then reconnect */ + trans_status = phHal4Nfc_Connect(gpphLibContext->psHwReference, + pRmtdev_info, + (pphHal4Nfc_ConnectCallback_t) + phLibNfc_Reconnect_Mifare_Cb, + (void *)gpphLibContext); + } + else if ((PHNFCSTATUS(status) == PN544_IO_TIMEOUT_RESPONSE) || + (PHNFCSTATUS(status) == NFCSTATUS_RF_TIMEOUT)) + { + // 0x89, 0x09 HCI response values from PN544 indicate timeout + trans_status = NFCSTATUS_TARGET_LOST; + } + else + { + // PN544 did get some reply from tag, just not valid + trans_status = NFCSTATUS_FAILED; + } + /*Update the state machine */ + phLibNfc_UpdateCurState(status,gpphLibContext); + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateConnect; + if(NFCSTATUS_PENDING != trans_status) + { + /* Tranceive over */ + PHDBG_INFO("LibNfc:TXRX Callback-Update the Transceive responce"); + if (NULL != pUpper_TagNtfCb) + { + if(trans_status == NFCSTATUS_SUCCESS) + { + gpphLibContext->LastTrancvSuccess = TRUE; + pUpper_Context = gpphLibContext->CBInfo.pClientTranseCntx; + trans_resp->buffer = response->buffer; + trans_resp->length = response->length; + /* Notify the upper layer */ + PHDBG_INFO("LibNfc:Transceive Complete"); + /* Notify the Transceive Completion to upper layer */ + gpphLibContext->CBInfo.pClientTransceiveCb(pUpper_Context, + (phLibNfc_Handle)pRmtdev_info, + trans_resp, + trans_status); + } + else + { + gpphLibContext->LastTrancvSuccess = FALSE; + pUpper_Context = gpphLibContext->CBInfo.pClientTranseCntx; + trans_resp->length = 0; + /* Notify the upper layer */ + PHDBG_INFO("LibNfc:Transceive Complete"); + /* Notify the Transceive Completion to upper layer */ + gpphLibContext->CBInfo.pClientTransceiveCb(pUpper_Context, + (phLibNfc_Handle)pRmtdev_info, + trans_resp, + trans_status); + } + } + } + + } + else + { /*exception: wrong context pointer returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + + return; +} +/** +* Interface to configure P2P configurations. +*/ +NFCSTATUS +phLibNfc_Mgt_SetP2P_ConfigParams(phLibNfc_sNfcIPCfg_t* pConfigInfo, + pphLibNfc_RspCb_t pConfigRspCb, + void* pContext + ) +{ + NFCSTATUS RetVal = NFCSTATUS_FAILED; + /* LibNfc Initialized or not */ + if((NULL == gpphLibContext)|| + (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) + { + RetVal = NFCSTATUS_NOT_INITIALISED; + }/* Check for valid parameters */ + else if((NULL == pConfigInfo) || (NULL == pConfigRspCb) + || (NULL == pContext)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + RetVal = NFCSTATUS_SHUTDOWN; + } + else if(TRUE == gpphLibContext->status.GenCb_pending_status) + { /*Previous callback is pending */ + RetVal = NFCSTATUS_BUSY; + } + else + { + if(eLibNfcHalStatePresenceChk != + gpphLibContext->LibNfcState.next_state) + { + phHal_uConfig_t uConfig; + /* copy General bytes of Max length = 48 bytes */ + (void)memcpy((void *)&(uConfig.nfcIPConfig.generalBytes), + (void *)pConfigInfo->generalBytes, + pConfigInfo->generalBytesLength); + /* also copy the General Bytes length*/ + uConfig.nfcIPConfig.generalBytesLength = pConfigInfo->generalBytesLength; + + RetVal = phHal4Nfc_ConfigParameters( + gpphLibContext->psHwReference, + NFC_P2P_CONFIG, + &uConfig, + phLibNfc_Mgt_SetP2P_ConfigParams_Cb, + (void *)gpphLibContext + ); + } + else + { + gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCb= NULL; + RetVal = NFCSTATUS_PENDING; + } + if(NFCSTATUS_PENDING == RetVal) + { + /* save the context and callback for later use */ + gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCb = pConfigRspCb; + gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCntx = pContext; + gpphLibContext->status.GenCb_pending_status=TRUE; + /* Next state is configured */ + gpphLibContext->LibNfcState.next_state =eLibNfcHalStateConfigReady; + } + else + { + RetVal = NFCSTATUS_FAILED; + } + } + return RetVal; +} +/** +* Response callback for P2P configurations. +*/ +STATIC void phLibNfc_Mgt_SetP2P_ConfigParams_Cb(void *context, + NFCSTATUS status) +{ + pphLibNfc_RspCb_t pClientCb=NULL; + void *pUpperLayerContext=NULL; + /* Check for the context returned by below layer */ + if((phLibNfc_LibContext_t *)context != gpphLibContext) + { /*wrong context returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { /*shutdown called before completion of this api allow + shutdown to happen */ + phLibNfc_Pending_Shutdown(); + status = NFCSTATUS_SHUTDOWN; + } + else + { + gpphLibContext->status.GenCb_pending_status = FALSE; + if(NFCSTATUS_SUCCESS != status) + { + status = NFCSTATUS_FAILED; + } + else + { + status = NFCSTATUS_SUCCESS; + } + } + /*update the current state */ + phLibNfc_UpdateCurState(status,gpphLibContext); + + pClientCb = gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCb; + pUpperLayerContext = gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCntx; + + gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCb = NULL; + gpphLibContext->sNfcIp_Context.pClientNfcIpCfgCntx = NULL; + if (NULL != pClientCb) + { + /* Notify to upper layer status of configure operation */ + pClientCb(pUpperLayerContext, status); + } + } + return; +} + + + + + + + + + + diff --git a/libnfc-nxp/phLibNfc_initiator.h b/libnfc-nxp/phLibNfc_initiator.h new file mode 100644 index 0000000..66d7d2a --- /dev/null +++ b/libnfc-nxp/phLibNfc_initiator.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phLibNfc_initiator.h + * + * Project: NFC-FRI 1.1 + * + * $Workfile:: phLibNfc_1.1.h $ + * $Modtime:: $ + * $Author: ing07299 $ + * $Revision: 1.13 $ + * + */ +#ifndef PHLIBNFC_INITIATOR_H +#define PHLIBNFC_INITIATOR_H + +typedef struct phLibNfc_NfcIpInfo +{ + phNfc_sData_t *p_recv_data; + uint32_t recv_index; + /*NFC-IP Call back & it's context*/ + pphLibNfc_RspCb_t pClientNfcIpCfgCb; + void *pClientNfcIpCfgCntx; + /*NFC-IP send callback and its context*/ + pphLibNfc_RspCb_t pClientNfcIpTxCb; + void *pClientNfcIpTxCntx; + + /*NFC-IP receive callback and its context*/ + pphLibNfc_Receive_RspCb_t pClientNfcIpRxCb; + void *pClientNfcIpRxCntx; + /*Store the role of remote device*/ + phHal4Nfc_TransactInfo_t TransactInfoRole; + + /*NFC IP remote initator handle */ + uint32_t Rem_Initiator_Handle; + +}phLibNfc_NfcIpInfo_t; + + +#endif + + diff --git a/libnfc-nxp/phLibNfc_ioctl.h b/libnfc-nxp/phLibNfc_ioctl.h new file mode 100644 index 0000000..61e312f --- /dev/null +++ b/libnfc-nxp/phLibNfc_ioctl.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +*\file phLibNfc_ioctl.h +*\brief Contains LibNfc IOCTL details. +*Project: NFC-FRI 1.1 +* $Workfile:: phLibNfc_ioctl.h $ +* $Modtime:: $ +* $Author: ing07299 $ +* $Revision: 1.9 $ +* $Aliases: NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK949_SDK_INT,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK1003_SDK,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1008_SDK,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1007_SDK,NFC_FRI1.1_WK1014_SDK,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1024_SDK $ +*\defgroup grp_lib_ioctl IOCTL code details +*/ + + +#ifndef PHLIBNFCIOCTL_H /* */ +#define PHLIBNFCIOCTL_H /* */ + +#include +#include + +/** +* \ingroup grp_lib_ioctl +* \brief Allows to initiate firmware download to connected PN544 +* +*/ +#define PHLIBNFC_FW_DOWNLOAD NFC_FW_DOWNLOAD +/** +* \ingroup grp_lib_ioctl +* \brief Allows to read memory from connected PN544 . +* +*/ +#define PHLIBNFC_MEM_READ NFC_MEM_READ + +/** +* \ingroup grp_lib_ioctl +* \brief Allows to write PN544 memory. +* +*/ +#define PHLIBNFC_MEM_WRITE NFC_MEM_WRITE + +/** +* \ingroup grp_lib_ioctl +* \brief Allows to do Antenna test. +* +*/ +#define PHLIBNFC_ANTENNA_TEST DEVMGMT_ANTENNA_TEST +/** +* \ingroup grp_lib_ioctl +* \brief Allows to do SWP test. +* +*/ +#define PHLIBNFC_SWP_TEST DEVMGMT_SWP_TEST +/** +* \ingroup grp_lib_ioctl +* \brief Allows to do PRBS test. +* +*/ +#define PHLIBNFC_PRBS_TEST DEVMGMT_PRBS_TEST + +/** +* \ingroup grp_lib_ioctl +* \brief Allows to switch UICC mode. +* +*/ +#define PHLIBNFC_SWITCH_SWP_MODE NFC_SWITCH_SWP_MODE + +typedef struct +{ + void *pCliCntx; + pphLibNfc_IoctlCallback_t CliRspCb; + phHal_sHwReference_t *psHwReference; + phNfc_sData_t* pOutParam; + uint16_t IoctlCode; +}phLibNfc_Ioctl_Cntx_t; + +#endif /* PHLIBNFCIOCTL_H */ + + + + diff --git a/libnfc-nxp/phLibNfc_llcp.c b/libnfc-nxp/phLibNfc_llcp.c new file mode 100644 index 0000000..6050b1c --- /dev/null +++ b/libnfc-nxp/phLibNfc_llcp.c @@ -0,0 +1,1129 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +#include +#include +#include +#include +#include + +/* ---------------------------- Internal macros -------------------------------- */ + +#ifndef STATIC_DISABLE +#define STATIC static +#else +#define STATIC +#endif + +/* ----------------------- Internal functions headers -------------------------- */ + +STATIC +NFCSTATUS static_CheckState(); + +STATIC +NFCSTATUS static_CheckDevice(phLibNfc_Handle hRemoteDevice); + +STATIC +void phLibNfc_Llcp_CheckLlcp_Cb(void *pContext,NFCSTATUS status); + +STATIC +void phLibNfc_Llcp_Link_Cb(void *pContext,phLibNfc_Llcp_eLinkStatus_t status); + +/* --------------------------- Internal functions ------------------------------ */ + +STATIC NFCSTATUS static_CheckState() +{ + /* Check if the global context is set */ + if(gpphLibContext == NULL) + { + return NFCSTATUS_NOT_INITIALISED; + } + + /* Check if initialized */ + if(gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown) + { + return NFCSTATUS_NOT_INITIALISED; + } + + /* Check if shutting down */ + if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + return NFCSTATUS_SHUTDOWN; + } + + return NFCSTATUS_SUCCESS; +} + +STATIC NFCSTATUS static_CheckDevice(phLibNfc_Handle hRemoteDevice) +{ + phLibNfc_sRemoteDevInformation_t* psRemoteDevInfo = (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice; + + if (hRemoteDevice == 0) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* If local device is the Initiator (remote is Target), + * check if connection is correct + */ + if (psRemoteDevInfo->RemDevType == phHal_eNfcIP1_Target) + { + /* Check if any device connected */ + if(gpphLibContext->Connected_handle == 0) + { + return NFCSTATUS_TARGET_NOT_CONNECTED; + } + + /* Check if handle corresponds to connected one */ + if(hRemoteDevice != gpphLibContext->Connected_handle) + { + return NFCSTATUS_INVALID_HANDLE; + } + } + + /* Check if previous callback is pending or if remote peer is not LLCP compliant */ + if ((gpphLibContext->status.GenCb_pending_status == TRUE) || + (gpphLibContext->llcp_cntx.bIsLlcp == FALSE)) + { + return NFCSTATUS_REJECTED; + } + + return NFCSTATUS_SUCCESS; +} + +/* ---------------------------- Public functions ------------------------------- */ + +NFCSTATUS phLibNfc_Mgt_SetLlcp_ConfigParams( phLibNfc_Llcp_sLinkParameters_t* pConfigInfo, + pphLibNfc_RspCb_t pConfigRspCb, + void* pContext + ) +{ + NFCSTATUS result; + phNfc_sData_t sGeneralBytesBuffer; + phLibNfc_sNfcIPCfg_t sNfcIPCfg; + const uint8_t pMagicBuffer[] = { 0x46, 0x66, 0x6D }; + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((pConfigInfo == NULL) || (pConfigRspCb == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Save the config for later use */ + memcpy( &gpphLibContext->llcp_cntx.sLocalParams, + pConfigInfo, + sizeof(phLibNfc_Llcp_sLinkParameters_t) ); + + /* Copy magic number in NFCIP General Bytes */ + memcpy(sNfcIPCfg.generalBytes, pMagicBuffer, sizeof(pMagicBuffer)); + sNfcIPCfg.generalBytesLength = sizeof(pMagicBuffer); + + /* Encode link parameters in TLV to configure P2P General Bytes */ + sGeneralBytesBuffer.buffer = sNfcIPCfg.generalBytes + sizeof(pMagicBuffer); + sGeneralBytesBuffer.length = sizeof(sNfcIPCfg.generalBytes) - sizeof(pMagicBuffer); + result = phFriNfc_Llcp_EncodeLinkParams( &sGeneralBytesBuffer, + pConfigInfo, + PHFRINFC_LLCP_VERSION); + if (result != NFCSTATUS_SUCCESS) + { + return PHNFCSTATUS(result); + } + sNfcIPCfg.generalBytesLength += (uint8_t)sGeneralBytesBuffer.length; + + /* Set the P2P general bytes */ + result = phLibNfc_Mgt_SetP2P_ConfigParams(&sNfcIPCfg, pConfigRspCb, pContext); + if (result != NFCSTATUS_PENDING) + { + return PHNFCSTATUS(result); + } + + /* Resets the LLCP LLC component */ + result = phFriNfc_Llcp_Reset( &gpphLibContext->llcp_cntx.sLlcpContext, + gpphLibContext->psOverHalCtxt, + pConfigInfo, + gpphLibContext->llcp_cntx.pRxBuffer, + sizeof(gpphLibContext->llcp_cntx.pRxBuffer), + gpphLibContext->llcp_cntx.pTxBuffer, + sizeof(gpphLibContext->llcp_cntx.pTxBuffer), + phLibNfc_Llcp_Link_Cb, + gpphLibContext); + if (result != NFCSTATUS_SUCCESS) + { + return PHNFCSTATUS(result); + } + + /* Resets the LLCP Transport component */ + result = phFriNfc_LlcpTransport_Reset( &gpphLibContext->llcp_cntx.sLlcpTransportContext, + &gpphLibContext->llcp_cntx.sLlcpContext ); + if (result != NFCSTATUS_SUCCESS) + { + return PHNFCSTATUS(result); + } + + return NFCSTATUS_PENDING; +} + +NFCSTATUS phLibNfc_Llcp_CheckLlcp( phLibNfc_Handle hRemoteDevice, + pphLibNfc_ChkLlcpRspCb_t pCheckLlcp_RspCb, + pphLibNfc_LlcpLinkStatusCb_t pLink_Cb, + void* pContext + ) +{ + NFCSTATUS result; + phLibNfc_sRemoteDevInformation_t* psRemoteDevInfo = (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice; + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hRemoteDevice == 0) || + (pCheckLlcp_RspCb == NULL) || + (pLink_Cb == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* If local device is the Initiator (remote is Target), + * check if connection is correct + */ + if (psRemoteDevInfo->RemDevType == phHal_eNfcIP1_Target) + { + /* Check if any device connected */ + if(gpphLibContext->Connected_handle == 0) + { + return NFCSTATUS_TARGET_NOT_CONNECTED; + } + + /* Check if handle corresponds to connected one */ + if(hRemoteDevice != gpphLibContext->Connected_handle) + { + return NFCSTATUS_INVALID_HANDLE; + } + } + + /* Prepare callback */ + gpphLibContext->CBInfo.pClientLlcpLinkCb = pLink_Cb; + gpphLibContext->CBInfo.pClientLlcpLinkCntx = pContext; + + // DEBUG: Reset at least the state + gpphLibContext->llcp_cntx.sLlcpContext.state = 0; + + /* Prepare callback */ + gpphLibContext->CBInfo.pClientLlcpCheckRespCb = pCheckLlcp_RspCb; + gpphLibContext->CBInfo.pClientLlcpCheckRespCntx = pContext; + + /* Update state */ + result = phLibNfc_UpdateNextState(gpphLibContext, eLibNfcHalStateTransaction); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Call the component function */ + result = phFriNfc_Llcp_ChkLlcp( &gpphLibContext->llcp_cntx.sLlcpContext, + psRemoteDevInfo, + phLibNfc_Llcp_CheckLlcp_Cb, + gpphLibContext + ); + result = PHNFCSTATUS(result); + if (result == NFCSTATUS_PENDING) + { + gpphLibContext->status.GenCb_pending_status = TRUE; + } + else if (result == NFCSTATUS_SUCCESS) + { + /* Nothing to do */ + } + else if (result != NFCSTATUS_FAILED) + { + result = NFCSTATUS_TARGET_LOST; + } + + return result; +} + +/* LLCP link callback */ +STATIC +void phLibNfc_Llcp_Link_Cb(void *pContext, phLibNfc_Llcp_eLinkStatus_t status) +{ + phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)pContext; + pphLibNfc_LlcpLinkStatusCb_t pClientCb = NULL; + void *pClientContext = NULL; + + if(pLibNfc_Ctxt != gpphLibContext) + { + /*wrong context returned from below layer*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + /* Close all sockets */ + phFriNfc_LlcpTransport_CloseAll(&gpphLibContext->llcp_cntx.sLlcpTransportContext); + + /* Copy callback details */ + pClientCb = gpphLibContext->CBInfo.pClientLlcpLinkCb; + pClientContext = gpphLibContext->CBInfo.pClientLlcpLinkCntx; + + /* Trigger the callback */ + if(pClientCb != NULL) + { + pClientCb(pClientContext, status); + } + } +} + +/* Response callback for phLibNfc_Ndef_CheckNdef */ +STATIC +void phLibNfc_Llcp_CheckLlcp_Cb(void *pContext, NFCSTATUS status) +{ + phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)pContext; + NFCSTATUS RetStatus = NFCSTATUS_SUCCESS; + pphLibNfc_ChkLlcpRspCb_t pClientCb = NULL; + void *pClientContext = NULL; + + if(pLibNfc_Ctxt != gpphLibContext) + { + /*wrong context returned from below layer*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + /*shutdown called before completion of check Ndef, allow shutdown to happen */ + phLibNfc_Pending_Shutdown(); + RetStatus = NFCSTATUS_SHUTDOWN; + } + else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateRelease) + { + RetStatus = NFCSTATUS_ABORTED; + } + else + { + if(status == NFCSTATUS_SUCCESS) + { + /* Remote peer is LLCP compliant */ + gpphLibContext->llcp_cntx.bIsLlcp = TRUE; + } + else if(PHNFCSTATUS(status)== NFCSTATUS_FAILED) + { + RetStatus = NFCSTATUS_FAILED; + gpphLibContext->llcp_cntx.bIsLlcp = FALSE; + } + else + { + RetStatus = NFCSTATUS_TARGET_LOST; + } + } + + /* Update the current state */ + gpphLibContext->status.GenCb_pending_status = FALSE; + phLibNfc_UpdateCurState(RetStatus,gpphLibContext); + + /* Copy callback details */ + pClientCb = gpphLibContext->CBInfo.pClientLlcpCheckRespCb; + pClientContext = gpphLibContext->CBInfo.pClientLlcpCheckRespCntx; + + /* Reset saved callback */ + gpphLibContext->CBInfo.pClientCkNdefCb = NULL; + gpphLibContext->CBInfo.pClientCkNdefCntx = NULL; + + /* Trigger the callback */ + if(pClientCb != NULL) + { + pClientCb(pClientContext,RetStatus); + } + } +} + +NFCSTATUS phLibNfc_Llcp_Activate( phLibNfc_Handle hRemoteDevice ) +{ + NFCSTATUS result; + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if (hRemoteDevice == 0) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Start activation */ + result = phFriNfc_Llcp_Activate(&gpphLibContext->llcp_cntx.sLlcpContext); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_Deactivate( phLibNfc_Handle hRemoteDevice ) +{ + NFCSTATUS result; + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if (hRemoteDevice == 0) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Start deactivation */ + result = phFriNfc_Llcp_Deactivate(&gpphLibContext->llcp_cntx.sLlcpContext); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_GetLocalInfo( phLibNfc_Handle hRemoteDevice, + phLibNfc_Llcp_sLinkParameters_t* pConfigInfo + ) +{ + NFCSTATUS result; + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if (pConfigInfo == NULL) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Get local infos */ + result = phFriNfc_Llcp_GetLocalInfo(&gpphLibContext->llcp_cntx.sLlcpContext, pConfigInfo); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_GetRemoteInfo( phLibNfc_Handle hRemoteDevice, + phLibNfc_Llcp_sLinkParameters_t* pConfigInfo + ) +{ + NFCSTATUS result; + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hRemoteDevice == 0) || + (pConfigInfo == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Get local infos */ + result = phFriNfc_Llcp_GetRemoteInfo(&gpphLibContext->llcp_cntx.sLlcpContext, pConfigInfo); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_DiscoverServices( phLibNfc_Handle hRemoteDevice, + phNfc_sData_t *psServiceNameList, + uint8_t *pnSapList, + uint8_t nListSize, + pphLibNfc_RspCb_t pDiscover_Cb, + void *pContext + ) +{ + NFCSTATUS result; + PHNFC_UNUSED_VARIABLE(hRemoteDevice); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hRemoteDevice == 0) || + (psServiceNameList == NULL) || + (pnSapList == NULL) || + (nListSize == 0) || + (pDiscover_Cb == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Prepare callback */ + gpphLibContext->CBInfo.pClientLlcpDiscoveryCb = pDiscover_Cb; + gpphLibContext->CBInfo.pClientLlcpDiscoveryCntx = pContext; + + /* Update state */ + result = phLibNfc_UpdateNextState(gpphLibContext, eLibNfcHalStateTransaction); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Call the component function */ + result = phFriNfc_LlcpTransport_DiscoverServices( &gpphLibContext->llcp_cntx.sLlcpTransportContext, + psServiceNameList, + pnSapList, + nListSize, + pDiscover_Cb, + pContext + ); + result = PHNFCSTATUS(result); + if ((result == NFCSTATUS_PENDING) || (result == NFCSTATUS_SUCCESS)) + { + /* Nothing to do */ + } + else if (result != NFCSTATUS_FAILED) + { + result = NFCSTATUS_TARGET_LOST; + } + + return result; +} + +NFCSTATUS phLibNfc_Llcp_Socket( phLibNfc_Llcp_eSocketType_t eType, + phLibNfc_Llcp_sSocketOptions_t* psOptions, + phNfc_sData_t* psWorkingBuffer, + phLibNfc_Handle* phSocket, + pphLibNfc_LlcpSocketErrCb_t pErr_Cb, + void* pContext + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket; + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + /* NOTE: Transport Layer test psOption and psWorkingBuffer value */ + if ((phSocket == NULL) || + (pErr_Cb == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Get local infos */ + result = phFriNfc_LlcpTransport_Socket(&gpphLibContext->llcp_cntx.sLlcpTransportContext, + eType, + psOptions, + psWorkingBuffer, + &psSocket, + pErr_Cb, + pContext); + + /* Send back the socket handle */ + *phSocket = (phLibNfc_Handle)psSocket; + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_Close( phLibNfc_Handle hSocket ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if (hSocket == 0) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Get local infos */ + /* TODO: if connected abort and close else close only */ + result = phFriNfc_LlcpTransport_Close(psSocket); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_SocketGetLocalOptions( phLibNfc_Handle hSocket, + phLibNfc_Llcp_sSocketOptions_t* psLocalOptions + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hSocket == 0) || + (psLocalOptions == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Get local options */ + result = phFriNfc_LlcpTransport_SocketGetLocalOptions(psSocket, psLocalOptions); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_SocketGetRemoteOptions( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + phLibNfc_Llcp_sSocketOptions_t* psRemoteOptions + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + LLCP_PRINT("phLibNfc_Llcp_SocketGetRemoteOptions"); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hRemoteDevice == 0) || + (hSocket == 0) || + (psRemoteOptions == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Get remote infos */ + result = phFriNfc_LlcpTransport_SocketGetRemoteOptions(psSocket, psRemoteOptions); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_Bind( phLibNfc_Handle hSocket, + uint8_t nSap, + phNfc_sData_t * psServiceName + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + LLCP_PRINT("phLibNfc_Llcp_Bind"); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if (hSocket == 0) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Bind the socket to the designated port */ + result = phFriNfc_LlcpTransport_Bind(psSocket, nSap, psServiceName); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_Listen( phLibNfc_Handle hSocket, + pphLibNfc_LlcpSocketListenCb_t pListen_Cb, + void* pContext + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + LLCP_PRINT("phLibNfc_Llcp_Listen"); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + /* NOTE : psServiceName may be NULL, do not test it ! */ + if ((hSocket == 0) || + (pListen_Cb == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Start listening for incoming connections */ + result = phFriNfc_LlcpTransport_Listen( psSocket, + (pphFriNfc_LlcpTransportSocketListenCb_t)pListen_Cb, + pContext ); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_Accept( phLibNfc_Handle hSocket, + phLibNfc_Llcp_sSocketOptions_t* psOptions, + phNfc_sData_t* psWorkingBuffer, + pphLibNfc_LlcpSocketErrCb_t pErr_Cb, + pphLibNfc_LlcpSocketAcceptCb_t pAccept_RspCb, + void* pContext + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + LLCP_PRINT("phLibNfc_Llcp_Accept"); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hSocket == 0) || + (psOptions == NULL) || + (psWorkingBuffer == NULL) || + (pErr_Cb == NULL) || + (pAccept_RspCb == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Accept incoming connection */ + result = phFriNfc_LlcpTransport_Accept( psSocket, + psOptions, + psWorkingBuffer, + pErr_Cb, + pAccept_RspCb, + pContext ); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_Reject( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + pphLibNfc_LlcpSocketRejectCb_t pReject_RspCb, + void* pContext + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + LLCP_PRINT("phLibNfc_Llcp_Reject"); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hRemoteDevice == 0) || + (hSocket == 0) || + (pReject_RspCb == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Reject incoming connection */ + result = phFriNfc_LlcpTransport_Reject( psSocket, + pReject_RspCb, + pContext ); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_Connect( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + uint8_t nSap, + pphLibNfc_LlcpSocketConnectCb_t pConnect_RspCb, + void* pContext + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + LLCP_PRINT("phLibNfc_Llcp_Connect"); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hRemoteDevice == 0) || + (hSocket == 0) || + (pConnect_RspCb == NULL)) + { + LLCP_PRINT("phLibNfc_Llcp_Connect NFCSTATUS_INVALID_PARAMETER"); + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Try to connect on a remote service, given its SAP */ + result = phFriNfc_LlcpTransport_Connect( psSocket, + nSap, + pConnect_RspCb, + pContext ); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_ConnectByUri( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + phNfc_sData_t* psUri, + pphLibNfc_LlcpSocketConnectCb_t pConnect_RspCb, + void* pContext + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + LLCP_PRINT("phLibNfc_Llcp_ConnectByUri"); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hRemoteDevice == 0) || + (hSocket == 0) || + (psUri == NULL) || + (pConnect_RspCb == NULL)) + { + LLCP_PRINT("phLibNfc_Llcp_ConnectByUri NFCSTATUS_INVALID_PARAMETER"); + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Try to connect on a remote service, using SDP */ + result = phFriNfc_LlcpTransport_ConnectByUri( psSocket, + psUri, + pConnect_RspCb, + pContext ); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_Disconnect( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + pphLibNfc_LlcpSocketDisconnectCb_t pDisconnect_RspCb, + void* pContext + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + LLCP_PRINT("phLibNfc_Llcp_Disconnect"); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hRemoteDevice == 0) || + (hSocket == 0) || + (pDisconnect_RspCb == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Disconnect a logical link */ + result = phFriNfc_LlcpTransport_Disconnect( psSocket, + pDisconnect_RspCb, + pContext ); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_Recv( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + phNfc_sData_t* psBuffer, + pphLibNfc_LlcpSocketRecvCb_t pRecv_RspCb, + void* pContext + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + LLCP_PRINT("phLibNfc_Llcp_Recv"); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hRemoteDevice == 0) || + (hSocket == 0) || + (psBuffer == NULL) || + (pRecv_RspCb == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Receive data from the logical link */ + result = phFriNfc_LlcpTransport_Recv( psSocket, + psBuffer, + pRecv_RspCb, + pContext ); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_RecvFrom( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + phNfc_sData_t* psBuffer, + pphLibNfc_LlcpSocketRecvFromCb_t pRecv_Cb, + void* pContext + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + LLCP_PRINT("phLibNfc_Llcp_RecvFrom"); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hRemoteDevice == 0) || + (hSocket == 0) || + (psBuffer == NULL) || + (pRecv_Cb == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Receive data from the logical link */ + result = phFriNfc_LlcpTransport_RecvFrom( psSocket, + psBuffer, + pRecv_Cb, + pContext ); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_Send( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + phNfc_sData_t* psBuffer, + pphLibNfc_LlcpSocketSendCb_t pSend_RspCb, + void* pContext + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + LLCP_PRINT("phLibNfc_Llcp_Send"); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hRemoteDevice == 0) || + (hSocket == 0) || + (psBuffer == NULL) || + (pSend_RspCb == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Send data to the logical link */ + result = phFriNfc_LlcpTransport_Send( psSocket, + psBuffer, + pSend_RspCb, + pContext ); + + return PHNFCSTATUS(result); +} + +NFCSTATUS phLibNfc_Llcp_SendTo( phLibNfc_Handle hRemoteDevice, + phLibNfc_Handle hSocket, + uint8_t nSap, + phNfc_sData_t* psBuffer, + pphLibNfc_LlcpSocketSendCb_t pSend_RspCb, + void* pContext + ) +{ + NFCSTATUS result; + phFriNfc_LlcpTransport_Socket_t *psSocket = (phFriNfc_LlcpTransport_Socket_t*)hSocket; + + LLCP_PRINT("phLibNfc_Llcp_SendTo"); + + /* State checking */ + result = static_CheckState(); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Parameters checking */ + if ((hRemoteDevice == 0) || + (hSocket == 0) || + (psBuffer == NULL) || + (pSend_RspCb == NULL)) + { + return NFCSTATUS_INVALID_PARAMETER; + } + + /* Check device */ + result = static_CheckDevice(hRemoteDevice); + if (result != NFCSTATUS_SUCCESS) + { + return result; + } + + /* Send data to the logical link */ + result = phFriNfc_LlcpTransport_SendTo( psSocket, + nSap, + psBuffer, + pSend_RspCb, + pContext ); + + return PHNFCSTATUS(result); +} diff --git a/libnfc-nxp/phLibNfc_ndef_raw.c b/libnfc-nxp/phLibNfc_ndef_raw.c new file mode 100644 index 0000000..785c572 --- /dev/null +++ b/libnfc-nxp/phLibNfc_ndef_raw.c @@ -0,0 +1,2007 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phLibNfc_ndef_raw.c + + * Project: NFC FRI 1.1 + * + * $Date: Mon Dec 13 14:14:15 2010 $ + * $Author: ing02260 $ + * $Revision: 1.74 $ + * $Aliases: $ + * + */ + +/* +************************* Header Files **************************************** +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +*************************** Macro's **************************************** +*/ + +#ifndef STATIC_DISABLE +#define STATIC static +#else +//#undef STATIC +#define STATIC +#endif + +#define TOPAZ_NDEF_BITMASK 0x10U +#define TOPAZ_LEN_BITMASK 0x02U +#define TOPAZ_DYNAMIC_LEN 460U +#define TOPAZ_STATIC_CARD_LEN 128U +#define MIFARE_STD_BLOCK_SIZE 0x10U +/* +*************************** Global Variables ********************************** +*/ +phLibNfc_Ndef_Info_t NdefInfo; +phFriNfc_NdefRecord_t *pNdefRecord=NULL; +/* +*************************** Static Function Declaration *********************** +*/ + +/* Response callback for Check Ndef */ +STATIC +void phLibNfc_Ndef_CheckNdef_Cb(void *pContext, NFCSTATUS status); + +/* Response callback for Ndef Write */ +STATIC +void phLibNfc_Ndef_Write_Cb(void* Context,NFCSTATUS status); + +/* Response callback for Ndef Read*/ +STATIC +void phLibNfc_Ndef_Read_Cb(void* Context,NFCSTATUS status); + +/* Response callback forNdef Format*/ +STATIC +void phLibNfc_Ndef_format_Cb(void *Context,NFCSTATUS status); + +#ifdef LIBNFC_READONLY_NDEF +STATIC +void +phLibNfc_Ndef_ReadOnly_Cb ( + void *p_context, + NFCSTATUS status); +#endif /* #ifdef LIBNFC_READONLY_NDEF */ + +/* Response callback for Search Ndef Content */ +STATIC +void phLibNfc_Ndef_SrchNdefCnt_Cb(void *context, NFCSTATUS status); + +/* Response callback for Ndef Record Type Discovery */ +STATIC +void phLibNfc_Ndef_Rtd_Cb( void *CallBackParam); + +/* Response callback for Check Ndef timer callback */ +STATIC void CheckNdef_timer_cb(uint32_t timer_id, void *pContext); + +/*Callback for Presence check call from Chk Ndef*/ +STATIC void phLibNfc_Ndef_ChkNdef_Pchk_Cb(void *pContext, + NFCSTATUS status + ); +/* +*************************** Function Definitions ****************************** +*/ + +/** +* This function reads an NDEF message from already connected tag. +* the NDEF message is read starting after the position of the +* last read operation of the same tag during current session. +*/ + +NFCSTATUS phLibNfc_Ndef_Read( phLibNfc_Handle hRemoteDevice, + phNfc_sData_t *psRd, + phLibNfc_Ndef_EOffset_t Offset, + pphLibNfc_RspCb_t pNdefRead_RspCb, + void* pContext + ) +{ + NFCSTATUS RetVal = NFCSTATUS_FAILED; + + if((NULL == gpphLibContext)|| + (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) + { + RetVal = NFCSTATUS_NOT_INITIALISED; + } + else if((NULL == psRd) || (NULL == pNdefRead_RspCb) + || (NULL == psRd->buffer) + || (0 == psRd->length) + || (NULL == pContext) + || (0 == hRemoteDevice)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + RetVal = NFCSTATUS_SHUTDOWN; + } + else if(0 == gpphLibContext->Connected_handle) + { /*presently no target or tag is connected*/ + RetVal=NFCSTATUS_TARGET_NOT_CONNECTED; + } + else if(hRemoteDevice != gpphLibContext->Connected_handle) + { /*This handle of the device sent by application is not connected */ + RetVal=NFCSTATUS_INVALID_HANDLE; + } + else if((TRUE == gpphLibContext->status.GenCb_pending_status) + ||(NULL!=gpphLibContext->CBInfo.pClientRdNdefCb) + ||(CHK_NDEF_NOT_DONE == gpphLibContext->ndef_cntx.is_ndef)) + { + /*Previous callback is pending*/ + RetVal = NFCSTATUS_REJECTED; + } + else if(gpphLibContext->ndef_cntx.is_ndef == FALSE) + { + /*no Ndef Support in tag*/ + RetVal = NFCSTATUS_NON_NDEF_COMPLIANT; + } + else if((gpphLibContext->ndef_cntx.is_ndef == TRUE) + &&(0 == gpphLibContext->ndef_cntx.NdefActualSize)) + { + /*Card is empty- So Returning length as zero*/ + psRd->length = 0; + RetVal = NFCSTATUS_SUCCESS; + } +#ifdef LLCP_TRANSACT_CHANGES + else if ((LLCP_STATE_RESET_INIT != gpphLibContext->llcp_cntx.sLlcpContext.state) + && (LLCP_STATE_CHECKED != gpphLibContext->llcp_cntx.sLlcpContext.state)) + { + RetVal= NFCSTATUS_BUSY; + } +#endif /* #ifdef LLCP_TRANSACT_CHANGES */ + else + { + gpphLibContext->psRemoteDevList->psRemoteDevInfo->SessionOpened = SESSION_OPEN; + gpphLibContext->ndef_cntx.eLast_Call = NdefRd; + if((((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType == + phHal_eMifare_PICC) && (((phHal_sRemoteDevInformation_t*) + hRemoteDevice)->RemoteDevInfo.Iso14443A_Info.Sak != 0)&& + ((NULL == gpphLibContext->psBufferedAuth) + ||(phHal_eMifareAuthentA == gpphLibContext->psBufferedAuth->cmd.MfCmd)) + ) + { + if(NULL != gpphLibContext->psBufferedAuth) + { + if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sRecvData.buffer); + } + if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sSendData.buffer); + } + phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth); + } + gpphLibContext->psBufferedAuth + =(phLibNfc_sTransceiveInfo_t *) + phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t)); + gpphLibContext->psBufferedAuth->addr = + (uint8_t)gpphLibContext->ndef_cntx.psNdefMap + ->StdMifareContainer.currentBlock; + gpphLibContext->psBufferedAuth->cmd.MfCmd = phHal_eMifareRead16; + gpphLibContext->psBufferedAuth->sSendData.length + = 0; + gpphLibContext->psBufferedAuth->sRecvData.length + = MIFARE_STD_BLOCK_SIZE; + gpphLibContext->psBufferedAuth->sRecvData.buffer + = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); + gpphLibContext->psBufferedAuth->sSendData.buffer + = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); + } + if(eLibNfcHalStatePresenceChk != + gpphLibContext->LibNfcState.next_state) + { + uint8_t cr_index = 0; + gpphLibContext->ndef_cntx.psUpperNdefMsg = psRd; + for (cr_index = 0; cr_index < PH_FRINFC_NDEFMAP_CR; cr_index++) + { + RetVal= phFriNfc_NdefMap_SetCompletionRoutine( + gpphLibContext->ndef_cntx.psNdefMap, + cr_index, + phLibNfc_Ndef_Read_Cb, + (void *)gpphLibContext); + + } + gpphLibContext->ndef_cntx.NdefContinueRead =(uint8_t) ((phLibNfc_Ndef_EBegin==Offset) ? + PH_FRINFC_NDEFMAP_SEEK_BEGIN : + PH_FRINFC_NDEFMAP_SEEK_CUR); + /* call below layer Ndef Read*/ + RetVal = phFriNfc_NdefMap_RdNdef(gpphLibContext->ndef_cntx.psNdefMap, + gpphLibContext->ndef_cntx.psUpperNdefMsg->buffer, + (uint32_t*)&gpphLibContext->ndef_cntx.psUpperNdefMsg->length, + gpphLibContext->ndef_cntx.NdefContinueRead); + + RetVal = PHNFCSTATUS(RetVal); + if(NFCSTATUS_INSUFFICIENT_STORAGE == RetVal) + { + gpphLibContext->ndef_cntx.psUpperNdefMsg->length = 0; + RetVal = NFCSTATUS_SUCCESS; + } + } + else + { + gpphLibContext->CBInfo.pClientRdNdefCb= NULL; + RetVal = NFCSTATUS_PENDING; + } + if(NFCSTATUS_PENDING == RetVal) + { + gpphLibContext->CBInfo.pClientRdNdefCb = pNdefRead_RspCb; + gpphLibContext->CBInfo.pClientRdNdefCntx = pContext; + gpphLibContext->status.GenCb_pending_status=TRUE; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; + + } + else if (NFCSTATUS_SUCCESS == RetVal) + { + RetVal= NFCSTATUS_SUCCESS; + } + else + { + /*Ndef read failed*/ + RetVal = NFCSTATUS_FAILED; + } + } + return RetVal; +} +/* Response callback for phLibNfc_Ndef_Read */ +STATIC +void phLibNfc_Ndef_Read_Cb(void* Context,NFCSTATUS status) +{ + NFCSTATUS RetStatus = NFCSTATUS_SUCCESS; + pphLibNfc_RspCb_t pClientCb=NULL; + phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)Context; + void *pUpperLayerContext=NULL; + phHal_sRemoteDevInformation_t *ps_rem_dev_info = NULL; + + if(pLibNfc_Ctxt != gpphLibContext) + { + /*wrong context returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { /*shutdown called before completion of Ndef read allow + shutdown to happen */ + phLibNfc_Pending_Shutdown(); + RetStatus = NFCSTATUS_SHUTDOWN; + } + else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) + { + RetStatus = NFCSTATUS_ABORTED; + } + else + { + gpphLibContext->status.GenCb_pending_status = FALSE; + if (gpphLibContext->psBufferedAuth != NULL && gpphLibContext->ndef_cntx.psNdefMap != NULL) { + gpphLibContext->psBufferedAuth->addr = (uint8_t) + gpphLibContext->ndef_cntx.psNdefMap->StdMifareContainer.currentBlock; + } + + if(NFCSTATUS_FAILED == status ) + { + /*During Ndef read operation tag was not present in RF + field of reader*/ + RetStatus = NFCSTATUS_FAILED; + gpphLibContext->LastTrancvSuccess = FALSE; + gpphLibContext->ndef_cntx.is_ndef = FALSE; + ps_rem_dev_info = (phHal_sRemoteDevInformation_t *) + gpphLibContext->Connected_handle; + if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType && + ((0x08 == (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak & 0x08)) || + (0x01 == ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak)))) + { + + /* card type is mifare 1k/4k, then reconnect */ + RetStatus = phHal4Nfc_Connect(gpphLibContext->psHwReference, + ps_rem_dev_info, + (pphHal4Nfc_ConnectCallback_t) + phLibNfc_Reconnect_Mifare_Cb, + (void *)gpphLibContext); + } + + } + else if(status == NFCSTATUS_SUCCESS) + { + gpphLibContext->LastTrancvSuccess = TRUE; + RetStatus = NFCSTATUS_SUCCESS; + } + else + { + gpphLibContext->LastTrancvSuccess = FALSE; + RetStatus = NFCSTATUS_FAILED; + } + } + /*update the current state as connected*/ + phLibNfc_UpdateCurState(status,gpphLibContext); + + pClientCb = gpphLibContext->CBInfo.pClientRdNdefCb; + pUpperLayerContext = gpphLibContext->CBInfo.pClientRdNdefCntx; + + gpphLibContext->CBInfo.pClientRdNdefCb = NULL; + gpphLibContext->CBInfo.pClientRdNdefCntx = NULL; + if(NFCSTATUS_PENDING != RetStatus) + { + if (NULL != pClientCb) + { + /*Notify to upper layer status and read bytes*/ + pClientCb(pUpperLayerContext,RetStatus); + } + } + } + return; +} + +/** +* Write NDEF to a tag. +* +* This function allows the user to write a NDEF data to already connected NFC +* tag.Function writes a complete NDEF message to a tag. If a NDEF message +* already exists in the tag, it will be overwritten. When the transaction is +* complete,a notification callback is notified. +*/ +NFCSTATUS phLibNfc_Ndef_Write( + phLibNfc_Handle hRemoteDevice, + phNfc_sData_t *psWr, + pphLibNfc_RspCb_t pNdefWrite_RspCb, + void* pContext + ) +{ + NFCSTATUS RetVal = NFCSTATUS_FAILED; + uint8_t NdefWriteType=0xFF; + /*LibNfc is initilized or not */ + if((NULL == gpphLibContext)|| + (gpphLibContext->LibNfcState.cur_state + == eLibNfcHalStateShutdown)) + { + RetVal = NFCSTATUS_NOT_INITIALISED; + }/*Check for application has sent the valid parameters*/ + else if((NULL == psWr) || (NULL == pNdefWrite_RspCb) + || (NULL == psWr->buffer) + || (NULL == pContext) + || (0 ==hRemoteDevice)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + else if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { /* Lib Nfc Shutdown*/ + RetVal= NFCSTATUS_SHUTDOWN; + } + else if(0 == gpphLibContext->Connected_handle) + { + RetVal=NFCSTATUS_TARGET_NOT_CONNECTED; + } + else if(hRemoteDevice != gpphLibContext->Connected_handle) + { + RetVal=NFCSTATUS_INVALID_HANDLE; + } + else if((TRUE == gpphLibContext->status.GenCb_pending_status)|| + (gpphLibContext->ndef_cntx.is_ndef == CHK_NDEF_NOT_DONE)) + { + /* Previous callback is pending or Tag is not NDEF tag*/ + RetVal = NFCSTATUS_REJECTED; + PHDBG_INFO("LIbNfc:Previous Callback is Pending"); + } + else if(FALSE == gpphLibContext->ndef_cntx.is_ndef) + { + RetVal = NFCSTATUS_NON_NDEF_COMPLIANT; + } + else if(psWr->length > gpphLibContext->ndef_cntx.NdefLength) + { + RetVal = NFCSTATUS_NOT_ENOUGH_MEMORY; + } +#ifdef LLCP_TRANSACT_CHANGES + else if ((LLCP_STATE_RESET_INIT != gpphLibContext->llcp_cntx.sLlcpContext.state) + && (LLCP_STATE_CHECKED != gpphLibContext->llcp_cntx.sLlcpContext.state)) + { + RetVal= NFCSTATUS_BUSY; + } +#endif /* #ifdef LLCP_TRANSACT_CHANGES */ + else + { + uint8_t cr_index = 0; + gpphLibContext->ndef_cntx.psUpperNdefMsg = psWr; + gpphLibContext->ndef_cntx.AppWrLength= psWr->length; + gpphLibContext->ndef_cntx.eLast_Call = NdefWr; + gpphLibContext->psRemoteDevList->psRemoteDevInfo->SessionOpened + = SESSION_OPEN; + if((((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType == + phHal_eMifare_PICC) && (((phHal_sRemoteDevInformation_t*) + hRemoteDevice)->RemoteDevInfo.Iso14443A_Info.Sak != 0)&& + ((NULL == gpphLibContext->psBufferedAuth) + ||(phHal_eMifareAuthentA == + gpphLibContext->psBufferedAuth->cmd.MfCmd)) + ) + { + if(NULL != gpphLibContext->psBufferedAuth) + { + if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sRecvData.buffer); + } + if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sSendData.buffer); + } + phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth); + } + gpphLibContext->psBufferedAuth + =(phLibNfc_sTransceiveInfo_t *) + phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t)); + gpphLibContext->psBufferedAuth->addr = + (uint8_t)gpphLibContext->ndef_cntx.psNdefMap + ->StdMifareContainer.currentBlock; + gpphLibContext->psBufferedAuth->cmd.MfCmd = phHal_eMifareRead16; + gpphLibContext->psBufferedAuth->sSendData.length + = 0; + gpphLibContext->psBufferedAuth->sRecvData.length + = MIFARE_STD_BLOCK_SIZE; + gpphLibContext->psBufferedAuth->sRecvData.buffer + = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); + gpphLibContext->psBufferedAuth->sSendData.buffer + = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); + } + if(eLibNfcHalStatePresenceChk == + gpphLibContext->LibNfcState.next_state) + { + gpphLibContext->CBInfo.pClientWrNdefCb = NULL; + RetVal = NFCSTATUS_PENDING; + } + else + { + for (cr_index = 0; cr_index < PH_FRINFC_NDEFMAP_CR; cr_index++) + { + /* Registering the Completion Routine.*/ + RetVal= phFriNfc_NdefMap_SetCompletionRoutine( + gpphLibContext->ndef_cntx.psNdefMap, + cr_index, + phLibNfc_Ndef_Write_Cb, + (void *)gpphLibContext); + + } + if(0 == psWr->length) + { + /* Length of bytes to be written Zero- Erase the Tag */ + RetVal = phFriNfc_NdefMap_EraseNdef(gpphLibContext->ndef_cntx.psNdefMap); + } + else + { + /*Write from beginning or current location*/ + NdefWriteType = PH_FRINFC_NDEFMAP_SEEK_BEGIN; + /*Call FRI Ndef Write*/ + RetVal=phFriNfc_NdefMap_WrNdef(gpphLibContext->ndef_cntx.psNdefMap, + gpphLibContext->ndef_cntx.psUpperNdefMsg->buffer, + (uint32_t*)&gpphLibContext->ndef_cntx.psUpperNdefMsg->length, + NdefWriteType); + } + if(NFCSTATUS_PENDING == RetVal) + { + gpphLibContext->CBInfo.pClientWrNdefCb = pNdefWrite_RspCb; + gpphLibContext->CBInfo.pClientWrNdefCntx = pContext; + gpphLibContext->status.GenCb_pending_status=TRUE; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; + } + else + { + RetVal = NFCSTATUS_FAILED; + } + } + } + return RetVal; +} + +/* Response callback for phLibNfc_Ndef_Write */ +STATIC +void phLibNfc_Ndef_Write_Cb(void* Context,NFCSTATUS status) +{ + + pphLibNfc_RspCb_t pClientCb=NULL; + phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)Context; + void *pUpperLayerContext=NULL; + phHal_sRemoteDevInformation_t *ps_rem_dev_info = NULL; + + if(pLibNfc_Ctxt != gpphLibContext) + { /*wrong context returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { /*shutdown called before completion of Ndef write allow + shutdown to happen */ + phLibNfc_Pending_Shutdown(); + status = NFCSTATUS_SHUTDOWN; + } + else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) + { + status = NFCSTATUS_ABORTED; + } + else + { + gpphLibContext->status.GenCb_pending_status = FALSE; + if (gpphLibContext->psBufferedAuth != NULL && gpphLibContext->ndef_cntx.psNdefMap != NULL) { + gpphLibContext->psBufferedAuth->addr = (uint8_t) + gpphLibContext->ndef_cntx.psNdefMap->TLVStruct.NdefTLVBlock; + } + if(status == NFCSTATUS_FAILED ) + { + status = NFCSTATUS_FAILED; + gpphLibContext->LastTrancvSuccess = FALSE; + /*During Ndef write operation tag was not present in RF + field of reader*/ + ps_rem_dev_info = (phHal_sRemoteDevInformation_t *) + gpphLibContext->Connected_handle; + if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType && + 0x08 == (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak & 0x08))) + { + + + /* card type is mifare 1k/4k, then reconnect */ + status = phHal4Nfc_Connect(gpphLibContext->psHwReference, + ps_rem_dev_info, + (pphHal4Nfc_ConnectCallback_t) + phLibNfc_Reconnect_Mifare_Cb, + (void *)gpphLibContext); + } + } + else if( status== NFCSTATUS_SUCCESS) + { + gpphLibContext->LastTrancvSuccess = TRUE; + status = NFCSTATUS_SUCCESS; + if(gpphLibContext->ndef_cntx.AppWrLength > + gpphLibContext->ndef_cntx.NdefLength) + { + status = NFCSTATUS_NOT_ENOUGH_MEMORY; + } + else + { + pLibNfc_Ctxt->ndef_cntx.NdefActualSize = + pLibNfc_Ctxt->ndef_cntx.psUpperNdefMsg->length; + } + } + else + { + gpphLibContext->LastTrancvSuccess = FALSE; + status = NFCSTATUS_FAILED;; + } + } + phLibNfc_UpdateCurState(status,gpphLibContext); + + pClientCb = gpphLibContext->CBInfo.pClientWrNdefCb; + pUpperLayerContext = gpphLibContext->CBInfo.pClientWrNdefCntx; + + gpphLibContext->CBInfo.pClientWrNdefCb = NULL; + gpphLibContext->CBInfo.pClientWrNdefCntx = NULL; + if(NFCSTATUS_PENDING !=status) + { + if (NULL != pClientCb) + { + /*Notify to upper layer status and No. of bytes + actually written */ + pClientCb(pUpperLayerContext, status); + } + } + } + return; +} + + +/** +* Initialize structures needed for the Ndef +* related operation such as Check Ndef, read, write +* and Ndef foramt.only once allocation +*/ +void phLibNfc_Ndef_Init(void) +{ + if(gpphLibContext->psTransInfo==NULL) + { + /*Allocate memory for Transceiveinformation Structure*/ + gpphLibContext->psTransInfo = (phLibNfc_sTransceiveInfo_t *) + phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t)); + } + if(gpphLibContext->psTransInfo==NULL) + { + /*exception: Not enough memory*/ + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,1); + + } + if(NULL == gpphLibContext->ndef_cntx.psNdefMap) + { + /*Allocate memory for NDEF Mapping Component Context Structure*/ + gpphLibContext->ndef_cntx.psNdefMap = (phFriNfc_NdefMap_t *) + phOsalNfc_GetMemory(sizeof(phFriNfc_NdefMap_t)); + } + if(NULL != gpphLibContext->ndef_cntx.psNdefMap) + { + /*Allocation successful*/ + (void)memset(gpphLibContext->ndef_cntx.psNdefMap,0,sizeof(phFriNfc_NdefMap_t)); + gpphLibContext->ndef_cntx.NdefSendRecvLen = NDEF_SENDRCV_BUF_LEN; + gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf = + (uint8_t*) phOsalNfc_GetMemory(gpphLibContext-> + ndef_cntx.NdefSendRecvLen); + + if(NULL != gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf) + { + (void)memset(gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf, + 0, + gpphLibContext->ndef_cntx.NdefSendRecvLen); + + gpphLibContext->psOverHalCtxt =(phFriNfc_OvrHal_t *) + phOsalNfc_GetMemory(sizeof(phFriNfc_OvrHal_t)); + } + } + if(NULL == gpphLibContext->psOverHalCtxt) + { /*exception: Not enough memory*/ + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,1); + } + else + { + + (void)memset(gpphLibContext->psOverHalCtxt,0, + sizeof(phFriNfc_OvrHal_t)); + + /* Initialize the Overlapped hal structure*/ + gpphLibContext->psOverHalCtxt->psHwReference = + gpphLibContext->psHwReference; + if(NULL == gpphLibContext->psDevInputParam ) + { + gpphLibContext->psDevInputParam = (phHal_sDevInputParam_t *) + phOsalNfc_GetMemory(sizeof(phHal_sDevInputParam_t)); + } + gpphLibContext->ndef_cntx.is_ndef = CHK_NDEF_NOT_DONE; + } + if(NULL == gpphLibContext->ndef_cntx.ndef_fmt) + { + /*Allocate memory for Ndef format structure*/ + gpphLibContext->ndef_cntx.ndef_fmt = (phFriNfc_sNdefSmtCrdFmt_t *) + phOsalNfc_GetMemory(sizeof(phFriNfc_sNdefSmtCrdFmt_t)); + } + if(NULL != gpphLibContext->ndef_cntx.ndef_fmt) + { + (void)memset(gpphLibContext->ndef_cntx.ndef_fmt, + 0, + sizeof(phFriNfc_sNdefSmtCrdFmt_t)); + } + else + { + /*exception: Not enough memory*/ + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,1); + } + return; +} +/** +* Free the allocated memory used for Ndef operations +*/ +void phLibNfc_Ndef_DeInit(void) +{ + /* If only allocated then only free the memory*/ + if(gpphLibContext->ndef_cntx.psNdefMap !=NULL) + { + if(gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf !=NULL) + { + phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf); + gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf=NULL; + } + phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.psNdefMap); + gpphLibContext->ndef_cntx.psNdefMap =NULL; + } + + if(NULL != gpphLibContext->ndef_cntx.ndef_fmt) + { + phOsalNfc_FreeMemory(gpphLibContext->ndef_cntx.ndef_fmt); + gpphLibContext->ndef_cntx.ndef_fmt = NULL; + } + + if(gpphLibContext->psOverHalCtxt !=NULL) + { + phOsalNfc_FreeMemory(gpphLibContext->psOverHalCtxt); + gpphLibContext->psOverHalCtxt =NULL; + } + if(gpphLibContext->psDevInputParam !=NULL) + { + phOsalNfc_FreeMemory(gpphLibContext->psDevInputParam); + gpphLibContext->psDevInputParam = NULL; + } + if(gpphLibContext->psTransInfo!=NULL) + { + phOsalNfc_FreeMemory(gpphLibContext->psTransInfo); + gpphLibContext->psTransInfo= NULL; + } +} + + +/** +* This function allows the user to check whether a particular Remote Device +* is NDEF compliant or not +*/ +NFCSTATUS phLibNfc_Ndef_CheckNdef(phLibNfc_Handle hRemoteDevice, + pphLibNfc_ChkNdefRspCb_t pCheckNdef_RspCb, + void* pContext) +{ + NFCSTATUS RetVal = NFCSTATUS_FAILED; + + + if((NULL == gpphLibContext)|| + (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) + { + /*Lib Nfc not initialized*/ + RetVal = NFCSTATUS_NOT_INITIALISED; + } + else if((NULL == pCheckNdef_RspCb)|| + (NULL==pContext)|| + (hRemoteDevice == 0)) + { + /*parameter sent by upper layer are not valid */ + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + RetVal = NFCSTATUS_SHUTDOWN; + } + else if(0 == gpphLibContext->Connected_handle) + { + RetVal=NFCSTATUS_TARGET_NOT_CONNECTED; + } + else if(hRemoteDevice != gpphLibContext->Connected_handle) + { + RetVal=NFCSTATUS_INVALID_HANDLE; + } +#ifdef LLCP_TRANSACT_CHANGES + else if ((LLCP_STATE_RESET_INIT != gpphLibContext->llcp_cntx.sLlcpContext.state) + && (LLCP_STATE_CHECKED != gpphLibContext->llcp_cntx.sLlcpContext.state)) + { + RetVal= NFCSTATUS_BUSY; + } +#endif /* #ifdef LLCP_TRANSACT_CHANGES */ + else + { + uint8_t cr_index = 0; + static uint16_t data_cnt = 0; + /* Allocate memory for the ndef related structure */ + gpphLibContext->ndef_cntx.NdefSendRecvLen=300; + gpphLibContext->ndef_cntx.eLast_Call = ChkNdef; + + /* Resets the component instance */ + RetVal = phFriNfc_NdefMap_Reset( gpphLibContext->ndef_cntx.psNdefMap, + gpphLibContext->psOverHalCtxt, + (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice, + gpphLibContext->psDevInputParam, + gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf, + gpphLibContext->ndef_cntx.NdefSendRecvLen, + gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf, + &(gpphLibContext->ndef_cntx.NdefSendRecvLen), + &(data_cnt)); + + + for (cr_index = 0; cr_index < PH_FRINFC_NDEFMAP_CR; cr_index++) + { + /* Register the callback for the check ndef */ + RetVal = phFriNfc_NdefMap_SetCompletionRoutine( + gpphLibContext->ndef_cntx.psNdefMap, + cr_index, + phLibNfc_Ndef_CheckNdef_Cb, + (void *)gpphLibContext); + } + /*call below layer check Ndef function*/ + RetVal = phFriNfc_NdefMap_ChkNdef(gpphLibContext->ndef_cntx.psNdefMap); + RetVal =PHNFCSTATUS(RetVal); + + if(RetVal== NFCSTATUS_PENDING) + { + RetVal = NFCSTATUS_PENDING; + } + else if((RetVal == NFCSTATUS_FAILED) || (RetVal ==(PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_REMOTE_DEVICE)))) + { + RetVal= NFCSTATUS_FAILED; + } + else + { + if((0x00 == gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id)|| + (PH_OSALNFC_INVALID_TIMER_ID == gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id)) + { + gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id = + phOsalNfc_Timer_Create(); + } + if((0x00 == gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id)|| + (PH_OSALNFC_INVALID_TIMER_ID == gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id)) + { + RetVal = NFCSTATUS_FAILED; + } + else + { + phOsalNfc_Timer_Start(gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id, + CHK_NDEF_TIMER_TIMEOUT,CheckNdef_timer_cb,NULL); + RetVal = NFCSTATUS_PENDING; + } + } + if(RetVal== NFCSTATUS_PENDING) + { + gpphLibContext->CBInfo.pClientCkNdefCb = pCheckNdef_RspCb; + gpphLibContext->CBInfo.pClientCkNdefCntx = pContext; + gpphLibContext->status.GenCb_pending_status=TRUE; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; + } + + } + return RetVal; +} + +/* Response callback for phLibNfc_Ndef_CheckNdef */ +STATIC +void phLibNfc_Ndef_CheckNdef_Cb(void *pContext,NFCSTATUS status) +{ + phLibNfc_ChkNdef_Info_t Ndef_Info; + NFCSTATUS RetStatus = NFCSTATUS_SUCCESS; + pphLibNfc_ChkNdefRspCb_t pClientCb=NULL; + phLibNfc_LibContext_t *pLibNfc_Ctxt = + (phLibNfc_LibContext_t *)pContext; + void *pUpperLayerContext=NULL; + phHal_sRemoteDevInformation_t *ps_rem_dev_info = NULL; + + Ndef_Info.ActualNdefMsgLength = 0; + Ndef_Info.MaxNdefMsgLength = 0; + Ndef_Info.NdefCardState = PHLIBNFC_NDEF_CARD_INVALID; + if(pLibNfc_Ctxt != gpphLibContext) + { /*wrong context returned from below layer*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + ps_rem_dev_info = (phHal_sRemoteDevInformation_t *) + gpphLibContext->Connected_handle; + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { /*shutdown called before completion of check Ndef, allow + shutdown to happen */ + phLibNfc_Pending_Shutdown(); + RetStatus = NFCSTATUS_SHUTDOWN; + } + else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) + { + RetStatus = NFCSTATUS_ABORTED; + } + else + { + if(status == NFCSTATUS_SUCCESS) + { + /*Tag is Ndef tag*/ + gpphLibContext->ndef_cntx.is_ndef = TRUE; + (void)phFriNfc_NdefMap_GetContainerSize( + pLibNfc_Ctxt->ndef_cntx.psNdefMap, + &(pLibNfc_Ctxt->ndef_cntx.NdefLength), + &(pLibNfc_Ctxt->ndef_cntx.NdefActualSize)); + /*Get the data size support by particular ndef card */ + Ndef_Info.ActualNdefMsgLength = pLibNfc_Ctxt->ndef_cntx.NdefActualSize; + Ndef_Info.MaxNdefMsgLength = pLibNfc_Ctxt->ndef_cntx.NdefLength; + gpphLibContext->LastTrancvSuccess = TRUE; + RetStatus =NFCSTATUS_SUCCESS; + } + else if (PHNFCSTATUS(status) != NFCSTATUS_MORE_INFORMATION ) + { + /*Ndef check Failed.Issue a PresenceChk to ascertain if tag is + still in the field*/ + RetStatus = phHal4Nfc_PresenceCheck( + gpphLibContext->psHwReference, + phLibNfc_Ndef_ChkNdef_Pchk_Cb, + (void *)gpphLibContext + ); + } + else + { + RetStatus = NFCSTATUS_FAILED; + gpphLibContext->LastTrancvSuccess = FALSE; + gpphLibContext->ndef_cntx.is_ndef = FALSE; + + if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType) && + (0x08 == (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak & 0x08))) + { + + /* card type is mifare 1k/4k, then reconnect */ + RetStatus = phHal4Nfc_Connect(gpphLibContext->psHwReference, + ps_rem_dev_info, + (pphHal4Nfc_ConnectCallback_t) + phLibNfc_Reconnect_Mifare_Cb, + (void *)gpphLibContext); + } + else + { + if((phHal_eJewel_PICC == ps_rem_dev_info->RemDevType) + &&(TOPAZ_NDEF_BITMASK & + ps_rem_dev_info->RemoteDevInfo.Jewel_Info.HeaderRom0)) + { + gpphLibContext->ndef_cntx.is_ndef = TRUE; + RetStatus = phFriNfc_NdefMap_GetContainerSize( + pLibNfc_Ctxt->ndef_cntx.psNdefMap, + &(pLibNfc_Ctxt->ndef_cntx.NdefLength), + &(pLibNfc_Ctxt->ndef_cntx.NdefActualSize)); + /*Get the data size support by particular ndef card */ + Ndef_Info.ActualNdefMsgLength = + pLibNfc_Ctxt->ndef_cntx.NdefActualSize; + Ndef_Info.MaxNdefMsgLength + = pLibNfc_Ctxt->ndef_cntx.NdefLength + = (TOPAZ_LEN_BITMASK & + ps_rem_dev_info->RemoteDevInfo.Jewel_Info.HeaderRom0? + TOPAZ_DYNAMIC_LEN:TOPAZ_STATIC_CARD_LEN); + RetStatus = NFCSTATUS_SUCCESS; + } + } + } + gpphLibContext->LibNfcState.cur_state=eLibNfcHalStateConnect; + } + gpphLibContext->status.GenCb_pending_status = FALSE; + /* Update the current state */ + phLibNfc_UpdateCurState(RetStatus,gpphLibContext); + if(NFCSTATUS_PENDING != RetStatus) + { + if(((ps_rem_dev_info->RemDevType == phHal_eMifare_PICC) + && (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak != 0)&& + ((NULL == gpphLibContext->psBufferedAuth) + ||(phHal_eMifareAuthentA == gpphLibContext->psBufferedAuth->cmd.MfCmd))) + ) + { + if(NULL != gpphLibContext->psBufferedAuth) + { + if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sRecvData.buffer); + } + if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sSendData.buffer); + } + phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth); + } + gpphLibContext->psBufferedAuth + =(phLibNfc_sTransceiveInfo_t *) + phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t)); + gpphLibContext->psBufferedAuth->addr = + (uint8_t)gpphLibContext->ndef_cntx.psNdefMap + ->StdMifareContainer.currentBlock; + gpphLibContext->psBufferedAuth->cmd.MfCmd = phHal_eMifareRead16; + gpphLibContext->psBufferedAuth->sSendData.length + = 0; + gpphLibContext->psBufferedAuth->sRecvData.length + = MIFARE_STD_BLOCK_SIZE; + gpphLibContext->psBufferedAuth->sRecvData.buffer + = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); + gpphLibContext->psBufferedAuth->sSendData.buffer + = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); + } + pClientCb = gpphLibContext->CBInfo.pClientCkNdefCb; + pUpperLayerContext = gpphLibContext->CBInfo.pClientCkNdefCntx; + gpphLibContext->CBInfo.pClientCkNdefCb = NULL; + gpphLibContext->CBInfo.pClientCkNdefCntx = NULL; + if(NULL != pClientCb) + { + if (!RetStatus) + { + switch (pLibNfc_Ctxt->ndef_cntx.psNdefMap->CardState) + { + case PH_NDEFMAP_CARD_STATE_INITIALIZED: + { + Ndef_Info.NdefCardState = + PHLIBNFC_NDEF_CARD_INITIALISED; + break; + } + + case PH_NDEFMAP_CARD_STATE_READ_ONLY: + { + Ndef_Info.NdefCardState = + PHLIBNFC_NDEF_CARD_READ_ONLY; + break; + } + + case PH_NDEFMAP_CARD_STATE_READ_WRITE: + { + Ndef_Info.NdefCardState = + PHLIBNFC_NDEF_CARD_READ_WRITE; + break; + } + + default: + { + Ndef_Info.NdefCardState = + PHLIBNFC_NDEF_CARD_INVALID; + break; + } + } + } + /* call the upper check ndef callback */ + pClientCb(pUpperLayerContext,Ndef_Info,RetStatus); + } + } + } + return; +} + +/*Callback for Presence check call from Chk Ndef*/ +STATIC void phLibNfc_Ndef_ChkNdef_Pchk_Cb(void *pContext, + NFCSTATUS status + ) +{ + phLibNfc_ChkNdef_Info_t Ndef_Info = {0,0,0}; + NFCSTATUS RetStatus = NFCSTATUS_SUCCESS; + pphLibNfc_ChkNdefRspCb_t pClientCb=NULL; + phLibNfc_LibContext_t *pLibNfc_Ctxt = + (phLibNfc_LibContext_t *)pContext; + void *pUpperLayerContext=NULL; + phHal_sRemoteDevInformation_t *ps_rem_dev_info = NULL; + if(NFCSTATUS_SUCCESS == status) + { + RetStatus = NFCSTATUS_FAILED; + gpphLibContext->ndef_cntx.is_ndef = FALSE; + } + else + { + RetStatus = NFCSTATUS_TARGET_LOST; + } + if(pLibNfc_Ctxt != gpphLibContext) + { /*wrong context returned from below layer*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + ps_rem_dev_info = (phHal_sRemoteDevInformation_t *) + gpphLibContext->Connected_handle; + if(((ps_rem_dev_info->RemDevType == phHal_eMifare_PICC) + && (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak != 0)&& + ((NULL == gpphLibContext->psBufferedAuth) + ||(phHal_eMifareAuthentA == gpphLibContext->psBufferedAuth->cmd.MfCmd))) + ) + { + if(NULL != gpphLibContext->psBufferedAuth) + { + if(NULL != gpphLibContext->psBufferedAuth->sRecvData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sRecvData.buffer); + } + if(NULL != gpphLibContext->psBufferedAuth->sSendData.buffer) + { + phOsalNfc_FreeMemory( + gpphLibContext->psBufferedAuth->sSendData.buffer); + } + phOsalNfc_FreeMemory(gpphLibContext->psBufferedAuth); + } + gpphLibContext->psBufferedAuth + =(phLibNfc_sTransceiveInfo_t *) + phOsalNfc_GetMemory(sizeof(phLibNfc_sTransceiveInfo_t)); + gpphLibContext->psBufferedAuth->addr = + (uint8_t)gpphLibContext->ndef_cntx.psNdefMap + ->StdMifareContainer.currentBlock; + gpphLibContext->psBufferedAuth->cmd.MfCmd = phHal_eMifareRead16; + gpphLibContext->psBufferedAuth->sSendData.length + = 0; + gpphLibContext->psBufferedAuth->sRecvData.length + = MIFARE_STD_BLOCK_SIZE; + gpphLibContext->psBufferedAuth->sRecvData.buffer + = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); + gpphLibContext->psBufferedAuth->sSendData.buffer + = (uint8_t *)phOsalNfc_GetMemory(MIFARE_STD_BLOCK_SIZE); + } + pClientCb = gpphLibContext->CBInfo.pClientCkNdefCb; + pUpperLayerContext = gpphLibContext->CBInfo.pClientCkNdefCntx; + gpphLibContext->CBInfo.pClientCkNdefCb = NULL; + gpphLibContext->CBInfo.pClientCkNdefCntx = NULL; + if(NULL != pClientCb) + { + Ndef_Info.NdefCardState = PHLIBNFC_NDEF_CARD_INVALID; + /* call the upper check ndef callback */ + pClientCb(pUpperLayerContext,Ndef_Info,RetStatus); + } + } + return; +} +/* Check Ndef Timer Callback*/ +STATIC void CheckNdef_timer_cb(uint32_t timer_id, void *pContext) +{ + PHNFC_UNUSED_VARIABLE(pContext); + phOsalNfc_Timer_Stop(timer_id); + phOsalNfc_Timer_Delete(gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id); + gpphLibContext->ndef_cntx.Chk_Ndef_Timer_Id = 0x00; + phLibNfc_Ndef_CheckNdef_Cb((void *)gpphLibContext,NFCSTATUS_MORE_INFORMATION); +} + +void phLibNfc_Reconnect_Mifare_Cb ( + void *pContext, + phHal_sRemoteDevInformation_t *psRemoteDevInfo, + NFCSTATUS status) +{ + phLibNfc_ChkNdef_Info_t Ndef_Info; + phLibNfc_LibContext_t *pLibNfc_Ctxt = + (phLibNfc_LibContext_t *)pContext; + void *pUpperLayerContext = NULL; + switch(gpphLibContext->ndef_cntx.eLast_Call) + { + case ChkNdef: + { + pphLibNfc_ChkNdefRspCb_t pClientCb=NULL; + pClientCb = pLibNfc_Ctxt->CBInfo.pClientCkNdefCb; + pUpperLayerContext = pLibNfc_Ctxt->CBInfo.pClientCkNdefCntx; + pLibNfc_Ctxt->CBInfo.pClientCkNdefCb = NULL; + pLibNfc_Ctxt->CBInfo.pClientCkNdefCntx = NULL; + if (NULL != pClientCb) + { + status = (NFCSTATUS_SUCCESS == status? + NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST); + Ndef_Info.ActualNdefMsgLength = 0; + Ndef_Info.MaxNdefMsgLength = 0; + /* call the upper check ndef callback */ + pClientCb(pUpperLayerContext,Ndef_Info,status); + } + } + break; + case NdefRd: + { + pphLibNfc_RspCb_t pClientCb = pLibNfc_Ctxt->CBInfo.pClientRdNdefCb; + pUpperLayerContext = pLibNfc_Ctxt->CBInfo.pClientRdNdefCntx; + pLibNfc_Ctxt->CBInfo.pClientRdNdefCb = NULL; + pLibNfc_Ctxt->CBInfo.pClientRdNdefCntx = NULL; + if (NULL != pClientCb) + { + status = (NFCSTATUS_SUCCESS == status? + NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST); + /* call the upper ndef read callback */ + pClientCb(pUpperLayerContext,status); + } + } + break; + case NdefWr: + { + pphLibNfc_RspCb_t pClientCb = pLibNfc_Ctxt->CBInfo.pClientWrNdefCb; + pUpperLayerContext = pLibNfc_Ctxt->CBInfo.pClientWrNdefCntx; + pLibNfc_Ctxt->CBInfo.pClientWrNdefCb = NULL; + pLibNfc_Ctxt->CBInfo.pClientWrNdefCntx = NULL; + if (NULL != pClientCb) + { + status = (NFCSTATUS_SUCCESS == status? + NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST); + /* call the upper ndef write callback */ + pClientCb(pUpperLayerContext,status); + } + } + break; + case NdefFmt: +#ifdef LIBNFC_READONLY_NDEF + case NdefReadOnly: +#endif /* #ifdef LIBNFC_READONLY_NDEF */ + { + pphLibNfc_RspCb_t pClientCb = + pLibNfc_Ctxt->ndef_cntx.pClientNdefFmtCb; + pUpperLayerContext= pLibNfc_Ctxt->ndef_cntx.pClientNdefFmtCntx; + pLibNfc_Ctxt->ndef_cntx.pClientNdefFmtCb = NULL; + pLibNfc_Ctxt->ndef_cntx.pClientNdefFmtCntx = NULL; + if (NULL != pClientCb) + { + status = (NFCSTATUS_SUCCESS == status? + NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST); + /* call the upper ndef format callback */ + pClientCb(pUpperLayerContext,status); + } + } + break; + case RawTrans: + { + phNfc_sData_t trans_resp; + pphLibNfc_TransceiveCallback_t pClientCb = + pLibNfc_Ctxt->CBInfo.pClientTransceiveCb; + trans_resp.length = 0; + pUpperLayerContext = pLibNfc_Ctxt->CBInfo.pClientTranseCntx; + pLibNfc_Ctxt->CBInfo.pClientTranseCntx= NULL; + pLibNfc_Ctxt->CBInfo.pClientTransceiveCb= NULL; + if (NULL != pClientCb) + { + status = (NFCSTATUS_SUCCESS == status? + NFCSTATUS_FAILED:NFCSTATUS_TARGET_LOST); + /* call the upper transceive callback */ + pClientCb(pUpperLayerContext, + (phLibNfc_Handle)psRemoteDevInfo, + & trans_resp, + status); + } + } + break; + default: + { + } + break; + } + +} +/** +* Target format to make it NDEF compliant +*/ +NFCSTATUS phLibNfc_RemoteDev_FormatNdef(phLibNfc_Handle hRemoteDevice, + phNfc_sData_t* pScrtKey, + pphLibNfc_RspCb_t pNdefformat_RspCb, + void* pContext + ) +{ + NFCSTATUS RetVal = NFCSTATUS_FAILED; + + static uint8_t mif_std_key[6] ={0}, + Index = 0; + if((NULL == gpphLibContext) + ||(gpphLibContext->LibNfcState.cur_state + == eLibNfcHalStateShutdown)) + { + /*Lib Nfc not initialized*/ + RetVal = NFCSTATUS_NOT_INITIALISED; + } + else if((NULL == pContext) + || (NULL == pNdefformat_RspCb) + ||(NULL == pScrtKey) + ||(0 == hRemoteDevice)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + else if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + RetVal= NFCSTATUS_SHUTDOWN; + } + else if(0 == gpphLibContext->Connected_handle) + { + RetVal=NFCSTATUS_TARGET_NOT_CONNECTED; + } + else if(hRemoteDevice != gpphLibContext->Connected_handle) + { + RetVal=NFCSTATUS_INVALID_HANDLE; + } + else if((TRUE == gpphLibContext->status.GenCb_pending_status)|| + (NULL != gpphLibContext->ndef_cntx.pClientNdefFmtCb) + ||(gpphLibContext->ndef_cntx.is_ndef == TRUE)) + { + /*Previous Callback is Pending*/ + RetVal = NFCSTATUS_REJECTED; + PHDBG_INFO("LIbNfc:Previous Callback is Pending"); + } +#ifdef LLCP_TRANSACT_CHANGES + else if ((LLCP_STATE_RESET_INIT != gpphLibContext->llcp_cntx.sLlcpContext.state) + && (LLCP_STATE_CHECKED != gpphLibContext->llcp_cntx.sLlcpContext.state)) + { + RetVal= NFCSTATUS_BUSY; + } +#endif /* #ifdef LLCP_TRANSACT_CHANGES */ + else + { + uint8_t fun_id; + gpphLibContext->ndef_cntx.eLast_Call = NdefFmt; + gpphLibContext->ndef_cntx.NdefSendRecvLen = NDEF_SENDRCV_BUF_LEN; + + /* Call ndef format reset, this will initialize the ndef + format structure, and appropriate values are filled */ + RetVal = phFriNfc_NdefSmtCrd_Reset(gpphLibContext->ndef_cntx.ndef_fmt, + gpphLibContext->psOverHalCtxt, + (phHal_sRemoteDevInformation_t*)hRemoteDevice, + gpphLibContext->psDevInputParam, + gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf, + &(gpphLibContext->ndef_cntx.NdefSendRecvLen)); + for(fun_id = 0; fun_id < PH_FRINFC_SMTCRDFMT_CR; fun_id++) + { + /* Register for all the callbacks */ + RetVal = phFriNfc_NdefSmtCrd_SetCR(gpphLibContext->ndef_cntx.ndef_fmt, + fun_id, + phLibNfc_Ndef_format_Cb, + gpphLibContext); + } + /* mif_std_key is required to format the mifare 1k/4k card */ + for (Index =0 ;Index < (pScrtKey->length); Index++ ) + { + mif_std_key[Index] = *(pScrtKey->buffer++); + } + /* Start smart card formatting function */ + RetVal = phFriNfc_NdefSmtCrd_Format(gpphLibContext->ndef_cntx.ndef_fmt, + mif_std_key); + RetVal = PHNFCSTATUS(RetVal); + if(RetVal== NFCSTATUS_PENDING) + { + gpphLibContext->ndef_cntx.pClientNdefFmtCb = pNdefformat_RspCb; + gpphLibContext->ndef_cntx.pClientNdefFmtCntx = pContext; + gpphLibContext->status.GenCb_pending_status=TRUE; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; + } + else + { + RetVal = NFCSTATUS_FAILED; + } + } + return RetVal; +} + +#ifdef LIBNFC_READONLY_NDEF + +NFCSTATUS +phLibNfc_ConvertToReadOnlyNdef ( + phLibNfc_Handle hRemoteDevice, + phNfc_sData_t* pScrtKey, + pphLibNfc_RspCb_t pNdefReadOnly_RspCb, + void* pContext + ) +{ + NFCSTATUS ret_val = NFCSTATUS_FAILED; + static uint8_t mif_std_key[6] ={0}, + Index = 0; + + if ((NULL == gpphLibContext) + || (gpphLibContext->LibNfcState.cur_state + == eLibNfcHalStateShutdown)) + { + /* LibNfc not initialized */ + ret_val = NFCSTATUS_NOT_INITIALISED; + } + else if ((NULL == pContext) + || (NULL == pNdefReadOnly_RspCb) + || (0 == hRemoteDevice)) + { + ret_val = NFCSTATUS_INVALID_PARAMETER; + } + else if (gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + ret_val = NFCSTATUS_SHUTDOWN; + } + else if (0 == gpphLibContext->Connected_handle) + { + ret_val = NFCSTATUS_TARGET_NOT_CONNECTED; + } + else if (hRemoteDevice != gpphLibContext->Connected_handle) + { + ret_val = NFCSTATUS_INVALID_HANDLE; + } + else if ((TRUE == gpphLibContext->status.GenCb_pending_status) + || (NULL != gpphLibContext->ndef_cntx.pClientNdefFmtCb) + || (FALSE == gpphLibContext->ndef_cntx.is_ndef)) + { + /* Previous Callback is Pending */ + ret_val = NFCSTATUS_REJECTED; + PHDBG_INFO("LIbNfc:Previous Callback is Pending"); + } + else + { + gpphLibContext->ndef_cntx.eLast_Call = NdefReadOnly; + + if(eLibNfcHalStatePresenceChk != gpphLibContext->LibNfcState.next_state) + { + phHal_sRemoteDevInformation_t *ps_rem_dev_info = + (phHal_sRemoteDevInformation_t *)hRemoteDevice; + uint8_t fun_id; + + switch (ps_rem_dev_info->RemDevType) + { + case phHal_eMifare_PICC: + case phHal_eISO14443_A_PICC: + { + if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType) + && (0x00 != ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak)) + { + for (fun_id = 0; fun_id < PH_FRINFC_NDEFMAP_CR; fun_id++) + { + /* Register the callback for the check ndef */ + ret_val = phFriNfc_NdefMap_SetCompletionRoutine ( + gpphLibContext->ndef_cntx.psNdefMap, + fun_id, phLibNfc_Ndef_ReadOnly_Cb, + (void *)gpphLibContext); + } + + /* Start mifare NFC read only function */ + /* mif_std_key is required to format the mifare 1k/4k card */ + if(pScrtKey != NULL && pScrtKey->length == MIFARE_STD_KEY_LEN) + { + for (Index =0 ;Index < (pScrtKey->length); Index++ ) + { + mif_std_key[Index] = *(pScrtKey->buffer++); + } + + ret_val = phFriNfc_MifareStdMap_ConvertToReadOnly ( + gpphLibContext->ndef_cntx.psNdefMap, mif_std_key); + ret_val = PHNFCSTATUS(ret_val); + } + } + else + { + gpphLibContext->ndef_cntx.NdefSendRecvLen = NDEF_SENDRCV_BUF_LEN; + + /* Call ndef format reset, this will initialize the ndef + format structure, and appropriate values are filled */ + ret_val = phFriNfc_NdefSmtCrd_Reset (gpphLibContext->ndef_cntx.ndef_fmt, + gpphLibContext->psOverHalCtxt, + (phHal_sRemoteDevInformation_t*)hRemoteDevice, + gpphLibContext->psDevInputParam, + gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf, + &(gpphLibContext->ndef_cntx.NdefSendRecvLen)); + + for(fun_id = 0; fun_id < PH_FRINFC_SMTCRDFMT_CR; fun_id++) + { + /* Register for all the callbacks */ + ret_val = phFriNfc_NdefSmtCrd_SetCR (gpphLibContext->ndef_cntx.ndef_fmt, + fun_id, phLibNfc_Ndef_ReadOnly_Cb, + gpphLibContext); + } + + /* Start smart card formatting function */ + ret_val = phFriNfc_NdefSmtCrd_ConvertToReadOnly ( + gpphLibContext->ndef_cntx.ndef_fmt); + ret_val = PHNFCSTATUS(ret_val); + } + break; + } + + case phHal_eJewel_PICC: + case phHal_eISO15693_PICC: + { +// MC: Got the feedback this was #if 0'd because it was resetting the lock bits +// read in check NDEF, and these should not be reset here already. +#if 0 + static uint16_t data_cnt = 0; + + /* Resets the component instance */ + ret_val = phFriNfc_NdefMap_Reset (gpphLibContext->ndef_cntx.psNdefMap, + gpphLibContext->psOverHalCtxt, + (phLibNfc_sRemoteDevInformation_t*)hRemoteDevice, + gpphLibContext->psDevInputParam, + gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf, + gpphLibContext->ndef_cntx.NdefSendRecvLen, + gpphLibContext->ndef_cntx.psNdefMap->SendRecvBuf, + &(gpphLibContext->ndef_cntx.NdefSendRecvLen), + &(data_cnt)); +#endif /* #if 0 */ + + + for (fun_id = 0; fun_id < PH_FRINFC_NDEFMAP_CR; fun_id++) + { + /* Register the callback for the check ndef */ + ret_val = phFriNfc_NdefMap_SetCompletionRoutine ( + gpphLibContext->ndef_cntx.psNdefMap, + fun_id, phLibNfc_Ndef_ReadOnly_Cb, + (void *)gpphLibContext); + } + + /* call below layer check Ndef function */ + ret_val = phFriNfc_NdefMap_ConvertToReadOnly ( + gpphLibContext->ndef_cntx.psNdefMap); + ret_val = PHNFCSTATUS(ret_val); + break; + } + + default: + { + /* Tag not supported */ + ret_val = NFCSTATUS_REJECTED; + break; + } + } + } + else + { + gpphLibContext->ndef_cntx.pClientNdefFmtCb= NULL; + ret_val = NFCSTATUS_PENDING; + } + + if (NFCSTATUS_PENDING == ret_val) + { + gpphLibContext->ndef_cntx.pClientNdefFmtCb = pNdefReadOnly_RspCb; + gpphLibContext->ndef_cntx.pClientNdefFmtCntx = pContext; + + gpphLibContext->status.GenCb_pending_status = TRUE; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; + } + else + { + ret_val = NFCSTATUS_FAILED; + } + } + return ret_val; +} + +#endif /* #ifdef LIBNFC_READONLY_NDEF */ + +/** +* Response callback for NDEF format. +*/ +STATIC +void phLibNfc_Ndef_format_Cb(void *Context,NFCSTATUS status) +{ + NFCSTATUS RetStatus = NFCSTATUS_SUCCESS; + pphLibNfc_RspCb_t pClientCb=NULL; + phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)Context; + void *pUpperLayerContext=NULL; + phHal_sRemoteDevInformation_t *ps_rem_dev_info = NULL; + if(pLibNfc_Ctxt != gpphLibContext) + { /*wrong context returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { + /*shutdown is pending so issue shutdown*/ + phLibNfc_Pending_Shutdown(); + RetStatus = NFCSTATUS_SHUTDOWN; + } + else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) + { + RetStatus = NFCSTATUS_ABORTED; + } + else + { + gpphLibContext->status.GenCb_pending_status = FALSE; + if(NFCSTATUS_SUCCESS == status) + { + RetStatus = NFCSTATUS_SUCCESS; + } + else if(PHNFCSTATUS(status)==NFCSTATUS_FAILED) + { + RetStatus = NFCSTATUS_FAILED; + ps_rem_dev_info = (phHal_sRemoteDevInformation_t *) + gpphLibContext->Connected_handle; + if ((phHal_eMifare_PICC == ps_rem_dev_info->RemDevType) && + (0x08 == (ps_rem_dev_info->RemoteDevInfo.Iso14443A_Info.Sak & 0x08))) + { + + /* card type is mifare 1k/4k, then reconnect */ + RetStatus = phHal4Nfc_Connect(gpphLibContext->psHwReference, + (phHal_sRemoteDevInformation_t *) + gpphLibContext->Connected_handle, + (pphHal4Nfc_ConnectCallback_t) + phLibNfc_Reconnect_Mifare_Cb, + (void *)gpphLibContext); + } + } + else + { + /*Target was removed during transaction*/ + RetStatus = NFCSTATUS_FAILED; + } + gpphLibContext->LibNfcState.cur_state =eLibNfcHalStateConnect; + } + phLibNfc_UpdateCurState(status,gpphLibContext); + + pClientCb = gpphLibContext->ndef_cntx.pClientNdefFmtCb; + pUpperLayerContext= gpphLibContext->ndef_cntx.pClientNdefFmtCntx; + gpphLibContext->ndef_cntx.pClientNdefFmtCb = NULL; + gpphLibContext->ndef_cntx.pClientNdefFmtCntx = NULL; + if(NFCSTATUS_PENDING != RetStatus) + { + if (NULL != pClientCb) + { + /* Call the tag format upper layer callback */ + pClientCb(pUpperLayerContext,RetStatus); + } + } + } + return; +} + +#ifdef LIBNFC_READONLY_NDEF +STATIC +void +phLibNfc_Ndef_ReadOnly_Cb ( + void *p_context, + NFCSTATUS status) +{ + NFCSTATUS ret_status = NFCSTATUS_SUCCESS; + pphLibNfc_RspCb_t p_client_cb = NULL; + phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)p_context; + void *p_upper_layer_ctxt = NULL; + + if(pLibNfc_Ctxt != gpphLibContext) + { + /*wrong context returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { + /*shutdown is pending so issue shutdown*/ + phLibNfc_Pending_Shutdown(); + ret_status = NFCSTATUS_SHUTDOWN; + } + else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) + { + ret_status = NFCSTATUS_ABORTED; + } + else + { + gpphLibContext->status.GenCb_pending_status = FALSE; + if(NFCSTATUS_SUCCESS == status) + { + gpphLibContext->ndef_cntx.psNdefMap->CardState = + PH_NDEFMAP_CARD_STATE_READ_ONLY; + ret_status = NFCSTATUS_SUCCESS; + } + else + { + ret_status = NFCSTATUS_FAILED; + } + gpphLibContext->LibNfcState.cur_state =eLibNfcHalStateConnect; + } + + phLibNfc_UpdateCurState(status, gpphLibContext); + + p_client_cb = gpphLibContext->ndef_cntx.pClientNdefFmtCb; + p_upper_layer_ctxt = gpphLibContext->ndef_cntx.pClientNdefFmtCntx; + gpphLibContext->ndef_cntx.pClientNdefFmtCb = NULL; + gpphLibContext->ndef_cntx.pClientNdefFmtCntx = NULL; + if(NFCSTATUS_PENDING != ret_status) + { + if (NULL != p_client_cb) + { + /* Call the tag format upper layer callback */ + p_client_cb (p_upper_layer_ctxt, ret_status); + } + } + } +} +#endif /* #ifdef LIBNFC_READONLY_NDEF */ + +STATIC +void phLibNfc_Ndef_SrchNdefCnt_Cb(void *context, NFCSTATUS status) +{ + static NFCSTATUS RegPrSt=FALSE; + uint8_t RegStatus=0; + NFCSTATUS RetVal = NFCSTATUS_SUCCESS ; + uint32_t Index=0; + + + PHNFC_UNUSED_VARIABLE(context); + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { /*shutdown called before completion of Ndef read allow + shutdown to happen */ + phLibNfc_Pending_Shutdown(); + RetVal = NFCSTATUS_SHUTDOWN; + } + else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) + { + RetVal = NFCSTATUS_ABORTED; + } + else if(NFCSTATUS_SUCCESS != status) + { + RetVal = status; + } + else + { + /* This conditional branch is for QMORE fix */ + } + gpphLibContext->status.GenCb_pending_status = FALSE; + + phLibNfc_UpdateCurState(status,gpphLibContext); + /* Read is not success send failed to upperlayer Call back*/ + if( RetVal!= NFCSTATUS_SUCCESS ) + { + if((RetVal!=NFCSTATUS_SHUTDOWN)&& (RetVal!=NFCSTATUS_ABORTED)) + { + RetVal= NFCSTATUS_FAILED; + } + gpphLibContext->CBInfo.pClientNdefNtfRespCb( + gpphLibContext->CBInfo.pClientNdefNtfRespCntx, + NULL, + gpphLibContext->Connected_handle, + RetVal); + gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL; + gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL; + return; + } + + /*Get the Number of records ( If Raw record parameter is null then API gives number of Records*/ + RetVal = phFriNfc_NdefRecord_GetRecords( + gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer, + gpphLibContext->phLib_NdefRecCntx.ndef_message.length, + NULL, + gpphLibContext->phLib_NdefRecCntx.IsChunked, + &(gpphLibContext->phLib_NdefRecCntx.NumberOfRawRecords)); + + NdefInfo.pNdefMessage = gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer; + NdefInfo.NdefMessageLengthActual = gpphLibContext->ndef_cntx.NdefActualSize; + NdefInfo.NdefMessageLengthMaximum = gpphLibContext->ndef_cntx.NdefLength; + NdefInfo.NdefRecordCount =0; + + /*Allocate memory to hold the records Read*/ + NdefInfo.pNdefRecord = phOsalNfc_GetMemory + (sizeof(phFriNfc_NdefRecord_t)* gpphLibContext->phLib_NdefRecCntx.NumberOfRawRecords ); + if(NULL==NdefInfo.pNdefRecord) + { + gpphLibContext->CBInfo.pClientNdefNtfRespCb( + gpphLibContext->CBInfo.pClientNdefNtfRespCntx, + NULL, + gpphLibContext->Connected_handle, + NFCSTATUS_FAILED); + gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL; + gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL; + return; + } + + pNdefRecord=NdefInfo.pNdefRecord; + /*If phLibNfc_Ndef_SearchNdefContent Reg type is NULL return all the Records*/ + if(gpphLibContext->ndef_cntx.pNdef_NtfSrch_Type==NULL) + { + RetVal = phFriNfc_NdefRecord_GetRecords( + gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer, + gpphLibContext->phLib_NdefRecCntx.ndef_message.length, + gpphLibContext->phLib_NdefRecCntx.RawRecords, + gpphLibContext->phLib_NdefRecCntx.IsChunked, + &(gpphLibContext->phLib_NdefRecCntx.NumberOfRawRecords)); + + for (Index = 0; Index < gpphLibContext->phLib_NdefRecCntx.NumberOfRawRecords; Index++) + { + RetVal = phFriNfc_NdefRecord_Parse( + pNdefRecord, + gpphLibContext->phLib_NdefRecCntx.RawRecords[Index]); + pNdefRecord++; + NdefInfo.NdefRecordCount++; + } + } + else + { + + /* Look for registerd TNF */ + RetVal = phFriNfc_NdefReg_DispatchPacket( + &(gpphLibContext->phLib_NdefRecCntx.NdefReg), + gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer, + (uint16_t)gpphLibContext->phLib_NdefRecCntx.ndef_message.length); + if(NFCSTATUS_SUCCESS != RetVal) + { + /*phFriNfc_NdefReg_DispatchPacket is failed call upper layer*/ + gpphLibContext->CBInfo.pClientNdefNtfRespCb(gpphLibContext->CBInfo.pClientNdefNtfRespCntx, + NULL,gpphLibContext->Connected_handle,NFCSTATUS_FAILED); + gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL; + gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL; + return; + } + + while(1 != RegStatus) + { + /* Process the NDEF records, If match FOUND we will get Call back*/ + RegStatus = phFriNfc_NdefReg_Process( &(gpphLibContext->phLib_NdefRecCntx.NdefReg), + &RegPrSt); + if(RegPrSt == TRUE) + { + /* Processing Done */ + break; + } + /*If match found the CbParam will be updated by lower layer, copy the record info*/ + for(Index=0;IndexphLib_NdefRecCntx.CbParam.Count;Index++) + { + pNdefRecord->Tnf = gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].Tnf; + pNdefRecord->TypeLength = + gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].TypeLength; + pNdefRecord->PayloadLength = + gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].PayloadLength; + pNdefRecord->IdLength = + gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].IdLength; + pNdefRecord->Flags = + gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].Flags; + + pNdefRecord->Id = phOsalNfc_GetMemory(pNdefRecord->IdLength); + pNdefRecord->Type = phOsalNfc_GetMemory(pNdefRecord->TypeLength); + pNdefRecord->PayloadData = phOsalNfc_GetMemory(pNdefRecord->PayloadLength); + + (void)memcpy(pNdefRecord->Id, + gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].Id, + pNdefRecord->IdLength); + (void)memcpy(pNdefRecord->PayloadData, + gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].PayloadData, + pNdefRecord->PayloadLength); + (void)memcpy(pNdefRecord->Type, + gpphLibContext->phLib_NdefRecCntx.CbParam.Records[Index].Type, + pNdefRecord->TypeLength); + + pNdefRecord++; + NdefInfo.NdefRecordCount++; + } + } + } + /* If no record found call upper layer with failed status*/ + if(pNdefRecord == NdefInfo.pNdefRecord) + { + NdefInfo.NdefRecordCount =0; + gpphLibContext->CBInfo.pClientNdefNtfRespCb( + gpphLibContext->CBInfo.pClientNdefNtfRespCntx, + &NdefInfo,gpphLibContext->Connected_handle, + NFCSTATUS_SUCCESS); + + } + else + { + /*Call upperlayer Call back with match records*/ + + gpphLibContext->CBInfo.pClientNdefNtfRespCb( + gpphLibContext->CBInfo.pClientNdefNtfRespCntx, + &NdefInfo,gpphLibContext->Connected_handle, + NFCSTATUS_SUCCESS); + /*Remove entry from FRI*/ + RetVal = phFriNfc_NdefReg_RmCb( + &(gpphLibContext->phLib_NdefRecCntx.NdefReg), + gpphLibContext->phLib_NdefRecCntx.NdefCb ); + /*Free the memory*/ + if(gpphLibContext->ndef_cntx.pNdef_NtfSrch_Type!=NULL) + { + pNdefRecord=NdefInfo.pNdefRecord; + for(Index=0;IndexphLib_NdefRecCntx.CbParam.Count;Index++) + { + phOsalNfc_FreeMemory(pNdefRecord->Id); + phOsalNfc_FreeMemory(pNdefRecord->PayloadData); + phOsalNfc_FreeMemory(pNdefRecord->Type); + pNdefRecord++; + } + } + } + + gpphLibContext->CBInfo.pClientNdefNtfRespCb = NULL; + gpphLibContext->CBInfo.pClientNdefNtfRespCntx = NULL; + +} + +STATIC +void phLibNfc_Ndef_Rtd_Cb( void *CallBackParam) +{ + /*There will be single call back given to all match + It's processed in phLibNfc_Ndef_SrchNdefCnt_Cb*/ + PHNFC_UNUSED_VARIABLE(CallBackParam); +} + +NFCSTATUS phLibNfc_Ndef_SearchNdefContent( + phLibNfc_Handle hRemoteDevice, + phLibNfc_Ndef_SrchType_t* psSrchTypeList, + uint8_t uNoSrchRecords, + pphLibNfc_Ndef_Search_RspCb_t pNdefNtfRspCb, + void * pContext + ) +{ + + NFCSTATUS RetVal =NFCSTATUS_SUCCESS; + uint32_t Index=0; + uint8_t cr_index = 0; + + + if((NULL == gpphLibContext) || + (gpphLibContext->LibNfcState.cur_state + == eLibNfcHalStateShutdown)) + { + RetVal = NFCSTATUS_NOT_INITIALISED; + } + /* Check the state for DeInit is called or not,if yes return NFCSTATUS_SHUTDOWN*/ + else if(gpphLibContext->LibNfcState.next_state + == eLibNfcHalStateShutdown) + { + RetVal= NFCSTATUS_SHUTDOWN; + } + else if( (NULL == pNdefNtfRspCb) || + (NULL == pContext ) || + (0 == hRemoteDevice)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + else if( (NULL != psSrchTypeList) && (0==uNoSrchRecords)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + else if(0 == gpphLibContext->Connected_handle) + { /*presently no target or tag is connected*/ + RetVal=NFCSTATUS_TARGET_NOT_CONNECTED; + } + else if(hRemoteDevice != gpphLibContext->Connected_handle) + { /*This handle of the device sent by application is not connected */ + RetVal=NFCSTATUS_INVALID_HANDLE; + } + else if((TRUE == gpphLibContext->status.GenCb_pending_status) + ||(NULL!=gpphLibContext->CBInfo.pClientNdefNtfRespCb)) + { + /*Previous callback is pending*/ + RetVal = NFCSTATUS_REJECTED; + } + else + { + gpphLibContext->ndef_cntx.pNdef_NtfSrch_Type = psSrchTypeList; + + if(psSrchTypeList!=NULL) + { + /*Maximum records supported*/ + gpphLibContext->phLib_NdefRecCntx.NumberOfRecords = 255; + /*Reset the FRI component to add the Reg type*/ + RetVal = phFriNfc_NdefReg_Reset( + &(gpphLibContext->phLib_NdefRecCntx.NdefReg), + gpphLibContext->phLib_NdefRecCntx.NdefTypes_array, + &(gpphLibContext->phLib_NdefRecCntx.RecordsExtracted), + &(gpphLibContext->phLib_NdefRecCntx.CbParam), + gpphLibContext->phLib_NdefRecCntx.ChunkedRecordsarray, + gpphLibContext->phLib_NdefRecCntx.NumberOfRecords); + + gpphLibContext->phLib_NdefRecCntx.NdefCb = phOsalNfc_GetMemory(sizeof(phFriNfc_NdefReg_Cb_t)); + if(gpphLibContext->phLib_NdefRecCntx.NdefCb==NULL) + { + /*exception: Not enough memory*/ + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,1); + } + gpphLibContext->phLib_NdefRecCntx.NdefCb->NdefCallback = phLibNfc_Ndef_Rtd_Cb; + /*Copy the TNF types to search in global structure*/ + gpphLibContext->phLib_NdefRecCntx.NdefCb->NumberOfRTDs = uNoSrchRecords; + for(Index=0;IndexphLib_NdefRecCntx.NdefCb->NdefType[Index] = psSrchTypeList->Type; + gpphLibContext->phLib_NdefRecCntx.NdefCb->Tnf[Index] = psSrchTypeList->Tnf ; + gpphLibContext->phLib_NdefRecCntx.NdefCb->NdeftypeLength[Index] = psSrchTypeList->TypeLength; + psSrchTypeList++; + } + /* Add the TNF type to FRI component*/ + + RetVal = phFriNfc_NdefReg_AddCb(&(gpphLibContext->phLib_NdefRecCntx.NdefReg), + gpphLibContext->phLib_NdefRecCntx.NdefCb ); + + } + gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer = + phOsalNfc_GetMemory(gpphLibContext->ndef_cntx.NdefActualSize); + gpphLibContext->phLib_NdefRecCntx.ndef_message.length = + gpphLibContext->ndef_cntx.NdefActualSize; + /*Set Complete routine for NDEF Read*/ + for (cr_index = 0; cr_index < PH_FRINFC_NDEFMAP_CR; cr_index++) + { + RetVal= phFriNfc_NdefMap_SetCompletionRoutine( + gpphLibContext->ndef_cntx.psNdefMap, + cr_index, + phLibNfc_Ndef_SrchNdefCnt_Cb, + (void *)gpphLibContext); + + } + gpphLibContext->ndef_cntx.NdefContinueRead = PH_FRINFC_NDEFMAP_SEEK_BEGIN; + /* call below layer Ndef Read*/ + RetVal = phFriNfc_NdefMap_RdNdef(gpphLibContext->ndef_cntx.psNdefMap, + gpphLibContext->phLib_NdefRecCntx.ndef_message.buffer, + (uint32_t*)&gpphLibContext->phLib_NdefRecCntx.ndef_message.length, + PH_FRINFC_NDEFMAP_SEEK_BEGIN); + + if(NFCSTATUS_PENDING == RetVal) + { + gpphLibContext->CBInfo.pClientNdefNtfRespCb = pNdefNtfRspCb; + gpphLibContext->CBInfo.pClientNdefNtfRespCntx = pContext; + gpphLibContext->status.GenCb_pending_status=TRUE; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; + } + else if (NFCSTATUS_SUCCESS == RetVal) + { + RetVal= NFCSTATUS_SUCCESS; + } + else + { + /*Ndef read failed*/ + RetVal = NFCSTATUS_FAILED; + } + } + return RetVal; + +} + diff --git a/libnfc-nxp/phLibNfc_ndef_raw.h b/libnfc-nxp/phLibNfc_ndef_raw.h new file mode 100644 index 0000000..036803c --- /dev/null +++ b/libnfc-nxp/phLibNfc_ndef_raw.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phLibNfc_ndef_raw.h + * + * Project: NFC-FRI 1.1 + * + * $Workfile:: phLibNfc_1.1.h $ + * $Modtime:: $ + * $Author: ing07299 $ + * $Revision: 1.15 $ + * + */ +#ifndef PHLIBNFC_NDEF_RAW_H +#define PHLIBNFC_NDEF_RAW_H + +/*Check for type of NDEF Calls*/ +typedef enum phLibNfc_Last_Call{ + ChkNdef = 0x00, + NdefRd, + NdefWr, + NdefFmt, +#ifdef LIBNFC_READONLY_NDEF + NdefReadOnly, +#endif /* #ifdef LIBNFC_READONLY_NDEF */ + RawTrans +} phLibNfc_Last_Call_t; + +#define TAG_MIFARE 0x01 +#define TAG_FELICA 0x02 +#define TAG_JEWEL 0x04 +#define TAG_ISO14443_4A 0x08 +#define TAG_ISO14443_4B 0x10 +#define TAG_NFC_IP1 0x20 + +#define NDEF_READ_TIMER_TIMEOUT 60U +#define CHK_NDEF_TIMER_TIMEOUT 60U +#define NDEF_SENDRCV_BUF_LEN 252U +#define NDEF_TEMP_RECV_LEN 256U +#define NDEF_MIFARE_UL_LEN 46U +#define NDEF_FELICA_LEN 0U/*len to be set when supported*/ +#define NDEF_JEWEL_TOPAZ_LEN 0U +#define NDEF_ISO14443_4A_LEN 4096U +#define NDEF_ISO14443_4B_LEN 0U +#define NDEF_MIFARE_4K_LEN 3356U +#define NDEF_MIFARE_1K_LEN 716U +#define MIFARE_STD_DEFAULT_KEY {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} +#define MIFARE_STD_KEY_LEN 6 +#define ISO_SAK_VALUE 0x20U + + +#define UNKNOWN_BLOCK_ADDRESS 0xFF /***/ +#define SESSION_OPEN 0x01 + + +extern void phLibNfc_Ndef_Init(void); +extern void phLibNfc_Ndef_DeInit(void); +extern phLibNfc_Ndef_Info_t NdefInfo; +extern phFriNfc_NdefRecord_t *pNdefRecord; + +#endif + diff --git a/libnfc-nxp/phLibNfc_target.c b/libnfc-nxp/phLibNfc_target.c new file mode 100644 index 0000000..982d8dd --- /dev/null +++ b/libnfc-nxp/phLibNfc_target.c @@ -0,0 +1,404 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! + * \file phLibNfc_Target.c + + * Project: NFC FRI 1.1 + * + * $Date: Thu Oct 15 15:24:43 2009 $ + * $Author: ing07299 $ + * $Revision: 1.12 $ + * $Aliases: NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK944_SDK,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK949_SDK_INT,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK1003_SDK,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1008_SDK,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1007_SDK,NFC_FRI1.1_WK1014_SDK,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1024_SDK $ + * + */ + +/* +************************* Header Files *************************************** +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* +*************************** Macro's **************************************** +*/ + +#ifndef STATIC_DISABLE +#define STATIC static +#else +//#undef STATIC +#define STATIC +#endif +/* +*************************** Global Variables ********************************** +*/ + +/* +*************************** Static Function Declaration *********************** +*/ + +/* Remote device receive callback */ +STATIC void phLibNfc_RemoteDev_Receive_Cb( + void *context, + phNfc_sData_t *rec_rsp_data, + NFCSTATUS status + ); + +/* Remote device Send callback */ +STATIC void phLibNfc_RemoteDev_Send_Cb( + void *Context, + NFCSTATUS status + ); + +/* +*************************** Function Definitions ****************************** +*/ + +/** +* Interface used to receive data from initiator at target side during P2P +* communication. +*/ +NFCSTATUS phLibNfc_RemoteDev_Receive(phLibNfc_Handle hRemoteDevice, + pphLibNfc_Receive_RspCb_t pReceiveRspCb, + void *pContext + ) +{ + NFCSTATUS RetVal = NFCSTATUS_FAILED; + /*Check Lib Nfc is initialized*/ + if((NULL == gpphLibContext)|| + (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) + { + RetVal = NFCSTATUS_NOT_INITIALISED; + }/*Check application has sent valid parameters*/ + else if (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateRelease) + { + RetVal = NFCSTATUS_DESELECTED; + } + else if((NULL == pReceiveRspCb) + || (NULL == pContext) + || (0 == hRemoteDevice)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + RetVal = NFCSTATUS_SHUTDOWN; + } + else if((TRUE == gpphLibContext->status.GenCb_pending_status) + ||(NULL!=gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb) + ||(phHal_eNfcIP1_Target== + ((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType)) + { + /*Previous callback is pending or if initiator uses this api */ + RetVal = NFCSTATUS_REJECTED; + }/*check for Discovered initiator handle and handle sent by application */ + else if(gpphLibContext->sNfcIp_Context.Rem_Initiator_Handle != hRemoteDevice) + { + RetVal= NFCSTATUS_INVALID_DEVICE; + } +#ifdef LLCP_TRANSACT_CHANGES + else if ((LLCP_STATE_RESET_INIT != gpphLibContext->llcp_cntx.sLlcpContext.state) + && (LLCP_STATE_CHECKED != gpphLibContext->llcp_cntx.sLlcpContext.state)) + { + RetVal = NFCSTATUS_BUSY; + } +#endif /* #ifdef LLCP_TRANSACT_CHANGES */ + else + { + if(eLibNfcHalStatePresenceChk == + gpphLibContext->LibNfcState.next_state) + { + gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb = NULL; + RetVal = NFCSTATUS_PENDING; + } + else + { + /*Call below layer receive and register the callback with it*/ + PHDBG_INFO("LibNfc:P2P Receive In Progress"); + RetVal =phHal4Nfc_Receive( + gpphLibContext->psHwReference, + (phHal4Nfc_TransactInfo_t*)gpphLibContext->psTransInfo, + (pphLibNfc_Receive_RspCb_t) + phLibNfc_RemoteDev_Receive_Cb, + (void *)gpphLibContext + ); + } + if(NFCSTATUS_PENDING == RetVal) + { + /*Update the Next state as Transaction*/ + gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb= pReceiveRspCb; + gpphLibContext->sNfcIp_Context.pClientNfcIpRxCntx = pContext; + gpphLibContext->status.GenCb_pending_status=TRUE; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; + } + else + { + RetVal = NFCSTATUS_FAILED; + } + } + return RetVal; +} +/** +* Response callback for Remote Device Receive. +*/ +STATIC void phLibNfc_RemoteDev_Receive_Cb( + void *context, + phNfc_sData_t *rec_rsp_data, + NFCSTATUS status + ) +{ + pphLibNfc_Receive_RspCb_t pClientCb=NULL; + + phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)context; + void *pUpperLayerContext=NULL; + + /* Check for the context returned by below layer */ + if(pLibNfc_Ctxt != gpphLibContext) + { /*wrong context returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + pClientCb = gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb; + pUpperLayerContext = gpphLibContext->sNfcIp_Context.pClientNfcIpRxCntx; + + gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb = NULL; + gpphLibContext->sNfcIp_Context.pClientNfcIpRxCntx = NULL; + gpphLibContext->status.GenCb_pending_status = FALSE; + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { /*shutdown called before completion of P2P receive allow + shutdown to happen */ + phLibNfc_Pending_Shutdown(); + status = NFCSTATUS_SHUTDOWN; + } + else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) + { + status = NFCSTATUS_ABORTED; + } + else + { + if((NFCSTATUS_SUCCESS != status) && + (PHNFCSTATUS(status) != NFCSTATUS_MORE_INFORMATION ) ) + { + /*During p2p receive operation initiator was removed + from RF field of target*/ + status = NFCSTATUS_DESELECTED; + } + else + { + status = NFCSTATUS_SUCCESS; + } + } + /* Update current state */ + phLibNfc_UpdateCurState(status,gpphLibContext); + + if (NULL != pClientCb) + { + /*Notify to upper layer status and No. of bytes + actually received */ + pClientCb(pUpperLayerContext, rec_rsp_data, status); + } + } + return; +} + +/** +* Interface used to send data from target to initiator during P2P communication +*/ +NFCSTATUS +phLibNfc_RemoteDev_Send( + phLibNfc_Handle hRemoteDevice, + phNfc_sData_t * pTransferData, + pphLibNfc_RspCb_t pSendRspCb, + void *pContext + ) +{ + NFCSTATUS RetVal = NFCSTATUS_FAILED; + /*Check Lib Nfc stack is initilized*/ + if((NULL == gpphLibContext)|| + (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateShutdown)) + { + RetVal = NFCSTATUS_NOT_INITIALISED; + } + else if (gpphLibContext->LibNfcState.cur_state == eLibNfcHalStateRelease) + { + RetVal = NFCSTATUS_DESELECTED; + } + /*Check application has sent the valid parameters*/ + else if((NULL == pTransferData) + || (NULL == pSendRspCb) + || (NULL == pTransferData->buffer) + || (0 == pTransferData->length) + || (NULL == pContext) + || (0 == hRemoteDevice)) + { + RetVal= NFCSTATUS_INVALID_PARAMETER; + } + else if(gpphLibContext->LibNfcState.next_state == eLibNfcHalStateShutdown) + { + RetVal = NFCSTATUS_SHUTDOWN; + } + else if((TRUE == gpphLibContext->status.GenCb_pending_status) + ||(NULL!=gpphLibContext->sNfcIp_Context.pClientNfcIpRxCb) + ||(phHal_eNfcIP1_Target== + ((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType)) + { + /*Previous callback is pending or local device is Initiator + then don't allow */ + RetVal = NFCSTATUS_REJECTED; + }/*Check for Discovered initiator handle and handle sent by application */ + else if(gpphLibContext->sNfcIp_Context.Rem_Initiator_Handle != hRemoteDevice) + { + RetVal= NFCSTATUS_INVALID_DEVICE; + } + else if((NULL!=gpphLibContext->sNfcIp_Context.pClientNfcIpTxCb)) + { + RetVal =NFCSTATUS_BUSY ; + } +#ifdef LLCP_TRANSACT_CHANGES + else if ((LLCP_STATE_RESET_INIT != gpphLibContext->llcp_cntx.sLlcpContext.state) + && (LLCP_STATE_CHECKED != gpphLibContext->llcp_cntx.sLlcpContext.state)) + { + RetVal= NFCSTATUS_BUSY; + } +#endif /* #ifdef LLCP_TRANSACT_CHANGES */ + else + { + if(eLibNfcHalStatePresenceChk == + gpphLibContext->LibNfcState.next_state) + { + gpphLibContext->sNfcIp_Context.pClientNfcIpTxCb = NULL; + RetVal = NFCSTATUS_PENDING; + } + else + { + if(gpphLibContext->psTransInfo!=NULL) + { + (void)memset(gpphLibContext->psTransInfo, + 0, + sizeof(phLibNfc_sTransceiveInfo_t)); + + gpphLibContext->psTransInfo->addr =UNKNOWN_BLOCK_ADDRESS; + /*pointer to send data */ + gpphLibContext->psTransInfo->sSendData.buffer = + pTransferData->buffer; + /*size of send data*/ + gpphLibContext->psTransInfo->sSendData.length = + pTransferData->length; + + /* Copy remote device type */ + gpphLibContext->sNfcIp_Context.TransactInfoRole.remotePCDType = + ((phHal_sRemoteDevInformation_t*)hRemoteDevice)->RemDevType; + /*Call Hal4 Send API and register callback with it*/ + PHDBG_INFO("LibNfc:P2P send In Progress"); + RetVal= phHal4Nfc_Send( + gpphLibContext->psHwReference, + &(gpphLibContext->sNfcIp_Context.TransactInfoRole), + gpphLibContext->psTransInfo->sSendData, + (pphLibNfc_RspCb_t) + phLibNfc_RemoteDev_Send_Cb, + (void *)gpphLibContext + ); + } + } + if(NFCSTATUS_PENDING == RetVal) + { + /* Update next state to transaction */ + gpphLibContext->sNfcIp_Context.pClientNfcIpTxCb= pSendRspCb; + gpphLibContext->sNfcIp_Context.pClientNfcIpTxCntx = pContext; + gpphLibContext->status.GenCb_pending_status=TRUE; + gpphLibContext->LibNfcState.next_state = eLibNfcHalStateTransaction; + } + else + { + RetVal = NFCSTATUS_FAILED; + } + } + return RetVal; +} + +/* +* Response callback for Remote Device Send. +*/ +STATIC void phLibNfc_RemoteDev_Send_Cb( + void *Context, + NFCSTATUS status + ) +{ + pphLibNfc_RspCb_t pClientCb=NULL; + phLibNfc_LibContext_t *pLibNfc_Ctxt = (phLibNfc_LibContext_t *)Context; + void *pUpperLayerContext=NULL; + + /* Check for the context returned by below layer */ + if(pLibNfc_Ctxt != gpphLibContext) + { /*wrong context returned*/ + phOsalNfc_RaiseException(phOsalNfc_e_InternalErr,1); + } + else + { + if(eLibNfcHalStateShutdown == gpphLibContext->LibNfcState.next_state) + { /*shutdown called before completion p2p send allow + shutdown to happen */ + phLibNfc_Pending_Shutdown(); + status = NFCSTATUS_SHUTDOWN; + } + else if(eLibNfcHalStateRelease == gpphLibContext->LibNfcState.next_state) + { + status = NFCSTATUS_ABORTED; + } + else + { + gpphLibContext->status.GenCb_pending_status = FALSE; + if((NFCSTATUS_SUCCESS != status) && + (PHNFCSTATUS(status) != NFCSTATUS_MORE_INFORMATION ) ) + { + /*During p2p send operation initator was not present in RF + field of target*/ + status = NFCSTATUS_DESELECTED; + } + else + { + status = NFCSTATUS_SUCCESS; + } + } + /* Update current state */ + phLibNfc_UpdateCurState(status,gpphLibContext); + + pClientCb = gpphLibContext->sNfcIp_Context.pClientNfcIpTxCb; + pUpperLayerContext = gpphLibContext->sNfcIp_Context.pClientNfcIpTxCntx; + + gpphLibContext->sNfcIp_Context.pClientNfcIpTxCb = NULL; + gpphLibContext->sNfcIp_Context.pClientNfcIpTxCntx = NULL; + if (NULL != pClientCb) + { + /* Notify to upper layer status and No. of bytes + actually written or send to initiator */ + pClientCb(pUpperLayerContext, status); + } + } + return; +} + + + + diff --git a/libnfc-nxp/phLlcNfc.c b/libnfc-nxp/phLlcNfc.c new file mode 100644 index 0000000..36b442b --- /dev/null +++ b/libnfc-nxp/phLlcNfc.c @@ -0,0 +1,514 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phLlcNfc.c +* \brief Common LLC for the upper layer. +* +* Project: NFC-FRI-1.1 +* +* $Date: Wed Apr 28 17:07:03 2010 $ +* $Author: ing02260 $ +* $Revision: 1.59 $ +* $Aliases: NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +/*************************** Includes *******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*********************** End of includes ****************************/ + +/***************************** Macros *******************************/ + +/************************ End of macros *****************************/ + +/***************************** Global variables *******************************/ + +#ifdef LLC_RELEASE_FLAG + uint8_t g_release_flag; +#endif /* #ifdef LLC_RELEASE_FLAG */ + +/************************ End of global variables *****************************/ + + + +/*********************** Local functions ****************************/ +/** +* \ingroup grp_hal_nfc_llc +* +* \brief \b Init function +* +* \copydoc page_reg Initialise all variables of the LLC component (Asynchronous function). +* +* \param[in] pContext LLC context provided by the upper layer. The LLC +* context will be given to the upper layer through the +* \ref phLlcNfc_Register function +* \param[in] pLinkInfo Link information of the hardware +* +* \retval NFCSTATUS_PENDING If the command is yet to be processed. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* \retval Other errors Errors related to the lower layers +* +*/ +static +NFCSTATUS +phLlcNfc_Init ( + void *pContext, + void *pLinkInfo + ); + +/** +* \ingroup grp_hal_nfc_llc +* +* \brief \b Send function +* +* \copydoc page_reg This asynchronous function gets the information from the upper layer and creates the +* proper LLC packet to send the information it to the hardware. The number of +* bytes written is obtained from the send response callback which has been +* registered in \ref phLlcNfc_Register function +* +* \param[in] pContext LLC context is provided by the upper layer. The LLC +* context earlier was given to the upper layer through the +* \ref phLlcNfc_Register function +* \param[in] pLinkInfo Link information of the hardware. +* \param[in] pLlc_Buf The information given by the upper layer to send it to +* the lower layer +* \param[in] llcBufLength the length of pLlc_Buf, that needs to be sent to the +* lower layer is given by the upper layer +* +* \retval NFCSTATUS_PENDING If the command is yet to be process. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* \retval Other errors Errors related to the lower layers +* +*/ +static +NFCSTATUS +phLlcNfc_Send ( + void *pContext, + void *pLinkInfo, + uint8_t *pLlcBuf, + uint16_t llcBufLength + ); + +/** +* \ingroup grp_hal_nfc_llc +* +* \brief \b Receive function +* +* \copydoc page_reg This asynchronous function gets the length and the required buffer from +* the upper layer to receive the information from the the hardware. The +* received data will be given through the receive response callback +* which has been registered in the \b phLlcNfc_Register function +* +* \param[in] pContext LLC context is provided by the upper layer. The LLC +* context earlier was given to the upper layer through the +* \b phLlcNfc_Register function +* \param[in] pLinkInfo Link information of the hardware +* \param[in] pLlc_Buf The information given by the upper layer to receive data from +* the lower layer +* \param[in] llcBufLength The length of pLlc_Buf given by the upper layer +* +* \retval NFCSTATUS_PENDING If the command is yet to be process. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* \retval Other errors Errors related to the lower layers +* +*/ +static +NFCSTATUS +phLlcNfc_Receive ( + void *pContext, + void *pLinkInfo, + uint8_t *pLlcBuf, + uint16_t llcBufLength + ); +/******************** End of Local functions ************************/ + +/********************** Global variables ****************************/ + +/******************** End of Global Variables ***********************/ + +NFCSTATUS +phLlcNfc_Register ( + phNfcIF_sReference_t *psReference, + phNfcIF_sCallBack_t if_callback, + void *psIFConfig +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Context_t *ps_llc_ctxt = NULL; + phNfcLayer_sCfg_t *psconfig = (phNfcLayer_sCfg_t *)psIFConfig; + + PH_LLCNFC_PRINT("Llc Register called\n"); + if ((NULL == psReference) || (NULL == psIFConfig) || + (NULL == psReference->plower_if) || +#if 0 + (NULL == if_callback.pif_ctxt) || +#endif + (NULL == if_callback.notify) || + (NULL == if_callback.receive_complete) || + (NULL == if_callback.send_complete)) + { + result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Now LLC is in RESET state */ + ps_llc_ctxt = (phLlcNfc_Context_t*)phOsalNfc_GetMemory( + sizeof(phLlcNfc_Context_t)); + if (NULL == ps_llc_ctxt) + { + /* Memory allocation failed */ + result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INSUFFICIENT_RESOURCES); + } + else + { + result = NFCSTATUS_SUCCESS; + + (void)memset(ps_llc_ctxt, 0, sizeof(phLlcNfc_Context_t)); + + /* Register the LLC functions to the upper layer */ + psReference->plower_if->init = (pphNfcIF_Interface_t)&phLlcNfc_Init; + psReference->plower_if->release = (pphNfcIF_Interface_t)&phLlcNfc_Release; + psReference->plower_if->send = (pphNfcIF_Transact_t)&phLlcNfc_Send; + psReference->plower_if->receive = (pphNfcIF_Transact_t)&phLlcNfc_Receive; + /* Copy the LLC context to the upper layer */ + psReference->plower_if->pcontext = ps_llc_ctxt; + + /* Register the callback function from the upper layer */ + ps_llc_ctxt->cb_for_if.receive_complete = if_callback.receive_complete; + ps_llc_ctxt->cb_for_if.send_complete = if_callback.send_complete; + ps_llc_ctxt->cb_for_if.notify = if_callback.notify; + /* Get the upper layer context */ + ps_llc_ctxt->cb_for_if.pif_ctxt = if_callback.pif_ctxt; + + result = phLlcNfc_Interface_Register(ps_llc_ctxt, psconfig); + + if (NFCSTATUS_SUCCESS == result) + { +#ifdef LLC_RELEASE_FLAG + g_release_flag = FALSE; +#endif /* #ifdef LLC_RELEASE_FLAG */ + } + } + } + PH_LLCNFC_DEBUG("Llc Register result : 0x%x\n", result); + return result; +} + +static +NFCSTATUS +phLlcNfc_Init ( + void *pContext, + void *pLinkInfo +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; + phLlcNfc_LlcPacket_t s_packet_info; + + PH_LLCNFC_PRINT("Llc Init called\n"); + if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo)) + { + result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Initialisation */ + ps_llc_ctxt->phwinfo = pLinkInfo; + /* Call the internal frame initialise */ + phLlcNfc_H_Frame_Init(ps_llc_ctxt); + /* Call the internal LLC TL interface initialise */ + result = phLlcNfc_Interface_Init(ps_llc_ctxt); + if (NFCSTATUS_SUCCESS == result) + { + /* Call the internal LLC timer initialise */ + result = phLlcNfc_TimerInit(ps_llc_ctxt); + } + + if (NFCSTATUS_SUCCESS == result) + { + /* Create the static timer */ + phLlcNfc_CreateTimers(); + + /* Create a U frame */ + result = phLlcNfc_H_CreateUFramePayload(ps_llc_ctxt, + &s_packet_info, + &(s_packet_info.llcbuf_len), + phLlcNfc_e_rset); + } + if (NFCSTATUS_SUCCESS == result) + { + /* Call DAL write */ + result = phLlcNfc_Interface_Write(ps_llc_ctxt, + (uint8_t*)&(s_packet_info.s_llcbuf), + (uint32_t)s_packet_info.llcbuf_len); + } + if (NFCSTATUS_PENDING == result) + { + /* Start the timer */ + result = phLlcNfc_StartTimers(PH_LLCNFC_CONNECTIONTIMER, 0); + if (NFCSTATUS_SUCCESS == result) + { + ps_llc_ctxt->s_frameinfo.sent_frame_type = + init_u_rset_frame; + result = NFCSTATUS_PENDING; + } + } + + if (NFCSTATUS_PENDING != result) + { + (void)phLlcNfc_Release(ps_llc_ctxt, pLinkInfo); + } + } + PH_LLCNFC_DEBUG("Llc Init result : 0x%x\n", result); + return result; +} + +NFCSTATUS +phLlcNfc_Release( + void *pContext, + void *pLinkInfo +) +{ + NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; + /* + 1. Free all the memory allocated in initialise + */ + PH_LLCNFC_PRINT("Llc release called\n"); + + if ((NULL != ps_llc_ctxt) && (NULL != pLinkInfo)) + { + result = NFCSTATUS_SUCCESS; + ps_llc_ctxt->phwinfo = pLinkInfo; +#ifdef INCLUDE_DALINIT_DEINIT + if (NULL != ps_llc_ctxt->lower_if.release) + { + result = ps_llc_ctxt->lower_if.release( + ps_llc_ctxt->lower_if.pcontext, + pLinkInfo); + } +#endif + if (NULL != ps_llc_ctxt->lower_if.transact_abort) + { + result = ps_llc_ctxt->lower_if.transact_abort( + ps_llc_ctxt->lower_if.pcontext, + pLinkInfo); + } + if (NULL != ps_llc_ctxt->lower_if.unregister) + { + result = ps_llc_ctxt->lower_if.unregister( + ps_llc_ctxt->lower_if.pcontext, + pLinkInfo); + } + + /* Call the internal LLC timer un-initialise */ + phLlcNfc_TimerUnInit(ps_llc_ctxt); + phLlcNfc_H_Frame_DeInit(&ps_llc_ctxt->s_frameinfo); + (void)memset(ps_llc_ctxt, 0, sizeof(phLlcNfc_Context_t)); + phOsalNfc_FreeMemory(ps_llc_ctxt); + ps_llc_ctxt = NULL; + +#ifdef LLC_RELEASE_FLAG + g_release_flag = TRUE; +#endif /* #ifdef LLC_RELEASE_FLAG */ + + } + PH_LLCNFC_DEBUG("Llc release result : 0x%04X\n", result); + return result; +} + +static +NFCSTATUS +phLlcNfc_Send ( + void *pContext, + void *pLinkInfo, + uint8_t *pLlcBuf, + uint16_t llcBufLength +) +{ + /* + 1. Check the function parameters for valid values + 2. Create the I frame llc payload using the upper layer buffer + 3. Send the updated buffer to the below layer + 4. Store the I frame in a list, till acknowledge is received + */ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; + phLlcNfc_Frame_t *ps_frame_info = NULL; + phLlcNfc_LlcPacket_t s_packet_info; + phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; +#if 0 + uint8_t count = 1; +#endif /* #if 0 */ + + PH_LLCNFC_PRINT ("Llc Send called\n"); + if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo) || + (NULL == pLlcBuf) || (0 == llcBufLength) || + (llcBufLength > PH_LLCNFC_MAX_IFRAME_BUFLEN)) + { + /* Parameter check failed */ + result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + } + else if (ps_llc_ctxt->s_frameinfo.s_send_store.winsize_cnt >= + ps_llc_ctxt->s_frameinfo.window_size) + { + /* Window size check failed */ + result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_NOT_ALLOWED); + } + else + { + ps_frame_info = &(ps_llc_ctxt->s_frameinfo); + ps_store_frame = &(ps_frame_info->s_send_store); + + PH_LLCNFC_DEBUG ("Buffer length : 0x%04X\n", llcBufLength); + PH_LLCNFC_PRINT_BUFFER (pLlcBuf, llcBufLength); + + /* Copy the hardware information */ + ps_llc_ctxt->phwinfo = pLinkInfo; + + /* Create I frame with the user buffer */ + (void)phLlcNfc_H_CreateIFramePayload ( + &(ps_llc_ctxt->s_frameinfo), + &s_packet_info, + pLlcBuf, (uint8_t)llcBufLength); + + + /* Store the I frame in the send list */ + (void)phLlcNfc_H_StoreIFrame (ps_store_frame, s_packet_info); + result = NFCSTATUS_PENDING; + +#ifdef CTRL_WIN_SIZE_COUNT + + /* No check required */ + if ((TRUE != ps_frame_info->write_pending) && + (PH_LLCNFC_READPEND_REMAIN_BYTE != + ps_frame_info->read_pending)) + +#else /* #ifdef CTRL_WIN_SIZE_COUNT */ + + if (1 == ps_frame_info->s_send_store.winsize_cnt) + +#endif /* #ifdef CTRL_WIN_SIZE_COUNT */ + { + /* Call write to the below layer, only if previous write + is completed */ + result = phLlcNfc_Interface_Write (ps_llc_ctxt, + (uint8_t *)&(s_packet_info.s_llcbuf), + (uint32_t)s_packet_info.llcbuf_len); + + if ((NFCSTATUS_PENDING == result) || + (NFCSTATUS_BUSY == PHNFCSTATUS (result))) + { + ps_frame_info->write_status = result; + if (NFCSTATUS_BUSY == PHNFCSTATUS(result)) + { + result = NFCSTATUS_PENDING; + ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t) + ((resend_i_frame == ps_frame_info->write_wait_call) ? + ps_frame_info->write_wait_call : user_i_frame); + } + else + { + /* Start the timer */ + (void)phLlcNfc_StartTimers (PH_LLCNFC_GUARDTIMER, + ps_frame_info->n_s); + + /* "sent_frame_type is updated" only if the data is + written to the lower layer */ + ps_frame_info->sent_frame_type = user_i_frame; + } + } +#if 0 + /* Get the added frame array count */ + count = (uint8_t)((((ps_store_frame->start_pos + + ps_store_frame->winsize_cnt) - count)) % + PH_LLCNFC_MOD_NS_NR); +#endif /* #if 0 */ + } + else + { + ps_frame_info->write_status = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_BUSY); + ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t) + ((resend_i_frame == ps_frame_info->write_wait_call) ? + ps_frame_info->write_wait_call : user_i_frame); + } + } + + + PH_LLCNFC_DEBUG ("Llc Send result : 0x%04X\n", result); + return result; +} + +static +NFCSTATUS +phLlcNfc_Receive ( + void *pContext, + void *pLinkInfo, + uint8_t *pLlcBuf, + uint16_t llcBufLength +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; + phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; + + PH_LLCNFC_PRINT("Llc Receive called\n"); + if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo) || + (NULL == pLlcBuf) || (0 == llcBufLength) || + (llcBufLength > PH_LLCNFC_MAX_IFRAME_BUFLEN)) + { + result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + } + else + { + ps_llc_ctxt->phwinfo = pLinkInfo; + + ps_recv_pkt = &(ps_llc_ctxt->s_frameinfo.s_recvpacket); + /* Always read the first byte to read the length, then + read the entire data later using the 1 byte buffer */ + llcBufLength = PH_LLCNFC_BYTES_INIT_READ; + /* Call write to the below layer */ + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + &(ps_recv_pkt->s_llcbuf.llc_length_byte), + llcBufLength); + + ps_llc_ctxt->s_frameinfo.upper_recv_call = TRUE; + if (NFCSTATUS_PENDING != result) + { + ps_llc_ctxt->state = phLlcNfc_Initialised_State; + } + } + PH_LLCNFC_DEBUG("Llc Receive result : 0x%04X\n", result); + return result; +} diff --git a/libnfc-nxp/phLlcNfc.h b/libnfc-nxp/phLlcNfc.h new file mode 100644 index 0000000..552ec38 --- /dev/null +++ b/libnfc-nxp/phLlcNfc.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phLlcNfc.h +* \brief Common LLC for the upper layer. +* +* Project: NFC-FRI-1.1 +* +* $Date: Thu Sep 11 12:18:52 2008 $ +* $Author: ing02260 $ +* $Revision: 1.7 $ +* $Aliases: NFC_FRI1.1_WK838_PREP1,NFC_FRI1.1_WK838_R9_PREP2,NFC_FRI1.1_WK838_R9_1,NFC_FRI1.1_WK840_R10_PREP1,NFC_FRI1.1_WK840_R10_1,NFC_FRI1.1_WK842_R11_PREP1,NFC_FRI1.1_WK842_R11_PREP2,NFC_FRI1.1_WK842_R11_1,NFC_FRI1.1_WK844_PREP1,NFC_FRI1.1_WK844_R12_1,NFC_FRI1.1_WK846_PREP1,NFC_FRI1.1_WK846_R13_1,NFC_FRI1.1_WK848_PREP1,NFC_FRI1.1_WK848_R14_1,NFC_FRI1.1_WK849_PACK1_PREP1,NFC_FRI1.1_WK850_PACK1,NFC_FRI1.1_WK851_PREP1,NFC_FRI1.1_WK850_R15_1,NFC_FRI1.1_WK902_PREP1,NFC_FRI1.1_WK902_R16_1,NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +#ifndef PHLLCNFC_H +#define PHLLCNFC_H + +#ifdef ANDROID +#include +#endif + +/** +* \name LLC NFC +* +* File: \ref phLlcNfc.h +* +*/ +/*@{*/ +#define PH_LLCNFC_FILEREVISION "$Revision: 1.7 $" /**< \ingroup grp_file_attributes */ +#define PH_LLCNFC_FILEALIASES "$Aliases: NFC_FRI1.1_WK838_PREP1,NFC_FRI1.1_WK838_R9_PREP2,NFC_FRI1.1_WK838_R9_1,NFC_FRI1.1_WK840_R10_PREP1,NFC_FRI1.1_WK840_R10_1,NFC_FRI1.1_WK842_R11_PREP1,NFC_FRI1.1_WK842_R11_PREP2,NFC_FRI1.1_WK842_R11_1,NFC_FRI1.1_WK844_PREP1,NFC_FRI1.1_WK844_R12_1,NFC_FRI1.1_WK846_PREP1,NFC_FRI1.1_WK846_R13_1,NFC_FRI1.1_WK848_PREP1,NFC_FRI1.1_WK848_R14_1,NFC_FRI1.1_WK849_PACK1_PREP1,NFC_FRI1.1_WK850_PACK1,NFC_FRI1.1_WK851_PREP1,NFC_FRI1.1_WK850_R15_1,NFC_FRI1.1_WK902_PREP1,NFC_FRI1.1_WK902_R16_1,NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ +/*************************** Includes *******************************/ + +/*********************** End of includes ****************************/ +/** \defgroup grp_hal_nfc_llc LLC Component + * + * + * + */ + +/***************************** Macros *******************************/ + +/************************ End of macros *****************************/ + +/********************** Callback functions **************************/ + +/******************* End of Callback functions **********************/ + +/********************* Structures and enums *************************/ + + +/****************** End of structures and enums *********************/ + + +/******************** Function declarations *************************/ +/** +* \ingroup grp_hal_nfc_llc +* +* \brief \b Register function +* +* \copydoc page_reg Provides the callback to the LLC layer and register +* the calling functions to the upper layer (Synchronous function). +* +* \param[out] psReference Structure is used to give the LLC calling functions +* and also LLC context information to the upper layer +* \param[in] if_callback Callback information provided by the upper layer +* \param[in] psIFConfig This gives the information of the next register call +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* \retval Other errors Errors related to the lower layers +* +*/ + +NFCSTATUS +phLlcNfc_Register ( + phNfcIF_sReference_t *psReference, + phNfcIF_sCallBack_t if_callback, + void *psIFConfig +); + + + +/****************** End of function declarations ********************/ +#endif /* PHLLCNFC_H */ diff --git a/libnfc-nxp/phLlcNfc_DataTypes.h b/libnfc-nxp/phLlcNfc_DataTypes.h new file mode 100644 index 0000000..b84cd3e --- /dev/null +++ b/libnfc-nxp/phLlcNfc_DataTypes.h @@ -0,0 +1,646 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* +* \file phLlcNfc_DataTypes.h +* \brief Contains the structure information. +* +* Project: NFC-FRI-1.1 +* +* $Date: Fri Apr 30 10:03:36 2010 $ +* $Author: ing02260 $ +* $Revision: 1.43 $ +* $Aliases: NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +#ifndef PHLLCNFC_DATATYPES_H +#define PHLLCNFC_DATATYPES_H + +/** +* \name LLC NFC frame creation, deletion and processing +* +* File: \ref phLlcNfc_DataTypes.h +* +*/ +/*@{*/ +#define PH_LLCNFC_DATATYPES_FILEREVISION "$Revision: 1.43 $" /**< \ingroup grp_hal_nfc_llc */ +#define PH_LLCNFC_DATATYPES_FILEALIASES "$Aliases: NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_hal_nfc_llc */ +/*@}*/ +/*************************** Includes *******************************/ +#include +/*********************** End of includes ****************************/ +/***************************** Macros *******************************/ + +/* Trace buffer declaration */ +#if defined (LLC_TRACE) + #include + #include + + extern char phOsalNfc_DbgTraceBuffer[]; + #define trace_buffer phOsalNfc_DbgTraceBuffer + + #define MAX_TRACE_BUFFER 150 + #define PH_LLCNFC_PRINT( str ) phOsalNfc_DbgString(str) + #define PH_LLCNFC_PRINT_DATA(buf,len) + #define PH_LLCNFC_STRING( str ) + #define PH_LLCNFC_DEBUG(str, arg) \ + { \ + snprintf(trace_buffer,MAX_TRACE_BUFFER,str,arg); \ + phOsalNfc_DbgString(trace_buffer); \ + } + #define PH_LLCNFC_PRINT_BUFFER(buf,len) \ + { \ + /* uint16_t i = 0; \ + char trace_buffer[MAX_TRACE_BUFFER]; \ + snprintf(trace_buffer,MAX_TRACE_BUFFER,"\n\t %s:",msg); \ + phOsalNfc_DbgString(trace); */\ + phOsalNfc_DbgTrace(buf,len); \ + phOsalNfc_DbgString("\r"); \ + } +#endif /* #if defined (LLC_TRACE) */ + + +#if (!defined (LLC_TRACE) && defined (LLC_DATA_BYTES)) + #include + + extern char phOsalNfc_DbgTraceBuffer[]; + #define trace_buffer phOsalNfc_DbgTraceBuffer + + #define PH_LLCNFC_PRINT( str ) + #define PH_LLCNFC_PRINT_BUFFER(buf, len) + #define PH_LLCNFC_DEBUG(str, arg1) + #define PH_LLCNFC_STRING( str ) phOsalNfc_DbgString(str) + #define PH_LLCNFC_PRINT_DATA(buf,len) \ + { \ + /* uint16_t i = 0; \ + char trace_buffer[MAX_TRACE_BUFFER]; \ + snprintf(trace_buffer,MAX_TRACE_BUFFER,"\n\t %s:",msg); \ + phOsalNfc_DbgString(trace_buffer); */\ + phOsalNfc_DbgTrace(buf,len); \ + } +#endif /* #if (!defined (LLC_TRACE) && defined (LLC_DATA_BYTES)) */ + + +#if (!defined (LLC_TRACE) && !defined (LLC_DATA_BYTES)) + /** To disable prints */ + #define PH_LLCNFC_PRINT(str) + #define PH_LLCNFC_PRINT_BUFFER(buf, len) + #define PH_LLCNFC_DEBUG(str, arg1) + #define PH_LLCNFC_PRINT_DATA(buf,len) + #define PH_LLCNFC_STRING( str ) +#endif /* #if (!defined (LLC_TRACE) && !defined (LLC_DATA_BYTES)) */ + + +/* If the below MACRO (RECV_NR_CHECK_ENABLE) is +DEFINED : then check for the NR frame received from PN544 in the I frame is + added. This shall be greater than sent NS from the HOST. + This is used to stop the timer +COMMENTED : dont check the N(R) frame received from the PN544 +*/ +/* #define RECV_NR_CHECK_ENABLE */ + +/* If the below MACRO (LLC_UPP_LAYER_NTFY_WRITE_RSP_CB) is +DEFINED : then if an I frame is received and the + upper layer response callback (before another READ is pended) is called + only after sending S frame and wait for the callback and then notify the + upper layer +COMMENTED : then if an I frame is received and the + upper layer response callback (before another READ is pended) is called + immediately after sending S frame (not waiting for the sent S frame + callback) +*/ +/* #define LLC_UPP_LAYER_NTFY_WRITE_RSP_CB */ + +/* PN544 continuously sends an incorrect I frames to the HOST, + even after the REJ frame from HOST to PN544 +If the below MACRO (LLC_RR_INSTEAD_OF_REJ) is +DEFINED : then if the received NS = (expected NR - 1) then instead of REJ + RR frame is sent +COMMENTED : then REJ frame is sent +*/ +// #define LLC_RR_INSTEAD_OF_REJ + +#define SEND_UFRAME + +/* If the below MACRO (CTRL_WIN_SIZE_COUNT) is +DEFINED : then window size will be maximum +COMMENTED : then window size is 1 +*/ +#define CTRL_WIN_SIZE_COUNT + +/* +If the below MACRO (LLC_URSET_NO_DELAY) is +DEFINED : then after receiving the UA frame, then immediately this will be + notified or further operation will be carried on. +COMMENTED : then after receiving the UA frame, then a timer is started, to + delay the notifiation or to carry on the next operation +*/ +#define LLC_URSET_NO_DELAY + + /* + If the below MACRO (LLC_RELEASE_FLAG) is +DEFINED : then whenever LLC release is called the g_release_flag variable + will be made TRUE. Also, NO notification is allowed to the + upper layer. +COMMENTED : g_release_flag is not declared and not used + */ + #define LLC_RELEASE_FLAG + + + /* + Actually, there is a send and receive error count, if either of them reaches + limit, then exception is raised. + If the below MACRO (LLC_RSET_INSTEAD_OF_EXCEPTION) is +DEFINED : then exception is not raised, instead a U RSET command is sent. +COMMENTED : then exception is raised + */ +/* #define LLC_RSET_INSTEAD_OF_EXCEPTION */ + +#ifndef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB + /* + If the below MACRO (PIGGY_BACK) is + DEFINED : After receiving I frame, wait till the ACK timer to expire to send an ACK to PN544. + COMMENTED : immediately ACK the received I frame + */ + #define PIGGY_BACK + +#endif /* LLC_UPP_LAYER_NTFY_WRITE_RSP_CB */ + +#define LLC_SEND_ERROR_COUNT + +#define RECV_ERROR_FRAME_COUNT (0x50U) +#define SENT_ERROR_FRAME_COUNT (0x50U) + +/** Initial bytes to read */ +#define PH_LLCNFC_BYTES_INIT_READ (1) +/** Maximum buffer that I frame can send */ +#define PH_LLCNFC_MAX_IFRAME_BUFLEN (29) +#define PH_LLCNFC_MAX_UFRAME_BUFLEN (4) +#define PH_LLCNFC_CRC_LENGTH (2) +#define PH_LLCNFC_MAX_LLC_PAYLOAD ((PH_LLCNFC_MAX_IFRAME_BUFLEN) + (4)) +/** Maximum timer used in the Llc */ +#define PH_LLCNFC_MAX_TIMER_USED (3) +/** Maximum timer used in the Llc */ +#define PH_LLCNFC_MAX_ACK_GUARD_TIMER (4) +/** Maximum I frame that can be stored */ +#define PH_LLCNFC_MAX_I_FRAME_STORE (8) + +/** Read pending for one byte */ +#define PH_LLCNFC_READPEND_ONE_BYTE (0x01U) + /** Read pending for remaining byte */ +#define PH_LLCNFC_READPEND_REMAIN_BYTE (0x02U) +/** Read pending not done */ +#define PH_LLCNFC_READPEND_FLAG_OFF FALSE +#define PH_LLCNFC_MAX_REJ_RETRY_COUNT (200) + + +/**** Macros for state machine ****/ + +typedef enum phLlcNfc_State +{ + /** This specifies that LLC is in uninitialise state */ + phLlcNfc_Uninitialise_State = 0x00, + /** This specifies that LLC initialise is in progress */ + phLlcNfc_Initialising_State = 0x01, + /** This specifies that LLC is in initialise is complete */ + phLlcNfc_Initialised_State = 0x02, + /** This specifies that LLC is send with the + lower layer */ + phLlcNfc_Sending_State = 0x03, + /** This specifies that LLC is receive with the + lower layer */ + phLlcNfc_Receiving_State = 0x04, + /** This specifies that LLC is receive wait with the + lower layer */ + phLlcNfc_ReceiveWait_State = 0x05, + /** This specifies that LLC is resending the I frames */ + phLlcNfc_Resend_State = 0x06 +}phLlcNfc_State_t; +/**** Macros for state machine end ****/ + +/************************ End of macros *****************************/ + +/********************** Callback functions **************************/ + +/******************* End of Callback functions **********************/ + +/********************* Structures and enums *************************/ +/** +* \ingroup grp_hal_nfc_llc +* \brief Enum to get the baud rate +* +* This enum contains the baud rate information. +* +*/ +/*@{*/ +typedef enum phLlcNfc_LlcBaudRate +{ + /** Baud rate = 9600 */ + phLlcNfc_e_9600 = 0x00, + /** Baud rate = 19200 */ + phLlcNfc_e_19200 = 0x01, + /** Baud rate = 28800 */ + phLlcNfc_e_28800 = 0x02, + /** Baud rate = 38400 */ + phLlcNfc_e_38400 = 0x03, + /** Baud rate = 57600 */ + phLlcNfc_e_57600 = 0x04, + /** Baud rate = 115200 */ + phLlcNfc_e_115200 = 0x05, + /** Baud rate = 23400 */ + phLlcNfc_e_234000 = 0x06, + /** Baud rate = 46800 */ + phLlcNfc_e_460800 = 0x07, + /** Baud rate = 921600 */ + phLlcNfc_e_921600 = 0x08, + /** Baud rate = 1228000 */ + phLlcNfc_e_1228000 = 0x09, + /** Baud rate error */ + phLlcNfc_e_bdrate_err = 0xFF +}phLlcNfc_LlcBaudRate_t; +/*@}*/ + +/** +* \ingroup grp_hal_nfc_llc +* \brief Enum to select the U or I or S frame +* +* This enum is to set the frames. +* +*/ +/*@{*/ +typedef enum phLlcNfc_LlcCmd +{ + /** This command is for I frame (no command) */ + phLlcNfc_e_no_cmd = 0xFF, + /** This command is for U frame */ + phLlcNfc_e_rset = 0x19, + /** This command is for U frame */ + phLlcNfc_e_ua = 0x06, + /** This is RR command for S frame */ + phLlcNfc_e_rr = 0x00, + /** This is REJ command for S frame */ + phLlcNfc_e_rej = 0x08, + /** This is RNR command for S frame */ + phLlcNfc_e_rnr = 0x10, + /** This is SREJ command for S frame */ + phLlcNfc_e_srej = 0x18, + /** Error command */ + phLlcNfc_e_error = 0xFE +}phLlcNfc_LlcCmd_t; +/*@}*/ + +/** +* \ingroup grp_hal_nfc_llc +* \brief Enum to select the U or I or S frame +* +* This enum is to set the frames. +* +*/ +/*@{*/ +typedef enum phLlcNfc_FrameType +{ + /** U frame type */ + phLlcNfc_eU_frame = 0x00, + /** I frame type */ + phLlcNfc_eI_frame = 0x01, + /** S frame type */ + phLlcNfc_eS_frame = 0x02, + /** Error frame type */ + phLlcNfc_eErr_frame = 0x03 +}phLlcNfc_FrameType_t; +/*@}*/ + +/** +* \ingroup grp_hal_nfc_llc +* \brief LLC sent frame type +* +* This enum values defines what are the frames sent to the PN544 +* +*/ +/*@{*/ + +typedef enum phLlcNfc_eSentFrameType +{ + invalid_frame, + /* During initialisation the U RSET is sent to PN544 */ + init_u_rset_frame, + /* During initialisation the UA is sent to PN544 */ + init_u_a_frame, + /* After unsuccessful retries of sending I frame to PN544, + URSET is sent */ + u_rset_frame, + /* If PN544 sends the URSET frame in between any transaction, then + the UA response shall be sent */ + u_a_frame, + /* S frame is sent to PN544, this will be sent only if an I frame + is received from PN544 */ + s_frame, + /* User has sent an I frame, for that a write response callback + shall be called */ + user_i_frame, + /* LLC, internally (means stored non acknowledged frames) has sent + an I frame as it doesnt get a proper acknowledgement */ + resend_i_frame, + /* LLC, internally (means stored non acknowledged frames) has sent + an I frame as it doesnt get a reject as acknowledgement */ + rejected_i_frame, + /* LLC has received a I frame for the re-sent I frames, so an S + frame is sent */ + resend_s_frame, + /* LLC has received a I frame for the re-sent I frames, so an S + frame is sent */ + resend_rej_s_frame, + /* PN544 has sent an I frame, which is wrong, so send a reject S + frame */ + reject_s_frame, +#ifdef LLC_RR_INSTEAD_OF_REJ + + /* RR is sent instead of REJECT */ + rej_rr_s_frame, + +#endif /* #ifdef LLC_RR_INSTEAD_OF_REJ */ + /* For any of the above sent frames, the response shall be received */ + write_resp_received +}phLlcNfc_eSentFrameType_t; + +/*@}*/ + +/** +* \ingroup grp_hal_nfc_llc +* \brief LLC payload +* +* This structure contains both the header information and +* the exact length of the buffer. +* +*/ +/*@{*/ +typedef struct phLlcNfc_Payload +{ + /** Llc header information */ + uint8_t llcheader; + + /** User or received buffer */ + uint8_t llcpayload[PH_LLCNFC_MAX_LLC_PAYLOAD]; +}phLlcNfc_Payload_t; +/*@}*/ + +/** +* \ingroup grp_hal_nfc_llc +* \brief Llc buffer +* +* This structure contains the information of the LLC length byte +* and payload. +* +*/ +/*@{*/ +typedef struct phLlcNfc_Buffer +{ + /** Llc length */ + uint8_t llc_length_byte; + + /** LLC data including the LLC header and CRC */ + phLlcNfc_Payload_t sllcpayload; +}phLlcNfc_Buffer_t; +/*@}*/ + +/** +* \ingroup grp_hal_nfc_llc +* \brief Packet information +* +* This structure contains the length and buffer of the packet. +* +*/ +/*@{*/ +typedef struct phLlcNfc_LlcPacket +{ + /** Complete LLC buffer */ + phLlcNfc_Buffer_t s_llcbuf; + + /** LLC buffer length */ + uint8_t llcbuf_len; + + /** Stored frame needs completion callback, to be sent to HCI */ + phLlcNfc_eSentFrameType_t frame_to_send; + +}phLlcNfc_LlcPacket_t; +/*@}*/ + +/** +* \ingroup grp_hal_nfc_llc_helper +* \brief I frame details +* +* This structure stores the information of the I frame +* (to support sliding window). +* +*/ +/*@{*/ +typedef struct phLlcNfc_StoreIFrame +{ + /** Complete LLC packet */ + phLlcNfc_LlcPacket_t s_llcpacket[PH_LLCNFC_MAX_I_FRAME_STORE]; + + /** Window size count */ + uint8_t winsize_cnt; + + /** Start position */ + uint8_t start_pos; + +}phLlcNfc_StoreIFrame_t; +/*@}*/ + +/** +* \ingroup grp_hal_nfc_llc +* \brief LLC timer information +* +* This structure contains the timer related information +* +*/ +/*@{*/ +typedef struct phLlcNfc_Timerinfo +{ + /** Store the timer id for each timer create */ + uint32_t timer_id[PH_LLCNFC_MAX_TIMER_USED]; + + /** This will store the connection time out value */ + uint16_t con_to_value; + + /** This will store the guard time out values */ + uint16_t guard_to_value[PH_LLCNFC_MAX_ACK_GUARD_TIMER]; + + /** This will store the guard time out values */ + uint16_t iframe_send_count[PH_LLCNFC_MAX_ACK_GUARD_TIMER]; + + /** This will store ns value for the sent N(S) */ + uint8_t timer_ns_value[PH_LLCNFC_MAX_ACK_GUARD_TIMER]; + + /** Each frame stored needs to be */ + uint8_t frame_type[PH_LLCNFC_MAX_ACK_GUARD_TIMER]; + + /** Index to re-send */ + uint8_t index_to_send; + + /** This is a count for gaurd time out */ + uint8_t guard_to_count; + +#ifdef PIGGY_BACK + /** This will store the ack time out values */ + uint16_t ack_to_value; +#endif /* #ifdef PIGGY_BACK */ + + /** This is a timer flag + Bit 0 = 1 means connection time out started else stopped + Bit 1 = 1 means guard time out started else stopped + Bit 2 = 1 means ack time out started else stopped + */ + uint8_t timer_flag; +}phLlcNfc_Timerinfo_t; +/*@}*/ + +/** +* \ingroup grp_hal_nfc_llc +* \brief LLC frame information +* +* This structure contains the information of the LLC frame. +* +*/ +/*@{*/ +typedef struct phLlcNfc_Frame +{ + /** N(S) - Number of information frame */ + uint8_t n_s; + + /** N(R) - Number of next information frame to receive */ + uint8_t n_r; + + /** Store the window size */ + uint8_t window_size; + + /** SREJ is optional, so store the flag whether it is set or not */ + uint8_t srej_on_off; + + /** Store the baud rate */ + uint8_t baud_rate; + + /** Flag to find the rset_recvd */ + uint8_t rset_recvd; + + /** Complete LLC packet information */ + phLlcNfc_LlcPacket_t s_llcpacket; + + /** Store the I frames, that has been sent, Storage will be till + the window size */ + phLlcNfc_StoreIFrame_t s_send_store; + +#ifdef PIGGY_BACK + /** Store the I frames, that has been received, Storage will be + till the window size */ + phLlcNfc_StoreIFrame_t s_recv_store; + + /** Response received count to send the ACK once it reaches the window size */ + uint8_t resp_recvd_count; +#endif /* #ifdef PIGGY_BACK */ + + /** To receive the packet sent by below layer */ + phLlcNfc_LlcPacket_t s_recvpacket; + + /** Number of window I frames has to be sent again */ + uint8_t rejected_ns; + + /** To store the count received error frames like + wrong CRC, REJ and RNR frames */ + uint8_t recv_error_count; + + /** Sending error frames like REJ frames to the PN544 */ + uint8_t send_error_count; + + /** Send U frame count */ + uint8_t retry_cnt; + + /** Read pending flag, to know that read is already pended + or not. Use the below macros to ON and OFF the flag + PH_LLCNFC_READPEND_FLAG_OFF + PH_LLCNFC_READPEND_ONE_BYTE + PH_LLCNFC_READPEND_REMAIN_BYTE + */ + uint8_t read_pending; + + /** Write pending */ + uint8_t write_pending; + + /** Sent frame type */ + phLlcNfc_eSentFrameType_t sent_frame_type; + + /** upper receive called */ + uint8_t upper_recv_call; + + /** Status returned during DAL write */ + NFCSTATUS write_status; + + /** Depending on the "write_status", write call has to be called */ + phLlcNfc_eSentFrameType_t write_wait_call; +}phLlcNfc_Frame_t; +/*@}*/ + +/** +* \ingroup grp_hal_nfc_llc +* \brief LLC Component Context Structure +* +* This structure is used to store the current context information +* of the instance. +* +*/ +/*@{*/ +typedef struct phLlcNfc_Context +{ + /** Information regarding all the LLC frame */ + phLlcNfc_Frame_t s_frameinfo; + + /** Local send and receive */ + phNfc_sLowerIF_t lower_if; + + /** Register attention, send and receive callback from the + register functions of the upper layer */ + phNfcIF_sCallBack_t cb_for_if; + + /** Store the length, which shall be sent later through the + "send complete" callback */ + uint32_t send_cb_len; + + /** Receive buffer provided by the upper layer */ + uint8_t precv_buf[PH_LLCNFC_MAX_LLC_PAYLOAD]; + + /** Receive length provided by the upper layer */ + uint32_t recvbuf_length; + + /** Llc state */ + phLlcNfc_State_t state; + + /** Hardware information */ + void *phwinfo; + + /** Timer information */ + phLlcNfc_Timerinfo_t s_timerinfo; +}phLlcNfc_Context_t; +/*@}*/ +/****************** End of structures and enums *********************/ + +/******************** Function declarations *************************/ + +/******************** Function declarations *************************/ +#endif /* PHLLCNFC_DATATYPES_H */ + + diff --git a/libnfc-nxp/phLlcNfc_Frame.c b/libnfc-nxp/phLlcNfc_Frame.c new file mode 100644 index 0000000..e62b078 --- /dev/null +++ b/libnfc-nxp/phLlcNfc_Frame.c @@ -0,0 +1,2201 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phLlcNfc_Frame.c +* \brief To append the I or S or U frames (LLC header). +* +* Project: NFC-FRI-1.1 +* +* $Date: Tue Jun 1 14:41:26 2010 $ +* $Author: ing02260 $ +* $Revision: 1.88 $ +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +/*************************** Includes *******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef ANDROID +#include +#endif + +/*********************** End of includes ****************************/ + +/***************************** Macros *******************************/ + +/************************ End of macros *****************************/ + +/***************************** Global variables *******************************/ + +#ifdef LLC_RELEASE_FLAG + extern uint8_t g_release_flag; +#endif /* #ifdef LLC_RELEASE_FLAG */ +/************************ End of global variables *****************************/ + +/*********************** Local functions ****************************/ +static +void +phLlcNfc_H_UpdateCrc( + uint8_t crcByte, + uint16_t *pCrc +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions process the received U frame function +* +* \copydoc page_reg This function is to process the U frame received from +* the device +* +* \param[in] psLlcCtxt Llc main structure information +* \param[in] llcPacket LLC packet information, inlcuding length information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +static +NFCSTATUS +phLlcNfc_H_ProcessUFrame ( + phLlcNfc_Context_t *psLlcCtxt +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions process the received S frame function +* +* \copydoc page_reg This function is to process the S frame received from +* the device +* +* \param[in] psLlcCtxt Llc main structure information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +static +void +phLlcNfc_H_ProcessSFrame ( + phLlcNfc_Context_t *psLlcCtxt +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions Update I frame list function +* +* \copydoc page_reg This function checks the nr value with the stored I frames +* and deletes the nodes which has been acknowledged. +* +* \param[in/out] psFrameInfo Frame structure information +* \param[in/out] psListInfo List information +* +* \retval number of deleted frames +* +*/ +static +uint8_t +phLlcNfc_H_UpdateIFrameList( + phLlcNfc_Frame_t *psFrameInfo, + phLlcNfc_StoreIFrame_t *psListInfo +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions \b Delete list function +* +* \copydoc page_reg Delete the front node from the list +* +* \param[in] psFrameInfo Frame structure information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +static +void +phLlcNfc_H_DeleteIFrame ( + phLlcNfc_StoreIFrame_t *psList + ); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions Get the LLC header function +* +* \copydoc page_reg This function checks for the correctness fo the llc header +* +* \param[in] llcHeader The byte which gives the header information +* +* \retval phLlcNfc_eU_frame U frame type. +* \retval phLlcNfc_eI_frame I frame type. +* \retval phLlcNfc_eS_frame S frame type. +* \retval phLlcNfc_eErr_frame Error type +* +*/ +static +phLlcNfc_FrameType_t +phLlcNfc_H_ChkGetLlcFrameType ( + uint8_t llcHeader + ); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions \b Peek the data function +* +* \copydoc page_reg Get the packet information from the front node from the list +* +* \param[in] psListInfo The List information +* \param[in] packetinfo The packet information from the front node of the list +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +static +NFCSTATUS +phLlcNfc_H_IFrameList_Peek ( + phLlcNfc_StoreIFrame_t *psList, + phLlcNfc_LlcPacket_t **psPacketinfo, + uint8_t position + ); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions Update U frame information function +* +* \copydoc page_reg This function updates the U frame information in the +* phLlcNfc_sFrame_t structure +* +* \param[in/out] psFrameInfo Frame information structure +* \param[in] llcPayload Llc payload information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +static +NFCSTATUS +phLlcNfc_H_Update_ReceivedRSETInfo ( + phLlcNfc_Frame_t *psFrameInfo, + phLlcNfc_Payload_t llcInfo + ); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC Reset frame information function +* +* \copydoc page_reg resets ns and nr value, when ack for U frame is received +* +* \param[in, out] psLlcCtxt Llc main structure information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +static +void +phLlcNfc_H_ResetFrameInfo ( + phLlcNfc_Context_t *psLlcCtxt + ); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC Reset frame sending function +* +* \copydoc page_reg Send URSET frame to PN544 +* +* \param[in, out] psLlcCtxt Llc main structure information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_BUSY Write is pended, so wait till it completes. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +NFCSTATUS +phLlcNfc_H_SendRSETFrame ( + phLlcNfc_Context_t *psLlcCtxt + ); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions process the received I frame function +* +* \copydoc page_reg This function is to process the I frame received from +* the device +* +* \param[in] psLlcCtxt Llc main structure information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +void +phLlcNfc_H_ProcessIFrame ( + phLlcNfc_Context_t *psLlcCtxt +); + +/******************** End of Local functions ************************/ + +/********************** Global variables ****************************/ + +/******************** End of Global Variables ***********************/ + +void phLlcNfc_H_Frame_Init ( + phLlcNfc_Context_t *psLlcCtxt +) +{ + + if (NULL != psLlcCtxt) + { + /* Set all the other values to 0 */ + (void)memset (&psLlcCtxt->s_frameinfo.s_llcpacket, 0, + sizeof(phLlcNfc_LlcPacket_t)); + + psLlcCtxt->s_frameinfo.window_size = + PH_LLCNFC_U_FRAME_MAX_WIN_SIZE; + /* Initialise the window size, N(S) and N(R) */ +#ifdef PIGGY_BACK + psLlcCtxt->s_frameinfo.s_recv_store.winsize_cnt = 0; +#endif + psLlcCtxt->s_frameinfo.s_send_store.winsize_cnt = 0; + psLlcCtxt->s_frameinfo.n_s = 0; + psLlcCtxt->s_frameinfo.n_r = 0; + psLlcCtxt->s_frameinfo.rejected_ns = DEFAULT_PACKET_INPUT; + } +} + +void +phLlcNfc_H_Frame_DeInit ( + phLlcNfc_Frame_t *psFrameInfo +) +{ + if (NULL != psFrameInfo) + { + /* Empty the frame information */ + (void)memset(&psFrameInfo->s_llcpacket, 0, + sizeof(phLlcNfc_LlcPacket_t)); + } +} + +NFCSTATUS +phLlcNfc_H_CreateUFramePayload ( + phLlcNfc_Context_t *psLlcCtxt, + phLlcNfc_LlcPacket_t *psLlcPacket, + uint8_t *pLlcPacketLength, + phLlcNfc_LlcCmd_t cmdType +) +{ + /* + U frame packet (RSET) + Byte 0 = Length (4 to 6 bytes) + Byte 1 = Header + Byte 2 = window size (2 >= window size <= 4) + Byte 3 = capabilities (SREJ option enable/disable) (optional) + Byte 4 = Baud rate (optional) + Byte 5 = CRC1 + Byte 6 = CRC2 + */ + NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + phLlcNfc_Buffer_t *ps_llc_buf = NULL; + uint8_t index = 0; + + if ((NULL != psLlcCtxt) && (NULL != psLlcPacket) + && (NULL != pLlcPacketLength) && + ((phLlcNfc_e_rset == cmdType) || (phLlcNfc_e_ua == cmdType))) + { + result = NFCSTATUS_SUCCESS; + ps_llc_buf = &(psLlcPacket->s_llcbuf); + /* Get the header information */ + ps_llc_buf->sllcpayload.llcheader = + (uint8_t)PH_LLCNFC_U_HEADER_INIT; + if (phLlcNfc_e_rset == cmdType) + { + /* RSET command */ + ps_llc_buf->sllcpayload.llcheader = + (uint8_t)SET_BITS8( + ps_llc_buf->sllcpayload.llcheader, + PH_LLCNFC_U_FRAME_START_POS, + PH_LLCNFC_U_FRAME_NO_OF_POS, + (uint8_t)phLlcNfc_e_rset); + /* Default window size */ + ps_llc_buf->sllcpayload.llcpayload[index] = + PH_LLCNFC_U_FRAME_MAX_WIN_SIZE; + index++; + /* Endpoint capabilities, SREJ not supported */ + ps_llc_buf->sllcpayload.llcpayload[index] = + PH_LLCNFC_SREJ_BYTE_VALUE; + index++; +#ifdef ENABLE_BAUDRATE + /* baud rate 0x00 = 9600, 0x05 = 115200 */ + ps_llc_buf->sllcpayload.llcpayload[index] = + (uint8_t)phLlcNfc_e_115200; + index++; +#endif /* #ifdef ENABLE_BAUDRATE */ + + } + else + { + /* UA frame */ + ps_llc_buf->sllcpayload.llcheader = (uint8_t) + SET_BITS8(ps_llc_buf->sllcpayload.llcheader, + PH_LLCNFC_U_FRAME_START_POS, + PH_LLCNFC_U_FRAME_NO_OF_POS, + (uint8_t)phLlcNfc_e_ua); + } + /* LLC length byte updated (index + 2 CRC bytes + + 1 byte of header) */ + ps_llc_buf->llc_length_byte = (index + + PH_LLCNFC_NUM_OF_CRC_BYTES + 1); + /* Total LLC buffer size */ + *pLlcPacketLength = psLlcPacket->llcbuf_len = + (ps_llc_buf->llc_length_byte + 1); + /* + psLlcPacket->s_llcbuf : + consists llc length byte + llc header + data + CRC + (which needs to be calculated by the below function) + psLlcPacket->llcbuf_len : + Total length of the above buffer + psLlcPacket->llcbuf_len - 2 : + -2 because the CRC has to be calculated, only for the + bytes which has llc length byte + llc header + data. + But total length (llcbuf_len) consists of above mentioned + things with 2 byte CRC + psLlcPacket->s_llcbuf.sllcpayload.llcpayload : + consists only data (no length byte and no llc header) + (psLlcPacket->llcbuf_len - 4) : + is the array index of the first CRC byte to be calculated + (psLlcPacket->llcbuf_len - 3) : + is the array index of the second CRC byte to be calculated + */ + index = psLlcPacket->llcbuf_len; + + phLlcNfc_H_ComputeCrc((uint8_t *)ps_llc_buf, + (psLlcPacket->llcbuf_len - 2), + &(ps_llc_buf->sllcpayload.llcpayload[(index - 4)]), + &(ps_llc_buf->sllcpayload.llcpayload[(index - 3)])); + } + + return result; +} + +NFCSTATUS +phLlcNfc_H_CreateSFramePayload ( + phLlcNfc_Frame_t *psFrameInfo, + phLlcNfc_LlcPacket_t *psLlcPacket, + phLlcNfc_LlcCmd_t cmdType +) +{ + /* + S frame packet (RR or RNR or REJ or SREJ). Total bytes = 4 + Byte 0 = Length (Length = 3 always for S frame) + Byte 1 = Header + Byte 2 = CRC1 + Byte 3 = CRC2 + */ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Buffer_t *ps_llc_buf = NULL; + uint8_t length = 0; + + ps_llc_buf = &(psLlcPacket->s_llcbuf); + + /* Initial S frame header */ + ps_llc_buf->sllcpayload.llcheader = PH_LLCNFC_S_HEADER_INIT; + /* Update the N(R) value */ + ps_llc_buf->sllcpayload.llcheader = (uint8_t)SET_BITS8( + ps_llc_buf->sllcpayload.llcheader, + PH_LLCNFC_NR_START_BIT_POS, + PH_LLCNFC_NR_NS_NO_OF_BITS, + psFrameInfo->n_r); + + /* Update the type bits of S frame */ + ps_llc_buf->sllcpayload.llcheader = (uint8_t) + (ps_llc_buf->sllcpayload.llcheader | (uint8_t)cmdType); + + /* Maximum S frame length */ + psLlcPacket->llcbuf_len = (uint8_t)PH_LLCNFC_MAX_S_FRAME_LEN; + /* S frame length byte value */ + ps_llc_buf->llc_length_byte = (uint8_t) + (psLlcPacket->llcbuf_len - 1); + + /* + psFrameInfo->s_llcpacket.s_llcbuf : + consists llc length byte + llc header + data + CRC + (which needs to be calculated by the below function) + psFrameInfo->s_llcpacket.llcbuf_len : + Total length of the above buffer + psFrameInfo->s_llcpacket.llcbuf_len - 2 : + -2 because the CRC has to be calculated, only for the + bytes which has llc length byte + llc header + data. + But total length (llcbuf_len) consists of above mentioned + things with 2 byte CRC + psFrameInfo->s_llcpacket.s_llcbuf.sllcpayload.llcpayload : + consists only data (no length byte and no llc header) + psFrameInfo->s_llcpacket.s_llcbuf.sllcpayload.llcpayload : + contains only data sent by user. + (psFrameInfo->s_llcpacket.llcbuf_len - 4) : + is the array index of the first CRC byte to be calculated + (psFrameInfo->s_llcpacket.llcbuf_len - 3) : + is the array index of the second CRC byte to be calculated + */ + length = psLlcPacket->llcbuf_len; + phLlcNfc_H_ComputeCrc( + (uint8_t *)ps_llc_buf, (length - 2), + &(ps_llc_buf->sllcpayload.llcpayload[(length - 4)]), + &(ps_llc_buf->sllcpayload.llcpayload[(length - 3)])); + + return result; +} + +NFCSTATUS +phLlcNfc_H_CreateIFramePayload ( + phLlcNfc_Frame_t *psFrameInfo, + phLlcNfc_LlcPacket_t *psLlcPacket, + uint8_t *pLlcBuf, + uint8_t llcBufLength +) +{ + NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + phLlcNfc_Buffer_t *ps_llc_buf = NULL; + + if ((NULL != psFrameInfo) && (NULL != psLlcPacket) && + (NULL != pLlcBuf) && (llcBufLength > 0)) + { + result = NFCSTATUS_SUCCESS; + ps_llc_buf = &(psLlcPacket->s_llcbuf); + + (void)memcpy(&(ps_llc_buf->sllcpayload.llcpayload[0]), + pLlcBuf, llcBufLength); + + psLlcPacket->llcbuf_len = (uint8_t)llcBufLength; + + /* I frame header byte */ + ps_llc_buf->sllcpayload.llcheader = PH_LLCNFC_I_HEADER_INIT; + + /* Set the N(S) value */ + ps_llc_buf->sllcpayload.llcheader = (uint8_t) + SET_BITS8( + ps_llc_buf->sllcpayload.llcheader, + PH_LLCNFC_NS_START_BIT_POS, + PH_LLCNFC_NR_NS_NO_OF_BITS, + psFrameInfo->n_s); + + /* Set the N(R) value */ + ps_llc_buf->sllcpayload.llcheader = (uint8_t) + SET_BITS8( + ps_llc_buf->sllcpayload.llcheader, + PH_LLCNFC_NR_START_BIT_POS, + PH_LLCNFC_NR_NS_NO_OF_BITS, + psFrameInfo->n_r); + + /* Update the length byte, llc length byte value includes + data + CRC bytes + llc length byte */ + ps_llc_buf->llc_length_byte = + (psLlcPacket->llcbuf_len + + PH_LLCNFC_NUM_OF_CRC_BYTES + 1); + + /* Update total length, Total length is always equal to + llc length byte + 1 */ + psLlcPacket->llcbuf_len = + (ps_llc_buf->llc_length_byte + 1); + + /* + psFrameInfo->s_llcpacket.s_llcbuf : + consists llc length byte + llc header + data + CRC (which + needs to be calculated by the below function) + psFrameInfo->s_llcpacket.llcbuf_len : + Total length of the above buffer + psFrameInfo->s_llcpacket.llcbuf_len - 2 : + -2 because the CRC has to be calculated, only for the + bytes which has llc length byte + llc header + data. + But total length (llcbuf_len) consists of above mentioned + things with 2 byte CRC + psFrameInfo->s_llcpacket.s_llcbuf.sllcpayload.llcpayload : + contains only data sent by user. + (psFrameInfo->s_llcpacket.llcbuf_len - 4) : + is the array index of the first CRC byte to be calculated + (psFrameInfo->s_llcpacket.llcbuf_len - 3) : + is the array index of the second CRC byte to be calculated + + */ + phLlcNfc_H_ComputeCrc( + (uint8_t*)ps_llc_buf, + (psLlcPacket->llcbuf_len - 2), + &(ps_llc_buf->sllcpayload.llcpayload + [(psLlcPacket->llcbuf_len - 4)]), + &(ps_llc_buf->sllcpayload.llcpayload + [(psLlcPacket->llcbuf_len - 3)])); + + + } + + return result; +} + +static +phLlcNfc_FrameType_t +phLlcNfc_H_ChkGetLlcFrameType ( + uint8_t llcHeader +) +{ + phLlcNfc_FrameType_t frame_type = phLlcNfc_eErr_frame; + + /* Mask the header byte to know the actual frame types */ + switch((llcHeader & PH_LLCNFC_LLC_HEADER_MASK)) + { + case PH_LLCNFC_U_HEADER_INIT: + { + frame_type = phLlcNfc_eU_frame; + break; + } + + case PH_LLCNFC_S_HEADER_INIT: + { + frame_type = phLlcNfc_eS_frame; + break; + } + + default: + { + if (PH_LLCNFC_I_HEADER_INIT == + (PH_LLCNFC_I_FRM_HEADER_MASK & llcHeader)) + { + frame_type = phLlcNfc_eI_frame; + } + else + { + frame_type = phLlcNfc_eErr_frame; + } + break; + } + } + return frame_type; +} + +static +NFCSTATUS +phLlcNfc_H_Update_ReceivedRSETInfo ( + phLlcNfc_Frame_t *psFrameInfo, + phLlcNfc_Payload_t llcInfo +) +{ + NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_FORMAT); + uint8_t payload_index = 0; + + if ((llcInfo.llcpayload[payload_index] >= PH_LLCNFC_U_FRAME_MIN_WIN_SIZE) && + (llcInfo.llcpayload[payload_index] <= PH_LLCNFC_U_FRAME_MAX_WIN_SIZE)) + { + result = NFCSTATUS_SUCCESS; + /* From the received buffer, get the window size from the + 3rd byte (recvUBufLen[3]) of the buffer */ + psFrameInfo->window_size = llcInfo.llcpayload[payload_index]; + payload_index = (uint8_t)(payload_index + 1); + + /* If 4th byte of the receive buffer (pRecvUBuf[4]) is + 0x01 then SREJ can come from the device*/ + psFrameInfo->srej_on_off = ((PH_LLCNFC_SREJ_BYTE_VALUE == + llcInfo.llcpayload[payload_index])? + PH_LLCNFC_SREJ_BYTE_VALUE:0); + + /* For present implementation, this should be always false + later stage remove if statement to work */ + if (PH_LLCNFC_SREJ_BYTE_VALUE != psFrameInfo->srej_on_off) + { + result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_FORMAT); + } + else + { + payload_index = (uint8_t)(payload_index + 1); + + + if (llcInfo.llcpayload[payload_index] > + (uint8_t)phLlcNfc_e_1228000) + { + /* Error byte */ + result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_FORMAT); + } + else + { + /* Get the baud rate from the 5th byte of the receive buffer */ + psFrameInfo->baud_rate = (phLlcNfc_LlcBaudRate_t) + (llcInfo.llcpayload[payload_index]); + } + } + } + + return result; +} + +static +uint8_t +phLlcNfc_H_UpdateIFrameList( + phLlcNfc_Frame_t *psFrameInfo, + phLlcNfc_StoreIFrame_t *psListInfo +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_LlcPacket_t *pspktInfo = NULL; + uint8_t while_exit = FALSE; + uint8_t nr = 0; + uint8_t ns = 0; + uint8_t no_of_del_frames = 0; + + PHNFC_UNUSED_VARIABLE(result); + if(0 == psListInfo->winsize_cnt) + { + while_exit = TRUE; + } + while (FALSE == while_exit) + { + /* Get the first node from the list */ + result = phLlcNfc_H_IFrameList_Peek (psListInfo, &pspktInfo, + DEFAULT_PACKET_INPUT); + if (NULL != pspktInfo) + { + /* Get the N(R) value of the received packet and N(S) value of the + sent stored i frame */ + ns = (uint8_t)GET_BITS8 ( + pspktInfo->s_llcbuf.sllcpayload.llcheader, + PH_LLCNFC_NS_START_BIT_POS, + PH_LLCNFC_NR_NS_NO_OF_BITS); + + nr = (uint8_t)GET_BITS8( + psFrameInfo->s_recvpacket.s_llcbuf.sllcpayload.llcheader, + PH_LLCNFC_NR_START_BIT_POS, + PH_LLCNFC_NR_NS_NO_OF_BITS); + + /* Check the value of each i frame N(S) and + received ACKs N(R) */ +#if 0 + if(((ns <= nr) && ((nr - ns) <= psFrameInfo->window_size)) + || ((ns > nr) && (((PH_LLCNFC_MOD_NS_NR + nr) - ns) <= + PH_LLCNFC_U_FRAME_MAX_WIN_SIZE))) +#endif + if(((ns < nr) && ((nr - ns) <= psFrameInfo->window_size)) + || ((ns > nr) && (((PH_LLCNFC_MOD_NS_NR + nr) - ns) <= + PH_LLCNFC_U_FRAME_MAX_WIN_SIZE))) + { + phLlcNfc_H_DeleteIFrame (psListInfo); + no_of_del_frames = (uint8_t)(no_of_del_frames + 1); + } + else + { + while_exit = TRUE; + } + + if(0 == psListInfo->winsize_cnt) + { + while_exit = TRUE; + } + } + else + { + while_exit = TRUE; + } + } + return no_of_del_frames; +} + +NFCSTATUS +phLlcNfc_H_SendUserIFrame ( + phLlcNfc_Context_t *psLlcCtxt, + phLlcNfc_StoreIFrame_t *psListInfo +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Frame_t *ps_frame_info = NULL; + phLlcNfc_LlcPacket_t s_create_packet; + phLlcNfc_LlcPacket_t *ps_get_packet = NULL; + phLlcNfc_Payload_t *ps_llc_payload = NULL; + phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; + uint8_t llc_header = 0, + length = 0; + + if ((NULL == psLlcCtxt) || (NULL == psListInfo)) + { + result = PHNFCSTVAL (CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); + } + else if (0 == psListInfo->winsize_cnt) + { + result = PHNFCSTVAL (CID_NFC_LLC, NFCSTATUS_NOT_ALLOWED); + } + else + { + ps_frame_info = &(psLlcCtxt->s_frameinfo); + ps_store_frame = &(ps_frame_info->s_send_store); + + if ( + (ps_frame_info->n_s != ((ps_store_frame->winsize_cnt + + ps_store_frame->start_pos) % PH_LLCNFC_MOD_NS_NR)) + ) + { + /* Get the stored I frame, only if the new frame is sent + from the upper layer */ + result = phLlcNfc_H_IFrameList_Peek (psListInfo, &ps_get_packet, + ps_frame_info->n_s); + } + + if (NULL != ps_get_packet) + { + llc_header = ps_get_packet->s_llcbuf.sllcpayload.llcheader; + + /* Update n(r) value for the header */ + llc_header = (uint8_t)(llc_header | ps_frame_info->n_r); + + /* Create the packet */ + (void)memcpy ((void *)&(s_create_packet), (void *)ps_get_packet, + sizeof (phLlcNfc_LlcPacket_t)); + + s_create_packet.s_llcbuf.sllcpayload.llcheader = llc_header; + ps_llc_payload = &(s_create_packet.s_llcbuf.sllcpayload); + + /* Length of the complete llc buffer, sent to PN544 */ + length = s_create_packet.llcbuf_len; + + /* Compute CRC for the created packet */ + phLlcNfc_H_ComputeCrc ((uint8_t *)&(s_create_packet.s_llcbuf), + (length - 2), + (uint8_t *)&(ps_llc_payload->llcpayload[(length - 4)]), + (uint8_t *)&(ps_llc_payload->llcpayload[(length - 3)])); + + /* Send the i frame */ + result = phLlcNfc_Interface_Write (psLlcCtxt, + (uint8_t *)&(s_create_packet.s_llcbuf), + (uint32_t)s_create_packet.llcbuf_len); + + ps_frame_info->write_status = result; + + if (NFCSTATUS_BUSY == PHNFCSTATUS (result)) + { + /* The below check is added because, write is already pended by some other + operation, so it has to complete, when it completes, then immediately + next write shall be called using the below updated variable + + The below variable is checked for the resend or rejected i frame + because if due to timer or reject frame from PN544, an I frame + has been sent (means write has been pended then the variable shall + not be overwritten. + */ + ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t) + (((resend_i_frame == ps_frame_info->write_wait_call) || + (rejected_i_frame == ps_frame_info->write_wait_call)) ? + ps_frame_info->write_wait_call : user_i_frame); + } + else + { + if (NFCSTATUS_PENDING == result) + { + /* Start the timer */ + (void)phLlcNfc_StartTimers (PH_LLCNFC_GUARDTIMER, + ps_frame_info->n_s); + + /* "sent_frame_type is updated" only if the data is + written to the lower layer */ + ps_frame_info->sent_frame_type = user_i_frame; + } + } + } + } + return result; +} + +NFCSTATUS +phLlcNfc_H_SendRejectedIFrame ( + phLlcNfc_Context_t *psLlcCtxt, + phLlcNfc_StoreIFrame_t *psListInfo, + uint8_t ns_rejected +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Frame_t *ps_frame_info = NULL; + phLlcNfc_LlcPacket_t s_create_packet; + phLlcNfc_LlcPacket_t *ps_get_packet = NULL; + phLlcNfc_Payload_t *ps_llc_payload = NULL; + phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; + uint8_t llc_header = 0; + uint8_t length = 0; + + if ((NULL == psLlcCtxt) || (NULL == psListInfo)) + { + result = PHNFCSTVAL (CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); + } + else if (0 == psListInfo->winsize_cnt) + { + result = PHNFCSTVAL (CID_NFC_LLC, NFCSTATUS_NOT_ALLOWED); + } + else + { + ps_frame_info = &(psLlcCtxt->s_frameinfo); + ps_store_frame = &(ps_frame_info->s_send_store); + + + if (ns_rejected < (uint8_t)(ps_store_frame->winsize_cnt + + ps_store_frame->start_pos)) + { + /* To send rejected frame, first thing shall be done is + windows size count shall be checked. if the + start position + */ + if (invalid_frame != + ps_store_frame->s_llcpacket[ns_rejected].frame_to_send) + { + /* Above check is added to know only if */ + result = phLlcNfc_H_IFrameList_Peek (psListInfo, &ps_get_packet, + ns_rejected); + } + else + { + ps_frame_info->rejected_ns = DEFAULT_PACKET_INPUT; + /* Get the stored I frame, only if the new frame is sent + from the upper layer */ + result = phLlcNfc_H_SendUserIFrame (psLlcCtxt, psListInfo); + } + } + + if (NULL != ps_get_packet) + { + llc_header = ps_get_packet->s_llcbuf.sllcpayload.llcheader; + + /* Update n(r) value for the header */ + llc_header = (uint8_t)(llc_header | ps_frame_info->n_r); + + /* Create the packet */ + (void)memcpy ((void *)&(s_create_packet), (void *)ps_get_packet, + sizeof (phLlcNfc_LlcPacket_t)); + + s_create_packet.s_llcbuf.sllcpayload.llcheader = llc_header; + ps_llc_payload = &(s_create_packet.s_llcbuf.sllcpayload); + + /* Length of the complete llc buffer, sent to PN544 */ + length = s_create_packet.llcbuf_len; + + /* Compute CRC for the created packet */ + phLlcNfc_H_ComputeCrc ((uint8_t *)&(s_create_packet.s_llcbuf), + (length - 2), + (uint8_t *)&(ps_llc_payload->llcpayload[(length - 4)]), + (uint8_t *)&(ps_llc_payload->llcpayload[(length - 3)])); + + /* Send the i frame */ + result = phLlcNfc_Interface_Write (psLlcCtxt, + (uint8_t *)&(s_create_packet.s_llcbuf), + (uint32_t)s_create_packet.llcbuf_len); + + ps_frame_info->write_status = result; + + if (NFCSTATUS_BUSY == PHNFCSTATUS (result)) + { + /* Already a frame is sent and response is waited for the sent frame, + so update the below variable */ + ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t) + (((ns_rejected != ps_store_frame->start_pos) && + (resend_i_frame != ps_frame_info->write_wait_call))? + rejected_i_frame : ps_frame_info->write_wait_call); + } + else + { + /* NFCSTATUS_PENDING means that the no other write is pending, apart + from the present write + + Start the timer */ + (void)phLlcNfc_StartTimers (PH_LLCNFC_GUARDTIMER, ns_rejected); + + /* "sent_frame_type is updated" only if the data is + written to the lower layer. This will be used in the write + response callback and also indicates, what is the frame sent + and why + */ + ps_frame_info->sent_frame_type = rejected_i_frame; + + if ((ns_rejected + 1) < ps_frame_info->n_s) + { + ps_frame_info->rejected_ns = (uint8_t)(ns_rejected + 1); + + ps_frame_info->write_status = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_BUSY); + + if (invalid_frame == + ps_store_frame->s_llcpacket[ns_rejected].frame_to_send) + { + ps_frame_info->rejected_ns = DEFAULT_PACKET_INPUT; + ps_frame_info->write_wait_call = user_i_frame; + } + else + { + ps_frame_info->write_wait_call = rejected_i_frame; + } + } + else + { + ps_frame_info->rejected_ns = DEFAULT_PACKET_INPUT; + /* This check is added to see that new frame has arrived + from the upper layer */ + if (ps_frame_info->n_s < (ps_store_frame->start_pos + + ps_store_frame->winsize_cnt)) + { + ps_frame_info->write_wait_call = user_i_frame; + } + } + } + } + } + return result; +} + +NFCSTATUS +phLlcNfc_H_SendTimedOutIFrame ( + phLlcNfc_Context_t *psLlcCtxt, + phLlcNfc_StoreIFrame_t *psListInfo, + uint8_t frame_to_send +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Frame_t *ps_frame_info = NULL; + phLlcNfc_Timerinfo_t *ps_timer_info = NULL; + phLlcNfc_LlcPacket_t s_create_packet; + phLlcNfc_LlcPacket_t *ps_get_packet = NULL; + phLlcNfc_Payload_t *ps_llc_payload = NULL; + phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; + + PHNFC_UNUSED_VARIABLE(frame_to_send); + if((NULL == psLlcCtxt) || (NULL == psListInfo)) + { + result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); + } + else if (psListInfo->winsize_cnt == 0) + { + result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_NOT_ALLOWED); + } + else + { + uint8_t llc_header = 0; + uint8_t length = 0; + uint8_t timer_count = 0; + uint8_t timer_index = 0; + uint8_t ns_index = 0; + + ps_frame_info = &(psLlcCtxt->s_frameinfo); + ps_timer_info = &(psLlcCtxt->s_timerinfo); + ps_store_frame = &(ps_frame_info->s_send_store); + + timer_index = ps_timer_info->index_to_send; + timer_count = ps_timer_info->guard_to_count; + ns_index = ps_timer_info->timer_ns_value[timer_index]; + + PH_LLCNFC_DEBUG("SEND TIMEOUT CALL WIN SIZE CNT : 0x%02X\n", ps_store_frame->winsize_cnt); + PH_LLCNFC_DEBUG("SEND TIMEOUT CALL START POS : 0x%02X\n", ps_store_frame->start_pos); + PH_LLCNFC_DEBUG("SEND TIMEOUT CALL N S value : 0x%02X\n", ps_frame_info->n_s); + PH_LLCNFC_DEBUG("SEND TIMEOUT TIMER INDEX : 0x%02X\n", timer_index); + PH_LLCNFC_DEBUG("SEND TIMEOUT CALL frame type : 0x%02X\n", ps_timer_info->frame_type[timer_index]); + + if (resend_i_frame == ps_timer_info->frame_type[timer_index]) + { + /* Get the stored I frame */ + result = phLlcNfc_H_IFrameList_Peek (psListInfo, &ps_get_packet, + ns_index); + } + + PH_LLCNFC_DEBUG("SEND TIMEOUT CALL Packet : 0x%p\n", ps_get_packet); + if (NULL != ps_get_packet) + { + llc_header = ps_get_packet->s_llcbuf.sllcpayload.llcheader; + + /* Update n(r) value for the header */ + llc_header = (uint8_t)(llc_header | ps_frame_info->n_r); + + /* create the packet */ + (void)memcpy ((void *)&(s_create_packet), (void *)ps_get_packet, + sizeof (phLlcNfc_LlcPacket_t)); + + s_create_packet.s_llcbuf.sllcpayload.llcheader = llc_header; + ps_llc_payload = &(s_create_packet.s_llcbuf.sllcpayload); + + /* Length of the complete llc buffer, sent to PN544 */ + length = s_create_packet.llcbuf_len; + + /* Compute CRC */ + phLlcNfc_H_ComputeCrc((uint8_t *)&(s_create_packet.s_llcbuf), + (length - 2), + (uint8_t *)&(ps_llc_payload->llcpayload[(length - 4)]), + (uint8_t *)&(ps_llc_payload->llcpayload[(length - 3)])); + + /* Send the i frame */ + result = phLlcNfc_Interface_Write (psLlcCtxt, + (uint8_t *)&(s_create_packet.s_llcbuf), + (uint32_t)s_create_packet.llcbuf_len); + + ps_frame_info->write_status = result; + PH_LLCNFC_DEBUG("SEND TIMEOUT CALL Write status : 0x%02X\n", result); + + if (NFCSTATUS_BUSY == PHNFCSTATUS (result)) + { + ps_frame_info->write_wait_call = resend_i_frame; + } + else + { + /* result = NFCSTATUS_PENDING and + Timer is not started because the remaining timer + will be running */ + uint16_t time_out_value = 0; + + /* Each frame has the send count, so increment this + as soon as the frame is sent */ + ps_timer_info->iframe_send_count[timer_index] = (uint8_t) + (ps_timer_info->iframe_send_count[timer_index] + 1); + + PH_LLCNFC_DEBUG("SEND TIMEOUT CALL timer index : 0x%02X\n", timer_index); + + if (timer_index > 0) + { + PH_LLCNFC_DEBUG("SEND TIMEOUT CALL GUARD TO VALUE : 0x%02X\n", ps_timer_info->guard_to_value[(timer_index - 1)]); + /* Copy the maximum time-out value. */ + time_out_value = (uint16_t) + ((ps_timer_info->guard_to_value[(timer_index - 1)] >= + PH_LLCNFC_GUARD_TO_VALUE) ? + (ps_timer_info->guard_to_value[(timer_index - 1)] + + PH_LLCNFC_RESOLUTION): + PH_LLCNFC_GUARD_TO_VALUE); + } + else + { + /* If the timer_index is 0 means, the previous timed out + frame is the last frame in the list */ + time_out_value = (uint16_t) + ((ps_timer_info->guard_to_value[(timer_count - 1)] >= + PH_LLCNFC_GUARD_TO_VALUE) ? + (ps_timer_info->guard_to_value[(timer_count - 1)] + + PH_LLCNFC_RESOLUTION): + PH_LLCNFC_GUARD_TO_VALUE); + } + + ps_timer_info->guard_to_value[timer_index] = time_out_value; + + ps_frame_info->sent_frame_type = resend_i_frame; + + ps_timer_info->frame_type[timer_index] = invalid_frame; + + PH_LLCNFC_DEBUG("SEND TIMEOUT CALL Next frame type : 0x%02X\n", ps_timer_info->frame_type[((timer_index + 1) % PH_LLCNFC_MAX_ACK_GUARD_TIMER)]); + /* Now check if next timer has expired, if yes, + set the index to next, on receiving the write response + callback for this send, then next frame can be sent */ + if (resend_i_frame == + ps_timer_info->frame_type[((timer_index + 1) % + PH_LLCNFC_MAX_ACK_GUARD_TIMER)]) + { + /* If next frame has to be sent, then update write wait */ + ps_frame_info->write_status = NFCSTATUS_BUSY; + ps_frame_info->write_wait_call = resend_i_frame; + ps_timer_info->index_to_send = (uint8_t) + ((timer_index + 1) % + PH_LLCNFC_MAX_ACK_GUARD_TIMER); + } + else + { + /* Timer is not expired, + Now, Check if the new frame is ready to be sent, if yes, + then update the variable */ + if ( + (ps_frame_info->n_s != ((ps_store_frame->winsize_cnt + + ps_store_frame->start_pos) % PH_LLCNFC_MOD_NS_NR)) + ) + { + ps_frame_info->write_status = PHNFCSTVAL (CID_NFC_LLC, + NFCSTATUS_BUSY); + ps_frame_info->write_wait_call = user_i_frame; + } + } + +#if 0 + result = phLlcNfc_StartTimers (PH_LLCNFC_GUARDTIMER, + ((llc_header >> + PH_LLCNFC_NS_START_BIT_POS) | + MAX_NS_NR_VALUE)); +#endif /* #if 0 */ + + } + } + else + { + if ( + (ps_frame_info->n_s != ((ps_store_frame->winsize_cnt + + ps_store_frame->start_pos) % PH_LLCNFC_MOD_NS_NR)) + ) + { + ps_frame_info->write_status = PHNFCSTVAL (CID_NFC_LLC, + NFCSTATUS_BUSY); + ps_frame_info->write_wait_call = user_i_frame; + } + } + } + + return result; +} + + +void +phLlcNfc_H_ProcessIFrame ( + phLlcNfc_Context_t *psLlcCtxt +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t ns_index = 0; +#if defined (LLC_SEND_RR_ACK) + /* uint8_t nr_index = 0; */ +#endif /* #if defined (LLC_SEND_RR_ACK) */ + phLlcNfc_Frame_t *ps_frame_info = NULL; + phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; + phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; + phLlcNfc_LlcCmd_t cmdtype = phLlcNfc_e_error; + phLlcNfc_eSentFrameType_t eframe_type = invalid_frame; + uint8_t dont_send_s_frame = FALSE; + uint8_t no_of_del_frames = 0; + phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; + +#ifdef RECV_NR_CHECK_ENABLE + uint8_t recvd_nr = 0; +#endif /* #ifdef RECV_NR_CHECK_ENABLE */ + + ps_frame_info = &(psLlcCtxt->s_frameinfo); + ps_store_frame = &(ps_frame_info->s_send_store); + ps_recv_pkt = &(ps_frame_info->s_recvpacket); + + PHNFC_UNUSED_VARIABLE(result); + /* Received buffer, N(S) value */ + ns_index = (uint8_t)GET_BITS8( + ps_recv_pkt->s_llcbuf.sllcpayload.llcheader, + PH_LLCNFC_NS_START_BIT_POS, + PH_LLCNFC_NR_NS_NO_OF_BITS); + + PH_LLCNFC_DEBUG("NS START POS BEFORE DEL : 0x%02X\n", ps_store_frame->start_pos); + PH_LLCNFC_DEBUG("WIN SIZE BEFORE DEL : 0x%02X\n", ps_store_frame->winsize_cnt); + + /* Correct frame is received, so remove the stored i frame info */ + no_of_del_frames = phLlcNfc_H_UpdateIFrameList (ps_frame_info, + &(ps_frame_info->s_send_store)); + + PH_LLCNFC_DEBUG("NS START POS AFTER DEL : 0x%02X\n", ps_store_frame->start_pos); + PH_LLCNFC_DEBUG("WIN SIZE AFTER DEL : 0x%02X\n", ps_store_frame->winsize_cnt); + +#ifdef RECV_NR_CHECK_ENABLE + + recvd_nr = (uint8_t)GET_BITS8( + ps_recv_pkt->s_llcbuf.sllcpayload.llcheader, + PH_LLCNFC_NR_START_BIT_POS, + PH_LLCNFC_NR_NS_NO_OF_BITS); + + if (((ps_frame_info->n_s > recvd_nr) && + (0 == ((ps_frame_info->n_s + 1) % PH_LLCNFC_MOD_NS_NR))) + || (recvd_nr > ps_frame_info->n_s)) + +#else /* #ifdef RECV_NR_CHECK_ENABLE */ + + if (no_of_del_frames > 0) + +#endif /* #ifdef RECV_NR_CHECK_ENABLE */ + { + phLlcNfc_StopTimers (PH_LLCNFC_GUARDTIMER, no_of_del_frames); + } + + /* Received buffer, N(S) value = N(R) of host (our + structure) then send RR type of s frame else send + REJ type of s frame */ + if (ns_index == ps_frame_info->n_r +#if defined (LLC_SEND_RR_ACK) + + || ((ns_index < ps_frame_info->n_r) && + ((ps_frame_info->n_r - ns_index) < ps_frame_info->window_size)) + || ((ns_index > ps_frame_info->n_r) && + ((ns_index - ps_frame_info->n_r) > ps_frame_info->window_size)) + +#endif /* #if defined (LLC_SEND_RR_ACK) */ + ) + { + PH_LLCNFC_PRINT(" Type bits of S frame to be sent is RR \n"); + ps_frame_info->recv_error_count = 0; + ps_frame_info->send_error_count = 0; + + psLlcCtxt->recvbuf_length = (ps_recv_pkt->llcbuf_len - + PH_LLCNFC_LEN_APPEND); + + (void)memcpy ((void *)psLlcCtxt->precv_buf, (void *)( + ps_recv_pkt->s_llcbuf.sllcpayload.llcpayload), + psLlcCtxt->recvbuf_length); + +#if defined (LLC_SEND_RR_ACK) + + if (((ns_index < ps_frame_info->n_r) && + ((ps_frame_info->n_r - ns_index) < ps_frame_info->window_size)) + || ((ns_index > ps_frame_info->n_r) && + ((ns_index - ps_frame_info->n_r) > ps_frame_info->window_size))) + { + ps_frame_info->n_r = ((ns_index + 1) + % PH_LLCNFC_MOD_NS_NR); + } + else + +#endif /* #if defined (LLC_SEND_RR_ACK) */ + { + /* Update the N(R) value in I and S frame context */ + ps_frame_info->n_r = ((ps_frame_info->n_r + 1) + % PH_LLCNFC_MOD_NS_NR); + +#ifdef PIGGY_BACK + ps_frame_info->resp_recvd_count = (uint8_t) + (ps_frame_info->resp_recvd_count + 1); +#endif /* #ifdef PIGGY_BACK */ + + } + + if (NFCSTATUS_BUSY == PHNFCSTATUS (ps_frame_info->write_status)) + { + /* Any how write cannot be done and some frame is ready to be sent + so this frame will act as the ACK */ + result = phLlcNfc_H_WriteWaitCall (psLlcCtxt); + } + else + { + if ( + (ps_frame_info->n_s != ((ps_store_frame->winsize_cnt + + ps_store_frame->start_pos) % PH_LLCNFC_MOD_NS_NR)) + ) + { + /* If user has sent a frame and DAL write is busy, then + it has to be sent */ + result = phLlcNfc_H_SendUserIFrame (psLlcCtxt, ps_store_frame); + } + } + + if (NFCSTATUS_PENDING == result) + { + dont_send_s_frame = TRUE; +#ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB + phLlcNfc_H_SendInfo (psLlcCtxt); +#endif /* #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB */ + } + else + { + cmdtype = phLlcNfc_e_rr; + /* If i frame is sent from the stored list, it got the correct + acknowledge i frame, so now for an i frame , s frame acknowledge + is sent */ + eframe_type = ((resend_i_frame == ps_frame_info->sent_frame_type)? + resend_s_frame : s_frame); + } + +#ifdef PIGGY_BACK + phLlcNfc_H_SendInfo (psLlcCtxt); +#endif /* #ifdef PIGGY_BACK */ + + } + else + { + ps_frame_info->send_error_count = (uint8_t) + (ps_frame_info->send_error_count + 1); + +#ifdef LLC_SEND_ERROR_COUNT + + if (ps_frame_info->send_error_count < RECV_ERROR_FRAME_COUNT) + +#endif /* #ifdef LLC_SEND_ERROR_COUNT */ + { + +#ifdef LLC_RR_INSTEAD_OF_REJ + + if (((ps_frame_info->n_r > 0) && (ns_index == (ps_frame_info->n_r - 1))) + || ((0 == ps_frame_info->n_r) && + (ns_index == (PH_LLCNFC_MOD_NS_NR - 1)))) + { + cmdtype = phLlcNfc_e_rr; + eframe_type = rej_rr_s_frame; + } + else + +#endif /* #ifdef LLC_RR_INSTEAD_OF_REJ */ + { + cmdtype = phLlcNfc_e_rej; + eframe_type = ((resend_i_frame == ps_frame_info->sent_frame_type)? + resend_rej_s_frame : reject_s_frame); + } + } + +#ifdef LLC_SEND_ERROR_COUNT + else + { +#ifdef LLC_RSET_INSTEAD_OF_EXCEPTION + + result = phLlcNfc_H_SendRSETFrame (psLlcCtxt); + +#else /* #ifdef LLC_RSET_INSTEAD_OF_EXCEPTION */ + + dont_send_s_frame = TRUE; + PH_LLCNFC_DEBUG("SEND ERROR COUNT : 0x%02X\n", ps_frame_info->send_error_count); + /* Error count has reached the limit, raise exception */ + notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_BOARD_COMMUNICATION_ERROR); +#if 0 + phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); +#endif /* #if 0 */ + /* Resend done, no answer from the device */ + psLlcCtxt->cb_for_if.notify ( + psLlcCtxt->cb_for_if.pif_ctxt, + psLlcCtxt->phwinfo, + NFC_NOTIFY_DEVICE_ERROR, + ¬ifyinfo); + +#endif /* #ifdef LLC_RSET_INSTEAD_OF_EXCEPTION */ + } +#endif /* #ifdef LLC_SEND_ERROR_COUNT */ + } + +#ifdef LLC_RELEASE_FLAG + + if (FALSE == g_release_flag) + +#endif /* #ifdef LLC_RELEASE_FLAG */ + { + (void)phLlcNfc_Interface_Read(psLlcCtxt, + PH_LLCNFC_READWAIT_OFF, + &(ps_recv_pkt->s_llcbuf.llc_length_byte), + (uint8_t)PH_LLCNFC_BYTES_INIT_READ); + +#ifdef PIGGY_BACK + /* Check if any write call is performed or not */ + if (NFCSTATUS_PENDING != result) + { + /* No write is performed, So, now check */ + if (NFCSTATUS_BUSY == PHNFCSTATUS (ps_frame_info->write_status)) + { + /* Any how write cannot be done and some frame is ready to be sent + so this frame will act as the ACK */ + result = phLlcNfc_H_WriteWaitCall (psLlcCtxt); + } + } + + if (NFCSTATUS_PENDING != result) + { + if (ps_frame_info->window_size == ps_frame_info->resp_recvd_count) + { + phLlcNfc_LlcPacket_t s_packet_info; + /* Create S frame */ + (void)phLlcNfc_H_CreateSFramePayload (ps_frame_info, &(s_packet_info), cmdtype); + + result = phLlcNfc_Interface_Write(psLlcCtxt, + (uint8_t *)&(s_packet_info.s_llcbuf), + (uint32_t)(s_packet_info.llcbuf_len)); + + + if (0 == ps_frame_info->send_error_count) + { + ps_frame_info->write_wait_call = invalid_frame; + } + ps_frame_info->sent_frame_type = eframe_type; + } + else + { + result = phLlcNfc_StartTimers (PH_LLCNFC_ACKTIMER, 0); + } + } +#else /* #ifdef PIGGY_BACK */ + + if ((TRUE != ps_frame_info->write_pending) && + (PH_LLCNFC_READPEND_REMAIN_BYTE != ps_frame_info->read_pending) && + (FALSE == dont_send_s_frame)) + { + phLlcNfc_LlcPacket_t s_packet_info = {0}; + /* Create S frame */ + (void)phLlcNfc_H_CreateSFramePayload (ps_frame_info, &(s_packet_info), cmdtype); + + result = phLlcNfc_Interface_Write(psLlcCtxt, + (uint8_t *)&(s_packet_info.s_llcbuf), + (uint32_t)(s_packet_info.llcbuf_len)); + + + if (0 == ps_frame_info->send_error_count) + { + ps_frame_info->write_wait_call = invalid_frame; + } + ps_frame_info->sent_frame_type = eframe_type; + } +#endif /* #ifdef PIGGY_BACK */ + } + + return ; +} + +static +NFCSTATUS +phLlcNfc_H_ProcessUFrame ( + phLlcNfc_Context_t *psLlcCtxt +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Frame_t *ps_frame_info = NULL; + phLlcNfc_LlcPacket_t *ps_uframe_pkt = NULL; +#ifdef LLC_URSET_NO_DELAY + phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; +#else /* #ifdef LLC_URSET_NO_DELAY */ + uint32_t delay_timer_id = + PH_OSALNFC_INVALID_TIMER_ID; +#endif /* #ifdef LLC_URSET_NO_DELAY */ + uint8_t cmdtype = phLlcNfc_e_error; + + phLlcNfc_StopTimers(PH_LLCNFC_CONNECTIONTIMER, 0); + ps_frame_info = &(psLlcCtxt->s_frameinfo); + ps_uframe_pkt = &(ps_frame_info->s_recvpacket); + /* Check the command type */ + cmdtype = (ps_uframe_pkt->s_llcbuf.sllcpayload.llcheader & + PH_LLCNFC_U_FRAME_MODIFIER_MASK); + PHNFC_UNUSED_VARIABLE(result); + switch(cmdtype) + { + case phLlcNfc_e_rset: + { + psLlcCtxt->s_frameinfo.rset_recvd = TRUE; + /* command type is RSET, so update the U frame parameters */ + result = phLlcNfc_H_Update_ReceivedRSETInfo (ps_frame_info, + ps_uframe_pkt->s_llcbuf.sllcpayload); + /* Create a UA frame */ + result = phLlcNfc_H_CreateUFramePayload(psLlcCtxt, + ps_uframe_pkt, + &(ps_uframe_pkt->llcbuf_len), + phLlcNfc_e_ua); + + if (NFCSTATUS_SUCCESS == result) + { + /* Call DAL write */ + result = phLlcNfc_Interface_Write( psLlcCtxt, + (uint8_t*)&(ps_uframe_pkt->s_llcbuf), + (uint32_t)ps_uframe_pkt->llcbuf_len); + + phLlcNfc_H_ResetFrameInfo(psLlcCtxt); + ps_frame_info->write_status = result; + ps_frame_info->write_wait_call = invalid_frame; + if (NFCSTATUS_PENDING == result) + { + ps_frame_info->sent_frame_type = + ((ps_frame_info->sent_frame_type != init_u_rset_frame) ? + u_a_frame : init_u_a_frame); + } + else + { + if (NFCSTATUS_BUSY == PHNFCSTATUS(result)) + { + ps_frame_info->write_wait_call = + ((ps_frame_info->sent_frame_type != init_u_rset_frame) ? + u_a_frame : init_u_a_frame); + result = NFCSTATUS_PENDING; + } + } + } + break; + } + case phLlcNfc_e_ua: + { + phLlcNfc_H_ResetFrameInfo (psLlcCtxt); + /* Add timer here, to delay the next command to the PN544 */ +#ifdef LLC_URSET_NO_DELAY + if (ps_frame_info->s_send_store.winsize_cnt > 0) + { +#if 0 + /* Resend I frame */ + result = phLlcNfc_H_SendTimedOutIFrame (psLlcCtxt, + &(ps_frame_info->s_send_store, 0); +#else + result = phLlcNfc_H_SendUserIFrame (psLlcCtxt, + &(ps_frame_info->s_send_store)); +#endif /* #if 0 */ + } + else + { + if ((init_u_rset_frame == ps_frame_info->sent_frame_type) && + (NULL != psLlcCtxt->cb_for_if.notify)) + { + ps_frame_info->sent_frame_type = write_resp_received; + notifyinfo.status = NFCSTATUS_SUCCESS; + /* Send the notification to the upper layer */ + psLlcCtxt->cb_for_if.notify( + psLlcCtxt->cb_for_if.pif_ctxt, + psLlcCtxt->phwinfo, + NFC_NOTIFY_INIT_COMPLETED, + ¬ifyinfo); + } + } +#else /* #ifdef LLC_URSET_NO_DELAY */ + delay_timer_id = phOsalNfc_Timer_Create (); + phOsalNfc_Timer_Start (delay_timer_id, LLC_URSET_DELAY_TIME_OUT, + phLlcNfc_URSET_Delay_Notify, (void*)0); +#endif /* #ifdef LLC_URSET_NO_DELAY */ + break; + } + default: + { + result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_FORMAT); + break; + } + } + return result; +} + +static +void +phLlcNfc_H_ProcessSFrame ( + phLlcNfc_Context_t *psLlcCtxt) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t cmdtype = phLlcNfc_e_error; +#if 0 + prev_win_count = 0; +#endif /* #if 0 */ + phNfc_sTransactionInfo_t compinfo = {0, 0, 0, 0, 0}; + phLlcNfc_Frame_t *ps_frame_info = NULL; + phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; + phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; + uint8_t no_of_del_frames = 0; + phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; + + ps_frame_info = &(psLlcCtxt->s_frameinfo); + ps_recv_pkt = &(ps_frame_info->s_recvpacket); + ps_store_frame = &(ps_frame_info->s_send_store); + + cmdtype = (ps_recv_pkt->s_llcbuf.sllcpayload.llcheader & + PH_LLCNFC_S_FRAME_TYPE_MASK); + PHNFC_UNUSED_VARIABLE(result); + + PH_LLCNFC_DEBUG("NS START POS BEFORE DEL : 0x%02X\n", ps_store_frame->start_pos); + PH_LLCNFC_DEBUG("WIN SIZE BEFORE DEL : 0x%02X\n", ps_store_frame->winsize_cnt); + + /* Correct frame is received, so remove the + stored i frame info for the acknowledged frames */ + no_of_del_frames = phLlcNfc_H_UpdateIFrameList (ps_frame_info, + &(ps_frame_info->s_send_store)); + + PH_LLCNFC_DEBUG("NS START POS AFTER DEL : 0x%02X\n", ps_store_frame->start_pos); + PH_LLCNFC_DEBUG("WIN SIZE AFTER DEL : 0x%02X\n", ps_store_frame->winsize_cnt); + +#if 0 + prev_win_count = ps_frame_info->s_send_store.winsize_cnt; +#endif /* #if 0 */ + + /* Pend the read */ + result = phLlcNfc_Interface_Read (psLlcCtxt, + PH_LLCNFC_READWAIT_OFF, + &(ps_recv_pkt->s_llcbuf.llc_length_byte), + (uint8_t)PH_LLCNFC_BYTES_INIT_READ); + switch(cmdtype) + { + case phLlcNfc_e_rr: + case phLlcNfc_e_rej: + { + /* RR frame received */ + phLlcNfc_StopTimers (PH_LLCNFC_GUARDTIMER, no_of_del_frames); + + if (phLlcNfc_e_rr == cmdtype) + { + ps_frame_info->recv_error_count = 0; + ps_frame_info->send_error_count = 0; + } + else + { + ps_frame_info->recv_error_count = (uint8_t) + (ps_frame_info->recv_error_count + 1); + } + + if (ps_frame_info->recv_error_count >= RECV_ERROR_FRAME_COUNT) + { + /* Do nothing */ + } + else if (NFCSTATUS_BUSY == PHNFCSTATUS(ps_frame_info->write_status)) + { + result = phLlcNfc_H_WriteWaitCall (psLlcCtxt); + } + else + { + if ( + (ps_frame_info->n_s != ((ps_store_frame->winsize_cnt + + ps_store_frame->start_pos) % PH_LLCNFC_MOD_NS_NR)) + ) + { + /* If user has sent a frame and DAL write is busy, then + it has to be sent */ + result = phLlcNfc_H_SendUserIFrame (psLlcCtxt, ps_store_frame); + } + } + + if ((0 != psLlcCtxt->send_cb_len) && + (ps_store_frame->winsize_cnt < ps_frame_info->window_size)) + { + /* Due to the window size count (i.e., count has reached + the limit), send completion was not sent for the previous + send from the upper layer. So to allow next send from the + upper layer, send completion is called */ + compinfo.length = (uint16_t)psLlcCtxt->send_cb_len; + compinfo.status = NFCSTATUS_SUCCESS; + + if (NULL != psLlcCtxt->cb_for_if.send_complete) + { + psLlcCtxt->send_cb_len = 0; + /* Call the send callback, if the window size + count becomes less than actual window size */ + psLlcCtxt->cb_for_if.send_complete ( + psLlcCtxt->cb_for_if.pif_ctxt, + psLlcCtxt->phwinfo, &compinfo); + } + } + break; + } + +#if 0 + case phLlcNfc_e_rej: + { + ps_frame_info->recv_error_count = (uint8_t) + (ps_frame_info->recv_error_count + 1); + /* RR frame received */ + phLlcNfc_StopTimers (PH_LLCNFC_GUARDTIMER, no_of_del_frames); + + if (ps_frame_info->recv_error_count < RECV_ERROR_FRAME_COUNT) + { + /* Below check is added because if PN544 sends REJ to a frame, but + the next frame has already been sent from PN544, then + Send the user I frame */ + result = phLlcNfc_H_SendUserIFrame (psLlcCtxt, ps_store_frame); + } + break; + } +#endif /* #if 0 */ + + case phLlcNfc_e_rnr: + { + phLlcNfc_StopAllTimers (); + ps_frame_info->recv_error_count = (uint8_t) + (ps_frame_info->recv_error_count + 1); + break; + } + + case phLlcNfc_e_srej: + default: + { + ps_frame_info->recv_error_count = (uint8_t) + (ps_frame_info->recv_error_count + 1); + result = PHNFCSTVAL (CID_NFC_LLC, + NFCSTATUS_INVALID_FORMAT); + break; + } + } + + if (ps_frame_info->recv_error_count >= RECV_ERROR_FRAME_COUNT) + { +#ifdef LLC_RSET_INSTEAD_OF_EXCEPTION + + result = phLlcNfc_H_SendRSETFrame (psLlcCtxt); + +#else /* #ifdef LLC_RSET_INSTEAD_OF_EXCEPTION */ + + PH_LLCNFC_DEBUG("RECV ERROR COUNT : 0x%02X\n", ps_frame_info->recv_error_count); + /* Raise the exception for CRC error received from the */ + notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_BOARD_COMMUNICATION_ERROR); +#if 0 + phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); +#endif /* #if 0 */ + /* Resend done, no answer from the device */ + psLlcCtxt->cb_for_if.notify ( + psLlcCtxt->cb_for_if.pif_ctxt, + psLlcCtxt->phwinfo, + NFC_NOTIFY_DEVICE_ERROR, + ¬ifyinfo); + +#endif /* #ifdef LLC_RSET_INSTEAD_OF_EXCEPTION */ + } + + return ; +} + + +void +phLlcNfc_H_ComputeCrc( + uint8_t *pData, + uint8_t length, + uint8_t *pCrc1, + uint8_t *pCrc2 +) +{ + uint8_t crc_byte = 0, + index = 0; + uint16_t crc = 0; + +#ifdef CRC_A + crc = 0x6363; /* ITU-V.41 */ +#else + crc = 0xFFFF; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ +#endif /* #ifdef CRC_A */ + + do + { + crc_byte = pData[index]; + phLlcNfc_H_UpdateCrc(crc_byte, &crc); + index++; + } while (index < length); + +#ifndef INVERT_CRC + crc = ~crc; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ +#endif /* #ifndef INVERT_CRC */ + + *pCrc1 = (uint8_t) (crc & 0xFF); + *pCrc2 = (uint8_t) ((crc >> 8) & 0xFF); + return; +} + +static +void +phLlcNfc_H_UpdateCrc( + uint8_t crcByte, + uint16_t *pCrc +) +{ + crcByte = (crcByte ^ (uint8_t)((*pCrc) & 0x00FF)); + crcByte = (crcByte ^ (uint8_t)(crcByte << 4)); + *pCrc = (*pCrc >> 8) ^ ((uint16_t)crcByte << 8) ^ + ((uint16_t)crcByte << 3) ^ + ((uint16_t)crcByte >> 4); +} + +NFCSTATUS +phLlcNfc_H_StoreIFrame ( + phLlcNfc_StoreIFrame_t *psList, + phLlcNfc_LlcPacket_t sPacketInfo +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t ns_index = 0, + llc_header = 0; + + if ((NULL == psList) || (0 == sPacketInfo.llcbuf_len) || + (PH_LLCNFC_I_HEADER_INIT != + (sPacketInfo.s_llcbuf.sllcpayload.llcheader & + PH_LLCNFC_I_FRM_HEADER_MASK))) + { + result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Get the index from the start index */ + if(psList->winsize_cnt > 0) + { + ns_index = (uint8_t)((psList->start_pos + psList->winsize_cnt) % + PH_LLCNFC_MOD_NS_NR); + } + else + { + ns_index = psList->start_pos; + } + + llc_header = (uint8_t)(PH_LLCNFC_I_HEADER_INIT | (ns_index << + PH_LLCNFC_NS_START_BIT_POS)); + sPacketInfo.s_llcbuf.sllcpayload.llcheader = llc_header; + + (void)memcpy (&(psList->s_llcpacket[ns_index]), + &(sPacketInfo), sizeof(phLlcNfc_LlcPacket_t)); + + /* This variable says that LLC has to send complete + callback for stored I frame */ + psList->s_llcpacket[ns_index].frame_to_send = invalid_frame; + + psList->winsize_cnt++; + } + return result; +} + +static +void +phLlcNfc_H_DeleteIFrame ( + phLlcNfc_StoreIFrame_t *psList +) +{ + if (NULL != psList) + { + (void)memset( &(psList->s_llcpacket[psList->start_pos]), + 0, sizeof(phLlcNfc_LlcPacket_t)); + + /* Go to next N(S) position */ + psList->start_pos = ((psList->start_pos + 1) % + PH_LLCNFC_MOD_NS_NR); + + if (psList->winsize_cnt > 0) + { + psList->winsize_cnt--; + } + } +} + +static +NFCSTATUS +phLlcNfc_H_IFrameList_Peek ( + phLlcNfc_StoreIFrame_t *psList, + phLlcNfc_LlcPacket_t **psPacketinfo, + uint8_t position +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t index = 0; + + *psPacketinfo = NULL; + if ((NULL != psList) && (psList->winsize_cnt > 0)) + { + result = NFCSTATUS_SUCCESS; + if ((position < (psList->start_pos + psList->winsize_cnt)) || + (DEFAULT_PACKET_INPUT == position)) + { + index = (uint8_t)((DEFAULT_PACKET_INPUT == position) ? + psList->start_pos : position); + *psPacketinfo = &(psList->s_llcpacket[index]); + } + } + + return result; +} + +NFCSTATUS +phLlcNfc_H_ProRecvFrame ( + phLlcNfc_Context_t *psLlcCtxt +) +{ + NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + phLlcNfc_FrameType_t frame_type = phLlcNfc_eErr_frame; +#ifdef LLC_DATA_BYTES + uint8_t *print_buf = (uint8_t *) + &(psLlcCtxt->s_frameinfo.s_recvpacket.s_llcbuf); + uint8_t buf_len = + psLlcCtxt->s_frameinfo.s_recvpacket.llcbuf_len; + PH_LLCNFC_STRING("** Response "); + +#endif /* LLC_DATA_BYTES */ + if (NULL != psLlcCtxt) + { + result = NFCSTATUS_SUCCESS; + /* Get the received frame type */ + frame_type = phLlcNfc_H_ChkGetLlcFrameType( + psLlcCtxt->s_frameinfo.s_recvpacket.s_llcbuf.sllcpayload.llcheader); + + /* Depending on the received frame type, process the + received buffer */ + switch(frame_type) + { + case phLlcNfc_eU_frame: + { + PH_LLCNFC_PRINT("U frame received \n"); + PH_LLCNFC_STRING("U frame "); + PH_LLCNFC_PRINT_DATA(print_buf, buf_len); + PH_LLCNFC_STRING(";\n"); + result = phLlcNfc_H_ProcessUFrame(psLlcCtxt); + break; + } + case phLlcNfc_eI_frame: + { + PH_LLCNFC_PRINT("I frame received \n"); + PH_LLCNFC_STRING("I frame "); + PH_LLCNFC_PRINT_DATA(print_buf, buf_len); + PH_LLCNFC_STRING(";\n"); + phLlcNfc_H_ProcessIFrame(psLlcCtxt); + break; + } + case phLlcNfc_eS_frame: + { + PH_LLCNFC_PRINT("S frame received \n"); + PH_LLCNFC_STRING("S frame "); + PH_LLCNFC_PRINT_DATA(print_buf, buf_len); + PH_LLCNFC_STRING(";\n"); + phLlcNfc_H_ProcessSFrame(psLlcCtxt); + break; + } + case phLlcNfc_eErr_frame: + default: + { + PH_LLCNFC_PRINT("Error frame received \n"); + result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_FORMAT); + break; + } + } + + } + return result; +} + +#ifdef CRC_ERROR_REJ +NFCSTATUS +phLlcNfc_H_SendRejectFrame( + phLlcNfc_Context_t *psLlcCtxt + ) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_LlcPacket_t s_packet_info = {0}; + + result = phLlcNfc_H_CreateSFramePayload( + &(psLlcCtxt->s_frameinfo), + &(s_packet_info), + phLlcNfc_e_rej); + /* Send the "S" frame to the lower layer */ + result = phLlcNfc_Interface_Write(psLlcCtxt, + (uint8_t *)&(s_packet_info.s_llcbuf), + (uint32_t)(s_packet_info.llcbuf_len)); + + if (NFCSTATUS_PENDING == result) + { + /* Increment the retry count of the reject frame */ + psLlcCtxt->s_frameinfo.recv_error_count = + (psLlcCtxt->s_frameinfo.recv_error_count + 1); + } + + + return result; +} +#endif /* #ifdef CRC_ERROR_REJ */ + +static +void +phLlcNfc_H_ResetFrameInfo ( + phLlcNfc_Context_t *psLlcCtxt +) +{ + uint8_t i = 0, + win_cnt = 0, + pos = 0, + while_exit = FALSE, + index_flag = FALSE; + phLlcNfc_StoreIFrame_t *ps_send_store = NULL; + phLlcNfc_Buffer_t *ps_buffer = NULL; + + ps_send_store = &(psLlcCtxt->s_frameinfo.s_send_store); + win_cnt = ps_send_store->winsize_cnt; + pos = ps_send_store->start_pos; + PH_LLCNFC_PRINT ("\n\nLLC : phLlcNfc_H_ResetFrameInfo called\n\n"); + PH_LLCNFC_DEBUG ("\n\nLLC : ps_send_store->start_pos %08X\n", ps_send_store->start_pos); + PH_LLCNFC_DEBUG ("\n\nLLC : ps_send_store->winsize_cnt before reset %08X\n", ps_send_store->winsize_cnt); + + + if (0 != pos) + { + /* If the start position of the ns = 0, then + no need to shift the stored llc data, + Else it has to be shifted to the first + index of the array */ + if(TRUE == ((pos + win_cnt) / + PH_LLCNFC_MAX_I_FRAME_STORE)) + { + /* 'i' is the array index, So to store data in the array, + windows size count shall be subtracted by 1 */ + i = (win_cnt - 1); + /* if window size > 1 and ns for 2 frames are 7 and 0, then + to reset the ns index to 0, the frames are copied from + the reverse order, so to do it a flag is declared */ + index_flag = TRUE; + pos = (((pos - 1) + win_cnt) % PH_LLCNFC_MAX_I_FRAME_STORE); + } + + while (FALSE == while_exit) + { + (void)memcpy ((void *)&(ps_send_store->s_llcpacket[i]), + (void *)&(ps_send_store->s_llcpacket[pos]), + sizeof (phLlcNfc_LlcPacket_t)); + + ps_send_store->s_llcpacket[i].frame_to_send = invalid_frame; + + ps_buffer = &(ps_send_store->s_llcpacket[i].s_llcbuf); + /* change n(s) value */ + ps_buffer->sllcpayload.llcheader = (uint8_t) + (PH_LLCNFC_I_HEADER_INIT | + (i << PH_LLCNFC_NS_START_BIT_POS)); + if(TRUE == index_flag) + { + if(0 == i) + { + while_exit = TRUE; + } + else + { + i = ((i - 1) % PH_LLCNFC_MAX_I_FRAME_STORE); + if (0 == pos) + { + pos = (PH_LLCNFC_MAX_I_FRAME_STORE - 1); + } + else + { + pos = ((pos - 1) % PH_LLCNFC_MAX_I_FRAME_STORE); + } + } + } + else + { + if (i >= win_cnt) + { + while_exit = TRUE; + } + else + { + i = ((i + 1) % PH_LLCNFC_MAX_I_FRAME_STORE); + pos = ((pos + 1) % PH_LLCNFC_MAX_I_FRAME_STORE); + } + + } + } + } + psLlcCtxt->s_timerinfo.guard_to_count = 0; + psLlcCtxt->s_timerinfo.timer_flag = 0; + ps_send_store->start_pos = 0; + psLlcCtxt->s_frameinfo.n_r = psLlcCtxt->s_frameinfo.n_s = 0; + if (ps_send_store->winsize_cnt > 0) + { + psLlcCtxt->s_frameinfo.rejected_ns = 0; + } + else + { + psLlcCtxt->s_frameinfo.rejected_ns = DEFAULT_PACKET_INPUT; + } + + PH_LLCNFC_DEBUG ("\n\nLLC : ps_send_store->winsize_cnt after reset %08X\n", ps_send_store->winsize_cnt); + return; +} + +NFCSTATUS +phLlcNfc_H_WriteWaitCall ( + phLlcNfc_Context_t *psLlcCtxt + ) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_StoreIFrame_t *ps_store_info = NULL; + phLlcNfc_Frame_t *ps_frame_info = NULL; + + ps_frame_info = &(psLlcCtxt->s_frameinfo); + ps_store_info = &(ps_frame_info->s_send_store); + + PH_LLCNFC_PRINT ("\nLLC : phLlcNfc_H_WriteWaitCall call ..\n"); + PH_LLCNFC_DEBUG ("\n\nLLC : ps_frame_info->write_wait_call before call %08X\n", ps_frame_info->write_wait_call); + + ps_frame_info->write_status = NFCSTATUS_PENDING; + switch (ps_frame_info->write_wait_call) + { + case user_i_frame: + { + ps_frame_info->write_wait_call = invalid_frame; + result = phLlcNfc_H_SendUserIFrame (psLlcCtxt, ps_store_info); + break; + } + + case resend_i_frame: + { + ps_frame_info->write_wait_call = invalid_frame; + result = phLlcNfc_H_SendTimedOutIFrame (psLlcCtxt, ps_store_info, 0); + break; + } + + case rejected_i_frame: + { + ps_frame_info->write_wait_call = invalid_frame; + result = phLlcNfc_H_SendRejectedIFrame (psLlcCtxt, ps_store_info, + ps_frame_info->rejected_ns); + break; + } + + case resend_s_frame: + case reject_s_frame: + case resend_rej_s_frame: + { + ps_frame_info->write_wait_call = invalid_frame; + break; + } + + case u_rset_frame: + { + ps_frame_info->write_wait_call = invalid_frame; + result = phLlcNfc_H_SendRSETFrame (psLlcCtxt); + break; + } + + default : + { + ps_frame_info->write_wait_call = invalid_frame; + break; + } + } + + PH_LLCNFC_DEBUG ("\n\nLLC : ps_frame_info->write_wait_call after call %08X\n", ps_frame_info->write_wait_call); + PH_LLCNFC_PRINT ("\nLLC : phLlcNfc_H_WriteWaitCall end ..\n"); + return result; +} + +NFCSTATUS +phLlcNfc_H_SendRSETFrame ( + phLlcNfc_Context_t *psLlcCtxt + ) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_LlcPacket_t s_packet_info; + phLlcNfc_Frame_t *ps_frame_info = NULL; + + ps_frame_info = &(psLlcCtxt->s_frameinfo); + + result = phLlcNfc_H_CreateUFramePayload(psLlcCtxt, + &(s_packet_info), + &(s_packet_info.llcbuf_len), + phLlcNfc_e_rset); + + if (NFCSTATUS_SUCCESS == result) + { + /* Call DAL write */ + result = phLlcNfc_Interface_Write(psLlcCtxt, + (uint8_t*)&(s_packet_info.s_llcbuf), + (uint32_t)s_packet_info.llcbuf_len); + } + + ps_frame_info->write_status = result; + if (NFCSTATUS_PENDING == result) + { + /* Start the timer */ + result = phLlcNfc_StartTimers (PH_LLCNFC_CONNECTIONTIMER, 0); + if (NFCSTATUS_SUCCESS == result) + { + ps_frame_info->sent_frame_type = u_rset_frame; + result = NFCSTATUS_PENDING; + } + } + else + { + ps_frame_info->write_wait_call = u_rset_frame; + } + + return result; +} + + diff --git a/libnfc-nxp/phLlcNfc_Frame.h b/libnfc-nxp/phLlcNfc_Frame.h new file mode 100644 index 0000000..e76e017 --- /dev/null +++ b/libnfc-nxp/phLlcNfc_Frame.h @@ -0,0 +1,471 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phLlcNfc_Frame.h +* \brief To append and delete the I or S or U frames. +* +* Project: NFC-FRI-1.1 +* +* $Date: Fri Apr 30 10:03:36 2010 $ +* $Author: ing02260 $ +* $Revision: 1.19 $ +* $Aliases: NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +#ifndef PHLLCNFC_FRAME_H +#define PHLLCNFC_FRAME_H + +/** +* \name LLC NFC frame creation and deletion +* +* File: \ref phLlcNfc_Frame.h +* +*/ +/*@{*/ +#define PHLLCNFCFRAME_FILEREVISION "$Revision: 1.19 $" /**< \ingroup grp_hal_nfc_llc */ +#define PHLLCNFCFRAME_FILEALIASES "$Aliases: NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_hal_nfc_llc */ +/*@}*/ + +/*************************** Includes *******************************/ + +/*********************** End of includes ****************************/ + +/** \defgroup grp_hal_nfc_llc_helper LLC helper functions + * + * + * + */ + +/***************************** Macros *******************************/ +/** Maximum buffer that LLC can send and receive */ +#define PH_LLCNFC_MAX_BUFLEN_RECV_SEND (33) +/** Maximum buffer that LLC can send and receive */ +#define PH_LLCNFC_MIN_BUFLEN_RECVD (1) +/** Modulo to calculate the N(S) and N(R), when it extends 7, because + N(S) and N(R) can have the value maximum up to 7 */ +#define PH_LLCNFC_MOD_NS_NR (8) +/** When the entire LLC buffer is created or received, the header byte + will be the first byte (not the 0th byte which is the LLC length) + of the buffer */ +#define PH_LLCNFC_HEADER_BYTE_IN_BUFFER (1) +/** Maximum windows size, which is obtained by sending or + receiving the U - frame */ +#define PH_LLCNFC_U_FRAME_MAX_WIN_SIZE (4) +/** Minimum windows size, which is obtained by sending or + receiving the U - frame */ +#define PH_LLCNFC_U_FRAME_MIN_WIN_SIZE (2) +/** Start position of the U frame */ +#define PH_LLCNFC_U_FRAME_START_POS (0) +/** No of position to set the U frame */ +#define PH_LLCNFC_U_FRAME_NO_OF_POS (5) +/** This mask is to find the frame type ( S or U) */ +#define PH_LLCNFC_LLC_HEADER_MASK (0xE0) +/** This mask is to find the frame type (I, S or U) */ +#define PH_LLCNFC_I_FRM_HEADER_MASK (0x80) +/** If S frame is received or to be sent, the maximum length that + can be sent or received is 4 */ +#define PH_LLCNFC_MAX_S_FRAME_LEN (4) +/** If S frame is received, to know the command type like RR, RNR, + REJ or SREJ */ +#define PH_LLCNFC_S_FRAME_TYPE_MASK (0x18) +/** Maximum value of N(S) or N(R) */ +#define PH_LLCNFC_I_S_FRAME_MAX_NR (0x07) +/** If U frame is received or to be sent, the maximum length that + can be sent or received is 7 */ +#define PH_LLCNFC_U_FRAME_LEN (7) +/** If S frame is received, to know the command type like RSET or UA */ +#define PH_LLCNFC_U_FRAME_MODIFIER_MASK (0x1F) +/** Extra length to be append to the user buffer Length to create the + LLC buffer */ +#define PH_LLCNFC_LEN_APPEND (0x04) +/** U frame header without modifier */ +#define PH_LLCNFC_U_HEADER_INIT (0xE0) +/** I frame header without N(S) and N(R) */ +#define PH_LLCNFC_I_HEADER_INIT (0x80) +/** S frame header without type and N(R) */ +#define PH_LLCNFC_S_HEADER_INIT (0xC0) +/** N(S) start bit position */ +#define PH_LLCNFC_NS_START_BIT_POS (0x03) +/** N(R) start bit position */ +#define PH_LLCNFC_NR_START_BIT_POS (0x00) +/** Number of bits N(R) and N(S) */ +#define PH_LLCNFC_NR_NS_NO_OF_BITS (0x03) +/** S frame type start bit position */ +#define PH_LLCNFC_S_FRAME_TYPE_POS (0x03) +/** Number of bits (Type in S frame) */ +#define PH_LLCNFC_SFRAME_TYPE_NOOFBITS (0x02) +/** SREJ command */ +#define PH_LLCNFC_SREJ_BYTE_VALUE (0x00) +/** Number of CRC bytes in a LLC packet */ +#define PH_LLCNFC_NUM_OF_CRC_BYTES (0x02) + +/* This macro is used as the input for the function "phLlcNfc_H_IFrameList_Peek" + and "phLlcNfc_H_SendTimedOutIFrame" functions. This values means, take the starting + position as the reference */ +#define DEFAULT_PACKET_INPUT (0xFFU) +#define MAX_NS_NR_VALUE (0x07U) + +/************************ End of macros *****************************/ + +/********************** Callback functions **************************/ + +/******************* End of Callback functions **********************/ + +/********************* Structures and enums *************************/ + +/****************** End of structures and enums *********************/ + +/******************** Function declarations *************************/ +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions \b Frame Init function +* +* \copydoc page_reg Gets the LLC main context and stores it. +* +* \param[in] psLlcCtxt Llc main structure information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +void phLlcNfc_H_Frame_Init ( + phLlcNfc_Context_t *psLlcCtxt +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions \b DeInit function +* +* \copydoc page_reg +* +* \param[in] psFrameInfo Frame structure information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +void +phLlcNfc_H_Frame_DeInit ( + phLlcNfc_Frame_t *psFrameInfo +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions \b List append function +* +* \copydoc page_reg Append the new I frame information at the beginning of the list +* +* \param[in/out] psList List inofrmation to know where shall the packet should be stored +* \param[in] packetInfo Llc packet information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +NFCSTATUS +phLlcNfc_H_StoreIFrame ( + phLlcNfc_StoreIFrame_t *psList, + phLlcNfc_LlcPacket_t sPacketInfo + +); + + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions Create S frame function +* +* \copydoc page_reg This function creates a S frame +* +* \param[in/out] pllcSFrmBuf Required buffer to create the S frame +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +void +phLlcNfc_H_Create_S_Frame( + uint8_t *pllcSFrmBuf +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions Compute CRC function +* +* \copydoc page_reg This function is used to compute CRC for the llc data +* +* \param[in] pData Llc data for which the CRC needs to be calculated +* \param[in] length Length is the value till the CRC needs to be +* calculated for the Llc data +* \param[in] pCrc1 1st CRC byte +* \param[in] pCrc2 2nd CRC byte +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +void +phLlcNfc_H_ComputeCrc( + uint8_t *pData, + uint8_t length, + uint8_t *pCrc1, + uint8_t *pCrc2 +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions Create U frame payload function +* +* \copydoc page_reg This function is used to create a LLC packet with U frame +* +* \param[in/out] psLlcCtxt Llc main structure information +* \param[in/out] psLlcPacket Llc packet sent by the upper layer +* \param[in/out] pLlcPacketLength Length of the llc packet +* \param[in] cmdType U frame has RSET/UA commands +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +NFCSTATUS +phLlcNfc_H_CreateUFramePayload ( + phLlcNfc_Context_t *psLlcCtxt, + phLlcNfc_LlcPacket_t *psLlcPacket, + uint8_t *pLlcPacketLength, + phLlcNfc_LlcCmd_t cmdType +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC helper functions Create I frame payload function +* +* \copydoc page_reg This function is used to create a LLC packet with I frame +* +* \param[in/out] psFrameInfo Information related to LLC frames are stored +* in this structure +* \param[in/out] psLlcPacket Llc packet sent by the upper layer +* \param[in] pLlcBuf User given buffer or the buffer which needs LLC framing +* \param[in] llcBufLength Length of the parameter "pLlcBuf" +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +NFCSTATUS +phLlcNfc_H_CreateIFramePayload ( + phLlcNfc_Frame_t *psFrameInfo, + phLlcNfc_LlcPacket_t *psLlcPacket, + uint8_t *pLlcBuf, + uint8_t llcBufLength +); + +/** + * \ingroup grp_hal_nfc_llc_helper + * + * \brief LLC helper functions Process received frame function + * + * \copydoc page_reg This function process the received data + * + * \param[in] pLlcCtxt Llc main context + * + * \retval NFCSTATUS_SUCCESS Operation successful. + * \retval NFCSTATUS_INVALID_FORMAT If any error in the frame + */ +NFCSTATUS +phLlcNfc_H_ProRecvFrame ( + phLlcNfc_Context_t *psLlcCtxt +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC component resend the I frame function +* +* \copydoc page_reg This is a helper function which, sends back the timed out +* I frame to the PN544. This is due to the reason that ACK is not received +* from PN544 within the guard time-out value +* +* \param[in] psLlcCtxt Llc main structure information +* \param[in/out] psListInfo List of I frame information +* \param[in] ns_frame_no Frame number to send (to send the first stored +* frame send DEFAULT_PACKET_INPUT) +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +extern +NFCSTATUS +phLlcNfc_H_SendTimedOutIFrame ( + phLlcNfc_Context_t *psLlcCtxt, + phLlcNfc_StoreIFrame_t *psListInfo, + uint8_t ns_frame_no +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC state machine functions \b Change state function +* +* \copydoc page_reg changes the state if possible else returns error +* +* \param[in, out] psLlcCtxt Llc main structure information +* \param[in] changeStateTo Next state to change +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +extern +NFCSTATUS +phLlcNfc_H_ChangeState( + phLlcNfc_Context_t *psLlcCtxt, + phLlcNfc_State_t changeStateTo + ); + +#ifdef CRC_ERROR_REJ +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC send reject command function +* +* \copydoc page_reg Sends reject command, when CRC error is recieved +* +* \param[in, out] psLlcCtxt Llc main structure information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +extern +NFCSTATUS +phLlcNfc_H_SendRejectFrame( + phLlcNfc_Context_t *psLlcCtxt + ); +#endif /* #ifdef CRC_ERROR_REJ */ + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC Write wait call function +* +* \copydoc page_reg Write that has been ignored earlier will be called in this function +* +* \param[in, out] psLlcCtxt Llc main structure information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_BUSY Write is pended, so wait till it completes. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +extern +NFCSTATUS +phLlcNfc_H_WriteWaitCall ( + phLlcNfc_Context_t *psLlcCtxt + ); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC Send user frame function +* +* \copydoc page_reg Sends the stored user frame, that are not sent. +* +* \param[in, out] psLlcCtxt Llc main structure information +* \param[in] psListInfo Stored list of packets +* +* No return value +* +*/ +NFCSTATUS +phLlcNfc_H_SendUserIFrame ( + phLlcNfc_Context_t *psLlcCtxt, + phLlcNfc_StoreIFrame_t *psListInfo + ); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC Send rejected frame function +* +* \copydoc page_reg Sends the stored rejected frame from PN544. +* +* \param[in, out] psLlcCtxt Llc main structure information +* \param[in] psListInfo Stored list of packets +* \param[in] ns_rejected N(S) that was rejected +* +* No return value +* +*/ +NFCSTATUS +phLlcNfc_H_SendRejectedIFrame ( + phLlcNfc_Context_t *psLlcCtxt, + phLlcNfc_StoreIFrame_t *psListInfo, + uint8_t ns_rejected + ); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC component Create S frame function +* +* \copydoc page_reg This is a helper function which, creates the S frame +* +* \param[in/out] psFrameInfo Generic frame information +* \param[in/out] psLlcPacket Llc packet sent by the upper layer +* \param[in/out] cmdType Command type of S frame +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +NFCSTATUS +phLlcNfc_H_CreateSFramePayload ( + phLlcNfc_Frame_t *psFrameInfo, + phLlcNfc_LlcPacket_t *psLlcPacket, + phLlcNfc_LlcCmd_t cmdType +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC Send upper layer information function +* +* \copydoc page_reg Sends received information to the upper layer frame. +* +* \param[in, out] psLlcCtxt Llc main structure information +* +* No return value +* +*/ +void +phLlcNfc_H_SendInfo( + phLlcNfc_Context_t *psLlcCtxt + ); + + +/******************** Function declarations *************************/ +#endif /* #ifndef PHLLCNFC_FRAME_H */ + + diff --git a/libnfc-nxp/phLlcNfc_Interface.c b/libnfc-nxp/phLlcNfc_Interface.c new file mode 100644 index 0000000..5b40269 --- /dev/null +++ b/libnfc-nxp/phLlcNfc_Interface.c @@ -0,0 +1,1046 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phLlcNfc_Interface.c +* \brief Interface for both LLC and transport layer +* +* Project: NFC-FRI-1.1 +* +* $Date: Tue Jun 1 14:41:26 2010 $ +* $Author: ing02260 $ +* $Revision: 1.75 $ +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +/*************************** Includes *******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef PH_LLCNFC_STUB +#include +#endif +#ifdef PH_LLCNFC_DALINT +#include +#endif +#define LOG_TAG "NFC-LLC" + +#include +/*********************** End of includes ****************************/ + +/***************************** Macros *******************************/ +#define PH_LLCNFC_APPEND_LEN (4) +#define LLC_NS_FRAME_HEADER_MASK (0x38U) +/************************ End of macros *****************************/ + +/*********************** Local functions ****************************/ +static +void +phLlcNfc_WrResp_Cb( + void *pContext, + void *pHwInfo, + phNfc_sTransactionInfo_t *pCompInfo + ); + +static +void +phLlcNfc_RdResp_Cb( + void *pContext, + void *pHwInfo, + phNfc_sTransactionInfo_t *pCompInfo + ); + +/******************** End of Local functions ************************/ + +/********************** Global variables ****************************/ +int libnfc_llc_error_count = 0; + +/******************** End of Global Variables ***********************/ + +NFCSTATUS +phLlcNfc_Interface_Register( + phLlcNfc_Context_t *psLlcCtxt, + phNfcLayer_sCfg_t *psIFConfig +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phNfcIF_sCallBack_t if_cb = {0,0,0,0}; + phNfcIF_sReference_t sreference = {0,0,0}; + + if ((NULL == psLlcCtxt) || (NULL == psIFConfig)) + { + result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + } + else + { + result = NFCSTATUS_SUCCESS; + if_cb.notify = NULL; + if_cb.receive_complete = (pphNfcIF_Transact_Completion_CB_t)&phLlcNfc_RdResp_Cb; + if_cb.send_complete = (pphNfcIF_Transact_Completion_CB_t)&phLlcNfc_WrResp_Cb; + if_cb.pif_ctxt = psLlcCtxt; + sreference.plower_if = &(psLlcCtxt->lower_if); + result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); +#ifdef PH_LLCNFC_STUB + result = phDalNfc_StubRegister(&sreference, if_cb, psIFConfig->layer_next); +#endif /* #ifdef PH_LLCNFC_STUB */ +#ifdef PH_LLCNFC_DALINT + result = phDal4Nfc_Register(&sreference, if_cb, psIFConfig->layer_next); +#else + if ((NULL != psIFConfig->layer_next) && + (NULL != psIFConfig->layer_next->layer_registry)) + { + result = psIFConfig->layer_next->layer_registry( + &sreference, + if_cb, + (void *)&psIFConfig[(psIFConfig->layer_index - 1)]); + } +#endif /* #ifdef PH_LLCNFC_DALINT */ + } + PH_LLCNFC_DEBUG("Llc Dal Interface Register result : 0x%x\n", result); + return result; +} + +NFCSTATUS +phLlcNfc_Interface_Init( + phLlcNfc_Context_t *psLlcCtxt +) +{ + /* + 1. Get the pointer of the main llc context + */ + NFCSTATUS result = NFCSTATUS_SUCCESS; + if ((NULL == psLlcCtxt) || + (NULL == psLlcCtxt->lower_if.init)) + { + result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + } + else + { + /* Initialise the main context */ + result = psLlcCtxt->lower_if.init( psLlcCtxt->lower_if.pcontext, + psLlcCtxt->phwinfo); + } + PH_LLCNFC_DEBUG("Llc Dal Interface Init result : 0x%x\n", result); + return result; +} + +NFCSTATUS +phLlcNfc_Interface_Read( + phLlcNfc_Context_t *psLlcCtxt, + uint8_t readWaitOn, + uint8_t *pLlcBuffer, + uint32_t llcBufferLength +) +{ + NFCSTATUS result = NFCSTATUS_PENDING; + /* + 1. Call DAL or TL read with "phLlcNfc_LlcTl_RdResp_Cb" as + callback function + */ + PH_LLCNFC_PRINT("Llc Dal Interface Read called\n"); + if ((NULL == psLlcCtxt) || (NULL == pLlcBuffer) || + (0 == llcBufferLength) || (NULL == psLlcCtxt->lower_if.receive) || + (readWaitOn > PH_LLCNFC_READWAIT_ON)) + { + result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); + } + else if (PH_LLCNFC_READPEND_FLAG_OFF != + psLlcCtxt->s_frameinfo.read_pending) + { + /* do nothing */ + } + else + { + if (PH_LLCNFC_READWAIT_OFF == readWaitOn) + { + result = psLlcCtxt->lower_if.receive( + psLlcCtxt->lower_if.pcontext, + psLlcCtxt->phwinfo, + pLlcBuffer, + (uint8_t)llcBufferLength); + } + else + { + result = psLlcCtxt->lower_if.receive_wait( + psLlcCtxt->lower_if.pcontext, + psLlcCtxt->phwinfo, + pLlcBuffer, + (uint16_t)llcBufferLength); + } + + if(NFCSTATUS_PENDING == result) + { + if (PH_LLCNFC_READPEND_ONE_BYTE == llcBufferLength) + { + psLlcCtxt->s_frameinfo.read_pending = + PH_LLCNFC_READPEND_ONE_BYTE; + } + else + { + psLlcCtxt->s_frameinfo.read_pending = + PH_LLCNFC_READPEND_REMAIN_BYTE; + } + } + } + PH_LLCNFC_DEBUG("Llc Dal Interface Read result : 0x%x\n", result); + return result; +} + +NFCSTATUS +phLlcNfc_Interface_Write( + phLlcNfc_Context_t *psLlcCtxt, + uint8_t *pLlcBuffer, + uint32_t llcBufferLength +) +{ + NFCSTATUS result = NFCSTATUS_PENDING; + + PH_LLCNFC_PRINT("Llc Dal Interface Write called\n"); + /* + 1. Call DAL or TL write with "phLlcNfc_LlcTl_WrResp_Cb" as + callback function + */ + if ((NULL == psLlcCtxt) || (NULL == pLlcBuffer) || + (0 == llcBufferLength) || + (NULL == psLlcCtxt->lower_if.send)) + { + PH_LLCNFC_DEBUG ("psLlcCtxt : 0x%p\n", psLlcCtxt); + PH_LLCNFC_DEBUG ("pLlcBuffer : 0x%p\n", pLlcBuffer); + PH_LLCNFC_DEBUG ("llcBufferLength : 0x%08X\n", llcBufferLength); + result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); + } + else + { + PH_LLCNFC_PRINT("Buffer to be send to Dal : \n"); + PH_LLCNFC_PRINT_BUFFER(pLlcBuffer, llcBufferLength); + + if ((TRUE == psLlcCtxt->s_frameinfo.write_pending) || + (PH_LLCNFC_READPEND_REMAIN_BYTE == + psLlcCtxt->s_frameinfo.read_pending)) + { + result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_BUSY); + } + else + { +#ifdef LLC_DATA_BYTES + + PH_LLCNFC_PRINT_DATA (pLlcBuffer, llcBufferLength); + PH_LLCNFC_STRING (";\n"); + +#endif /* LLC_DATA_BYTES */ + + psLlcCtxt->s_frameinfo.s_llcpacket.llcbuf_len = (uint8_t)llcBufferLength; + (void)memcpy ((void *)&(psLlcCtxt->s_frameinfo.s_llcpacket.s_llcbuf), + (void *)pLlcBuffer, llcBufferLength); + + result = psLlcCtxt->lower_if.send(psLlcCtxt->lower_if.pcontext, + psLlcCtxt->phwinfo, + (uint8_t *)&(psLlcCtxt->s_frameinfo.s_llcpacket.s_llcbuf), + (uint16_t)llcBufferLength); + if(NFCSTATUS_PENDING == result) + { + psLlcCtxt->s_frameinfo.write_pending = TRUE; +#ifdef PIGGY_BACK + /* Stop the ACK timer, as the ACK or I frame is sent */ + phLlcNfc_StopTimers (PH_LLCNFC_ACKTIMER, 0); + /* ACK is sent, so reset the response received count */ + psLlcCtxt->s_frameinfo.resp_recvd_count = 0; +#endif /* #ifdef PIGGY_BACK */ + } + } + } + PH_LLCNFC_DEBUG("Llc Dal Interface Write result : 0x%x\n", result); + return result; +} + +static +void +phLlcNfc_WrResp_Cb( + void *pContext, + void *pHwInfo, + phNfc_sTransactionInfo_t *pCompInfo +) +{ + /* + 1. Check the window size, if window size = windows + 1. Call the send callback, which has been registered by upper + layer + */ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; + phLlcNfc_Frame_t *ps_frame_info = NULL; + phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; + phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; + phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; + uint8_t count = 0; + + PH_LLCNFC_PRINT("\n\nLLC : WRITE RESP CB CALLED\n\n"); + + if ((NULL != ps_llc_ctxt) && (NULL != pCompInfo) && (NULL != pHwInfo)) + { + ps_llc_ctxt->s_frameinfo.write_pending = FALSE; + + PHNFC_UNUSED_VARIABLE(result); + + if(NFCSTATUS_SUCCESS == pCompInfo->status) + { + ps_frame_info = &(ps_llc_ctxt->s_frameinfo); + ps_recv_pkt = &(ps_frame_info->s_recvpacket); + ps_store_frame = &(ps_frame_info->s_send_store); + count = ps_frame_info->s_send_store.start_pos; + + PH_LLCNFC_DEBUG("RECEIVE length : 0x%02X\n", ps_recv_pkt->llcbuf_len); + PH_LLCNFC_DEBUG("SENT frame type : 0x%02X\n", ps_frame_info->sent_frame_type); + PH_LLCNFC_DEBUG("WRITE PENDING : 0x%02X\n", ps_frame_info->write_pending); + PH_LLCNFC_DEBUG("WRITE PENDING status : 0x%04X\n", ps_frame_info->write_status); + PH_LLCNFC_DEBUG("WRITE wait frame type : 0x%02X\n", ps_frame_info->write_wait_call); + PH_LLCNFC_DEBUG("NS START POS : 0x%02X\n", ps_store_frame->start_pos); + PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_store_frame->winsize_cnt); + + switch(ps_frame_info->sent_frame_type) + { + case init_u_rset_frame: + { + /* First U frame sent properly, update sent frame type + in the callback */ + result = phLlcNfc_Interface_Read (ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + &(ps_recv_pkt->s_llcbuf.llc_length_byte), + (uint8_t)PH_LLCNFC_BYTES_INIT_READ); + + if (NFCSTATUS_BUSY == + PHNFCSTATUS (ps_frame_info->write_status)) + { + ps_frame_info->write_status = NFCSTATUS_PENDING; + result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); + } + break; + } + + case init_u_a_frame: + { + /* First UA frame sent properly, update sent frame type + in the callback. Send the notification to the + upper layer */ + ps_frame_info->sent_frame_type = write_resp_received; + result = phLlcNfc_Interface_Read (ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + &(ps_recv_pkt->s_llcbuf.llc_length_byte), + (uint8_t)PH_LLCNFC_BYTES_INIT_READ); + + if(NULL != ps_llc_ctxt->cb_for_if.notify) + { + notifyinfo.status = NFCSTATUS_SUCCESS; + ps_llc_ctxt->cb_for_if.notify ( + ps_llc_ctxt->cb_for_if.pif_ctxt, + ps_llc_ctxt->phwinfo, + NFC_NOTIFY_INIT_COMPLETED, + ¬ifyinfo); + } + break; + } + + case u_rset_frame: + { + /* Retries has failed to work, so U frame is sent */ + ps_frame_info->sent_frame_type = write_resp_received; + + if (NFCSTATUS_BUSY == + PHNFCSTATUS (ps_frame_info->write_status)) + { + ps_frame_info->write_status = NFCSTATUS_PENDING; + result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); + } + break; + } + + case user_i_frame: + { + /* Send complete */ + count = ps_frame_info->n_s; + + ps_store_frame->s_llcpacket[count].frame_to_send = + ps_frame_info->sent_frame_type = write_resp_received; + + /* N(S) shall be incremented now, because, this callback + ensures that packet is sent */ + count = + ps_frame_info->n_s = ((ps_frame_info->n_s + 1) % + PH_LLCNFC_MOD_NS_NR); + + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + &(ps_recv_pkt->s_llcbuf.llc_length_byte), + (uint8_t)PH_LLCNFC_BYTES_INIT_READ); + + if (NFCSTATUS_BUSY == + PHNFCSTATUS (ps_frame_info->write_status)) + { + ps_frame_info->write_status = NFCSTATUS_PENDING; + result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); + } + + + if ((((ps_store_frame->start_pos + ps_store_frame->winsize_cnt) % + PH_LLCNFC_MOD_NS_NR) == ps_frame_info->n_s) && + (ps_frame_info->window_size == ps_store_frame->winsize_cnt)) + { + /* Don't call the upper layer send completion callback, + because last sent frame is the maximum that can be + held by LLC due to windowing + store the callback info, call send completion shall + be sent to upper layer only after the ACK is received for the + I frames */ + ps_llc_ctxt->send_cb_len = (pCompInfo->length - + PH_LLCNFC_APPEND_LEN); + } + else + { + /* Send completion is sent to upper layer + Actually, this allows the upper layer to send data, if any + */ + if (NULL != ps_llc_ctxt->cb_for_if.send_complete) + { + pCompInfo->length = (pCompInfo->length - + PH_LLCNFC_APPEND_LEN); + ps_llc_ctxt->cb_for_if.send_complete ( + ps_llc_ctxt->cb_for_if.pif_ctxt, + pHwInfo, pCompInfo); + } + } + break; + } + + case s_frame: + { +#if 0 + uint8_t i_frame_ns_value = 0; +#endif /* #if 0 */ + /* S frame is only sent when ever a I frame is received from + the PN544 in the read response callback, so the received I + frame is acknowledged with S frame. The write response + callback for sent S frame is in progress. */ + ps_frame_info->sent_frame_type = write_resp_received; + +#if 0 + i_frame_ns_value = + ((ps_store_frame->s_llcpacket[count].s_llcbuf.sllcpayload.llcheader + & LLC_NS_FRAME_HEADER_MASK) >> PH_LLCNFC_NS_START_BIT_POS); + + + PH_LLCNFC_DEBUG("Actual ns value : 0x%02X\n", + i_frame_ns_value); +#endif /* #if 0 */ + + PH_LLCNFC_DEBUG("Window size : 0x%02X\n", + ps_frame_info->s_send_store.winsize_cnt); + PH_LLCNFC_DEBUG("frame to send : 0x%02X\n", + ps_store_frame->s_llcpacket[count].frame_to_send); + + if (NFCSTATUS_BUSY == + PHNFCSTATUS(ps_frame_info->write_status)) + { + ps_frame_info->write_status = NFCSTATUS_PENDING; + result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); + } +#ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB + phLlcNfc_H_SendInfo (ps_llc_ctxt); +#endif /* #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB */ + break; + } + +#ifdef LLC_RR_INSTEAD_OF_REJ + case rej_rr_s_frame: + { + if (NFCSTATUS_BUSY == + PHNFCSTATUS(ps_frame_info->write_status)) + { + ps_frame_info->write_status = NFCSTATUS_PENDING; + result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); + } + break; + } +#endif /* #ifdef LLC_RR_INSTEAD_OF_REJ */ + + case resend_i_frame: + { + /* The code reaches here, only if stored I frame is sent + No changes here, but send next I frame from the stored list, + in the read response callback, only if proper S or I frame + is received from the PN544 */ + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + &(ps_recv_pkt->s_llcbuf.llc_length_byte), + (uint8_t)PH_LLCNFC_BYTES_INIT_READ); + + if (NFCSTATUS_BUSY == PHNFCSTATUS(ps_frame_info->write_status)) + { + ps_frame_info->write_status = NFCSTATUS_PENDING; + result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); + } + + if (ps_store_frame->winsize_cnt == + ps_frame_info->window_size) + { + /* Don't call the upper layer send completion callback, + store the callback info, call send completion after + ack for written frame + ps_llc_ctxt->send_cb_len = pCompInfo->length; */ + } + else + { + /* ***** This notification needs to be disabled ***** */ + if(NULL != ps_llc_ctxt->cb_for_if.send_complete) + { + pCompInfo->length = (pCompInfo->length - + PH_LLCNFC_APPEND_LEN); + ps_llc_ctxt->cb_for_if.send_complete( + ps_llc_ctxt->cb_for_if.pif_ctxt, + pHwInfo, pCompInfo); + } + } + + if(user_i_frame == + ps_store_frame->s_llcpacket[count].frame_to_send) + { + /* Send complete */ + ps_store_frame->s_llcpacket[count].frame_to_send = + resend_i_frame; + } + break; + } + + case rejected_i_frame: + { + /* Update the sent frame type, if window size count is 0 */ + ps_frame_info->sent_frame_type = write_resp_received; + /* The code enters here, whenever a I frame is resent and for + this resent I frame, an I frame received from PN544. + So the S frame is sent as the acknowledgment */ + if (NFCSTATUS_BUSY == + PHNFCSTATUS(ps_frame_info->write_status)) + { + ps_frame_info->write_status = NFCSTATUS_PENDING; + result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); + } + break; + } + + case resend_s_frame: + { + /* Update the sent frame type, if window size count is 0 */ + ps_frame_info->sent_frame_type = write_resp_received; + /* The code enters here, whenever a I frame is resent and for + this resent I frame, an I frame received from PN544. + So the S frame is sent as the acknowledgment */ + if (NFCSTATUS_BUSY == + PHNFCSTATUS(ps_frame_info->write_status)) + { + ps_frame_info->write_status = NFCSTATUS_PENDING; + result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); + } + +#ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB + phLlcNfc_H_SendInfo (ps_llc_ctxt); +#endif /* #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB */ + break; + } + + case reject_s_frame: + { + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + &(ps_recv_pkt->s_llcbuf.llc_length_byte), + (uint8_t)PH_LLCNFC_BYTES_INIT_READ); + + if (NFCSTATUS_BUSY == + PHNFCSTATUS(ps_frame_info->write_status)) + { + ps_frame_info->write_status = NFCSTATUS_PENDING; + result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); + } + break; + } + + case u_a_frame: + { + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + &(ps_recv_pkt->s_llcbuf.llc_length_byte), + (uint8_t)PH_LLCNFC_BYTES_INIT_READ); + + PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_frame_info->s_send_store.winsize_cnt); + + if(ps_frame_info->s_send_store.winsize_cnt > 0) + { + result = phLlcNfc_H_SendUserIFrame (ps_llc_ctxt, + &(ps_frame_info->s_send_store)); + } + break; + } + + case resend_rej_s_frame: + { + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + &(ps_recv_pkt->s_llcbuf.llc_length_byte), + (uint8_t)PH_LLCNFC_BYTES_INIT_READ); + + PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_frame_info->s_send_store.winsize_cnt); + + if(ps_frame_info->s_send_store.winsize_cnt > 0) + { + result = phLlcNfc_H_SendTimedOutIFrame (ps_llc_ctxt, + &(ps_frame_info->s_send_store), 0); + } + break; + } + + default : + { + break; + } + } + } + else + { + /* Write not successful */ + if(NULL != ps_llc_ctxt->cb_for_if.send_complete) + { + phLlcNfc_StopTimers(PH_LLCNFC_GUARDTIMER, + ps_llc_ctxt->s_timerinfo.guard_to_count); + PH_LLCNFC_DEBUG("Error status received : 0x%x\n", pCompInfo->status); + ps_llc_ctxt->cb_for_if.send_complete( + ps_llc_ctxt->cb_for_if.pif_ctxt, + pHwInfo, pCompInfo); + } + } + } + PH_LLCNFC_PRINT("\n\nLLC : WRITE RESP CB END\n\n"); +} + +static +void +phLlcNfc_RdResp_Cb( + void *pContext, + void *pHwInfo, + phNfc_sTransactionInfo_t *pCompInfo +) +{ + /* + 1. LLC Receive has been called by the upper layer, the response + for this function is called by the lower layer + 2. Get the frame information from the receive buffer + 3. Depending on the received frame type, process the received + buffer + */ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; + void *p_upperctxt = NULL; + uint8_t crc1 = 0, + crc2 = 0; + phLlcNfc_Frame_t *ps_frame_info = NULL; + phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; + phLlcNfc_Payload_t *ps_llc_payload = NULL; + pphNfcIF_Notification_CB_t notifyul = NULL; + phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; + + PH_LLCNFC_PRINT("\n\nLLC : READ RESP CB CALLED\n\n"); + + if ((NULL != ps_llc_ctxt) && (NULL != pCompInfo) && (NULL != pHwInfo) + && (NULL != pCompInfo->buffer)) + { + ps_frame_info = &(ps_llc_ctxt->s_frameinfo); + ps_recv_pkt = &(ps_frame_info->s_recvpacket); + ps_llc_payload = &(ps_recv_pkt->s_llcbuf.sllcpayload); + + ps_llc_ctxt->s_frameinfo.read_pending = PH_LLCNFC_READPEND_FLAG_OFF; + + if (NFCSTATUS_SUCCESS == pCompInfo->status) + { + if ((PH_LLCNFC_MIN_BUFLEN_RECVD == pCompInfo->length) && + (((PH_LLCNFC_MIN_BUFLEN_RECVD + 1) < *(pCompInfo->buffer)) && + (PH_LLCNFC_MAX_BUFLEN_RECV_SEND > *(pCompInfo->buffer)))) + { + PH_LLCNFC_PRINT("Buffer received : \n"); + PH_LLCNFC_PRINT_BUFFER(pCompInfo->buffer, pCompInfo->length); + +#if 0 + /* Received length is 1 and receive buffer + contains the length field which is greater than 2, + so read the remaining bytes*/ + ps_recv_pkt->s_llcbuf.llc_length_byte = pCompInfo->buffer[0]; +#endif + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + (uint8_t *)ps_llc_payload, + (uint32_t)(ps_recv_pkt->s_llcbuf.llc_length_byte)); + + if ((init_u_rset_frame == ps_frame_info->sent_frame_type) && + (NFCSTATUS_PENDING != result) && + (NULL != ps_llc_ctxt->cb_for_if.notify)) + { + PH_LLCNFC_PRINT("Initialised error\n"); + notifyinfo.status = result; + /* Copy the upper layer callback pointer and the upper + layer context, after that call release */ + notifyul = ps_llc_ctxt->cb_for_if.notify; + p_upperctxt = ps_llc_ctxt->cb_for_if.pif_ctxt; + result = phLlcNfc_Release(ps_llc_ctxt, pHwInfo); + + /* Wrong result, so Init failed sent */ + notifyul(p_upperctxt, pHwInfo, + NFC_NOTIFY_INIT_FAILED, ¬ifyinfo); + } + } + else if (TRUE == ps_llc_ctxt->s_frameinfo.write_pending) + { + /* Ignore the bytes as write is not complete and + pend a read for reading 1 byte */ + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + (uint8_t *)&( + ps_recv_pkt->s_llcbuf.llc_length_byte), + PH_LLCNFC_MIN_BUFLEN_RECVD); + } + else if (((PH_LLCNFC_MIN_BUFLEN_RECVD + 1) < pCompInfo->length) && + (PH_LLCNFC_MAX_BUFLEN_RECV_SEND > pCompInfo->length) && + (pCompInfo->length == ps_recv_pkt->s_llcbuf.llc_length_byte)) + { + PH_LLCNFC_PRINT("Buffer received : \n"); + PH_LLCNFC_PRINT_BUFFER(pCompInfo->buffer, pCompInfo->length); + PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_frame_info->s_send_store.winsize_cnt); + + /* Receive is complete, so move the state to INITIALISED */ + if (phLlcNfc_Resend_State != ps_llc_ctxt->state) + { + result = phLlcNfc_H_ChangeState(ps_llc_ctxt, + phLlcNfc_Initialised_State); + } + /* Copy the received buffer and length */ + ps_recv_pkt->llcbuf_len = (uint8_t) + (ps_recv_pkt->s_llcbuf.llc_length_byte + 1); +#if 0 + (void)memcpy(ps_llc_payload, pCompInfo->buffer, + pCompInfo->length); +#endif + + /* + Check the CRC + ps_llc_ctxt->s_frameinfo.s_recvpacket.s_llcbuf : + consists llc length byte + llc header + data + CRC + (which needs to be calculated by the below function) + ps_llc_ctxt->s_frameinfo.s_recvpacket.llcbuf_len : + Total length of the above buffer + ps_llc_ctxt->s_frameinfo.s_recvpacket.llcbuf_len - 2 : + -2 because the CRC has to be calculated, only for the + bytes which has llc length byte + llc header + data. + But total length (llcbuf_len) consists of above mentioned + things with 2 byte CRC + ps_llc_ctxt->s_frameinfo.s_recvpacket.s_llcbuf.sllcpayload.llcpayload : + consists only data (no length byte and no llc header) + (psllcctxt->s_frameinfo.s_recvpacket.llcbuf_len - 4) : + is the array index of the first CRC byte to be calculated + (psllcctxt->s_frameinfo.s_recvpacket.llcbuf_len - 3) : + is the array index of the second CRC byte to be calculated + */ + phLlcNfc_H_ComputeCrc((uint8_t *)&(ps_recv_pkt->s_llcbuf), + (ps_recv_pkt->llcbuf_len - 2), + &crc1, &crc2); + + if ((crc1 == ps_llc_payload->llcpayload[ + (ps_recv_pkt->llcbuf_len - 4)]) + && (crc2 == ps_llc_payload->llcpayload[ + (ps_recv_pkt->llcbuf_len - 3)])) + { + result = phLlcNfc_H_ProRecvFrame(ps_llc_ctxt); + } +#ifdef LLC_DISABLE_CRC + else + { + result = phLlcNfc_H_ProRecvFrame(ps_llc_ctxt); + } +#else + else if (ps_frame_info->recv_error_count < + PH_LLCNFC_MAX_REJ_RETRY_COUNT) + { + ALOGW("LLC bad crc"); + PH_LLCNFC_PRINT("CRC ERROR RECVD \n"); + PH_LLCNFC_DEBUG("RECV ERROR COUNT : 0x%02X\n", ps_frame_info->recv_error_count); + + ps_frame_info->recv_error_count = (uint8_t) + (ps_frame_info->recv_error_count + 1); + libnfc_llc_error_count++; + + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), + PH_LLCNFC_BYTES_INIT_READ); +#ifdef CRC_ERROR_REJ + /* Send REJ (S frame), as the CRC received has error */ + result = phLlcNfc_H_SendRejectFrame (ps_llc_ctxt); + +#endif /* #ifdef CRC_ERROR_REJ */ + + } + else + { + ALOGE("max LLC retries exceeded, stack restart"); + result = phLlcNfc_Interface_Read (ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), + PH_LLCNFC_BYTES_INIT_READ); + + /* Raise the exception for CRC error received from the */ + notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_BOARD_COMMUNICATION_ERROR); +#if 0 + phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); +#endif /* #if 0 */ + /* Resend done, no answer from the device */ + ps_llc_ctxt->cb_for_if.notify ( + ps_llc_ctxt->cb_for_if.pif_ctxt, + ps_llc_ctxt->phwinfo, + NFC_NOTIFY_DEVICE_ERROR, + ¬ifyinfo); + } + +#endif /* #ifdef LLC_DISABLE_CRC */ + } /* read more than 1 byte */ + else if (ps_frame_info->recv_error_count >= + PH_LLCNFC_MAX_REJ_RETRY_COUNT) + { + ALOGE("max LLC retries exceeded, stack restart"); + result = phLlcNfc_Interface_Read (ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), + PH_LLCNFC_BYTES_INIT_READ); + + /* Raise the exception for CRC error received from the */ + notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_BOARD_COMMUNICATION_ERROR); +#if 0 + phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); +#endif /* #if 0 */ + /* Resend done, no answer from the device */ + ps_llc_ctxt->cb_for_if.notify ( + ps_llc_ctxt->cb_for_if.pif_ctxt, + ps_llc_ctxt->phwinfo, + NFC_NOTIFY_DEVICE_ERROR, + ¬ifyinfo); + } + else if (((PH_LLCNFC_MIN_BUFLEN_RECVD + 1) < pCompInfo->length) && + (PH_LLCNFC_MAX_BUFLEN_RECV_SEND > pCompInfo->length) && + (pCompInfo->length != ps_recv_pkt->s_llcbuf.llc_length_byte)) + { + ALOGE("bad LLC length1 %d", pCompInfo->length); + ps_frame_info->recv_error_count = (uint8_t) + (ps_frame_info->recv_error_count + 1); + libnfc_llc_error_count++; + + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), + PH_LLCNFC_BYTES_INIT_READ); + +#ifdef CRC_ERROR_REJ + + /* Send REJ (S frame), as the CRC received has error */ + result = phLlcNfc_H_SendRejectFrame (ps_llc_ctxt); + +#endif /* #ifdef CRC_ERROR_REJ */ + } + else if ((PH_LLCNFC_MIN_BUFLEN_RECVD == pCompInfo->length) && + ((*(pCompInfo->buffer) > (PH_LLCNFC_MAX_BUFLEN_RECV_SEND - 1)) + ||(*(pCompInfo->buffer) <= (PH_LLCNFC_MIN_BUFLEN_RECVD + 1)))) + { + /* Temporary fix for the 0xFF data received + Solution for the read one byte, giving error in buffer + PH_LLCNFC_MAX_BUFLEN_RECV_SEND (0x21) is the maximum + bytes expected by LLC, if the buffer + value is greater than (0x21 - 1), then pend a read to + get 1 byte again + */ + ALOGW("bad LLC length byte %x\n", *(pCompInfo->buffer)); + ps_frame_info->recv_error_count = (uint8_t) + (ps_frame_info->recv_error_count + 1); + libnfc_llc_error_count++; + + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), + PH_LLCNFC_BYTES_INIT_READ); + } + else + { + ALOGW("unknown LLC error1"); + ps_frame_info->recv_error_count = (uint8_t) + (ps_frame_info->recv_error_count + 1); + libnfc_llc_error_count++; + + phLlcNfc_StopTimers(PH_LLCNFC_GUARDTIMER, + ps_llc_ctxt->s_timerinfo.guard_to_count); + pCompInfo->status = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_FORMAT); + pCompInfo->buffer = NULL; + pCompInfo->length = 0; + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), + PH_LLCNFC_BYTES_INIT_READ); + if (NULL != ps_llc_ctxt->cb_for_if.receive_complete) + { + ps_llc_ctxt->cb_for_if.receive_complete( + ps_llc_ctxt->cb_for_if.pif_ctxt, + pHwInfo, pCompInfo); + } + } + } else if (NFCSTATUS_READ_FAILED == pCompInfo->status) { + // partial read - try reading the length byte again + ALOGV("LLC length mis-match\n"); + ps_frame_info->recv_error_count = (uint8_t) + (ps_frame_info->recv_error_count + 1); + libnfc_llc_error_count++; + + result = phLlcNfc_Interface_Read(ps_llc_ctxt, + PH_LLCNFC_READWAIT_OFF, + (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), + PH_LLCNFC_BYTES_INIT_READ); + } + else + { + ALOGW("unknown LLC error2"); + ps_frame_info->recv_error_count = (uint8_t) + (ps_frame_info->recv_error_count + 1); + libnfc_llc_error_count++; + + phLlcNfc_StopTimers(PH_LLCNFC_GUARDTIMER, + ps_llc_ctxt->s_timerinfo.guard_to_count); + PH_LLCNFC_DEBUG("Status Error : 0x%x\n", pCompInfo->status); + if (NULL != ps_llc_ctxt->cb_for_if.receive_complete) + { + ps_llc_ctxt->cb_for_if.receive_complete( + ps_llc_ctxt->cb_for_if.pif_ctxt, + pHwInfo, pCompInfo); + } + } + } + else + { + if ((NULL != ps_llc_ctxt) && (NULL != pCompInfo) + && (NULL != ps_llc_ctxt->cb_for_if.receive_complete)) + { + ps_llc_ctxt->cb_for_if.receive_complete( + ps_llc_ctxt->cb_for_if.pif_ctxt, + pHwInfo, pCompInfo); + } + } + + PH_LLCNFC_PRINT("\n\nLLC : READ RESP CB END\n\n"); +} + +void +phLlcNfc_H_SendInfo ( + phLlcNfc_Context_t *psLlcCtxt + ) +{ + phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; + phLlcNfc_Frame_t *ps_frame_info = NULL; + phNfc_sTransactionInfo_t comp_info = {0,0,0,0,0}; + + ps_frame_info = &(psLlcCtxt->s_frameinfo); + ps_recv_pkt = &(ps_frame_info->s_recvpacket); + + if ((ps_recv_pkt->llcbuf_len > 0) && + (ps_recv_pkt->llcbuf_len <= PH_LLCNFC_MAX_LLC_PAYLOAD)) + { + comp_info.status = NFCSTATUS_SUCCESS; + /* Chop the extra Llc bytes received */ +#if 0 + comp_info.length = (ps_recv_pkt->llcbuf_len - + PH_LLCNFC_LEN_APPEND); +#else + comp_info.length = (uint16_t)psLlcCtxt->recvbuf_length; +#endif /* */ + + if (0 != comp_info.length) + { +#if 0 + (void)memcpy ((void *)psLlcCtxt->precv_buf, (void *)( + ps_recv_pkt->s_llcbuf.sllcpayload.llcpayload), + comp_info.length); +#endif /* #if 0 */ + comp_info.buffer = psLlcCtxt->precv_buf; + } + else + { + comp_info.buffer = NULL; + } + } + else + { + comp_info.status = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_FORMAT); + comp_info.length = 0; + comp_info.buffer = NULL; + } + + (void)phLlcNfc_Interface_Read(psLlcCtxt, + PH_LLCNFC_READWAIT_OFF, + &(ps_recv_pkt->s_llcbuf.llc_length_byte), + (uint8_t)PH_LLCNFC_BYTES_INIT_READ); + + if ((NFCSTATUS_SUCCESS == comp_info.status) && + (0 == comp_info.length)) + { + /* May be a NULL I frame received from PN544, so dont do + any thing */ + } + else + { + if ((NULL != psLlcCtxt->cb_for_if.receive_complete) && + (TRUE == ps_frame_info->upper_recv_call)) + { + ps_frame_info->upper_recv_call = FALSE; + psLlcCtxt->cb_for_if.receive_complete( + psLlcCtxt->cb_for_if.pif_ctxt, + psLlcCtxt->phwinfo, + &comp_info); + } + else + { + if (NULL != psLlcCtxt->cb_for_if.notify) + { + psLlcCtxt->cb_for_if.notify( + psLlcCtxt->cb_for_if.pif_ctxt, + psLlcCtxt->phwinfo, + NFC_NOTIFY_RECV_COMPLETED, + &comp_info); + } + } + } + return; +} + diff --git a/libnfc-nxp/phLlcNfc_Interface.h b/libnfc-nxp/phLlcNfc_Interface.h new file mode 100644 index 0000000..45bf703 --- /dev/null +++ b/libnfc-nxp/phLlcNfc_Interface.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phLlcNfc_Interface.h +* \brief Interface for both LLC and transport layer +* +* Project: NFC-FRI-1.1 +* +* $Date: Thu Sep 11 12:19:29 2008 $ +* $Author: ing02260 $ +* $Revision: 1.9 $ +* $Aliases: NFC_FRI1.1_WK838_PREP1,NFC_FRI1.1_WK838_R9_PREP2,NFC_FRI1.1_WK838_R9_1,NFC_FRI1.1_WK840_R10_PREP1,NFC_FRI1.1_WK840_R10_1,NFC_FRI1.1_WK842_R11_PREP1,NFC_FRI1.1_WK842_R11_PREP2,NFC_FRI1.1_WK842_R11_1,NFC_FRI1.1_WK844_PREP1,NFC_FRI1.1_WK844_R12_1,NFC_FRI1.1_WK846_PREP1,NFC_FRI1.1_WK846_R13_1,NFC_FRI1.1_WK848_PREP1,NFC_FRI1.1_WK848_R14_1,NFC_FRI1.1_WK849_PACK1_PREP1,NFC_FRI1.1_WK850_PACK1,NFC_FRI1.1_WK851_PREP1,NFC_FRI1.1_WK850_R15_1,NFC_FRI1.1_WK902_PREP1,NFC_FRI1.1_WK902_R16_1,NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +#ifndef PHLLCNFC_INTERFACE_H +#define PHLLCNFC_INTERFACE_H + +/** +* \name LLC TL NFC interface +* +* File: \ref phLlcTlNfc_Interface.h +* +*/ +/*@{*/ +#define PH_LLCNFC_INTERFACE_FILEREVISION "$Revision: 1.9 $" /**< \ingroup grp_hal_nfc_llc */ +#define PH_LLCNFC_INTERFACE_FILEALIASES "$Aliases: NFC_FRI1.1_WK838_PREP1,NFC_FRI1.1_WK838_R9_PREP2,NFC_FRI1.1_WK838_R9_1,NFC_FRI1.1_WK840_R10_PREP1,NFC_FRI1.1_WK840_R10_1,NFC_FRI1.1_WK842_R11_PREP1,NFC_FRI1.1_WK842_R11_PREP2,NFC_FRI1.1_WK842_R11_1,NFC_FRI1.1_WK844_PREP1,NFC_FRI1.1_WK844_R12_1,NFC_FRI1.1_WK846_PREP1,NFC_FRI1.1_WK846_R13_1,NFC_FRI1.1_WK848_PREP1,NFC_FRI1.1_WK848_R14_1,NFC_FRI1.1_WK849_PACK1_PREP1,NFC_FRI1.1_WK850_PACK1,NFC_FRI1.1_WK851_PREP1,NFC_FRI1.1_WK850_R15_1,NFC_FRI1.1_WK902_PREP1,NFC_FRI1.1_WK902_R16_1,NFC_FRI1.1_WK904_PREP1,NFC_FRI1.1_WK904_R17_1,NFC_FRI1.1_WK906_R18_1,NFC_FRI1.1_WK908_PREP1,NFC_FRI1.1_WK908_R19_1,NFC_FRI1.1_WK910_PREP1,NFC_FRI1.1_WK910_R20_1,NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_hal_nfc_llc */ +/*@}*/ +/*************************** Includes *******************************/ + +/*********************** End of includes ****************************/ + +/***************************** Macros *******************************/ +#define PH_LLCNFC_READWAIT_OFF 0 +#define PH_LLCNFC_READWAIT_ON 1 + +/************************ End of macros *****************************/ + +/********************** Callback functions **************************/ + +/******************* End of Callback functions **********************/ + +/********************* Structures and enums *************************/ + +/****************** End of structures and enums *********************/ + +/******************** Function declarations *************************/ + +NFCSTATUS +phLlcNfc_Interface_Register( + phLlcNfc_Context_t *psLlcCtxt, + phNfcLayer_sCfg_t *psIFConfig +); + +NFCSTATUS +phLlcNfc_Interface_Init( + phLlcNfc_Context_t *psLlcCtxt +); + +NFCSTATUS +phLlcNfc_Interface_Read( + phLlcNfc_Context_t *psLlcCtxt, + uint8_t readWaitOn, + uint8_t *pLlcBuffer, + uint32_t llcBufferLength +); + +NFCSTATUS +phLlcNfc_Interface_Write( + phLlcNfc_Context_t *psLlcCtxt, + uint8_t *pLlcBuffer, + uint32_t llcBufferLength +); + +/** +* \ingroup grp_hal_nfc_llc +* +* \brief \b Release function +* +* \copydoc page_reg Release all the variables of the LLC component, that has been +* initialised in \b phLlcNfc_Init function (Synchronous function). +* +* \param[in] pContext LLC context is provided by the upper layer. The LLC +* context earlier was given to the upper layer through the +* \ref phLlcNfc_Register function +* \param[in] pLinkInfo Link information of the hardware +* +* \retval NFCSTATUS_PENDING If the command is yet to be processed. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* \retval Other errors Errors related to the lower layers +* +*/ +extern +NFCSTATUS +phLlcNfc_Release( + void *pContext, + void *pLinkInfo + ); +/****************** End of Function declarations ********************/ +#endif /* PHLLCTLNFC_INTERFACE_H */ diff --git a/libnfc-nxp/phLlcNfc_StateMachine.c b/libnfc-nxp/phLlcNfc_StateMachine.c new file mode 100644 index 0000000..4543265 --- /dev/null +++ b/libnfc-nxp/phLlcNfc_StateMachine.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phLlcNfc_StateMachine.c +* \brief Llc state machine implemenatation. +* +* Project: NFC-FRI-1.1 +* +* $Date: Fri Apr 17 09:17:48 2009 $ +* $Author: ing02260 $ +* $Revision: 1.8 $ +* $Aliases: NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK926_R28_2,NFC_FRI1.1_WK926_R28_3,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +/*************************** Includes *******************************/ +#include +#include +#include +#include +#include +#include + +/*********************** End of includes ****************************/ + +/***************************** Macros *******************************/ + +/************************ End of macros *****************************/ + +/*********************** Local functions ****************************/ + +/******************** End of Local functions ************************/ + +/********************** Global variables ****************************/ + +/******************** End of Global Variables ***********************/ + +NFCSTATUS +phLlcNfc_H_ChangeState( + phLlcNfc_Context_t *psLlcCtxt, + phLlcNfc_State_t changeStateTo +) +{ + NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_STATE); + if ((NULL != psLlcCtxt) && + (changeStateTo != phLlcNfc_Uninitialise_State)) + { + switch(psLlcCtxt->state) + { + case phLlcNfc_Uninitialise_State: + { + if (phLlcNfc_Initialising_State == changeStateTo) + { + result = NFCSTATUS_SUCCESS; + psLlcCtxt->state = changeStateTo; + } + break; + } + case phLlcNfc_Initialising_State: + { + if (phLlcNfc_Initialised_State == changeStateTo) + { + result = NFCSTATUS_SUCCESS; + psLlcCtxt->state = changeStateTo; + } + break; + } + case phLlcNfc_Initialised_State: + { + if (changeStateTo > phLlcNfc_Initialising_State) + { + result = NFCSTATUS_SUCCESS; + psLlcCtxt->state = changeStateTo; + } + break; + } + case phLlcNfc_ReceiveWait_State: + { + if (changeStateTo >= phLlcNfc_Initialised_State) + { + result = NFCSTATUS_SUCCESS; + psLlcCtxt->state = changeStateTo; + } + break; + } + case phLlcNfc_Sending_State: + { + if ((phLlcNfc_Initialised_State == changeStateTo) || + (phLlcNfc_Sending_State == changeStateTo)) + { + result = NFCSTATUS_SUCCESS; + psLlcCtxt->state = changeStateTo; + } + break; + } + case phLlcNfc_Receiving_State: + { + if ((phLlcNfc_Initialised_State == changeStateTo) || + (phLlcNfc_Sending_State == changeStateTo)) + { + result = NFCSTATUS_SUCCESS; + psLlcCtxt->state = changeStateTo; + } + break; + } + case phLlcNfc_Resend_State: + { + if (phLlcNfc_Initialised_State == changeStateTo) + { + result = NFCSTATUS_SUCCESS; + psLlcCtxt->state = changeStateTo; + } + if (phLlcNfc_Sending_State == changeStateTo) + { + result = NFCSTATUS_SUCCESS; + if (0 != psLlcCtxt->s_frameinfo.s_send_store.winsize_cnt) + { + psLlcCtxt->state = changeStateTo; + } + } + break; + } + default: + { + /* Error scenario: There cant be any change in the state, + while LLC is in these states */ + result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_FORMAT); + break; + } + } + } + if ((NULL != psLlcCtxt) && + (phLlcNfc_Uninitialise_State == changeStateTo)) + { + psLlcCtxt->state = changeStateTo; + } + return result; +} diff --git a/libnfc-nxp/phLlcNfc_Timer.c b/libnfc-nxp/phLlcNfc_Timer.c new file mode 100644 index 0000000..06ca7e4 --- /dev/null +++ b/libnfc-nxp/phLlcNfc_Timer.c @@ -0,0 +1,1070 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phLlcNfc_Timer.c +* \brief To create, start, stop and destroy timer. +* +* Project: NFC-FRI-1.1 +* +* $Date: Mon Jun 14 11:47:54 2010 $ +* $Author: ing02260 $ +* $Revision: 1.55 $ +* $Aliases: NFC_FRI1.1_WK1023_R35_2,NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +/*************************** Includes *******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*********************** End of includes ****************************/ + +/***************************** Macros *******************************/ +/**< Timer for connection timer index */ +#define PH_LLCNFC_CONNECTION_TO_INDEX (0x00) +/**< Maximum guard timer can be present */ +#define PH_LLCNFC_MAX_GUARD_TIMER (0x04) +/** Connection time out bit to set */ +#define PH_LLCNFC_CON_TO_BIT (0) +/** Guard time out bit to set */ +#define PH_LLCNFC_GUARD_TO_BIT (1) +/** Ack time out bit to set */ +#define PH_LLCNFC_ACK_TO_BIT (2) +/** No of bits to set */ +#define PH_LLCNFC_TO_NOOFBITS (1) +/** Connection time out bit value */ +#define PH_LLCNFC_CON_TO_BIT_VAL (0x01) +/** Guard time out bit to set */ +#define PH_LLCNFC_GUARD_TO_BIT_VAL (0x02) +/** ACK time out bit to set */ +#define PH_LLCNFC_ACK_TO_BIT_VAL (0x04) + +#define GUARD_TO_URSET + + +/************************ End of macros *****************************/ + +/*********************** Local functions ****************************/ +/* This callback is for guard time out */ +#ifdef LLC_TIMER_ENABLE +static +void +phLlcNfc_GuardTimeoutCb ( + uint32_t TimerId, + void *pContext +); + + +#ifdef PIGGY_BACK +/* This callback is for acknowledge time out */ +static +void +phLlcNfc_AckTimeoutCb ( + uint32_t TimerId +); +#endif /* #ifdef PIGGY_BACK */ + +/* This callback is for connection time out */ +static +void +phLlcNfc_ConnectionTimeoutCb ( + uint32_t TimerId, + void *pContext +); +#endif /* #ifdef LLC_TIMER_ENABLE */ + +/******************** End of Local functions ************************/ + +/********************** Global variables ****************************/ +static phLlcNfc_Context_t *gpphLlcNfc_Ctxt = NULL; + +/******************** End of Global Variables ***********************/ + +NFCSTATUS +phLlcNfc_TimerInit( + phLlcNfc_Context_t *psLlcCtxt +) +{ + NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + uint8_t index = 0; + if (NULL != psLlcCtxt) + { + result = NFCSTATUS_SUCCESS; + gpphLlcNfc_Ctxt = psLlcCtxt; + while (index < PH_LLCNFC_MAX_TIMER_USED) + { +#ifdef LLC_TIMER_ENABLE + gpphLlcNfc_Ctxt->s_timerinfo.timer_id[index] = + PH_OSALNFC_INVALID_TIMER_ID; +#endif /* #ifdef LLC_TIMER_ENABLE */ + index++; + } + } + return result; +} + +void +phLlcNfc_TimerUnInit( + phLlcNfc_Context_t *psLlcCtxt +) +{ + uint8_t index = 0; + if ((NULL != gpphLlcNfc_Ctxt) && + (gpphLlcNfc_Ctxt == psLlcCtxt)) + { + while (index <= PH_LLCNFC_ACKTIMER) + { + if (PH_LLCNFC_GUARDTIMER == index) + { + phLlcNfc_StopTimers (index, + gpphLlcNfc_Ctxt->s_timerinfo.guard_to_count); + } + else + { + phLlcNfc_StopTimers (index, 0); + } + index++; + } + phLlcNfc_DeleteTimer(); + } +} + +void +phLlcNfc_CreateTimers(void) +{ + uint8_t index = 0; + + while (index < PH_LLCNFC_MAX_TIMER_USED) + { +#ifdef LLC_TIMER_ENABLE + gpphLlcNfc_Ctxt->s_timerinfo.timer_id[index] = + phOsalNfc_Timer_Create(); +#endif /* #ifdef LLC_TIMER_ENABLE */ + index++; + } + return; +} + +NFCSTATUS +phLlcNfc_StartTimers ( + uint8_t TimerType, + uint8_t ns_value +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; +#ifdef LLC_TIMER_ENABLE + + uint32_t timerid = 0; + uint8_t timerstarted = 0; + uint8_t timer_count = 0; + uint16_t timer_resolution = 0; + ppCallBck_t Callback = NULL; + phLlcNfc_Timerinfo_t *ps_timer_info = NULL; + + ps_timer_info = &(gpphLlcNfc_Ctxt->s_timerinfo); + PHNFC_UNUSED_VARIABLE(result); + + PH_LLCNFC_PRINT("\n\nLLC : START TIMER CALLED\n\n"); + /* Depending on the timer type, use the Osal callback */ + switch(TimerType) + { + case PH_LLCNFC_CONNECTIONTIMER: + { + /* Get the connection timer flag */ + timerstarted = (uint8_t) + GET_BITS8(ps_timer_info->timer_flag, + PH_LLCNFC_CON_TO_BIT, + PH_LLCNFC_TO_NOOFBITS); + if (0 == timerstarted) + { + /* Timer not started, so start the timer */ + gpphLlcNfc_Ctxt->s_timerinfo.timer_flag = (uint8_t) + SET_BITS8 (ps_timer_info->timer_flag, + PH_LLCNFC_CON_TO_BIT, + PH_LLCNFC_TO_NOOFBITS, + (PH_LLCNFC_CON_TO_BIT + 1)); + } + + timerid = ps_timer_info->timer_id[PH_LLCNFC_CONNECTION_TO_INDEX]; + Callback = (ppCallBck_t)&phLlcNfc_ConnectionTimeoutCb; + timer_resolution = ps_timer_info->con_to_value = (uint16_t) + PH_LLCNFC_CONNECTION_TO_VALUE; + break; + } + + case PH_LLCNFC_GUARDTIMER: + { + if (ps_timer_info->guard_to_count < PH_LLCNFC_MAX_GUARD_TIMER) + { + timer_count = ps_timer_info->guard_to_count; + timer_resolution = (uint16_t)PH_LLCNFC_RESOLUTION; + + PH_LLCNFC_DEBUG("RESOLUTION VALUE : 0x%02X\n", PH_LLCNFC_RESOLUTION); + PH_LLCNFC_DEBUG("TIME-OUT VALUE : 0x%02X\n", PH_LLCNFC_GUARD_TO_VALUE); + + /* Get the guard timer flag */ + timerstarted = (uint8_t) + GET_BITS8 (ps_timer_info->timer_flag, + PH_LLCNFC_GUARD_TO_BIT, + PH_LLCNFC_TO_NOOFBITS); + + PH_LLCNFC_DEBUG("GUARD TIMER NS INDEX : 0x%02X\n", ns_value); + PH_LLCNFC_DEBUG("GUARD TIMER COUNT : 0x%02X\n", timer_count); + PH_LLCNFC_DEBUG("GUARD TIMER STARTED : 0x%02X\n", timerstarted); + + if (0 == timerstarted) + { + /* Timer not started, so start the timer */ + ps_timer_info->timer_flag = (uint8_t) + SET_BITS8 (ps_timer_info->timer_flag, + PH_LLCNFC_GUARD_TO_BIT, + PH_LLCNFC_TO_NOOFBITS, + PH_LLCNFC_GUARD_TO_BIT); + } + + timerid = ps_timer_info->timer_id[PH_LLCNFC_GUARDTIMER]; + Callback = (ppCallBck_t)&phLlcNfc_GuardTimeoutCb; + + /* Guard time out value */ + ps_timer_info->guard_to_value[timer_count] = (uint16_t) + PH_LLCNFC_GUARD_TO_VALUE; + + ps_timer_info->timer_ns_value[timer_count] = ns_value; + ps_timer_info->frame_type[timer_count] = (uint8_t)invalid_frame; + ps_timer_info->iframe_send_count[timer_count] = 0; + + if ((timer_count > 0) && + (ps_timer_info->guard_to_value[(timer_count - 1)] >= + PH_LLCNFC_GUARD_TO_VALUE)) + { + /* If the timer has been started already and the + value is same as the previous means that timer has still + not expired, so the time out value is increased by + a resolution */ + ps_timer_info->guard_to_value[timer_count] = (uint16_t) + (ps_timer_info->guard_to_value[(timer_count - 1)] + + PH_LLCNFC_RESOLUTION); + } + + PH_LLCNFC_DEBUG("GUARD TIMER VALUE : 0x%04X\n", ps_timer_info->guard_to_value[timer_count]); + + + ps_timer_info->guard_to_count = (uint8_t)( + ps_timer_info->guard_to_count + 1); + } + else + { + /* TIMER should not start, because the time out count has readched the limit */ + timerstarted = TRUE; + } + break; + } + +#ifdef PIGGY_BACK + + case PH_LLCNFC_ACKTIMER: + { + /* Get the ack timer flag */ + timerstarted = (uint8_t)GET_BITS8 ( + ps_timer_info->timer_flag, + PH_LLCNFC_ACK_TO_BIT, + PH_LLCNFC_TO_NOOFBITS); + + if (FALSE == timerstarted) + { + /* Timer not started, so start the timer */ + ps_timer_info->timer_flag = (uint8_t) + SET_BITS8 (ps_timer_info->timer_flag, + PH_LLCNFC_ACK_TO_BIT, + PH_LLCNFC_TO_NOOFBITS, + (PH_LLCNFC_ACK_TO_BIT - 1)); + } + + + timer_resolution = ps_timer_info->ack_to_value = (uint16_t) + PH_LLCNFC_ACK_TO_VALUE; + timerid = ps_timer_info->timer_id[PH_LLCNFC_ACKTIMER]; + Callback = (ppCallBck_t)&phLlcNfc_AckTimeoutCb; + break; + } + +#endif /* #ifdef PIGGY_BACK */ + + default: + { + result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + break; + } + } + if ((NFCSTATUS_SUCCESS == result) && + (FALSE == timerstarted)) + { + PH_LLCNFC_DEBUG("OSAL START TIMER CALLED TIMER ID : 0x%02X\n", timerid); + phOsalNfc_Timer_Start (timerid, timer_resolution, Callback, NULL); + } + + PH_LLCNFC_PRINT("\n\nLLC : START TIMER END\n\n"); + +#else /* #ifdef LLC_TIMER_ENABLE */ + + PHNFC_UNUSED_VARIABLE(result); + PHNFC_UNUSED_VARIABLE(TimerType); + PHNFC_UNUSED_VARIABLE(ns_value); + +#endif /* #ifdef LLC_TIMER_ENABLE */ + return result; +} + +void +phLlcNfc_StopTimers ( + uint8_t TimerType, + uint8_t no_of_guard_to_del +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; +#ifdef LLC_TIMER_ENABLE + + uint32_t timerid = 0, + timerflag = FALSE; + uint8_t timer_count = 0; + phLlcNfc_Timerinfo_t *ps_timer_info = NULL; + + + ps_timer_info = &(gpphLlcNfc_Ctxt->s_timerinfo); + timerflag = ps_timer_info->timer_flag; + + PHNFC_UNUSED_VARIABLE (result); + PH_LLCNFC_PRINT("\n\nLLC : STOP TIMER CALLED\n\n"); + switch(TimerType) + { + case PH_LLCNFC_CONNECTIONTIMER: + { + ps_timer_info->timer_flag = (uint8_t) + SET_BITS8(ps_timer_info->timer_flag, + PH_LLCNFC_CON_TO_BIT, + PH_LLCNFC_TO_NOOFBITS, 0); + timerid = ps_timer_info->timer_id + [PH_LLCNFC_CONNECTION_TO_INDEX]; + break; + } + + case PH_LLCNFC_GUARDTIMER: + { + uint8_t start_index = 0; + + timer_count = ps_timer_info->guard_to_count; + + PH_LLCNFC_DEBUG("GUARD TIMER COUNT BEFORE DELETE: 0x%02X\n", timer_count); + PH_LLCNFC_DEBUG("GUARD TIMER TO DELETE: 0x%02X\n", no_of_guard_to_del); + + if (timer_count > no_of_guard_to_del) + { + /* The number of guard timer count is more than the + guard timer to delete */ + while (start_index < (timer_count - no_of_guard_to_del)) + { + /* Copy the previous stored timer values to the present */ + ps_timer_info->guard_to_value[start_index] = (uint16_t) + (ps_timer_info->guard_to_value[ + (no_of_guard_to_del + start_index)]); + + ps_timer_info->iframe_send_count[start_index] = (uint8_t) + (ps_timer_info->iframe_send_count[ + (no_of_guard_to_del + start_index)]); + + PH_LLCNFC_DEBUG("GUARD TIMER NS INDEX DELETED : 0x%02X\n", ps_timer_info->timer_ns_value[start_index]); + + ps_timer_info->timer_ns_value[start_index] = (uint8_t) + (ps_timer_info->timer_ns_value[ + (no_of_guard_to_del + start_index)]); + + ps_timer_info->frame_type[start_index] = (uint8_t) + (ps_timer_info->frame_type[ + (no_of_guard_to_del + start_index)]); + + start_index = (uint8_t)(start_index + 1); + } + } + else + { + while (start_index < no_of_guard_to_del) + { + ps_timer_info->guard_to_value[start_index] = 0; + + ps_timer_info->iframe_send_count[start_index] = 0; + + PH_LLCNFC_DEBUG("GUARD TIMER NS INDEX DELETED ELSE : 0x%02X\n", ps_timer_info->timer_ns_value[start_index]); + + ps_timer_info->timer_ns_value[start_index] = 0; + + ps_timer_info->frame_type[start_index] = 0; + + start_index = (uint8_t)(start_index + 1); + } + } + + if (timer_count >= no_of_guard_to_del) + { + timer_count = (uint8_t)(timer_count - no_of_guard_to_del); + } + else + { + if (0 != no_of_guard_to_del) + { + timer_count = 0; + } + } + + timerid = ps_timer_info->timer_id[PH_LLCNFC_GUARDTIMER]; + ps_timer_info->guard_to_count = timer_count; + PH_LLCNFC_DEBUG("GUARD TIMER COUNT AFTER DELETE: 0x%02X\n", timer_count); + + if (0 == ps_timer_info->guard_to_count) + { + /* This means that there are no frames to run guard + timer, so set the timer flag to 0 */ + ps_timer_info->timer_flag = (uint8_t) + SET_BITS8 (ps_timer_info->timer_flag, + PH_LLCNFC_GUARD_TO_BIT, + PH_LLCNFC_TO_NOOFBITS, 0); + } + else + { + timerflag = 0; + } + break; + } + +#ifdef PIGGY_BACK + case PH_LLCNFC_ACKTIMER: + { + timerflag = (timerflag & PH_LLCNFC_ACK_TO_BIT_VAL); + + ps_timer_info->timer_flag = (uint8_t) + SET_BITS8 (ps_timer_info->timer_flag, + PH_LLCNFC_ACK_TO_BIT, + PH_LLCNFC_TO_NOOFBITS, 0); + timerid = ps_timer_info->timer_id[PH_LLCNFC_ACKTIMER]; + ps_timer_info->ack_to_value = 0; + break; + } +#endif /* #ifdef PIGGY_BACK */ + + default: + { + result = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_INVALID_PARAMETER); + break; + } + } + + if ((NFCSTATUS_SUCCESS == result) && (timerflag > 0)) + { + PH_LLCNFC_DEBUG("OSAL STOP TIMER CALLED TIMER ID : 0x%02X\n", timerid); + phOsalNfc_Timer_Stop (timerid); + } + + PH_LLCNFC_PRINT("\n\nLLC : STOP TIMER END\n\n"); + +#else /* #ifdef LLC_TIMER_ENABLE */ + + PHNFC_UNUSED_VARIABLE (result); + PHNFC_UNUSED_VARIABLE (TimerType); + PHNFC_UNUSED_VARIABLE (no_of_guard_to_del); + +#endif /* #ifdef LLC_TIMER_ENABLE */ +} + +void +phLlcNfc_StopAllTimers (void) +{ + +#ifdef LLC_TIMER_ENABLE + + phLlcNfc_Timerinfo_t *ps_timer_info = NULL; + uint8_t timer_started = 0; + uint32_t timerid = 0; + uint8_t timer_index = 0; + + + ps_timer_info = &(gpphLlcNfc_Ctxt->s_timerinfo); + + PH_LLCNFC_PRINT("\n\nLLC : STOP ALL TIMERS CALLED \n\n"); + + timerid = ps_timer_info->timer_id[timer_index]; + timer_started = (uint8_t) + GET_BITS8(ps_timer_info->timer_flag, + PH_LLCNFC_CON_TO_BIT, + PH_LLCNFC_TO_NOOFBITS); + + PH_LLCNFC_DEBUG("CONNECTION TIMER ID: 0x%02X\n", timerid); + + if (0 != timer_started) + { + /* Connection timer is started, so now stop it */ + ps_timer_info->timer_flag = (uint8_t) + SET_BITS8 (ps_timer_info->timer_flag, + PH_LLCNFC_CON_TO_BIT, + PH_LLCNFC_TO_NOOFBITS, 0); +#if 0 + + ps_timer_info->con_to_value = 0; + +#endif /* #if 0 */ + + phOsalNfc_Timer_Stop (timerid); + } + + timer_index = (uint8_t)(timer_index + 1); + timerid = ps_timer_info->timer_id[timer_index]; + timer_started = (uint8_t)GET_BITS8 (ps_timer_info->timer_flag, + PH_LLCNFC_GUARD_TO_BIT, + PH_LLCNFC_TO_NOOFBITS); + + if (0 != timer_started) + { + /* Guard timer is already started */ + ps_timer_info->timer_flag = (uint8_t) + SET_BITS8 (ps_timer_info->timer_flag, + PH_LLCNFC_GUARD_TO_BIT, + PH_LLCNFC_TO_NOOFBITS, 0); + + timer_index = 0; + ps_timer_info->guard_to_count = 0; + +#if 0 + + /* Reset all the guard timer related variables */ + while (timer_index < ps_timer_info->guard_to_count) + { + ps_timer_info->guard_to_value[timer_index] = 0; + ps_timer_info->iframe_send_count[timer_index] = 0; + + timer_index = (uint8_t)(timer_index + 1); + } + +#endif /* #if 0 */ + + PH_LLCNFC_DEBUG("GUARD TIMER ID: 0x%02X\n", timerid); + + /* Stop the timer */ + phOsalNfc_Timer_Stop (timerid); + + PH_LLCNFC_PRINT("\n\nLLC : STOP ALL TIMERS END \n\n"); + } + +#endif /* #ifdef LLC_TIMER_ENABLE */ +} + +void +phLlcNfc_DeleteTimer (void) +{ + uint8_t index = 0; + while (index < PH_LLCNFC_MAX_TIMER_USED) + { +#ifdef LLC_TIMER_ENABLE + phOsalNfc_Timer_Delete( + gpphLlcNfc_Ctxt->s_timerinfo.timer_id[index]); + gpphLlcNfc_Ctxt->s_timerinfo.timer_id[index] = + PH_OSALNFC_INVALID_TIMER_ID; +#endif /* #ifdef LLC_TIMER_ENABLE */ + index++; + } +} + +#ifdef LLC_TIMER_ENABLE + +#define LLC_GUARD_TIMER_RETRIES (0x03U) + +static +void +phLlcNfc_GuardTimeoutCb ( + uint32_t TimerId, + void *pContext +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Timerinfo_t *ps_timer_info = NULL; + phLlcNfc_Frame_t *ps_frame_info = NULL; + phLlcNfc_LlcPacket_t s_packet_info; + uint8_t index = 0; + /* zero_to_index = Time out index has become 0 */ + uint8_t zero_to_index = 0; + +#if defined (GUARD_TO_ERROR) + phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; +#endif /* #if defined (GUARD_TO_ERROR) */ + + PH_LLCNFC_PRINT("\n\nLLC : GUARD TIMEOUT CB CALLED \n\n"); + + if ((NULL != gpphLlcNfc_Ctxt) && (TimerId == + gpphLlcNfc_Ctxt->s_timerinfo.timer_id[PH_LLCNFC_GUARDTIMER]) && + (PH_LLCNFC_GUARD_TO_BIT_VAL == + (gpphLlcNfc_Ctxt->s_timerinfo.timer_flag & + PH_LLCNFC_GUARD_TO_BIT_VAL))) + { + uint8_t timer_expired = FALSE; + + ps_frame_info = &(gpphLlcNfc_Ctxt->s_frameinfo); + ps_timer_info = &(gpphLlcNfc_Ctxt->s_timerinfo); + +#if !defined (CYCLIC_TIMER) + phOsalNfc_Timer_Stop( + ps_timer_info->timer_id[PH_LLCNFC_GUARDTIMER]); +#endif + + PH_LLCNFC_DEBUG("NO OF TIMEOUT COUNT : 0x%02X\n", ps_timer_info->guard_to_count); + /* Loop is completely depending on the number of different LLC + send called */ + while (index < ps_timer_info->guard_to_count) + { + /* This loop runs for all the timer present in the data structure. + This means if there are 2 I frame has been sent and + response is not received for the I frames sent then the + each time this timer expires, the time out value is decremented + by the PH_LLCNFC_RESOLUTION value */ + if (0 != ps_timer_info->guard_to_value[index]) + { + /* If timer value is not zero then enter, + this means that the value is not zero */ + if (ps_timer_info->guard_to_value[index] > 0) + { + if (ps_timer_info->guard_to_value[index] >= + PH_LLCNFC_RESOLUTION) + { + ps_timer_info->guard_to_value[index] = (uint16_t) + (ps_timer_info->guard_to_value[index] - + PH_LLCNFC_RESOLUTION); + } + else + { + ps_timer_info->guard_to_value[index] = 0; + } + } + + if (0 == ps_timer_info->guard_to_value[index]) + { + /* Timer value has expired, so resend has to be done + Timer value is 0 */ + ps_timer_info->frame_type[index] = (uint8_t)resend_i_frame; + if (FALSE == timer_expired) + { + /* As the statement is in the loop, so there are possibilities + of more than 1 timer value can be 0, so if previous timer + value has already been 0, then again dont change the + index */ + zero_to_index = index; + timer_expired = TRUE; + } + } + } + index = (uint8_t)(index + 1); + } + +#if !defined (CYCLIC_TIMER) + /* Start the timer again */ + phOsalNfc_Timer_Start( + ps_timer_info->timer_id[PH_LLCNFC_GUARDTIMER], + PH_LLCNFC_RESOLUTION, phLlcNfc_GuardTimeoutCb, NULL); +#endif + PH_LLCNFC_DEBUG("TIMER EXPIRED : 0x%02X\n", timer_expired); + + if (TRUE == timer_expired) + { + PH_LLCNFC_DEBUG("TIMER EXPIRED INDEX: 0x%02X\n", zero_to_index); + PH_LLCNFC_DEBUG("TIMER EXPIRED NS INDEX: 0x%02X\n", ps_timer_info->timer_ns_value[zero_to_index]); + PH_LLCNFC_DEBUG("TIMER EXPIRED RETRIES : 0x%02X\n", ps_timer_info->iframe_send_count[zero_to_index]); + + PH_LLCNFC_DEBUG("TIMER EXPIRED GUARD TIME-OUT COUNT: 0x%02X\n", ps_timer_info->guard_to_value[zero_to_index]); + + if ((0 == ps_timer_info->guard_to_value[zero_to_index]) && + (ps_timer_info->iframe_send_count[zero_to_index] < + LLC_GUARD_TIMER_RETRIES)) + { + if (ps_frame_info->s_send_store.winsize_cnt > 0) + { + uint8_t start_index = 0; + uint8_t timer_count = 0; + uint8_t while_exit = FALSE; + + timer_count = ps_timer_info->guard_to_count; + + /* Check before changing the index to resend, if index + already exist then dont set the index */ + while ((FALSE == while_exit) && (start_index < timer_count)) + { + if (resend_i_frame == + ps_timer_info->frame_type[start_index]) + { + while_exit = TRUE; + } + else + { + start_index = (uint8_t)(start_index + 1); + } + } + + if (FALSE == while_exit) + { + /* This " ps_timer_info->index_to_send " member is + useful, when 2 time out values are 0, then + only first timed out value has to be resent and + other has to wait until the the first timed out + I frame is resent + This statement is executed only if, none of the timer + has expires previously, this is the first timer in the + list that has time out value has 0 + */ + ps_timer_info->index_to_send = zero_to_index; + } + else + { + /* This statement is executed only if, any one of the time + out value was 0 previously, so first resend has to be done + for the previous I frame, so the index is set to the previous + I frame + */ + ps_timer_info->index_to_send = start_index; + } + + /* Now resend the frame stored */ + result = phLlcNfc_H_SendTimedOutIFrame (gpphLlcNfc_Ctxt, + &(ps_frame_info->s_send_store), + 0); + } + } + else + { + if ((LLC_GUARD_TIMER_RETRIES == + ps_timer_info->iframe_send_count[zero_to_index]) && + (NULL != gpphLlcNfc_Ctxt->cb_for_if.notify)) + { + phLlcNfc_StopAllTimers (); +#if defined (GUARD_TO_ERROR) + + notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_BOARD_COMMUNICATION_ERROR); +#if 0 + phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); +#endif /* #if 0 */ + /* Resend done, no answer from the device */ + gpphLlcNfc_Ctxt->cb_for_if.notify ( + gpphLlcNfc_Ctxt->cb_for_if.pif_ctxt, + gpphLlcNfc_Ctxt->phwinfo, + NFC_NOTIFY_DEVICE_ERROR, + ¬ifyinfo); + +#endif /* #if defined (GUARD_TO_ERROR) */ + +#if (!defined (GUARD_TO_ERROR) && defined (GUARD_TO_URSET)) + + PH_LLCNFC_PRINT("U-RSET IS SENT \n"); + + result = phLlcNfc_H_CreateUFramePayload(gpphLlcNfc_Ctxt, + &(s_packet_info), + &(s_packet_info.llcbuf_len), + phLlcNfc_e_rset); + + result = phLlcNfc_Interface_Write(gpphLlcNfc_Ctxt, + (uint8_t*)&(s_packet_info.s_llcbuf), + (uint32_t)s_packet_info.llcbuf_len); + + ps_frame_info->write_status = result; + if (NFCSTATUS_PENDING == result) + { + /* Start the timer */ + result = phLlcNfc_StartTimers (PH_LLCNFC_CONNECTIONTIMER, 0); + if (NFCSTATUS_SUCCESS == result) + { + ps_frame_info->retry_cnt = 0; + gpphLlcNfc_Ctxt->s_frameinfo.sent_frame_type = + u_rset_frame; + result = NFCSTATUS_PENDING; + } + } + else + { + if (NFCSTATUS_BUSY == PHNFCSTATUS (result)) + { + ps_frame_info->write_wait_call = u_rset_frame; + } + } + +#endif /* #if defined (GUARD_TO_ERROR) */ + } + } + } + } + PH_LLCNFC_PRINT("\n\nLLC : GUARD TIMEOUT CB END\n\n"); +} + +#ifdef PIGGY_BACK + +static +void +phLlcNfc_AckTimeoutCb ( + uint32_t TimerId +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phLlcNfc_Frame_t *ps_frame_info = NULL; + phLlcNfc_Timerinfo_t *ps_timer_info = NULL; + phLlcNfc_LlcPacket_t s_packet_info; + + PH_LLCNFC_PRINT("\n\nLLC : ACK TIMEOUT CB CALLED\n\n"); + + if ((NULL != gpphLlcNfc_Ctxt) && (TimerId == + gpphLlcNfc_Ctxt->s_timerinfo.timer_id[PH_LLCNFC_ACKTIMER]) + && (PH_LLCNFC_ACK_TO_BIT_VAL == + (gpphLlcNfc_Ctxt->s_timerinfo.timer_flag & + PH_LLCNFC_ACK_TO_BIT_VAL))) + { + ps_frame_info = &(gpphLlcNfc_Ctxt->s_frameinfo); + ps_timer_info = &(gpphLlcNfc_Ctxt->s_timerinfo); + + phLlcNfc_StopTimers (PH_LLCNFC_ACKTIMER, 0); + + if (NFCSTATUS_BUSY == PHNFCSTATUS (ps_frame_info->write_status)) + { + /* Any how write cannot be done and some frame is ready to be sent + so this frame will act as the ACK */ + result = phLlcNfc_H_WriteWaitCall (gpphLlcNfc_Ctxt); + } + else + { + /* Create S frame */ + (void)phLlcNfc_H_CreateSFramePayload (ps_frame_info, &(s_packet_info), phLlcNfc_e_rr); + + result = phLlcNfc_Interface_Write(gpphLlcNfc_Ctxt, + (uint8_t *)&(s_packet_info.s_llcbuf), + (uint32_t)(s_packet_info.llcbuf_len)); + + if (NFCSTATUS_PENDING == result) + { + if (0 == ps_frame_info->send_error_count) + { + ps_frame_info->write_wait_call = invalid_frame; + } + ps_frame_info->sent_frame_type = s_frame; + } + else + { + if (invalid_frame == ps_frame_info->write_wait_call) + { + ps_frame_info->write_wait_call = s_frame; + } + } + } + } + + /* ACK is sent, so reset the response received count */ + gpphLlcNfc_Ctxt->s_frameinfo.resp_recvd_count = 0; + + PH_LLCNFC_PRINT("\n\nLLC : ACK TIMEOUT CB END\n\n"); +} + +#endif /* #ifdef PIGGY_BACK */ + +static +void +phLlcNfc_ConnectionTimeoutCb ( + uint32_t TimerId, + void *pContext +) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; + pphNfcIF_Notification_CB_t notifyul = NULL; + void *p_upperctxt = NULL; + phLlcNfc_Frame_t *ps_frame_info = NULL; + phLlcNfc_Timerinfo_t *ps_timer_info = NULL; + phLlcNfc_LlcPacket_t s_packet_info; + + PH_LLCNFC_PRINT("\n\nLLC : CONNECTION TIMEOUT CB CALLED\n\n"); + if ((NULL != gpphLlcNfc_Ctxt) && (TimerId == + gpphLlcNfc_Ctxt->s_timerinfo.timer_id[PH_LLCNFC_CONNECTIONTIMER]) + && (PH_LLCNFC_CON_TO_BIT_VAL == + (gpphLlcNfc_Ctxt->s_timerinfo.timer_flag & + PH_LLCNFC_CON_TO_BIT_VAL))) + { + ps_frame_info = &(gpphLlcNfc_Ctxt->s_frameinfo); + ps_timer_info = &(gpphLlcNfc_Ctxt->s_timerinfo); + if (ps_timer_info->con_to_value > 0) + { +#if !defined (CYCLIC_TIMER) + phOsalNfc_Timer_Stop( + ps_timer_info->timer_id[PH_LLCNFC_CONNECTIONTIMER]); + /* phLlcNfc_StopTimers(PH_LLCNFC_CONNECTIONTIMER, 0); */ +#endif + ps_timer_info->con_to_value = 0; + + if (0 == ps_timer_info->con_to_value) + { + PH_LLCNFC_DEBUG("TIMER EXPIRED RETRY COUNT : %02X\n", ps_frame_info->retry_cnt); + phLlcNfc_StopTimers (PH_LLCNFC_CONNECTIONTIMER, 0); + + if (ps_frame_info->retry_cnt < PH_LLCNFC_MAX_RETRY_COUNT) + { + /* Create a U frame */ + result = phLlcNfc_H_CreateUFramePayload(gpphLlcNfc_Ctxt, + &(s_packet_info), + &(s_packet_info.llcbuf_len), + phLlcNfc_e_rset); + + if (NFCSTATUS_SUCCESS == result) + { + /* Call DAL write */ + result = phLlcNfc_Interface_Write (gpphLlcNfc_Ctxt, + (uint8_t*)&(s_packet_info.s_llcbuf), + (uint32_t)(s_packet_info.llcbuf_len)); + } + if (NFCSTATUS_PENDING == result) + { + /* Start the timer */ + result = phLlcNfc_StartTimers(PH_LLCNFC_CONNECTIONTIMER, 0); + if (NFCSTATUS_SUCCESS == result) + { + ps_frame_info->retry_cnt++; + result = NFCSTATUS_PENDING; + } + } + else + { + if (NFCSTATUS_BUSY == PHNFCSTATUS(result)) + { + result = NFCSTATUS_PENDING; + } + } + } + else + { + PH_LLCNFC_PRINT("RETRY COUNT LIMIT REACHED \n"); + if ((ps_frame_info->retry_cnt == PH_LLCNFC_MAX_RETRY_COUNT) + && (NULL != gpphLlcNfc_Ctxt->cb_for_if.notify)) + { + void *p_hw_info = NULL; + uint8_t type = 0; + + p_hw_info = gpphLlcNfc_Ctxt->phwinfo; + notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_BOARD_COMMUNICATION_ERROR); + + notifyul = gpphLlcNfc_Ctxt->cb_for_if.notify; + p_upperctxt = gpphLlcNfc_Ctxt->cb_for_if.pif_ctxt; + type = NFC_NOTIFY_ERROR; + if (init_u_rset_frame == ps_frame_info->sent_frame_type) + { + type = NFC_NOTIFY_INIT_FAILED; + /* Release if, the initialisation is not complete */ + result = phLlcNfc_Release(gpphLlcNfc_Ctxt, p_hw_info); + gpphLlcNfc_Ctxt = NULL; + } + else + { + type = NFC_NOTIFY_DEVICE_ERROR; + notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC, + NFCSTATUS_BOARD_COMMUNICATION_ERROR); +#if 0 + phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); +#endif /* #if 0 */ + } + /* Notify the upper layer */ + notifyul(p_upperctxt, p_hw_info, type, ¬ifyinfo); + } + } + } +#if !defined (CYCLIC_TIMER) + else + { + /* Start the timer again */ + phOsalNfc_Timer_Start( + ps_timer_info->timer_id[PH_LLCNFC_CONNECTIONTIMER], + ps_timer_info->con_to_value, phLlcNfc_ConnectionTimeoutCb, NULL); + } +#endif + } + } + PH_LLCNFC_PRINT("\n\nLLC : CONNECTION TIMEOUT CB END\n\n"); +} +#endif /* #ifdef LLC_TIMER_ENABLE */ + +#ifdef LLC_URSET_NO_DELAY + + /* NO definition required */ + +#else /* #ifdef LLC_URSET_NO_DELAY */ + +void +phLlcNfc_URSET_Delay_Notify ( + uint32_t delay_id, + void *pContext) +{ + phLlcNfc_Frame_t *ps_frame_info = NULL; + phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; + + if (NULL != gpphLlcNfc_Ctxt) + { + ps_frame_info = &(gpphLlcNfc_Ctxt->s_frameinfo); + + phOsalNfc_Timer_Stop (delay_id); + phOsalNfc_Timer_Delete (delay_id); + if (ps_frame_info->s_send_store.winsize_cnt > 0) + { +#if 0 + + /* Resend I frame */ + (void)phLlcNfc_H_SendTimedOutIFrame (gpphLlcNfc_Ctxt, + &(ps_frame_info->s_send_store), 0); + +#else + + (void)phLlcNfc_H_SendUserIFrame (gpphLlcNfc_Ctxt, + &(ps_frame_info->s_send_store)); + +#endif /* #if 0 */ + gpphLlcNfc_Ctxt->state = phLlcNfc_Resend_State; + } + else + { + if ((init_u_rset_frame == ps_frame_info->sent_frame_type) && + (NULL != gpphLlcNfc_Ctxt->cb_for_if.notify)) + { + ps_frame_info->sent_frame_type = write_resp_received; + notifyinfo.status = NFCSTATUS_SUCCESS; + /* Send the notification to the upper layer */ + gpphLlcNfc_Ctxt->cb_for_if.notify ( + gpphLlcNfc_Ctxt->cb_for_if.pif_ctxt, + gpphLlcNfc_Ctxt->phwinfo, + NFC_NOTIFY_INIT_COMPLETED, + ¬ifyinfo); + } + } + } +} + +#endif /* #ifdef LLC_URSET_NO_DELAY */ + diff --git a/libnfc-nxp/phLlcNfc_Timer.h b/libnfc-nxp/phLlcNfc_Timer.h new file mode 100644 index 0000000..f212a32 --- /dev/null +++ b/libnfc-nxp/phLlcNfc_Timer.h @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/*! +* \file phLlcNfc_Timer.h +* \brief To create, start, stop and destroy timer. +* +* Project: NFC-FRI-1.1 +* +* $Date: Thu Jun 10 17:26:41 2010 $ +* $Author: ing02260 $ +* $Revision: 1.14 $ +* $Aliases: NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + +#ifndef PHLLCNFC_TIMER_H +#define PHLLCNFC_TIMER_H + +/** +* \name LLC NFC state machine handling +* +* File: \ref phLlcNfc_StateMachine.h +* +*/ +/*@{*/ +#define PH_LLCNFC_TIMER_FILEREVISION "$Revision: 1.14 $" /**< \ingroup grp_hal_nfc_llc_helper */ +#define PH_LLCNFC_TIMER_FILEALIASES "$Aliases: NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_hal_nfc_llc_helper */ +/*@}*/ +/*************************** Includes *******************************/ + +/*********************** End of includes ****************************/ + +/***************************** Macros *******************************/ +#define PH_LLCNFC_CONNECTIONTIMER (0x00) /**< Timer for connection time out */ +#define PH_LLCNFC_GUARDTIMER (0x01) /**< Timer for guard time out */ +#define PH_LLCNFC_ACKTIMER (0x02) /**< Timer for ack time out */ +#define PH_LLCNFC_MAX_RETRY_COUNT (0x03) /**< Retries */ +/** Resolution value for the timer */ +#define PH_LLCNFC_RESOLUTION TIMER_RESOLUTION +/**< 0x05 Timer for connection time out value */ +#define PH_LLCNFC_CONNECTION_TO_VALUE LINK_CONNECTION_TIMEOUT +/**< 0x05 Timer for guard time out value */ +#define PH_LLCNFC_GUARD_TO_VALUE LINK_GUARD_TIMEOUT + +#ifdef PIGGY_BACK + +#define PH_LLCNFC_ACK_TO_VALUE LINK_ACK_TIMEOUT + +#endif /* #ifdef PIGGY_BACK */ + +#ifdef LLC_RESET_DELAY + #define LLC_URSET_DELAY_TIME_OUT LLC_RESET_DELAY +#else + #define LLC_URSET_DELAY_TIME_OUT 50 +#endif /* */ + + + +/************************ End of macros *****************************/ + +/********************** Callback functions **************************/ + +/******************* End of Callback functions **********************/ + +/********************* Structures and enums *************************/ + +/****************** End of structures and enums *********************/ + +/******************** Function declarations *************************/ +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC timer functions \b Timer Init function +* +* \copydoc page_reg This is to store LLCs main context structure +* +* \param[in, out] psLlcCtxt Llc main structure information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +NFCSTATUS +phLlcNfc_TimerInit ( + phLlcNfc_Context_t *psLlcCtxt +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC timer functions \b Timer UnInit function +* +* \copydoc page_reg This is to uninitialise all timer related information +* +* \param[in, out] psLlcCtxt Llc main structure information +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* +*/ +void +phLlcNfc_TimerUnInit ( + phLlcNfc_Context_t *psLlcCtxt +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC timer functions \b Create timer function +* +* \copydoc page_reg creates all the timers in the LLC context +* +* +*/ +void +phLlcNfc_CreateTimers (void); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC timer functions \b Start timer function +* +* \copydoc page_reg starts the timer type given by the user +* +* \param[in] TimerType Timer type to start +* \param[in] ns_value Value of N(S) for which the timer is started +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* \retval Others Errors related to OsalNfc. +* +*/ +NFCSTATUS +phLlcNfc_StartTimers ( + uint8_t TimerType, + uint8_t ns_value +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC timer functions \b Stop timer function +* +* \copydoc page_reg stop the timer type given by the user +* +* \param[in] TimerType Timer type to start +* \param[in] no_of_gaurd_to_del Guard time-out count shall be decreased as and when +* frame is removed +* +* +*/ +void +phLlcNfc_StopTimers ( + uint8_t TimerType, + uint8_t no_of_guard_to_del +); + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC timer functions \b Stop timer function +* +* \copydoc page_reg stop the timer type given by the user +* +* +* +* +*/ +void +phLlcNfc_StopAllTimers (void); + + +/** +* \ingroup grp_hal_nfc_llc_helper +* +* \brief LLC timer functions \b Delete timer function +* +* \copydoc page_reg deletes all the timers in the LLC context +* +* \retval NFCSTATUS_SUCCESS Operation successful. +* \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid. +* \retval Others Errors related to OsalNfc. +* +*/ +void +phLlcNfc_DeleteTimer (void); + +#ifdef LLC_URSET_NO_DELAY + + /* NO definition required */ + +#else /* #ifdef LLC_URSET_NO_DELAY */ + +void +phLlcNfc_URSET_Delay_Notify ( + + uint32_t delay_id); + + + +#endif /* #ifdef LLC_URSET_NO_DELAY */ + +/****************** End of Function declarations ********************/ +#endif /* PHLLCNFC_TIMER_H */ diff --git a/libnfc-nxp/phNfcCompId.h b/libnfc-nxp/phNfcCompId.h new file mode 100644 index 0000000..4cb95af --- /dev/null +++ b/libnfc-nxp/phNfcCompId.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phNfcCompId.h + * \brief NFC Component ID Values - Used for Function Return Codes + * + * Project: NFC MW / HAL + * + * $Date: Thu Mar 12 12:00:30 2009 $ + * $Author: ing04880 $ + * $Revision: 1.6 $ + * $Aliases: NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PHNFCCOMPID_H /* */ +#define PHNFCCOMPID_H /* */ + +#ifndef PH_FRINFC_EXCLUDE_FROM_TESTFW /* */ + +/** + * \name NFC Comp. ID + * + * File: \ref phNfcCompId.h + * + */ +/*@{*/ +#define PHNFCCOMPID_FILEREVISION "$Revision: 1.6 $" /**< \ingroup grp_file_attributes */ +#define PHNFCCOMPID_FILEALIASES "$Aliases: NFC_FRI1.1_WK912_PREP1,NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +#endif /* PH_FRINFC_EXCLUDE_FROM_TESTFW */ + +/** + * \ingroup grp_comp_id + * + * \name Component IDs + * + * IDs for all NFC components. Combined with the Status Code they build the value (status) + * returned by each function. + * + * ID Number Spaces: + * - 01..1F: HAL + * - 20..3F: NFC-MW (Local Device) + * - 40..5F: NFC-MW (Remote Device) + * . + * + * \note The value \ref CID_NFC_NONE does not exist for Component IDs. Do not use this value except + * for \ref NFCSTATUS_SUCCESS. The enumeration function uses \ref CID_NFC_NONE + * to mark unassigned \ref phHal_sHwReference_t "Hardware References". + * + * \if hal + * \sa \ref phHalNfc_Enumerate + * \endif + */ +/*@{*/ +#define CID_NFC_NONE 0x00 /**< \ingroup grp_comp_id + Unassigned or doesn't apply (see \ref NFCSTATUS_SUCCESS). */ +#define CID_NFC_DAL 0x01 /**< \ingroup grp_comp_id + Driver Abstraction Layer + \if hal (\ref grp_subcomponents) \endif . */ +#define CID_NFC_LLC 0x07 /**< \ingroup grp_comp_id + Logical Link Control Layer + \if hal (\ref grp_subcomponents) \endif . */ +#define CID_NFC_HCI 0x08 /**< \ingroup grp_comp_id + Host Control Interface Layer + \if hal (\ref grp_subcomponents) \endif . */ +#define CID_NFC_DNLD 0x09 /**< \ingroup grp_comp_id + Firmware Download Management Layer + \if hal (\ref grp_subcomponents) \endif . */ +#define CID_NFC_HAL 0x10 /**< \ingroup grp_comp_id + Hardware Abstraction Layer \if hal (\ref grp_hal_common) \endif . */ +#define CID_FRI_NFC_OVR_HAL 0x20 /**< \ingroup grp_comp_id + NFC-Device, HAL-based. */ +#define CID_FRI_NFC_NDEF_RECORD 0x22 /**< \ingroup grp_comp_id + NDEF Record Tools Library. */ +#define CID_FRI_NFC_NDEF_MAP 0x23 /**< \ingroup grp_comp_id + NDEF Mapping. */ +#define CID_FRI_NFC_NDEF_REGISTRY 0x24 /**< \ingroup grp_comp_id + NDEF_REGISTRY. */ +#define CID_FRI_NFC_AUTO_DEV_DIS 0x25 /**< \ingroup grp_comp_id + Automatic Device Discovery. */ +#define CID_FRI_NFC_NDEF_SMTCRDFMT 0x26 /**< \ingroup grp_comp_id + Smart Card Formatting */ +#define CID_FRI_NFC_LLCP 0x27 /**< \ingroup grp_comp_id + LLCP Core. */ +#define CID_FRI_NFC_LLCP_MAC 0x28 /**< \ingroup grp_comp_id + LLCP Mac Mappings. */ +#define CID_FRI_NFC_LLCP_TRANSPORT 0x29 /**< \ingroup grp_comp_id + LLCP Transport. */ +#define CID_NFC_LIB 0x30 /**< \ingroup grp_comp_id + NFC Library Layer \if hal (\ref grp_hal_common) \endif . */ +#define CID_MAX_VALUE 0xF0 /**< \ingroup grp_comp_id + The maximum CID value that is defined. */ + +/*@}*/ + +#endif /* PHNFCCOMPID_H */ diff --git a/libnfc-nxp/phNfcConfig.h b/libnfc-nxp/phNfcConfig.h new file mode 100644 index 0000000..955c26b --- /dev/null +++ b/libnfc-nxp/phNfcConfig.h @@ -0,0 +1,543 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/** +* \file phNfcConfig.h +* \brief HAL Configurations +* +* +* \note This is the configuration header file of the HAL 4.0.All configurable parameters of the HAL 4.0 +* are provided in this file +* +* Project: NFC-FRI-1.1 / HAL4.0 +* +* $Date: Thu Sep 9 14:56:35 2010 $ +* $Author: ing04880 $ +* $Revision: 1.39 $ +* $Aliases: $ +* +*/ + + +/*@{*/ +#ifndef PHNFC_CONFIG_H +#define PHNFC_CONFIG_H +/*@}*/ + + +/** +* \name Hal +* +* File: \ref phNfcConfig.h +* +*/ + +/*@{*/ +#define PH_NFC_CONFIG_FILEREVISION "$Revision: 1.39 $" /**< \ingroup grp_file_attributes */ +#define PH_NFC_CONFIG_FILEALIASES "$Aliases: $" /**< \ingroup grp_file_attributes */ +/*@}*/ + + +/* -----------------Include files ---------------------------------------*/ + +#ifdef NFC_CUSTOM_CONFIG_INCLUDE +#include +#endif + +/* ---------------- Macros ----------------------------------------------*/ + + + +/* + ***************************************************************** + ********************** DEFAULT MACROS ************************** + ***************************************************************** + */ + + +/**< External Clock Request Configuration for the NFC Device, + 0x00U No Clock Request, + 0x01U Clock Request through CLKREQ pin (GPIO pin 2), + 0x02U Clock Request through NXP_EVT_CLK_REQUEST Event, + */ +#ifndef NXP_DEFAULT_CLK_REQUEST +#define NXP_DEFAULT_CLK_REQUEST 0x00U +#endif + +/**< External Input Clock Setting for the NFC Device, + 0x00U No Input Clock Required (Use the Xtal), + 0x01U 13 MHZ, + 0x02U 19.2 MHZ, + 0x03U 26 MHZ, + 0x04U 38.4 MHZ, + 0x05U Custom (Set the Custome Clock Registry), + */ + +#ifndef NXP_DEFAULT_INPUT_CLK +#define NXP_DEFAULT_INPUT_CLK 0x00U +#endif + +/**< UICC Power Request configuration for the NFC Device, + 0x00U No Power Request, + 0x01U Power Request through CLKREQ pin (GPIO pin 2), + 0x02U Power Request through PWR_REQUEST (GPIO Pin 3), + */ + +#ifndef NXP_UICC_PWR_REQUEST +#define NXP_UICC_PWR_REQUEST 0x00U +#endif + +/**< TX LDO Configuration + 0x00 00b 3.0 V, + 0x01 01b 3.0 V, + 0x02 10b 2.7 V, + 0x03 11b 3.3 V, + */ + +#ifndef NXP_DEFAULT_TX_LDO +#define NXP_DEFAULT_TX_LDO 0x00U +#endif + +/**< UICC Bit Rate Configuration + 0x02 212Kbits/Sec + 0x04 424Kbits/Sec + 0x08 828Kbits/Sec + */ + +#ifndef NXP_UICC_BIT_RATE +#define NXP_UICC_BIT_RATE 0x08U +#endif + + +/**< Indicates PN544 Power Modes Configuration for the NFC Device, + 0x00U -> PN544 stays in active bat mode + (except when generating RF field) + 0x01U -> PN544 goes in standby when possible otherwise + stays in active bat mode + 0x02U -> PN544 goes in idle mode as soon as it can + (otherwise it is in active bat except when generating RF field) + 0x03U -> PN544 goes in standby when possible otherwise goes in idle mode + as soon as it can (otherwise it is in active bat except when + generating RF field) + */ + +#ifndef NXP_SYSTEM_PWR_STATUS +#define NXP_SYSTEM_PWR_STATUS 0x01U +#endif + +/**< Default Session ID for Initialisation */ +#ifndef DEFAULT_SESSION +#define DEFAULT_SESSION "android8" +#endif + + +/* The Other Integration Configuration Values */ + +/**< Max number of remote devices supported */ + +#ifndef MAX_REMOTE_DEVICES +#define MAX_REMOTE_DEVICES 0x0A +#endif + +/**< System Event Notification + 0x01 Overcurrent + 0x02 PMUVCC Switch + 0x04 External RF Field + 0x08 Memory Violation + 0x10 Temperature Overheat + */ + +#ifndef NXP_SYSTEM_EVT_INFO +#define NXP_SYSTEM_EVT_INFO 0x3DU +#endif + + +#ifndef NFC_DEV_HWCONF_DEFAULT +#define NFC_DEV_HWCONF_DEFAULT 0xBCU +#endif + + +#ifndef NXP_ISO_XCHG_TIMEOUT +#define NXP_ISO_XCHG_TIMEOUT 0x1BU +#endif + +#ifndef NXP_MIFARE_XCHG_TIMEOUT +#define NXP_MIFARE_XCHG_TIMEOUT 0x0BU +#endif + +#ifndef NXP_FELICA_XCHG_TIMEOUT +#define NXP_FELICA_XCHG_TIMEOUT 0xFFU +#endif + + +#ifndef NXP_NFCIP_PSL_BRS_DEFAULT +#define NXP_NFCIP_PSL_BRS_DEFAULT 0x00U +#endif + + + +/**< ID For Invalid Timer */ +#ifndef NXP_INVALID_TIMER_ID +#define NXP_INVALID_TIMER_ID 0xFFFFFFFFU +#endif + +/**< Presence check interval in milliseconds */ +#ifndef PRESENCE_CHECK_INTERVAL +#define PRESENCE_CHECK_INTERVAL 500U +#endif + +/** Resolution value for the timer, here the + timer resolution is 500 milliseconds */ +#ifndef TIMER_RESOLUTION +#define TIMER_RESOLUTION 500U +#endif + +/* Kindly note that the below Timeout values should be + * in Multiples of the value provided to TIMER_RESOLUTION + */ + +/**< Defines guard time out value for LLC timer, + 1000 is in milliseconds */ +#ifndef LINK_GUARD_TIMEOUT +#define LINK_GUARD_TIMEOUT 1000U +#endif + + +/**< Defines connection time out value for LLC timer, + 1000 is in milliseconds */ +#ifndef LINK_CONNECTION_TIMEOUT +#define LINK_CONNECTION_TIMEOUT 1000U +#endif + +/**< Defines ACK time out value for LLC timer, + 150 is in milliseconds */ +#ifndef LINK_ACK_TIMEOUT +#define LINK_ACK_TIMEOUT 1U +#endif + + +/**< Defines Firmware Download Completion Timeout value , + 120000 is in milliseconds */ + + +#ifndef NXP_DNLD_COMPLETE_TIMEOUT +#define NXP_DNLD_COMPLETE_TIMEOUT 60000U +#endif + + +/**< Define to configure the Active Mode Polling Guard Time-out + */ + +#ifndef DEV_MGMT_ACT_GRD_TO_DEFAULT +#define DEV_MGMT_ACT_GRD_TO_DEFAULT 0x20U +#endif + +/**< NFCIP Active Mode Default Configuration (when acting as Target) + 0x01 106 kbps + 0x02 212 kbps + 0x04 424 kbps + */ + +#ifndef NXP_NFCIP_ACTIVE_DEFAULT +#define NXP_NFCIP_ACTIVE_DEFAULT 0x01U +#endif + + + + +#ifndef NXP_NFC_HCI_TIMER +#define NXP_NFC_HCI_TIMER 1 +#define NXP_NFC_HCI_TIMEOUT 6000 +#endif + + +/* + ***************************************************************** + DO NOT MODIFY THE BELOW MACROS UNLESS OTHERWISE MENTIONED + ***************************************************************** + */ + + + +#ifndef HOST_CE_A_SAK_DEFAULT +#define HOST_CE_A_SAK_DEFAULT 0x20U +#endif + +#ifndef NXP_CE_A_ATQA_HIGH +#define NXP_CE_A_ATQA_HIGH 0x00U +#endif + +#ifndef NXP_CE_A_ATQA_LOW +#define NXP_CE_A_ATQA_LOW 0x04U +#endif + + +#ifndef NXP_UICC_CE_RIGHTS +#define NXP_UICC_CE_RIGHTS 0x0FU +#endif + +#ifndef NXP_UICC_RD_RIGHTS +#define NXP_UICC_RD_RIGHTS 0x00U +#endif + + +/* + ***************************************************************** + DO NOT DISABLE/ENABLE BELOW MACROS UNLESS OTHERWISE MENTIONED + ***************************************************************** + */ + +#define ES_HW_VER 32 + +/* + ***************************************************************** + *************** FEATURE SPECIFIC MACROS ************************* + ***************************************************************** + */ + + + +/**< Macro to Enable SMX Feature During + * Initialisation */ + +#if !defined(NXP_SMX) +#define NXP_SMX 1 +#endif + +#if (NXP_SMX == 1) +#define NXP_HAL_ENABLE_SMX +#endif + +/**< Macro to Enable the Host Session + * Initialisation */ +#define ESTABLISH_SESSION + +/**< Macro to Enable the Peer to Peer Feature */ +#define ENABLE_P2P + +#define DEFAULT_NFCIP_INITIATOR_MODE_SUPPORT 0x3FU +#define DEFAULT_NFCIP_TARGET_MODE_SUPPORT 0x0FU + +/**< Macro to Enable the ISO14443-B Feature */ +#define TYPE_B + +/**< Macro to Enable the Felica Feature */ +#define TYPE_FELICA + +/**< Macro to Enable the JEWEL Feature */ +#define TYPE_JEWEL + +/**< Macro to Enable the ISO15693 Feature */ +#define TYPE_ISO15693 + +/*< Macro to Verify the Poll Parameters Set */ +/* #define ENABLE_VERIFY_PARAM */ + +/**< Macro to Enable ISO 18092 Protocol compliancy + * SAK to be merged with the TYPE A Card RF Feature :3.1*/ +#define TGT_MERGE_SAK + + +/**< Macro to Configure the default power status + * to allow the PN544 to enter into the Standby */ +#define CFG_PWR_STATUS + + +/**< Macro to Enable the SWP Protocol + * to detect UICC During Initialisation */ +#define ENABLE_UICC + +/**< Macro to Enable the RAW Mode of Transaction + * for the ISO-14443-3A Compliant Targets */ +#define ENABLE_MIFARE_RAW + +/**< Macro to Enable the HOST List + * to allow the UICC Communication */ +#define HOST_WHITELIST + +/**< Support reconnecting to a different handle on the same tag */ +#define RECONNECT_SUPPORT + +/**< Macro to Enable the Card Emulation Feature */ +/* #define HOST_EMULATION */ + +#define NXP_HAL_VERIFY_EEPROM_CRC 0x01U + +/**< Macro to Enable the Download Mode Feature */ +#define FW_DOWNLOAD + +/**< Macro to Enable the Firmware Download Timer */ +/* 0x01U to use overall timeout */ +/* 0x02U to use per frame timeout */ +#define FW_DOWNLOAD_TIMER 0x02U + +/**< Macro to Verify the Firmware Download */ +/* #define FW_DOWNLOAD_VERIFY */ + +#ifndef FW_DOWNLOAD_VERIFY +#define NXP_FW_INTEGRITY_CHK 1 +#endif + +/* To specify the Maximum TX/RX Len */ +#define NXP_FW_MAX_TX_RX_LEN 0x200 + +#define UICC_CONNECTIVITY_PATCH + +/* Work around to Delay the initiator activation */ +/* #define NXP_NFCIP_ACTIVATE_DELAY */ + +/* Work around to Release the Discovered Target */ +#define SW_RELEASE_TARGET + +/* Macro to Allow the HCI Release in any state */ +#define NXP_HCI_SHUTDOWN_OVERRIDE + + +/* Macro to Enable The P2P Transaction Timers */ +#define P2P_TGT_TRANSACT_TIMER + +#if (ES_HW_VER == 32) +/* Macro to Configure the Target Disable Register */ +#define NFCIP_TGT_DISABLE_CFG + +#endif + +/*< Macro to Disable the Felica Mapping */ +/* #define DISABLE_FELICA_MAPPING */ + +/*< Macro to Disable the Felica Mapping */ +/* #define DISABLE_JEWEL_MAPPING */ + +/**< Macro to enable LLC timer */ +#define LLC_TIMER_ENABLE + +/**< Macro to enable HCI Response timer */ +#define NXP_NFC_HCI_TIMER 1 + +/* A Workaround to Delay and obtain the UICC Status Information */ +/* #define UICC_STATUS_DELAY */ + +#ifdef UICC_STATUS_DELAY +#define UICC_STATUS_DELAY_COUNT 0x00100000 +#endif + +/**< Macro to delay the LLC RESET response callback, + Value is in milli-seconds */ +#define LLC_RESET_DELAY 10 + +/* Macro to Enable the workaround for Tuning of + * RF for TYPE B and F + */ +/* #define SW_TYPE_RF_TUNING_BF */ + +/* Workaround to update the Active Guard Timeout */ +/* #define MAX_ACTIVATE_TIMEOUT */ + +/* #define ONE_BYTE_LEN */ + +#define NFC_RF_NOISE_SW + +/**< Define to configure the PMOS Modulation Index value + */ + +#ifndef NFC_DEV_PMOS_MOD_DEFAULT +/* 0x3F -> 6%, 0x3A -> 10%, 0x3C -> 10%, 0x35 -> 15.8%, 0x28 -> 25.8% */ +#define NFC_DEV_PMOS_MOD_DEFAULT 0x3CU +#endif + + +#ifndef SW_TYPE_RF_TUNING_BF +#define SW_TYPE_RF_TUNING_BF 0x80U +#endif + + +/* Reset the Default values of Host Link Timers */ +/* Macro to Enable the Host Side Link Timeout Configuration + * 0x00 ----> Default Pre-defined Configuration; + * 0x01 ----> Update only the Host Link Guard Timeout Configuration; + * 0x03 ----> Update Both the Host Link Guard Timeout + and ACK Timeout Configuration; + */ + +#ifndef HOST_LINK_TIMEOUT +#define HOST_LINK_TIMEOUT 0x00U +#endif + + +#ifndef NXP_NFC_LINK_GRD_CFG_DEFAULT +#define NXP_NFC_LINK_GRD_CFG_DEFAULT 0x0032U +#endif + +#ifndef NXP_NFC_LINK_ACK_CFG_DEFAULT +#define NXP_NFC_LINK_ACK_CFG_DEFAULT 0x0005U +#endif + +/* Macro to Enable the Interface Character Timeout Configuration + * 0x00 ----> Default Pre-defined Configuration; + * 0x01 ----> Update the IFC Timeout Default Configuration; + */ + +#ifndef NXP_NFC_IFC_TIMEOUT +#define NXP_NFC_IFC_TIMEOUT 0x00 +#endif + + +#ifndef NXP_NFC_IFC_CONFIG_DEFAULT +#define NXP_NFC_IFC_CONFIG_DEFAULT 0x203AU +#endif + +#ifndef NFC_ISO_15693_MULTIPLE_TAGS_SUPPORT +#define NFC_ISO_15693_MULTIPLE_TAGS_SUPPORT 0x00 +#endif + +/* + ***************************************************************** + *********** MACROS ENABLE EEPROM REGISTER WRITE **************** + ***************************************************************** + */ + + +/* Enable this to Disable the WI Notification */ +/* #define DISABLE_WI_NOTIFICATION */ + +/* Macro to Enable the Configuration of Initiator + * speed during Discovery configuration + */ +#define INITIATOR_SPEED +#define TARGET_SPEED + + +/**/ +/* #define UICC_SESSION_RESET */ + +/* Macro to Enable the Configuration of UICC + * Timer and Bitrate during Initialisation + */ + + + + +/* -----------------Structures and Enumerations -------------------------*/ + + + + +/* -----------------Exported Functions----------------------------------*/ + + +#endif /*PHNFC_CONFIG_H*/ + diff --git a/libnfc-nxp/phNfcHalTypes.h b/libnfc-nxp/phNfcHalTypes.h new file mode 100644 index 0000000..522df6d --- /dev/null +++ b/libnfc-nxp/phNfcHalTypes.h @@ -0,0 +1,1349 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phNfcHalTypes.h + * \brief Structure declarations/type definitions belonging to the HAL subsystem. + * + * Project: NFC MW / HAL + * + * $Date: Thu Apr 8 17:11:39 2010 $ + * $Author: ing04880 $ + * $Revision: 1.106 $ + * $Aliases: NFC_FRI1.1_WK1007_SDK,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + + +#ifndef PHNFCHALTYPES_H /* */ +#define PHNFCHALTYPES_H /* */ + +/** + * \name HAL Types + * + * File: \ref phNfcHalTypes.h + * + */ + +/*@{*/ +#define PHNFCHALTYPES_FILEREVISION "$Revision: 1.106 $" /**< \ingroup grp_file_attributes */ +#define PHNFCHALTYPES_FILEALIASES "$Aliases: NFC_FRI1.1_WK1007_SDK,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +#include +#include +#include + +#ifndef NXP_HAL_MEM_INFO_SIZE +#define NXP_HAL_MEM_INFO_SIZE 0x01U +#endif + +#if (NXP_HAL_MEM_INFO_SIZE > 0x01) +#define NXP_FW_UPLOAD_PROGRESS 0x965AU +#define NXP_FW_UPLOAD_SUCCESS 0x0000U +#else +#define NXP_FW_UPLOAD_PROGRESS 0x5AU +#define NXP_FW_UPLOAD_SUCCESS 0x00U +#endif + + +typedef struct phHal_sMemInfo +{ + uint16_t fw_magic; + uint16_t fw_rfu; + uint32_t hal_version; +}phHal_sMemInfo_t; + + +/** \ingroup grp_hal_common + * + * \if hal + * \brief Protocol Support Information + * \else + * \brief HAL-Specific + * \endif + * + * The Supported Protocols Structure holds all protocol supported by the current NFC + * device. + * + * \note All members of this structure are output parameters [out]. + * + */ +typedef phNfc_sSupProtocol_t phHal_sSupProtocol_t; + + +/** \ingroup grp_hal_common + * + * + * \if hal + * \brief Information related to the NFC Device + * \else + * \brief HAL-Specific + * \endif + * + * The Device Information Structure holds information + * related to the NFC IC read during initialization time. + * It allows the caller firware, hardware version, the model id, + * HCI verison supported and vendor name. Refer to the NFC Device + * User Manual on how to interpret each of the values. In addition + * it also contains capabilities of the NFC Device such as the + * protocols supported in Reader and emulation mode + * + */ + +typedef phNfc_sDeviceCapabilities_t phHal_sDeviceCapabilities_t; + + +/** + * \ingroup grp_hal_common + * + * \if hal + * \brief Hardware Reference - The Peripheral Representation + * \else + * \brief HAL-Specific + * \endif + * + * The Hardware Reference structure is filled as part of the open function and + * contains information regarding connected peripheral NFC device. It also + * stores the refernce to the communication driver passed by the HAL client + * for usage during communication with the NFC Device + * + * \note The caller can consider this structure atomic, no interpretation is required + * for HAL operation. + * + * \sa phHal4Nfc_Open . + * + */ + +/** + * \ingroup grp_hal_common + * + * \brief Hardware Reference - The Peripheral Representation + * + * The Hardware Reference structure is filled as part of the open function and + * contains information regarding connected peripheral NFC device. It also + * stores the refernce to the communication driver passed by the HAL client + * for usage during communication with the NFC Device + * + * \note The caller can consider this structure atomic, no interpretation is required + * for HAL operation. + * + */ +typedef struct phHal_sHwReference +{ + /**< Will be usable/valid after the Open function. */ + void *p_board_driver; + /**< Session Identifier for the established session */ + uint8_t session_id[SESSIONID_SIZE]; + /**< SMX Connected TRUE/FALSE */ + uint8_t smx_connected; + /**< UICC Connected TRUE/FALSE */ + uint8_t uicc_connected; + /**< UICC Reader Mode is Active TRUE/FALSE */ + uint8_t uicc_rdr_active; + /**< Device information. */ + phNfc_sDeviceCapabilities_t device_info; + /**< Context of the HAL Layer */ + void *hal_context; + /**< Context of the DAL Layer */ + void *dal_context; +} phHal_sHwReference_t; + + +/** \ingroup grp_hal_common + * + * \if hal + * \brief Hardware configuration - Configuration Parameters for the NFC Device + * \else + * \brief HAL-Specific + * \endif + * + * The parameters used to configure the device during the initialisation. + * This structure is used internally by the HAL implementation and is filled + * up based on various configuration parameters from the config file + * \note None. + * + */ + +typedef struct phHal_sHwConfig +{ + + uint8_t session_id[SESSIONID_SIZE]; /**< Session Identifier for + the established session */ + + uint8_t clk_req; /**< Clock Request Setting */ + + uint8_t input_clk; /**< Input Clock Setting */ + +} phHal_sHwConfig_t; + + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +/* This data structure is not used anymore and will be removed in subsequent + release */ +typedef struct phHal_sDepFlags +{ + unsigned int MetaChaining : 1; + unsigned int NADPresent : 1; +} phHal_sDepFlags_t; + +/* This data structure is not used anymore and will be removed in subsequent + release */ + +typedef struct phHal_sDepAdditionalInfo +{ + phHal_sDepFlags_t DepFlags; + uint8_t NAD; +} phHal_sDepAdditionalInfo_t; + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + + +/** \ingroup grp_hal_common + * + * \if hal + * \brief Enumerated MIFARE Commands + * \else + * \brief HAL-Specific + * \endif + * + * The Mifare Command List Enumerator lists all available Mifare native commands. + * + * \note None. + * + */ + +typedef phNfc_eMifareCmdList_t phHal_eMifareCmdList_t; + +#define phHal_eMifareRaw phNfc_eMifareRaw +#define phHal_eMifareAuthentA phNfc_eMifareAuthentA +#define phHal_eMifareAuthentB phNfc_eMifareAuthentB +#define phHal_eMifareRead16 phNfc_eMifareRead16 +#define phHal_eMifareRead phNfc_eMifareRead +#define phHal_eMifareWrite16 phNfc_eMifareWrite16 +#define phHal_eMifareWrite4 phNfc_eMifareWrite4 +#define phHal_eMifareInc phNfc_eMifareInc +#define phHal_eMifareDec phNfc_eMifareDec +#define phHal_eMifareTransfer phNfc_eMifareTransfer +#define phHal_eMifareRestore phNfc_eMifareRestore +#define phHal_eMifareReadSector phNfc_eMifareReadSector +#define phHal_eMifareWriteSector phNfc_eMifareWriteSector +#define phHal_eMifareInvalidCmd phNfc_eMifareInvalidCmd + + +/** \ingroup grp_hal_common + * + * The T=Cl Command List Enumerator lists all available T=Cl Commands. + * + * \note None. + * + */ +typedef phNfc_eIso14443_4_CmdList_t phHal_eIso14443_4_CmdList_t; + +#define phHal_eIso14443_4_Raw phNfc_eIso14443_4_Raw + + +/** \ingroup grp_hal_common + * + * The NFCIP1 Command List Enumerator lists all available NFCIP1 Commands. + * + * \note None. + * + */ +typedef phNfc_eNfcIP1CmdList_t phHal_eNfcIP1CmdList_t; + +#define phHal_eNfcIP1_Raw phNfc_eNfcIP1_Raw + + +/** \ingroup grp_hal_common + * + * The ISO15693 Command List Enumerator lists all available ISO15693 Commands. + * + * \note None. + * + */ + +typedef phNfc_eIso15693_CmdList_t phHal_eIso15693_CmdList_t; + +#if 0 +#define phHal_eIso15693_Raw phNfc_eIso15693_Raw +#endif +#define phHal_eIso15693_Cmd phNfc_eIso15693_Cmd +#define phHal_eIso15693_Invalid phNfc_eIso15693_Invalid + +/** \ingroup grp_hal_common + * + * The Felica Command List Enumerator lists all available Felica Commands. + * + * \note None. + * + */ + +typedef enum phHal_eFelicaCmdList +{ + phHal_eFelica_Raw = 0xF0U, /**< Felica Raw command:\n + - This command sends the data buffer directly + to the remote device */ + phHal_eFelica_Check = 0x00, /**< Felica Check command:\n + - This command checks the data from the Felica + remote device */ + phHal_eFelica_Update = 0x01, /**< Felica Update command:\n + - This command updates the data onto the Felica + remote device */ + phHal_eFelica_Invalid = 0xFFU /**< Invalid Command */ +} phHal_eFelicaCmdList_t; + + +typedef enum phHal_eJewelCmdList +{ + phHal_eJewel_Raw = 0x00U, /**< Jewel command:\n + - This command sends the data buffer directly + to the remote device */ + phHal_eJewel_Invalid = 0xFFU /**< Invalid jewel command */ +}phHal_eJewelCmdList_t; + + + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief Remote Device Reader A RF Gate Information Container +* \else +* \brief HAL-Specific +* \endif +* +* The Reader A structure includes the available information +* related to the discovered ISO14443A remote device. This information +* is updated for every device discovery. +* \note None. +* +*/ +typedef phNfc_sIso14443AInfo_t phHal_sIso14443AInfo_t; + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief Remote Device Reader B RF Gate Information Container +* \else +* \brief HAL-Specific +* \endif +* +* The Reader B structure includes the available information +* related to the discovered ISO14443B remote device. This information +* is updated for every device discovery. +* \note None. +* +*/ + +typedef phNfc_sIso14443BInfo_t phHal_sIso14443BInfo_t; + +typedef phNfc_sIso14443BPrimeInfo_t phHal_sIso14443BPrimeInfo; + + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief Remote Device Jewel Reader RF Gate Information Container +* \else +* \brief HAL-Specific +* \endif +* +* The Jewel Reader structure includes the available information +* related to the discovered Jewel remote device. This information +* is updated for every device discovery. +* \note None. +* +*/ + + +typedef phNfc_sJewelInfo_t phHal_sJewelInfo_t; + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief Remote Device Felica Reader RF Gate Information Container +* \else +* \brief HAL-Specific +* \endif +* +* The Felica Reader structure includes the available information +* related to the discovered Felica remote device. This information +* is updated for every device discovery. +* \note None. +* +*/ + +typedef phNfc_sFelicaInfo_t phHal_sFelicaInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief Remote Device Reader 15693 RF Gate Information Container +* \else +* \brief HAL-Specific +* \endif +* +* The Reader A structure includes the available information +* related to the discovered ISO15693 remote device. This information +* is updated for every device discovery. +* \note None. +* +*/ + +typedef phNfc_sIso15693Info_t phHal_sIso15693Info_t; + + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief NFC Data Rate Supported between the Reader and the Target +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHalNfc_eDataRate enum lists all the Data Rate +* values to be used to determine the rate at which the data is transmitted +* to the target. +* +* \note None. +*/ + + +typedef phNfc_eDataRate_t phHalNfc_eDataRate_t; + + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief NFCIP1 Gate Information Container +* \else +* \brief HAL-Specific +* \endif +* +* The NFCIP1 structure includes the available information +* related to the discovered NFCIP1 remote device. This information +* is updated for every device discovery. +* \note None. +* +*/ + +typedef phNfc_sNfcIPInfo_t phHal_sNfcIPInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief Remote Device Specific Information Container +* \else +* \brief HAL-Specific +* \endif +* +* The Remote Device Information Union includes the available Remote Device Information +* structures. Following the device detected, the corresponding data structure is used. +* +* \note None. +* +*/ + +typedef phNfc_uRemoteDevInfo_t phHal_uRemoteDevInfo_t; + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief RF Device Type Listing +* \else +* \brief HAL-Specific +* \endif +* +* The RF Device Type List is used to identify the type of +* remote device that is discovered/connected. There seperate +* types to identify a Remote Reader (denoted by _PCD) and +* Remote Tag (denoted by _PICC) +* \note None. +* +*/ + +typedef phNfc_eRFDevType_t phHal_eRFDevType_t; + +#define phHal_eUnknown_DevType phNfc_eUnknown_DevType + + /* Specific PCD Devices */ +#define phHal_eISO14443_A_PCD phNfc_eISO14443_A_PCD +#define phHal_eISO14443_B_PCD phNfc_eISO14443_B_PCD +#define phHal_eISO14443_BPrime_PCD phNfc_eISO14443_BPrime_PCD +#define phHal_eFelica_PCD phNfc_eFelica_PCD +#define phHal_eJewel_PCD phNfc_eJewel_PCD +#define phHal_eISO15693_PCD phNfc_eISO15693_PCD + /* Generic PCD Type */ +#define phHal_ePCD_DevType phNfc_ePCD_DevType + + /* Generic PICC Type */ +#define phHal_ePICC_DevType phNfc_ePICC_DevType + /* Specific PICC Devices */ +#define phHal_eISO14443_A_PICC phNfc_eISO14443_A_PICC +#define phHal_eISO14443_4A_PICC phNfc_eISO14443_4A_PICC +#define phHal_eISO14443_3A_PICC phNfc_eISO14443_3A_PICC +#define phHal_eMifare_PICC phNfc_eMifare_PICC +#define phHal_eISO14443_B_PICC phNfc_eISO14443_B_PICC +#define phHal_eISO14443_4B_PICC phNfc_eISO14443_4B_PICC +#define phHal_eISO14443_BPrime_PICC phNfc_eISO14443_BPrime_PICC +#define phHal_eFelica_PICC phNfc_eFelica_PICC +#define phHal_eJewel_PICC phNfc_eJewel_PICC +#define phHal_eISO15693_PICC phNfc_eISO15693_PICC + + /* NFC-IP1 Device Types */ +#define phHal_eNfcIP1_Target phNfc_eNfcIP1_Target +#define phHal_eNfcIP1_Initiator phNfc_eNfcIP1_Initiator + + /* Other Sources */ +#define phHal_eInvalid_DevType phNfc_eInvalid_DevType + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief Remote Device Type Listing +* \else +* \brief HAL-Specific +* \endif +* +* The Remote Device Type List is used to identify the type of +* remote device that is discovered/connected +* \note This is same as RF Device Type List. +* +*/ +typedef phNfc_eRemDevType_t phHal_eRemDevType_t; + +/** \ingroup grp_hal_common + * + * + * \if hal + * \brief Common Command Attribute + * \else + * \brief HAL-Specific + * \endif + * + * The Hal Command Union includes each available type of Commands. + * + * \note None. + * + */ + +typedef phNfc_uCmdList_t phHal_uCmdList_t; + + +/** \ingroup grp_hal_nfci + * + * \if hal + * \brief Remote Device Information Structure + * \else + * \brief HAL-Specific + * \endif + * + * The Remote Device Information Structure holds information about one single Remote + * Device detected by the polling function .\n + * It lists parameters common to all supported remote devices. + * + * \note + * + * \if hal + * \sa \ref phHal4Nfc_ConfigureDiscovery and \ref phHal4Nfc_Connect + * \else + * \sa + * \endif + * + */ + +typedef phNfc_sRemoteDevInformation_t phHal_sRemoteDevInformation_t; + + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +/* This data structure is not used anymore and will be removed in subsequent + release */ + +typedef struct phHal_sDevInputParam +{ + uint8_t FelicaPollPayload[5]; + + + uint8_t NfcPollPayload[5]; + + + uint8_t NFCIDAuto; + + + uint8_t NFCID3i[PHHAL_NFCID_LENGTH]; + + + + uint8_t DIDiUsed; + + uint8_t CIDiUsed; + + uint8_t NfcNADiUsed; + + /*+ MantisId : 31 - JP - 09-01-2006 */ + /*uint8_t TClNADiUsed; */ + + /*- MantisId : 31 - JP - 09-01-2006 */ + uint8_t GeneralByte[48]; + + + uint8_t GeneralByteLength; + + + uint8_t ISO14443_4B_AFI; + +} phHal_sDevInputParam_t; + + + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* TARGET STRUCTURES */ + + +/** \ingroup grp_hal_common + * + * \if hal + * \brief Transceive Information Data Structure for sending commands/response + * to the remote device + * \else + * \brief HAL-Specific + * \endif + * + * The Transceive Information Data Structure is used to pass the + * Command, Address (only required for MIFARE) and the send and receive data + * data structure (buffer and length) for communication with remote device + * + * + */ + +typedef phNfc_sTransceiveInfo_t phHal_sTransceiveInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief Input information for the Type A tags +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sIso14443ACfg structure holds the information +* required for the NFC device to be used during ISO14443A target discovery +* +* \note None. +*/ +typedef struct phHal_sIso14443ACfg +{ + uint8_t Auto_Activation; /**< Enable Auto Activation for + Technology A \n + If set to 0, the activation procedure will stop + after Select (SAK has been received). + The host could evaluate SAK value and then decide: + - to start communicating with the remote card + using proprietary commands (see NXP_MIFARE_RAW + and NXP_MIFARE_CMD) + or + - to activate the remote card up to ISO14443-4 + level (RATS and PPS) using + CONTINUE ACTIVATION command + If set to 1, activation follows the flow described in + ETSI HCI specification (restrict detection to + ISO14443-4 compliant cards). + */ +}phHal_sIso14443ACfg_t; + + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief Input information for the Type B tags +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sIso14443BCfg structure holds the information +* required for the NFC device to be used during ISO14443B target discovery +* +* \note None. +*/ +typedef struct phHal_sIso14443BCfg +{ + uint8_t AppFamily_ID; /**< Application Family Identifier for + Technology B, 0x00 means all application */ +}phHal_sIso14443BCfg_t; + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief Input information for the Felica tags +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sFelicaCfg_t structure holds the information +* required for the NFC device to be used during Felica target discovery +* +* \note None. +*/ + +typedef struct phHal_sFelicaCfg +{ + uint8_t SystemCode[PHHAL_FEL_SYS_CODE_LEN]; /**< System code for Felica tags */ + +}phHal_sFelicaCfg_t; + + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief Poll Device Information for conifiguring the discovery wheel + Reader and Card Emulation Phases +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sPollDevInfo_t enum is used to enable/disable +* phases of the discovery wheel related to specific reader types and +* card emulation phase +* \note Enabling specific Reader technology when NFCIP1 speed is set in the +* phNfc_sADD_Cfg_t is implicitly done in HAL. Use this structure to only +* enable/disable Card Reader Functionality +*/ +typedef phNfc_sPollDevInfo_t phHal_sPollDevInfo_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Identifies Type of Host +* \else +* \brief HAL-Specific +* \endif +* +* This enumeration is used to identify the type of the host providing the +* information or the notification to the Terminal host. +* \note None. +*/ + +typedef enum phHal_HostType { + /* + * This type identifies the host controller + * in the NFC device + */ + phHal_eHostController = 0x00U, + /* + * This type identifies the Host Device + * controlling the NFC device. + */ + phHal_eTerminalHost = 0x01U, + /* + * This type identifies the uicc host + * connnected to the NFC device + */ + phHal_eUICCHost = 0x02U, + /* Host type is unknown */ + phHal_eUnknownHost = 0xFFU +}phHal_HostType_t; + + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief P2P speed for the Initiator +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_eP2PMode enum lists all the NFCIP1 speeds +* to be used for configuring the NFCIP1 discovery +* +* \note None. +*/ + +#define phHal_eDefaultP2PMode phNfc_eDefaultP2PMode +#define phHal_ePassive106 phNfc_ePassive106 +#define phHal_ePassive212 phNfc_ePassive212 +#define phHal_ePassive424 phNfc_ePassive424 +#define phHal_eActive phNfc_eActive +#define phHal_eP2P_ALL phNfc_eP2P_ALL +#define phHal_eInvalidP2PMode phNfc_eInvalidP2PMode + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Identities the type of Notification +* \else +* \brief HAL-Specific +* \endif +* +* This enumeration is used to specify the type of notification notified +* to the upper layer. This classifies the notification into two types +* one for the discovery notifications and the other for all the remaining +* event notifications +* \note None. +*/ + + +typedef phNfc_eNotificationType_t phHal_eNotificationType_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Identifies the type of event notification +* \else +* \brief HAL-Specific +* \endif +* +* This enumeration is used to identify the type of the event notified +* to the Terminal host. +* \note None. +*/ + +typedef enum phHal_Event { + + + /* Transaction Events */ + NFC_EVT_END_OF_TRANSACTION = 0x11U , + NFC_EVT_TRANSACTION = 0x12U , + NFC_EVT_START_OF_TRANSACTION = 0x20U , + + /* Field Events */ + NFC_EVT_FIELD_ON = 0x31U, + NFC_EVT_FIELD_OFF = 0x34U, + + /* Card/Target Activation Events */ + NFC_EVT_ACTIVATED = 0x33U, + NFC_EVT_DEACTIVATED = 0x32U, + + NFC_EVT_PROTECTED = 0x24U , + + /* Reader Phases configuration request by UICC */ + NFC_UICC_RDPHASES_ACTIVATE_REQ = 0x43U, + NFC_UICC_RDPHASES_DEACTIVATE_REQ = 0x44U, + + /* Connectivity and Triggering Events - Future Use */ + NFC_EVT_CONNECTIVITY = 0x10U , + NFC_EVT_OPERATION_ENDED = 0x13U , + + /* NXP Specific System Information Events */ + NFC_INFO_TXLDO_OVERCUR = 0x71U, + NFC_INFO_MEM_VIOLATION = 0x73U, + NFC_INFO_TEMP_OVERHEAT = 0x74U, + NFC_INFO_LLC_ERROR = 0x75U, + + /* NXP EVENTS */ + NFC_EVT_MIFARE_ACCESS = 0x35, + NFC_EVT_APDU_RECEIVED = 0x36, + NFC_EVT_EMV_CARD_REMOVAL = 0x37 + +}phHal_Event_t; + +typedef phNfc_sUiccInfo_t phHal_sUiccInfo_t; + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Event notification Information +* \else +* \brief HAL-Specific +* \endif +* +* This structure provides the information about the event notified +* to the terminal host. +* \note None. +*/ + +typedef struct phHal_sEventInfo +{ + /* Type of the host issuing the event */ + phHal_HostType_t eventHost; + /* Type of the source issuing the event */ + phHal_eRFDevType_t eventSource; + /* Type of the source issuing the event */ + phHal_Event_t eventType; + union uEventInfo + { + /* Parameter information Information is obtained if the eventType is + * NFC_EVT_TRANSACTION for UICC. + */ + phHal_sUiccInfo_t uicc_info; + /* AID Information is obtained if the eventType is + * NFC_EVT_TRANSACTION. + */ + phNfc_sData_t aid; + /* Overheat Status Information is obtained if the eventType is + * NFC_INFO_TEMP_OVERHEAT. + */ + uint8_t overheat_status; + /* rd_phases Information is obtained if the eventType is + * NFC_UICC_RDPHASES_ACTIVATE_REQ. + */ + uint8_t rd_phases; + /* Remote Device Information is obtained if the eventType is + * NFC_EVT_ACTIVATED. + */ + phHal_sRemoteDevInformation_t *pRemoteDevInfo; + }eventInfo; +}phHal_sEventInfo_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Information for the Host/Uicc Emulation Support +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sEmuSupport structure holds the type +* of the target emulation supported. +* +* \note None. +*/ + +typedef struct phHal_sEmuSupport +{ + unsigned int TypeA:1; + unsigned int TypeB:1; + unsigned int TypeBPrime:1; + unsigned int TypeFelica:1; + unsigned int TypeMifare:1; + unsigned int TypeNfcIP1:1; + unsigned int RFU:2; + +}phHal_sEmuSupport_t; + + +/** \ingroup grp_hal_nfci +* +* \if hal +* \brief P2P Information for the Initiator +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sNfcIPCfg holds the P2P related information +* use by the NFC Device during P2P Discovery and connection +* +* \note None. +*/ + +typedef phNfc_sNfcIPCfg_t phHal_sNfcIPCfg_t; + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Enumeration used to choose which type of parameters +* are to be configured +* \else +* \brief HAL-Specific +* \endif +* +* +* \note None. +*/ +typedef enum phHal_eConfigType +{ + NFC_INVALID_CONFIG = 0x00U, /**< Invalid Configuration */ + NFC_RF_READER_CONFIG, /**< Reader Parmaeters */ + NFC_P2P_CONFIG, /**< NFCIP1 Parameters */ + NFC_SE_PROTECTION_CONFIG, /**< Secure Element + Protection Cofiguration */ + NFC_EMULATION_CONFIG /**< Emulation Parameters */ +}phHal_eConfigType_t; + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Discovery Configuration Mode +* \else +* \brief HAL-Specific +* \endif +* +* This enumeration is used to choose the Discovery Configuration +* Mode :- Configure and Start, Stop or Start with last set +* configuration +* \note None. +*/ + +typedef phNfc_eDiscoveryConfigMode_t phHal_eDiscoveryConfigMode_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Target or Tag Release Mode +* \else +* \brief HAL-Specific +* \endif +* +* This enumeration defines various modes of releasing an acquired target +* or tag. +* \note None. +*/ +typedef phNfc_eReleaseType_t phHal_eReleaseType_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Configuration of specific Emulation Feature +* \else +* \brief HAL-Specific +* \endif +* +* This enumeration is used to choose configuration for a specific +* emulation feature. +* \note None. +*/ + +typedef enum phHal_eEmulationType +{ + NFC_UNKNOWN_EMULATION = 0x00U, /**< Invalid Configuration */ + NFC_HOST_CE_A_EMULATION = 0x01U, /**< Configure parameters for Type A + card emulation from host */ + NFC_HOST_CE_B_EMULATION = 0x02U, /**< Configure parameters for Type B + card emulation from host */ + NFC_B_PRIME_EMULATION = 0x03U, /**< Configure parameters for Type B' + card emulation from host */ + NFC_FELICA_EMULATION = 0x04U, /**< Configure parameters for Type F + card emulation from host */ + NFC_MIFARE_EMULATION = 0x06U, /**< Configure parameters for MIFARE + card emulation - For Future Use */ + NFC_SMARTMX_EMULATION = 0x07U, /**< Configure parameters for SmartMX + */ + NFC_UICC_EMULATION = 0x08U /**< Configure parameters for UICC + emulation */ +}phHal_eEmulationType_t; + +#if 0 +/** \ingroup grp_hal_nfct + * + * \if hal + * \brief Information for Target Mode Start-Up + * \else + * \brief HAL-Specific + * \endif + * + * The Target Information Structure required to start Target mode. + * It contains all the information for the Target mode. + * + * \note None. + * + */ + +typedef struct phHal_sTargetInfo +{ + uint8_t enableEmulation; + phHal_sNfcIPCfg_t targetConfig; +} phHal_sTargetInfo_t; +#endif + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Mode of operation for SmartMX +* \else +* \brief HAL-Specific +* \endif +* +* This enumeration is used to choose the mode of operation for the SmartMx Module. +* Default static configuration at initialization time. +* \note None. +*/ + +typedef enum phHal_eSmartMX_Mode{ + eSmartMx_Wired = 0x00U, /* SmartMX is in Wired Mode */ + eSmartMx_Default, /* SmartMX is in Default Configuration Mode */ + eSmartMx_Virtual, /* SmartMx in the Virutal Mode */ + eSmartMx_Off /* SmartMx Feature is Switched off */ +} phHal_eSmartMX_Mode_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Mode of operation for SWP +* \else +* \brief HAL-Specific +* \endif +* +* This enumeration is used to choose the mode of operation for the SWP Link +* for UICC Module. Default static configuration at initialization time. +* \note None. +*/ + +typedef enum phHal_eSWP_Mode{ + eSWP_Switch_Off = 0x00U, /* SWP Link is Switched off */ + eSWP_Switch_Default, /* SWP is in Default Configuration Mode */ + eSWP_Switch_On /* SWP Link is Switched on */ +} phHal_eSWP_Mode_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Information for the Configuring the SmartMX +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sSmartMX_Cfg structure holds the information +* to configure the SmartMX Module in the NFC Device. +* +* \note None. +*/ + + +typedef struct phHal_sSmartMX_Cfg +{ + uint8_t enableEmulation; + uint8_t lowPowerMode; + phHal_eSmartMX_Mode_t smxMode; +}phHal_sSmartMX_Cfg_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Information for the Configuring the UICC +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sUiccEmuCfg structure holds the information +* to configure the UICC Host. +* +* \note None. +*/ + + +typedef struct phHal_sUiccEmuCfg +{ + uint8_t enableUicc; + uint8_t uiccEmuSupport; + uint8_t uiccReaderSupport; + uint8_t lowPowerMode; + /* TODO: This will be updated later */ +}phHal_sUiccEmuCfg_t; + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Information for the Configuring the Type A Host Emulation Feature +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sHostEmuCfg_A structure holds the information +* to configure the Host Emulation for Type A. +* +* \note None. +*/ + +typedef struct phHal_sHostEmuCfg_A +{ + uint8_t enableEmulation; + phNfc_sIso14443AInfo_t hostEmuCfgInfo; + uint8_t enableCID; +}phHal_sHostEmuCfg_A_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Information for the Configuring the Type B Host Emulation Feature +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sHostEmuCfg_B structure holds the information +* to configure the Host Emulation for Type B. +* +* \note None. +*/ + +typedef struct phHal_sHostEmuCfg_B +{ + uint8_t enableEmulation; + phNfc_sIso14443BInfo_t hostEmuCfgInfo; +}phHal_sHostEmuCfg_B_t; + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Information for the Configuring the Felica Host Emulation Feature +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sHostEmuCfg_F structure holds the information +* to configure the Felica Host Emulation. +* +* \note None. +*/ + + +typedef struct phHal_sHostEmuCfg_F +{ + uint8_t enableEmulation; +}phHal_sHostEmuCfg_F_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Information for the Configuring the Emulation +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sEmulationCfg structure holds the information +* required for the device to act as a Tag or NFCIP1 Target. +* +* \note phHal_sHostEmuCfg_F_t Type F emulation is not presently supported +* is reserved for future use. +*/ + +typedef struct phHal_sEmulationCfg +{ + phHal_HostType_t hostType; + phHal_eEmulationType_t emuType; + union phHal_uEmuConfig + { + phHal_sSmartMX_Cfg_t smartMxCfg; + phHal_sHostEmuCfg_A_t hostEmuCfg_A; + phHal_sHostEmuCfg_B_t hostEmuCfg_B; + phHal_sHostEmuCfg_F_t hostEmuCfg_F; + phHal_sUiccEmuCfg_t uiccEmuCfg; + }config; +}phHal_sEmulationCfg_t; + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Information for the Configuring the Reader parameters +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sReaderCfg structure holds the information +* to configure the Reader A or Reader B parameters. +* +* \note None. +*/ + +typedef struct phHal_sReaderCfg +{ + phHal_eRFDevType_t readerType; + union phHal_uReaderCfg + { + phHal_sIso14443ACfg_t Iso14443ACfg; + phHal_sIso14443BCfg_t Iso14443BCfg; + }config; +}phHal_sReaderCfg_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Information for Configuring the Protected Mode for +* the Secure Elements. +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_sSEProtectionCfg structure holds the +* information to configure the Secure Element Protection configuration. +* +* \note None. +*/ + +typedef struct phHal_sSEProtectionCfg +{ + uint8_t mode; +}phHal_sSEProtectionCfg_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Poll configuration structure +* \else +* \brief HAL-Specific +* \endif +* +* The Poll configuration structure holds information about the +* enabling the the type of discovery required by the application. This +* structure is the input parameter for the discovery call +* +* \note All members of this structure are input parameters [out]. +* +* \if hal +* \sa \ref phHal4Nfc_Connect, \ref phHal4Nfc_ConfigParameters, +* \ref phHal_eP2PMode_t and \ref phHal4Nfc_Disconnect. +* \endif +* +*/ + +typedef phNfc_sADD_Cfg_t phHal_sADD_Cfg_t; + + +/** \ingroup grp_hal_common +* +* \if hal +* \brief Configuration information. +* \else +* \brief HAL-Specific +* \endif +* +* The \ref phHal_uConfig structure holds the information +* required for Configuring the Device. +* +* \note None. +*/ + + +typedef union phHal_uConfig +{ + phHal_sEmulationCfg_t emuConfig; + phHal_sNfcIPCfg_t nfcIPConfig; /**< Gives the information about + * the General Bytes for NFC-IP + * Communication. + */ + phHal_sReaderCfg_t readerConfig; + phHal_sSEProtectionCfg_t protectionConfig; +}phHal_uConfig_t; + + +#endif + +/* EOF */ diff --git a/libnfc-nxp/phNfcInterface.h b/libnfc-nxp/phNfcInterface.h new file mode 100644 index 0000000..fdae2ed --- /dev/null +++ b/libnfc-nxp/phNfcInterface.h @@ -0,0 +1,422 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + + +/*! +* ============================================================================= +* \file phNfcInterface.h +* \brief Generic Interface Layer Function Definitions. +* +* Project: NFC-FRI-1.1 +* +* $Date: Thu Feb 11 19:01:36 2010 $ +* $Author: ing04880 $ +* $Revision: 1.42 $ +* $Aliases: NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ +* +* ============================================================================= +*/ + +#ifndef PHNFCINTERFACE_H /* */ +#define PHNFCINTERFACE_H /* */ + +/** +* \name NFC Inteface +* +* File: \ref phNfcInterface.h +* +*/ + +/*@{*/ +#define PHNFCINTERFACE_FILEREVISION "$Revision: 1.42 $" /**< \ingroup grp_file_attributes */ +#define PHNFCINTERFACE_FILEALIASES "$Aliases: NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +/* +################################################################################ +***************************** Header File Inclusion **************************** +################################################################################ +*/ + +#include +#include + + +/* +################################################################################ +****************************** Macro Definitions ******************************* +################################################################################ +*/ + +#define NFC_FSM_IN_PROGRESS 0x01U +#define NFC_FSM_COMPLETE 0x00U + +#define NFC_FSM_CURRENT 0x00U +#define NFC_FSM_NEXT 0x01U + +/* NFC Notification Types */ + +#define NFC_NOTIFY_INIT_COMPLETED 0x01 +#define NFC_NOTIFY_INIT_FAILED 0xF1 + +#define NFC_NOTIFY_DEINIT_COMPLETED 0x02 +#define NFC_NOTIFY_DEINIT_FAILED 0xF2 + +#define NFC_NOTIFY_EVENT 0x70 + +#define NFC_NOTIFY_DEVICE_ACTIVATED 0x82 +#define NFC_NOTIFY_DEVICE_DEACTIVATED 0x83 + +#define NFC_NOTIFY_SEND_COMPLETED 0x03 +#define NFC_NOTIFY_SEND_ERROR 0xF3 + +#define NFC_NOTIFY_RECV_COMPLETED 0x04 +#define NFC_NOTIFY_RECV_ERROR 0xF4 +#define NFC_NOTIFY_RECV_EVENT 0x74 +#define NFC_NOTIFY_RECV_CANCELLED 0x34 + +#define NFC_NOTIFY_TRANSCEIVE_COMPLETED 0x05 +#define NFC_NOTIFY_TRANSCEIVE_ERROR 0xF5 + +#define NFC_NOTIFY_POLL_ENABLED 0x06 +#define NFC_NOTIFY_POLL_RESTARTED 0x16 +#define NFC_NOTIFY_POLL_DISABLED 0x26 +#define NFC_NOTIFY_CONFIG_SUCCESS 0x36 +#define NFC_NOTIFY_CONFIG_ERROR 0xF6 + +#define NFC_NOTIFY_TARGET_DISCOVERED 0x10 +#define NFC_NOTIFY_DISCOVERY_ERROR 0xFA +#define NFC_NOTIFY_TARGET_RELEASED 0x11 +#define NFC_NOTIFY_TARGET_CONNECTED 0x12 +#define NFC_NOTIFY_TARGET_PRESENT 0x13 +#define NFC_NOTIFY_TARGET_REACTIVATED 0x14 +#define NFC_NOTIFY_CONNECT_FAILED 0xFC +#define NFC_NOTIFY_TARGET_DISCONNECTED 0x15 +#define NFC_NOTIFY_DISCONNECT_FAILED 0xFD + +#define NFC_NOTIFY_TRANSACTION 0x07 + +#define NFC_NOTIFY_RESULT 0x08 + +#define NFC_NOTIFY_DEVICE_ERROR 0xFEU +#define NFC_NOTIFY_ERROR 0xFFU + + +#define BYTE_SIZE 0x08U +#define BYTE_MASK 0xFFU +/* HCI GET and SET BITS Macros */ +#define MASK_BITS8(p,l) \ + ( ( (((uint8_t)(p))+((uint8_t)(l)))<=BYTE_SIZE )? \ + (~(0xFFU<<((p)+(l))) & (0xFFU<<(p))):(0U) ) +#ifdef MASK_BITS +#define GET_BITS8(num,p,l) \ + ( ((((uint8_t)(p))+((uint8_t)(l)))<=BYTE_SIZE)? \ + (((num)& (MASK_BITS8(p,l)))>>(p)):(0U) ) +#else +#define GET_BITS8(num,p,l) \ + ( ((((p)+(l))<=BYTE_SIZE))? \ + (((num)>>(p))& (~(0xFFU<<(l)))):(0U) ) +#endif +#define SET_BITS8(num,p,l,val) \ + ( ((((uint8_t)(p))+((uint8_t)(l)))<=BYTE_SIZE)? \ + (((num)& (~MASK_BITS8(p,l)))|((val)<<(p))):(0U)) + +/* +################################################################################ +******************** Enumeration and Structure Definition ********************** +################################################################################ +*/ + + +enum phNfcIF_eExecution{ + NFC_EXEC_NORMAL = 0x00, /**< Normal Execution Sequence */ + NFC_EXEC_CALLBACK = 0x01, /**< Callback Execution Sequence */ + NFC_EXEC_UNKNOWN = 0xFF /**< Callback Execution Sequence */ +}; + + +typedef enum phNfc_eModeType{ + MODE_ON = 0x00U, /**< Switches the particular feature ON*/ + MODE_OFF /**< Switches the particular feature OFF*/ +}phNfc_eModeType_t; + +/** + * State Structure to hold the State Information + * + * This structure holds the state Information of a specified + * Layer . + * + */ + +typedef struct phNfc_sState +{ + uint8_t cur_state; + uint8_t transition; + uint8_t next_state; + /* uint8_t event; */ + +}phNfc_sState_t; + + + +/** + * Transaction Completion Information Structure + * + * This structure holds the completion callback information of the + * transaction passed from the lower layer to the upper layer + * along with the completion callback. + */ + +typedef struct phNfc_sTransactionInfo +{ + /* Returns the status of the Transaction Completion routine */ + NFCSTATUS status; + /* Indicates the Type of the Transaction */ + uint8_t type; + /* To contain more Transaction Notification specific info */ + void *info; + /* The data response from the Transaction */ + uint8_t *buffer; + /* The size of the data response from the Transaction */ + uint16_t length; +}phNfc_sTransactionInfo_t; + +/** + * Notification Information Structure + * + * This structure holds the notification callback information passed from + * the lower layer to the upper layer along with the notification callback. + */ + +typedef struct phNfc_sCompletionInfo +{ + /* Returns the status of the completion routine */ + NFCSTATUS status; + + /* Indicates the Type of the Information + * associated with the completion + */ + uint8_t type; + + /* To contain more completion specific info */ + void *info; + +}phNfc_sCompletionInfo_t; + + +/** + * Notification Information + * + */ +typedef struct phNfc_sNotificationInfo +{ + /* Returns the status of the Notification routine */ + NFCSTATUS status; + /* Indicates the Type of the Notification */ + phHal_eNotificationType_t type; + /* To contain more Notification specific info */ + void *info; + +}phNfc_sNotificationInfo_t; + + +/* +################################################################################ +********************* Callback Function Type Definition ************************ +################################################################################ +*/ + +/** +* Interface Notification Callback +* +* This callback notifies the occurrance of an event in the Lower Interface. +* +* \param [in] pContext Context for the Callback Function +* \param [in] pHwRef Pointer to the Hardware Reference +* \param [in] type Type of the Notification sent +* \param [out] pInfo Pointer to the Transaction Information Structure +* which contains the Status of the operation, data +* obtained or sent and size of the data sent or received +*/ + +typedef void (*pphNfcIF_Notification_CB_t) ( + void *pContext, + void *pHwRef, + uint8_t type, + void *pInfo + ); + +/** +* asynchronous Interface Transaction Completion callback +* +* This callback signals the completion of the asynchronous send or receive +* operation. The number of bytes sent or recieved is returned back. +* +* \param [in] pContext Context for the Callback Function +* \param [in] pHwRef Pointer to the Hardware Reference +* \param [out] pInfo Pointer to the Transaction Information Structure +* which contains the Status of the operation, data +* obtained or sent and size of the data sent or received +*/ + +typedef void (*pphNfcIF_Transact_Completion_CB_t) ( + void *pContext, + void *pHwRef, + phNfc_sTransactionInfo_t *pInfo + ); + +/* +################################################################################ +********************** Generic Interface Function Prototype ******************** +################################################################################ +*/ + +/** + * Generic NFC Interface Function Type . + * + * \param [in] pContext Context pointer for the Generic Interface. + * \param [in] pHwRef pointer for the device interface link information. + */ + +typedef NFCSTATUS (*pphNfcIF_Interface_t) ( + void *pContext, + void *pHwRef + ); +/** + * Data Transaction between the lower layer interface + * + * Sends or Receives the given amount of data to the lower layer. + * The call returns immediately and the registered callback is + * called when all data has been written. + *

+ * + * @note If the interface is not initialized the function does nothing. + * + * \param [in] pContext Context pointer for sending the data. + * \param [in] pHwRef pointer for the device interface link information. + * \param[in] data pointer to data buffer containing the data to be sent or + * to be received. The data pointer is valid at least until + * the registered callback is called. + * \param[in] length length of the data to be sent or to be received. + */ + +typedef NFCSTATUS (*pphNfcIF_Transact_t) ( + void *pContext, + void *pHwRef, + uint8_t *data, + uint16_t length + ); + + +/** + * Generic Interface structure with the Lower Layer + * + * This structure holds the context and function pointers of all functions + * required to interface with the Lower Layers. + */ + +typedef struct phNfc_sLowerIF +{ + void *pcontext; + pphNfcIF_Interface_t init; + pphNfcIF_Interface_t release; + pphNfcIF_Transact_t send; + pphNfcIF_Transact_t receive; + pphNfcIF_Transact_t receive_wait; + pphNfcIF_Interface_t transact_abort; + pphNfcIF_Interface_t unregister; +} phNfc_sLowerIF_t,*pphNfc_sLowerIF_t; + + +/** + * Generic Callback interface structure for the Lower layer. + * + * This structure holds the callback function pointers of the functions that + * performs the completion of a particular operation. These functions are used + * by the Lower Layer interface to convey the completion of an operation. + */ + +typedef struct phNfcIF_sCallBack +{ + /** +#include + +/*=========== CONSTANTS ===========*/ + +/** + * \name LLCP default parameters. + * + * Definitions for use when wanting to use default LLCP parameter values. + * + */ + /*@{*/ +#define PHFRINFC_LLCP_MIU_DEFAULT 128 /**< Default MIU value (in bytes).*/ +#define PHFRINFC_LLCP_WKS_DEFAULT 1 /**< Default WKS value (bitfield).*/ +#define PHFRINFC_LLCP_LTO_DEFAULT 10 /**< Default LTO value (in step of 10ms).*/ +#define PHFRINFC_LLCP_RW_DEFAULT 1 /**< Default RW value (in frames).*/ +#define PHFRINFC_LLCP_OPTION_DEFAULT 0 /**< Default OPTION value (in frames).*/ +#define PHFRINFC_LLCP_MIUX_DEFAULT 0 /**< Default MIUX value (in bytes) */ +#define PHFRINFC_LLCP_MIUX_MAX 0x7FF /**< Max MIUX value (in bytes) */ +#define PHFRINFC_LLCP_PDU_HEADER_MAX 3 /**< Max size of PDU header (in bytes) */ +#define PHFRINFC_LLCP_SN_MAX_LENGTH 255 /**< Max length value for the Service Name */ +#define PHFRINFC_LLCP_RW_MAX 15 /**< Max RW value (in frames).*/ +/*@}*/ + +/** + * \name LLCP config parameters. + * + * Definitions used for internal LLCP configuration. + * + */ + /*@{*/ +#define PHFRINFC_LLCP_NB_SOCKET_MAX 10 /**< Max.number of simultaneous sockets */ +#define PHFRINFC_LLCP_SNL_RESPONSE_MAX 256 /**< Max.number of simultaneous discovery requests */ +/*@}*/ + +/** + * \internal + * \name Fixed value for ERROR op code. + * + */ +/*@{*/ +#define PHFRINFC_LLCP_ERR_DISCONNECTED 0x00 +#define PHFRINFC_LLCP_ERR_FRAME_REJECTED 0x01 +#define PHFRINFC_LLCP_ERR_BUSY_CONDITION 0x02 +#define PHFRINFC_LLCP_ERR_NOT_BUSY_CONDITION 0x03 + +/** + * \internal + * \name Fixed value for DM op code. + * + */ +/*@{*/ +#define PHFRINFC_LLCP_DM_OPCODE_DISCONNECTED 0x00 +#define PHFRINFC_LLCP_DM_OPCODE_SAP_NOT_ACTIVE 0x01 +#define PHFRINFC_LLCP_DM_OPCODE_SAP_NOT_FOUND 0x02 +#define PHFRINFC_LLCP_DM_OPCODE_CONNECT_REJECTED 0x03 +#define PHFRINFC_LLCP_DM_OPCODE_CONNECT_NOT_ACCEPTED 0x20 +#define PHFRINFC_LLCP_DM_OPCODE_SOCKET_NOT_AVAILABLE 0x21 + + +/*========== ENUMERATES ===========*/ + +/* Enum reperesents the different LLCP Link status*/ +typedef enum phFriNfc_LlcpMac_eLinkStatus +{ + phFriNfc_LlcpMac_eLinkDefault, + phFriNfc_LlcpMac_eLinkActivated, + phFriNfc_LlcpMac_eLinkDeactivated +}phFriNfc_LlcpMac_eLinkStatus_t; + +/* Enum represents the different Socket types */ +typedef enum phFriNfc_LlcpTransport_eSocketType +{ + phFriNfc_LlcpTransport_eDefaultType, + phFriNfc_LlcpTransport_eConnectionOriented, + phFriNfc_LlcpTransport_eConnectionLess +}phFriNfc_LlcpTransport_eSocketType_t; + + +/*========== STRUCTURES ===========*/ + +typedef struct phFriNfc_LlcpTransport_sSocketOptions +{ + /** The remote Maximum Information Unit Extension (NOTE: this is MIUX, not MIU !)*/ + uint16_t miu; + + /** The Receive Window size (4 bits)*/ + uint8_t rw; + +}phFriNfc_LlcpTransport_sSocketOptions_t; + +typedef struct phFriNfc_Llcp_sLinkParameters +{ + /** The remote Maximum Information Unit (NOTE: this is MIU, not MIUX !)*/ + uint16_t miu; + + /** The remote Well-Known Services*/ + uint16_t wks; + + /** The remote Link TimeOut (in 1/100s)*/ + uint8_t lto; + + /** The remote options*/ + uint8_t option; + +} phFriNfc_Llcp_sLinkParameters_t; + +#endif + +/* EOF */ diff --git a/libnfc-nxp/phNfcStatus.h b/libnfc-nxp/phNfcStatus.h new file mode 100644 index 0000000..01f48fb --- /dev/null +++ b/libnfc-nxp/phNfcStatus.h @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phNfcStatus.h + * \brief NFC Status Values - Function Return Codes + * + * Project: NFC MW / HAL + * + * $Date: Wed Apr 29 16:28:21 2009 $ + * $Author: ing04880 $ + * $Revision: 1.31 $ + * $Aliases: NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PHNFCSTATUS_H /* */ +#define PHNFCSTATUS_H/* */ + +#ifndef PH_FRINFC_EXCLUDE_FROM_TESTFW /* */ + +/** + * \name NFC Status + * + * File: \ref phNfcStatus.h + * + *\defgroup grp_retval ERROR Status Codes + */ +/*@{*/ +#define PHNFCSTATUS_FILEREVISION "$Revision: 1.31 $" /**< \ingroup grp_file_attributes */ +#define PHNFCSTATUS_FILEALIASES "$Aliases: NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +#endif /* PH_FRINFC_EXCLUDE_FROM_TESTFW */ + +#include + +/* Internally required by \ref PHNFCSTVAL. */ +#define PHNFCSTSHL8 (8U) +/* Required by \ref PHNFCSTVAL. */ +#define PHNFCSTBLOWER ((NFCSTATUS)(0x00FFU)) + +/** + * \name NFC Status Composition Macro + * + * This is the macro which must be used to compose status values. + * + * \param[in] phNfcCompID Component ID, as defined in \ref phNfcCompId.h . + * \param[in] phNfcStatus Status values, as defined in \ref phNfcStatus.h . + * + * \note The macro is not required for the \ref NFCSTATUS_SUCCESS value. This is the only + * return value to be used directly. + * For all other values it shall be used in assigment and conditional statements e.g.: + * - NFCSTATUS status = PHNFCSTVAL(phNfcCompID, phNfcStatus); ... + * - if (status == PHNFCSTVAL(phNfcCompID, phNfcStatus)) ... + * + */ +#define PHNFCSTVAL(phNfcCompID, phNfcStatus) \ + ( ((phNfcStatus) == (NFCSTATUS_SUCCESS)) ? (NFCSTATUS_SUCCESS) : \ + ( (((NFCSTATUS)(phNfcStatus)) & (PHNFCSTBLOWER)) | \ + (((uint16_t)(phNfcCompID)) << (PHNFCSTSHL8)) ) ) /**< \ingroup grp_retval + Use this macro for return value composition. */ +#define PHNFCSTATUS(phNfcStatus) ((phNfcStatus) & 0x00FFU) +#define PHNFCCID(phNfcStatus) (((phNfcStatus) & 0xFF00U)>>8) + +/** + * \name Status Codes + * + * Generic Status codes for the NFC components. Combined with the Component ID + * they build the value (status) returned by each + * function. Some Specific E.g.:\n + *

    + *
  • \ref grp_comp_id "Component ID" - e.g. 0x10, plus
  • + *
  • status code as listed in this file - e.g. 0x03
  • + *
+ * result in a status value of 0x0003. + * + * \note The \ref grp_comp_id "Component ID" used for return codes + must not be \ref CID_NFC_NONE + * except for the value \ref NFCSTATUS_SUCCESS. + */ +/*@{*/ + +/** \ingroup grp_retval + The function indicates successful completion. */ +#define NFCSTATUS_SUCCESS (0x0000) + +/** \ingroup grp_retval + At least one paramter could not be properly interpreted. */ +#define NFCSTATUS_INVALID_PARAMETER (0x0001) + +/** \ingroup grp_retval + The buffer provided by the caller is too small. */ +#define NFCSTATUS_BUFFER_TOO_SMALL (0x0003) + +/** \ingroup grp_retval + Device specifier/handle value is invalid for the operation. */ +#define NFCSTATUS_INVALID_DEVICE (0x0006) + +/** \ingroup grp_retval + The function executed successfully but could have returned + more information than space provided by the caller. */ +#define NFCSTATUS_MORE_INFORMATION (0x0008) + +/** \ingroup grp_retval + No response from the remote device received: Time-out.*/ +#define NFCSTATUS_RF_TIMEOUT (0x0009) + +/** \ingroup grp_retval + RF Error during data transaction with the remote device.*/ +#define NFCSTATUS_RF_ERROR (0x000A) + +/** \ingroup grp_retval + Not enough resources (e.g. allocation failed.). */ +#define NFCSTATUS_INSUFFICIENT_RESOURCES (0x000C) + +/** \ingroup grp_retval + A non-blocking function returns this immediately to indicate + that an internal operation is in progress. */ +#define NFCSTATUS_PENDING (0x000D) + +/** \ingroup grp_retval + A board communication error occurred + (e.g. configuration went wrong). */ +#define NFCSTATUS_BOARD_COMMUNICATION_ERROR (0x000F) + +/** \ingroup grp_retval + Invalid State of the particular state machine + */ +#define NFCSTATUS_INVALID_STATE (0x0011) + + +/** \ingroup grp_retval + This Layer is Not initialised, hence initialisation required. + */ +#define NFCSTATUS_NOT_INITIALISED (0x0031) + + +/** \ingroup grp_retval + The Layer is already initialised, hence initialisation repeated. + */ +#define NFCSTATUS_ALREADY_INITIALISED (0x0032) + + +/** \ingroup grp_retval + Feature not supported . */ +#define NFCSTATUS_FEATURE_NOT_SUPPORTED (0x0033) + +/** \ingroup grp_retval + The Unregistration command has failed because the user wants to unregister on + an element for which he was not registered*/ +#define NFCSTATUS_NOT_REGISTERED (0x0034) + + +/** \ingroup grp_retval + The Registration command has failed because the user wants to register on + an element for which he is already registered*/ +#define NFCSTATUS_ALREADY_REGISTERED (0x0035) + +/** \ingroup grp_retval + Single Tag with Multiple + Protocol support detected. */ +#define NFCSTATUS_MULTIPLE_PROTOCOLS (0x0036) + +/** \ingroup grp_retval + Feature not supported . */ +#define NFCSTATUS_MULTIPLE_TAGS (0x0037) + +/** \ingroup grp_retval + A DESELECT event has occurred. */ +#define NFCSTATUS_DESELECTED (0x0038) + +/** \ingroup grp_retval + A RELEASE event has occurred. */ +#define NFCSTATUS_RELEASED (0x0039) + +/** \ingroup grp_retval + The operation is currently not possible or not allowed */ +#define NFCSTATUS_NOT_ALLOWED (0x003A) + +/** \ingroup grp_retval + The sytem is busy with the previous operation. +*/ +#define NFCSTATUS_BUSY (0x006F) + + +/* NDEF Mapping error codes */ + +/** \ingroup grp_retval + The remote device (type) is not valid for this request. */ +#define NFCSTATUS_INVALID_REMOTE_DEVICE (0x001D) + +/** \ingroup grp_retval + Smart tag functionality not supported */ +#define NFCSTATUS_SMART_TAG_FUNC_NOT_SUPPORTED (0x0013) + +/** \ingroup grp_retval + Read operation failed */ +#define NFCSTATUS_READ_FAILED (0x0014) + +/** \ingroup grp_retval + Write operation failed */ +#define NFCSTATUS_WRITE_FAILED (0x0015) + +/** \ingroup grp_retval + Non Ndef Compliant */ +#define NFCSTATUS_NO_NDEF_SUPPORT (0x0016) + +/** \ingroup grp_retval + Could not proceed further with the write operation: reached card EOF*/ +#define NFCSTATUS_EOF_NDEF_CONTAINER_REACHED (0x001A) + +/** \ingroup grp_retval + Incorrect number of bytes received from the card*/ +#define NFCSTATUS_INVALID_RECEIVE_LENGTH (0x001B) + +/** \ingroup grp_retval + The data format/composition is not understood/correct. */ +#define NFCSTATUS_INVALID_FORMAT (0x001C) + + +/** \ingroup grp_retval + There is not sufficient storage available. */ +#define NFCSTATUS_INSUFFICIENT_STORAGE (0x001F) + +/** \ingroup grp_retval + The Ndef Format procedure has failed. */ +#define NFCSTATUS_FORMAT_ERROR (0x0023) + + +/* + * Macros Required for FRI Stack +NFCSTATUS_INVALID_PARAMETER +NFCSTATUS_CMD_ABORTED +NFCSTATUS_FORMAT_STATUS +NFSTATUS_SUCCESS +NFCSTATUS_INVALID_REMOTE_DEVICE +NFCSTATUS_PENDING +NFCSTATUS_EOF_NDEF_CONTAINED_REACHED +NFCSTATUS_NO_NDEF_SUPPORT +NFCSTATUS_SMART_TAG_FUNC_NOT_SUPPORTED +NFCSTATUS_READ_FAILED +NFCSTATUS_WRITE_FAILED +NFCSTATUS_INVALID_RECEIVE_LENGTH +NFCSTATUS_BUFFER_TOO_SMALL +NFCSTATUS_NODE_NOT_FOUND +*/ + + +/* 0x70 to 0xCF Values are Component Specific Error Values */ + + +/** \ingroup grp_retval + Max number of Status Codes*/ +#define NFCSTATUS_FAILED (0x00FF) + +/*@}*/ + +#ifdef RFU_STATUS_CODES /* To Be Removed later */ + +/** \ingroup grp_retval + The function/command has been aborted. */ +#define NFCSTATUS_CMD_ABORTED (0x0002) + +/** \ingroup grp_retval + * Repeated call of the connecting function is not allowed. + * \if hal + * \sa \ref phHalNfc_Connect + * \endif */ +#define NFCSTATUS_ALREADY_CONNECTED (0x0004) + +/** \ingroup grp_retval + * Calling the polling function is not allowed when remote device + * are allready connected. + * \if hal + * \sa \ref phHalNfc_Poll + * \endif */ +#define NFCSTATUS_MULTI_POLL_NOT_SUPPORTED (0x0005) + + +/** \ingroup grp_retval + No target found after poll.*/ +#define NFCSTATUS_NO_DEVICE_FOUND (0x000A) + +/** \ingroup grp_retval + No target found after poll.*/ +#define NFCSTATUS_NO_TARGET_FOUND (0x000A) + +/** \ingroup grp_retval + Attempt to disconnect a not connected remote device. */ +#define NFCSTATUS_NO_DEVICE_CONNECTED (0x000B) + +/** \ingroup grp_retval + External RF field detected. */ +#define NFCSTATUS_EXTERNAL_RF_DETECTED (0x000E) + +/** \ingroup grp_retval + Message is not allowed by the state machine + (e.g. configuration went wrong). */ +#define NFCSTATUS_MSG_NOT_ALLOWED_BY_FSM (0x0010) + +/** \ingroup grp_retval + No access has been granted. */ +#define NFCSTATUS_ACCESS_DENIED (0x001E) + +/** \ingroup grp_retval + No registry node matches the specified input data. */ +#define NFCSTATUS_NODE_NOT_FOUND (0x0017) + +/** \ingroup grp_retval + The current module is busy ; one might retry later */ +#define NFCSTATUS_SMX_BAD_STATE (0x00F0) + + +/** \ingroup grp_retval + The Abort mechanism has failed for unexpected reason: user can try again*/ +#define NFCSTATUS_ABORT_FAILED (0x00F2) + + +/** \ingroup grp_retval + The Registration command has failed because the user wants to register as target + on a operating mode not supported*/ +#define NFCSTATUS_REG_OPMODE_NOT_SUPPORTED (0x00F5) + + +#endif + + +#endif /* PHNFCSTATUS_H */ + diff --git a/libnfc-nxp/phNfcTypes.h b/libnfc-nxp/phNfcTypes.h new file mode 100644 index 0000000..0bba933 --- /dev/null +++ b/libnfc-nxp/phNfcTypes.h @@ -0,0 +1,1109 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* + * \file phNfcTypes.h + * \brief Basic type definitions. + * + * Project: NFC MW / HAL + * + * $Date: Thu Jun 25 21:24:53 2009 $ + * $Author: ing04880 $ + * $Revision: 1.13 $ + * $Aliases: NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#ifndef PHNFCTYPES /* */ +#define PHNFCTYPES /* */ + +/** + * \name NFC Types + * + * File: \ref phNfcTypes.h + * + */ +/*@{*/ +#define PHNFCTYPES_FILEREVISION "$Revision: 1.13 $" /**< \ingroup grp_file_attributes */ +#define PHNFCTYPES_FILEALIASES "$Aliases: NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $" /**< \ingroup grp_file_attributes */ +/*@}*/ + +#ifndef _WIN32 +#include +#else +#include +#include +#define snprintf _snprintf + +#ifndef linux +/** + * \name Basic Type Definitions + * + * Constant-length-type definition ('C99). + * + */ +/*@{*/ +#ifndef __int8_t_defined /* */ +#define __int8_t_defined /* */ +typedef signed char int8_t; /**< \ingroup grp_nfc_common + 8 bit signed integer */ +#endif + +#ifndef __int16_t_defined /* */ +#define __int16_t_defined /* */ +typedef signed short int16_t; /**< \ingroup grp_nfc_common + 16 bit signed integer */ +#endif + +#ifndef __stdint_h +#ifndef __int32_t_defined /* */ +#define __int32_t_defined /* */ +typedef signed long int32_t; /**< \ingroup grp_nfc_common + 32 bit signed integer */ +#endif +#endif + +#ifndef __uint8_t_defined /* */ +#define __uint8_t_defined /* */ +typedef unsigned char uint8_t; /**< \ingroup grp_nfc_common + 8 bit unsigned integer */ +#endif + +#ifndef __uint16_t_defined /* */ +#define __uint16_t_defined /* */ +typedef unsigned short uint16_t; /**< \ingroup grp_nfc_common + 16 bit unsigned integer */ +#endif + +#ifndef __stdint_h +#ifndef __uint32_t_defined /* */ +#define __uint32_t_defined /* */ +typedef unsigned long uint32_t; /**< \ingroup grp_nfc_common + 32 bit unsigned integer */ +#endif +#endif + +#endif /* linux */ + +#endif /* _WIN32 */ + +#ifndef TRUE +#define TRUE (0x01) /**< \ingroup grp_nfc_common + Logical True Value */ +#endif + +#ifndef FALSE +#define FALSE (0x00) /**< \ingroup grp_nfc_common + Logical False Value */ +#endif + +typedef uint8_t utf8_t; /**< \ingroup grp_nfc_common + UTF8 Character String */ + +typedef uint8_t bool_t; /**< \ingroup grp_nfc_common + boolean data type */ + +typedef uint16_t NFCSTATUS; /**< \ingroup grp_nfc_common + NFC return values + \ref phNfcStatus.h for different status + values */ + +#ifndef NULL +#define NULL ((void *)0) +#endif + +/* This Macro to be used to resolve Unused and unreference + * compiler warnings. + */ + +#define PHNFC_UNUSED_VARIABLE(x) (void)x + +/*@}*/ + +/** + * + * \name HAL Overall Definitions + * + * Definitions applicable to a variety of purposes and functions/features. + * + */ + /*@{*/ + +#define PHHAL_COMMON_MAX_STRING_LENGTH 0x40U /**< \ingroup grp_hal_common + Maximum vendor name length in bytes. */ +#define PHHAL_UNKNOWN_DEVICE_TYPE 0x00U /**< \ingroup grp_hal_common + Unknown device type. */ +#define PHHAL_SERIAL_DEVICE 0x01U /**< \ingroup grp_hal_common + Serial device type. */ +#define PHHAL_USB_DEVICE 0x02U /**< \ingroup grp_hal_common + USB device type. */ +#define PHHAL_I2C_DEVICE 0x03U /**< \ingroup grp_hal_common + I2C device type. */ +#define PHHAL_SPI_DEVICE 0x04U /**< \ingroup grp_hal_common + SPI device type. */ +#define PHHAL_PARALLEL_DEVICE 0x05U /**< \ingroup grp_hal_common + Parallel device type. */ +#define PHHAL_NFCID_LENGTH 0x0AU /**< \ingroup grp_hal_common + Maximum length of NFCID 1..3. */ + +#define PHHAL_MAX_DATASIZE 0xFBU /* 256 * Maximum Data size sent + * by the HAL + */ + +#define PHHAL_ATQA_LENGTH 0x02U /**< ATQA length */ +#define PHHAL_MAX_UID_LENGTH 0x0AU /**< Maximum UID length expected */ +#define PHHAL_MAX_ATR_LENGTH 0x30U /**< Maximum ATR_RES (General Bytes) + * length expected */ + +#define PHHAL_ATQB_LENGTH 0x0BU /**< ATQB length */ + +#define PHHAL_PUPI_LENGTH 0x04U /**< PUPI length */ +#define PHHAL_APP_DATA_B_LENGTH 0x04U /**< Application Data length for Type B */ +#define PHHAL_PROT_INFO_B_LENGTH 0x03U /**< Protocol info length for Type B */ +#define PHHAL_FEL_SYS_CODE_LEN 0x02U /**< Felica System Code Length */ +#define PHHAL_FEL_ID_LEN 0x08U /**< Felica current ID Length */ +#define PHHAL_FEL_PM_LEN 0x08U /**< Felica current PM Length */ +#define PHHAL_15693_UID_LENGTH 0x08U /**< Length of the Inventory bytes for + ISO15693 Tag */ + +#define VENDOR_NAME_LEN 0x14U +#define MAX_TRANSFER_UNIT 0x21U +#define SESSIONID_SIZE 0x08U +#define MAX_AID_LEN 0x10U +#define MAX_UICC_PARAM_LEN 0xFFU + +#define MIFARE_BITMASK 0x08U +#define ISO_14443_BITMASK 0x20U +#define ISO_14443_DETECTED 0x20U +#define NFCIP_BITMASK 0x40U +#define NFCIP_DETECTED 0x40U + +#define MAX_TARGET_SUPPORTED MAX_REMOTE_DEVICES + +#define NFC_HW_PN65N 0x10U + +#define NXP_NFCIP_NFCID2_ID 0x01FEU + +#define NXP_FULL_VERSION_LEN 0x0BU + + +/*@}*/ + + +/** + * \name NFC specific Type Definitions + * + */ +/*@{*/ + +/** + * Data Buffer Structure to hold the Data Buffer + * + * This structure holds the Data in the Buffer of the specified + * size. + * + */ +typedef struct phNfc_sData_t +{ + uint8_t *buffer; + uint32_t length; +} phNfc_sData_t; + +/** + * \brief Possible Hardware Configuration exposed to upper layer. + * Typically this should be at least the communication link (Ex:"COM1","COM2") + * the controller is connected to. + */ +typedef struct phLibNfc_sConfig_t +{ + /** Device node of the controller */ + const char* deviceNode; + /** The client ID (thread ID or message queue ID) */ + intptr_t nClientId; +} phLibNfc_sConfig_t, *pphLibNfc_sConfig_t; + + +/*! + * NFC Message structure contains message specific details like + * message type, message specific data block details, etc. + */ +typedef struct phLibNfc_Message_t +{ + uint32_t eMsgType;/**< Type of the message to be posted*/ + void * pMsgData;/**< Pointer to message specific data block in case any*/ + uint32_t Size;/**< Size of the datablock*/ +} phLibNfc_Message_t,*pphLibNfc_Message_t; + + +#ifdef WIN32 +#define PH_LIBNFC_MESSAGE_BASE (WM_USER+0x3FF) +#endif +/** + * Deferred message. This message type will be posted to the client application thread + * to notify that a deferred call must be invoked. + */ +#define PH_LIBNFC_DEFERREDCALL_MSG (0x311) + +/** + *\brief Deferred call declaration. + * This type of API is called from ClientApplication ( main thread) to notify + * specific callback. + */ +typedef void (*pphLibNfc_DeferredCallback_t) (void*); +/** + *\brief Deferred parameter declaration. + * This type of data is passed as parameter from ClientApplication (main thread) to the + * callback. + */ +typedef void *pphLibNfc_DeferredParameter_t; +/** + *\brief Deferred message specific info declaration. + * This type of information is packed as message data when \ref PH_LIBNFC_DEFERREDCALL_MSG + * type message is posted to message handler thread. + */ +typedef struct phLibNfc_DeferredCall_t +{ + pphLibNfc_DeferredCallback_t pCallback;/**< pointer to Deferred callback */ + pphLibNfc_DeferredParameter_t pParameter;/**< pointer to Deferred parameter */ +} phLibNfc_DeferredCall_t; + + +/** \ingroup grp_hal_common + * + * \brief Protocol Support Information + * + * The Supported Protocols Structure holds all protocol supported by the current NFC + * device. + * + * \note All members of this structure are output parameters [out]. + * + */ +typedef struct phNfc_sSupProtocol_t +{ + unsigned int MifareUL : 1; /**< Protocol Mifare Ultra Light or + any NFC Forum Type-2 tags */ + unsigned int MifareStd : 1; /**< Protocol Mifare Standard. */ + unsigned int ISO14443_4A : 1; /**< Protocol ISO14443-4 Type A. */ + unsigned int ISO14443_4B : 1; /**< Protocol ISO14443-4 Type B. */ + unsigned int ISO15693 : 1; /**< Protocol ISO15693 HiTag. */ + unsigned int Felica : 1; /**< Protocol Felica. */ + unsigned int NFC : 1; /**< Protocol NFC. */ + unsigned int Jewel : 1; /**< Protocol Innovision Jewel Tag. */ + /*** TODO: Add SWP, ETSI HCI to this list **/ +} phNfc_sSupProtocol_t; + + +/** \ingroup grp_hal_common + * + * + * \brief Information related to the NFC Device + * + * The Device Information Structure holds information + * related to the NFC IC read during initialization time. + * It allows the caller firware, hardware version, the model id, + * HCI verison supported and vendor name. Refer to the NFC Device + * User Manual on how to interpret each of the values. In addition + * it also contains capabilities of the NFC Device such as the + * protocols supported in Reader and emulation mode + * + */ +typedef struct phNfc_sDeviceCapabilities_t +{ + /* */ + uint32_t hal_version; /**< \ingroup grp_hal_common + HAL 4.0 Version Information. */ + uint32_t fw_version; /**< \ingroup grp_hal_common + Firmware Version Info. */ + uint32_t hw_version; /**< \ingroup grp_hal_common + Hardware Version Info. */ + uint8_t model_id; /**< \ingroup grp_hal_common + IC Variant . */ + uint8_t hci_version; /**< \ingroup grp_hal_common + ETSI HCI Version Supported */ + utf8_t vendor_name[VENDOR_NAME_LEN]; /**< \ingroup grp_hal_common + Vendor name (Null terminated string)*/ + uint8_t full_version[NXP_FULL_VERSION_LEN]; + + phNfc_sSupProtocol_t ReaderSupProtocol; /**< Supported protocols + (Bitmapped) in Reader mode. */ + phNfc_sSupProtocol_t EmulationSupProtocol; /**< Supported protocols + (Bitmapped) in Emulation + mode. */ + char firmware_update_info; /** */ +} phNfc_sDeviceCapabilities_t; + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + +/** \ingroup grp_hal_common + * + * \brief Enumerated MIFARE Commands + * + * The Mifare Command List Enumerator lists all available Mifare native commands. + * + * \note None. + * + */ +typedef enum phNfc_eMifareCmdList_t +{ + phNfc_eMifareRaw = 0x00U, /**< This command performs raw transcations . + Format of the phLibNfc_sTransceiveInfo_t + content in this case shall be as below: + • cmd: filed shall set to phHal_eMifareRaw . + • addr : doesn't carry any significance. + • sSendData : Shall contain formatted raw buffer + based on MIFARE commands type used. + Formatted buffer shall follow below + formating scheme. + + CmdType+ Block No + CommandSpecific data + 2 byte CRC + Ex: With Write 4 byte command on block 8 looks as + " 0xA2,0x08,0x01,0x02,0x03,0x04,CRC1,CRC2 + Note : For MIFARE Std card we recommend use MIFARE + commands directly. + */ + phNfc_eMifareAuthentA = 0x60U, /**< Mifare Standard:\n + This command performs an authentication with KEY A for a sector.\n + Format of the phLibNfc_sTransceiveInfo_t content in this case is : + • cmd: field shall set to phHal_eMifareAuthentA . + • addr : indicates MIFARE block address. + Ex: 0x08 indicates block 8 needs to be authenticated. + • sSendData : Shall contain authentication key values. + sSendData ,buffer shall contain authentication + key values 01 02 03 04 05 06 authenticates + block 08 with the key 0x01[..]06. If this + command fails, then user needs to reactivate + the remote Mifare card. + */ + phNfc_eMifareAuthentB = 0x61U, /**< Mifare Standard:\n + This command performs an authentication with KEY B for a sector.\n + Format of the phLibNfc_sTransceiveInfo_t content in this case is : + • cmd: field shall set to phHal_eMifareAuthentB . + • addr : indicates MIFARE block address. + Ex: 0x08 indicates block 8 needs to be authenticated. + • sSendData : Shall contain authentication key values. + sSendData ,buffer shall contain authentication + key values 01 02 03 04 05 06 authenticates + block 08 with the key 0x01[..]06. If this + command fails, then user needs to reactivate + the remote Mifare card. + */ + phNfc_eMifareRead16 = 0x30U, /**< Mifare Standard and Ultra Light:\n + Read 16 Bytes from a Mifare Standard block or 4 Mifare Ultra Light pages.\n + Format of the phLibNfc_sTransceiveInfo_t content in this case is : + • cmd: field shall set to phHal_eMifareRead16 . + • addr : memory adress to read. + • sRecvData : Shall contain buffer of size 16 + to read the data into. + + If this command fails, the user needs to reactivate the + the remote Mifare card + */ + phNfc_eMifareRead = 0x30U, + phNfc_eMifareWrite16 = 0xA0U, /**< Mifare Standard and Ultra Light:\n + Write 16 Bytes to a Mifare Standard block or 4 Mifare Ultra Light pages.\n + Format of the phLibNfc_sTransceiveInfo_t content in this case is : + • cmd: field shall set to phHal_eMifareWrite16 . + • addr : starting memory adress to write from. + • sSendData : Shall contain buffer of size 16 containing + the data bytes to be written. + + If this command fails, the user needs to reactivate the + the remote Mifare card + */ + phNfc_eMifareWrite4 = 0xA2U, /**< Mifare Ultra Light:\n + Write 4 bytes.\n + Format of the phLibNfc_sTransceiveInfo_t content in this case is : + • cmd: field shall set to phHal_eMifareWrite4 . + • addr : starting memory adress to write from. + • sSendData : Shall contain buffer of size 4 containing + the data bytes to be written. + + If this command fails, the user needs to reactivate the + the remote Mifare card + */ + phNfc_eMifareInc = 0xC1U, /**< Increment. */ + phNfc_eMifareDec = 0xC0U, /**< Decrement. */ + phNfc_eMifareTransfer = 0xB0U, /**< Tranfer. */ + phNfc_eMifareRestore = 0xC2U, /**< Restore. */ + phNfc_eMifareReadSector = 0x38U, /**< Read Sector. */ + phNfc_eMifareWriteSector= 0xA8U, /**< Write Sector. */ + phNfc_eMifareInvalidCmd = 0xFFU /**< Invalid Command */ +} phNfc_eMifareCmdList_t; + + +/** \ingroup grp_hal_common + * + * The T=Cl Command List Enumerator lists all available T=Cl Commands. + * + * \note None. + * + */ +typedef enum phNfc_eIso14443_4_CmdList_t +{ + phNfc_eIso14443_4_Raw = 0x00U /**< ISO 14443-4 Exchange command:\n + - This command sends the data buffer directly + to the remote device */ + +} phNfc_eIso14443_4_CmdList_t; + + +/** \ingroup grp_hal_common + * + * The NFCIP1 Command List Enumerator lists all available NFCIP1 Commands. + * + * \note None. + * + */ +typedef enum phNfc_eNfcIP1CmdList_t +{ + phNfc_eNfcIP1_Raw = 0x00U /**< NfcIP Exchange command:\n + - This command sends the data buffer directly + to the remote device */ +}phNfc_eNfcIP1CmdList_t; + + +/** \ingroup grp_hal_common + * + * The ISO15693 Command List Enumerator lists all available ISO15693 Commands. + * + * \note None. + * + */ +typedef enum phNfc_eIso15693_CmdList_t +{ +#if 0 + phNfc_eIso15693_Raw = 0x00U, /**< ISO 15693 Exchange Raw command:\n + - This command sends the data buffer directly + to the remote device */ +#endif + phNfc_eIso15693_Cmd = 0x20U, /**< ISO 15693 Exchange command:\n + - This command is used to access the card + to the remote device */ + phNfc_eIso15693_Invalid = 0xFFU /**< Invalid Command */ +} phNfc_eIso15693_CmdList_t; + + +/** \ingroup grp_hal_common + * + * The Felica Command List Enumerator lists all available Felica Commands. + * + * \note None. + * + */ +typedef enum phNfc_eFelicaCmdList_t +{ + phNfc_eFelica_Raw = 0xF0U, /**< Felica Raw command:\n + - This command sends the data buffer directly + to the remote device */ + phNfc_eFelica_Check = 0x00, /**< Felica Check command:\n + - This command checks the data from the Felica + remote device */ + phNfc_eFelica_Update = 0x01, /**< Felica Update command:\n + - This command updates the data onto the Felica + remote device */ + phNfc_eFelica_Invalid = 0xFFU /**< Invalid Command */ +} phNfc_eFelicaCmdList_t; + + +/** \ingroup grp_hal_common + * + * The Jewel Command List Enumerator lists all available Jewel Commands. + * + * \note None. + * + */ +typedef enum phNfc_eJewelCmdList_t +{ + phNfc_eJewel_Raw = 0x00U, /**< Jewel command:\n + - This command sends the data buffer directly + to the remote device */ + phNfc_eJewel_Invalid = 0xFFU /**< Invalid jewel command */ +}phNfc_eJewelCmdList_t; + + +/** \ingroup grp_hal_nfci +* +* \brief Remote Device Reader A RF Gate Information Container +* +* The Reader A structure includes the available information +* related to the discovered ISO14443A remote device. This information +* is updated for every device discovery. +* \note None. +* +*/ +typedef struct phNfc_sIso14443AInfo_t +{ + uint8_t Uid[PHHAL_MAX_UID_LENGTH]; /**< UID information of the TYPE A + Tag Discovered */ + uint8_t UidLength; /**< UID information length, shall not be greater + than PHHAL_MAX_UID_LENGTH i.e., 10 */ + uint8_t AppData[PHHAL_MAX_ATR_LENGTH]; /**< Application data information of the + tag discovered (= Historical bytes for + type A) */ + uint8_t AppDataLength; /**< Application data length */ + uint8_t Sak; /**< SAK informationof the TYPE A + Tag Discovered */ + uint8_t AtqA[PHHAL_ATQA_LENGTH]; /**< ATQA informationof the TYPE A + Tag Discovered */ + uint8_t MaxDataRate; /**< Maximum data rate supported by the TYPE A + Tag Discovered */ + uint8_t Fwi_Sfgt; /**< Frame waiting time and start up frame guard + time as defined in ISO/IEC 14443-4[7] for + type A */ +} phNfc_sIso14443AInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \brief Remote Device Reader B RF Gate Information Container +* +* The Reader B structure includes the available information +* related to the discovered ISO14443B remote device. This information +* is updated for every device discovery. +* \note None. +* +*/ +typedef struct phNfc_sIso14443BInfo_t +{ + union phNfc_uAtqBInfo + { + struct phNfc_sAtqBInfo + { + uint8_t Pupi[PHHAL_PUPI_LENGTH]; /**< PUPI information of the TYPE B + Tag Discovered */ + uint8_t AppData[PHHAL_APP_DATA_B_LENGTH]; /**< Application Data of the TYPE B + Tag Discovered */ + uint8_t ProtInfo[PHHAL_PROT_INFO_B_LENGTH]; /**< Protocol Information of the TYPE B + Tag Discovered */ + } AtqResInfo; + uint8_t AtqRes[PHHAL_ATQB_LENGTH]; /**< ATQB Response Information of TYPE B + Tag Discovered */ + } AtqB; + uint8_t HiLayerResp[PHHAL_MAX_ATR_LENGTH]; /**< Higher Layer Response information + in answer to ATRRIB Command for Type B */ + uint8_t HiLayerRespLength; /**< Higher Layer Response length */ + uint8_t Afi; /**< Application Family Identifier of TYPE B + Tag Discovered */ + uint8_t MaxDataRate; /**< Maximum data rate supported by the TYPE B + Tag Discovered */ +} phNfc_sIso14443BInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \brief Remote Device Reader B prime RF Gate Information Container +* +*/ +typedef struct phNfc_sIso14443BPrimeInfo_t +{ + /* TODO: This will be updated later */ + void *BPrimeCtxt; +} phNfc_sIso14443BPrimeInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \brief Remote Device Jewel Reader RF Gate Information Container +* +* The Jewel Reader structure includes the available information +* related to the discovered Jewel remote device. This information +* is updated for every device discovery. +* \note None. +* +*/ +typedef struct phNfc_sJewelInfo_t +{ + uint8_t Uid[PHHAL_MAX_UID_LENGTH]; /**< UID information of the TYPE A + Tag Discovered */ + uint8_t UidLength; /**< UID information length, shall not be greater + than PHHAL_MAX_UID_LENGTH i.e., 10 */ + uint8_t HeaderRom0; /**< Header Rom byte zero */ + uint8_t HeaderRom1; /**< Header Rom byte one */ + +} phNfc_sJewelInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \brief Remote Device Felica Reader RF Gate Information Container +* +* The Felica Reader structure includes the available information +* related to the discovered Felica remote device. This information +* is updated for every device discovery. +* \note None. +* +*/ +typedef struct phNfc_sFelicaInfo_t +{ + uint8_t IDm[(PHHAL_FEL_ID_LEN + 2)]; /**< Current ID of Felica tag */ + uint8_t IDmLength; /**< IDm length, shall not be greater + than PHHAL_FEL_ID_LEN i.e., 8 */ + uint8_t PMm[PHHAL_FEL_PM_LEN]; /**< Current PM of Felica tag */ + uint8_t SystemCode[PHHAL_FEL_SYS_CODE_LEN]; /**< System code of Felica tag */ +} phNfc_sFelicaInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \brief Remote Device Reader 15693 RF Gate Information Container +* +* The Reader A structure includes the available information +* related to the discovered ISO15693 remote device. This information +* is updated for every device discovery. +* \note None. +* +*/ + +typedef struct phNfc_sIso15693Info_t +{ + uint8_t Uid[PHHAL_15693_UID_LENGTH]; /**< UID information of the 15693 + Tag Discovered */ + uint8_t UidLength; /**< UID information length, shall not be greater + than PHHAL_15693_UID_LENGTH i.e., 8 */ + uint8_t Dsfid; /**< DSF information of the 15693 + Tag Discovered */ + uint8_t Flags; /**< Information about the Flags + in the 15693 Tag Discovered */ + uint8_t Afi; /**< Application Family Identifier of + 15693 Tag Discovered */ +} phNfc_sIso15693Info_t; + + +/** \ingroup grp_hal_nfci +* +* \brief NFC Data Rate Supported between the Reader and the Target +* +* The \ref phHalNfc_eDataRate enum lists all the Data Rate +* values to be used to determine the rate at which the data is transmitted +* to the target. +* +* \note None. +*/ + + +/** \ingroup grp_hal_nfci +* +* \brief NFCIP1 Data rates +* +*/ +typedef enum phNfc_eDataRate_t{ + phNfc_eDataRate_106 = 0x00U, + phNfc_eDataRate_212, + phNfc_eDataRate_424, + /* phNfc_eDataRate_848, + phNfc_eDataRate_1696, + phNfc_eDataRate_3392, + phNfc_eDataRate_6784,*/ + phNfc_eDataRate_RFU +} phNfc_eDataRate_t; + + +/** \ingroup grp_hal_nfci +* +* \brief NFCIP1 Gate Information Container +* +* The NFCIP1 structure includes the available information +* related to the discovered NFCIP1 remote device. This information +* is updated for every device discovery. +* \note None. +* +*/ +typedef struct phNfc_sNfcIPInfo_t +{ + /* Contains the random NFCID3I conveyed with the ATR_REQ. + always 10 bytes length + or contains the random NFCID3T conveyed with the ATR_RES. + always 10 bytes length */ + uint8_t NFCID[PHHAL_MAX_UID_LENGTH]; + uint8_t NFCID_Length; + /* ATR_RES = General bytes length, Max length = 48 bytes */ + uint8_t ATRInfo[PHHAL_MAX_ATR_LENGTH]; + uint8_t ATRInfo_Length; + /**< SAK information of the tag discovered */ + uint8_t SelRes; + /**< ATQA information of the tag discovered */ + uint8_t SenseRes[PHHAL_ATQA_LENGTH]; + /**< Is Detection Mode of the NFCIP Target Active */ + uint8_t Nfcip_Active; + /**< Maximum frame length supported by the NFCIP device */ + uint16_t MaxFrameLength; + /**< Data rate supported by the NFCIP device */ + phNfc_eDataRate_t Nfcip_Datarate; + +} phNfc_sNfcIPInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \brief Remote Device Specific Information Container +* +* The Remote Device Information Union includes the available Remote Device Information +* structures. Following the device detected, the corresponding data structure is used. +* +* \note None. +* +*/ +typedef union phNfc_uRemoteDevInfo_t +{ + phNfc_sIso14443AInfo_t Iso14443A_Info; + phNfc_sIso14443BInfo_t Iso14443B_Info; + phNfc_sIso14443BPrimeInfo_t Iso14443BPrime_Info; + phNfc_sNfcIPInfo_t NfcIP_Info; + phNfc_sFelicaInfo_t Felica_Info; + phNfc_sJewelInfo_t Jewel_Info; + phNfc_sIso15693Info_t Iso15693_Info; +} phNfc_uRemoteDevInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \brief RF Device Type Listing +* +* The RF Device Type List is used to identify the type of +* remote device that is discovered/connected. There seperate +* types to identify a Remote Reader (denoted by _PCD) and +* Remote Tag (denoted by _PICC) +* \note None. +* +*/ +typedef enum phNfc_eRFDevType_t +{ + phNfc_eUnknown_DevType = 0x00U, + + /* Specific PCD Devices */ + phNfc_eISO14443_A_PCD, + phNfc_eISO14443_B_PCD, + phNfc_eISO14443_BPrime_PCD, + phNfc_eFelica_PCD, + phNfc_eJewel_PCD, + phNfc_eISO15693_PCD, + /* Generic PCD Type */ + phNfc_ePCD_DevType, + + /* Generic PICC Type */ + phNfc_ePICC_DevType, + /* Specific PICC Devices */ + phNfc_eISO14443_A_PICC, + phNfc_eISO14443_4A_PICC, + phNfc_eISO14443_3A_PICC, + phNfc_eMifare_PICC, + phNfc_eISO14443_B_PICC, + phNfc_eISO14443_4B_PICC, + phNfc_eISO14443_BPrime_PICC, + phNfc_eFelica_PICC, + phNfc_eJewel_PICC, + phNfc_eISO15693_PICC, + + /* NFC-IP1 Device Types */ + phNfc_eNfcIP1_Target, + phNfc_eNfcIP1_Initiator, + + /* Other Sources */ + phNfc_eInvalid_DevType + +} phNfc_eRFDevType_t; + + +/** \ingroup grp_hal_nfci +* +* \brief Remote Device Type Listing +* +* The Remote Device Type List is used to identify the type of +* remote device that is discovered/connected +* \note This is same as RF Device Type List. +* +*/ +typedef phNfc_eRFDevType_t phNfc_eRemDevType_t; + + +/** \ingroup grp_hal_common + * + * + * \brief Common Command Attribute + * + * The Hal Command Union includes each available type of Commands. + * + * \note None. + * + */ +typedef union phNfc_uCommand_t +{ + phNfc_eMifareCmdList_t MfCmd; /**< Mifare command structure. */ + phNfc_eIso14443_4_CmdList_t Iso144434Cmd; /**< ISO 14443-4 command structure. */ + phNfc_eFelicaCmdList_t FelCmd; /**< Felica command structure. */ + phNfc_eJewelCmdList_t JewelCmd; /**< Jewel command structure. */ + phNfc_eIso15693_CmdList_t Iso15693Cmd; /**< ISO 15693 command structure. */ + phNfc_eNfcIP1CmdList_t NfcIP1Cmd; /**< ISO 18092 (NFCIP1) command structure */ +} phNfc_uCmdList_t; + + +/** \ingroup grp_hal_nfci + * + * \brief Remote Device Information Structure + * + * The Remote Device Information Structure holds information about one single Remote + * Device detected by the polling function .\n + * It lists parameters common to all supported remote devices. + * + * \note + * + * \sa \ref phHal4Nfc_ConfigureDiscovery and \ref phHal4Nfc_Connect + * + */ +typedef struct phNfc_sRemoteDevInformation_t +{ + uint8_t SessionOpened; /**< [out] Boolean + * Flag indicating the validity of + * the handle of the remote device. */ + phNfc_eRemDevType_t RemDevType; /**< [out] Remote device type which says that remote + is Reader A or Reader B or NFCIP or Felica or + Reader B Prime or Jewel*/ + phNfc_uRemoteDevInfo_t RemoteDevInfo; /**< Union of available Remote Device. + * \ref phNfc_uRemoteDevInfo_t Information. */ +} phNfc_sRemoteDevInformation_t; + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +/* TARGET STRUCTURES */ + + +/** \ingroup grp_hal_common + * + * \brief Transceive Information Data Structure for sending commands/response + * to the remote device + * + * The Transceive Information Data Structure is used to pass the + * Command, Address (only required for MIFARE) and the send and receive data + * data structure (buffer and length) for communication with remote device + * + * + */ +typedef struct phNfc_sTransceiveInfo_t +{ + phNfc_uCmdList_t cmd; + + /** \internal Address Field required for only Mifare + * Family Proprietary Cards. + * The Address Size is Valid only upto 255 Blocks limit + * i:e for Mifare 4K + */ + uint8_t addr; + phNfc_sData_t sSendData; + phNfc_sData_t sRecvData; +} phNfc_sTransceiveInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \brief Poll Device Information for conifiguring the discovery wheel + Reader and Card Emulation Phases +* +* The \ref phNfc_sPollDevInfo_t enum is used to enable/disable +* phases of the discovery wheel related to specific reader types and +* card emulation phase +* \note Enabling specific Reader technology when NFCIP1 speed is set in the +* phNfc_sADD_Cfg_t is implicitly done in HAL. Use this structure to only +* enable/disable Card Reader Functionality +*/ +typedef struct phNfc_sPollDevInfo_t +{ + unsigned EnableIso14443A : 1; /**< Flag to enable + Reader A discovery */ + unsigned EnableIso14443B : 1; /**< Flag to enable + Reader B discovery */ + unsigned EnableFelica212 : 1; /**< Flag to enable + Felica 212 discovery */ + unsigned EnableFelica424 : 1; /**< Flag to enable + Felica 424 discovery */ + unsigned EnableIso15693 : 1; /**< Flag to enable + ISO 15693 discovery */ + unsigned EnableNfcActive : 1; /**< Flag to enable + Active Mode of NFC-IP discovery. + This is updated internally + based on the NFC-IP speed. + */ + unsigned RFU : 1; /**< Reserved for future use */ + unsigned DisableCardEmulation : 1; /**< Flag to + disable the card emulation */ +} phNfc_sPollDevInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \brief P2P speed for the Initiator +* +* The \ref phNfc_eP2PMode_t enum lists all the NFCIP1 speeds +* to be used for configuring the NFCIP1 discovery +* +* \note None. +*/ +typedef enum phNfc_eP2PMode_t +{ + phNfc_eDefaultP2PMode = 0x00U, + phNfc_ePassive106 = 0x01U, + phNfc_ePassive212 = 0x02U, + phNfc_ePassive424 = 0x04U, + phNfc_eActive106 = 0x08U, + phNfc_eActive212 = 0x10U, + phNfc_eActive424 = 0x20U, + phNfc_eP2P_ALL = 0x27U, /* All Passive and 424 Active */ + phNfc_eInvalidP2PMode = 0xFFU +} phNfc_eP2PMode_t; + + +/** \ingroup grp_hal_common +* +* \brief Identities the type of Notification +* +* This enumeration is used to specify the type of notification notified +* to the upper layer. This classifies the notification into two types +* one for the discovery notifications and the other for all the remaining +* event notifications +* \note None. +*/ +typedef enum phNfc_eNotificationType_t +{ + INVALID_NFC_NOTIFICATION = 0x00U, /* Invalid Notification */ + NFC_DISCOVERY_NOTIFICATION, /* Remote Device Discovery Notification */ + NFC_EVENT_NOTIFICATION /* Event Notification from the other hosts */ +} phNfc_eNotificationType_t; + + +/** \ingroup grp_hal_common +* +* \brief +* +* \note None. +*/ +typedef struct phNfc_sUiccInfo_t +{ + /* AID and Parameter Information is obtained if the + * eventType is NFC_EVT_TRANSACTION. + */ + phNfc_sData_t aid; + phNfc_sData_t param; + +} phNfc_sUiccInfo_t; + + +/** \ingroup grp_hal_nfci +* +* \brief P2P Information for the Initiator +* +* The \ref phNfc_sNfcIPCfg_t holds the P2P related information +* use by the NFC Device during P2P Discovery and connection +* +* \note None. +*/ +typedef struct phNfc_sNfcIPCfg_t +{ + /* ATR_RES = General bytes length, Max length = 48 bytes */ + uint8_t generalBytesLength; + uint8_t generalBytes[PHHAL_MAX_ATR_LENGTH]; + + /* TODO: This will be updated later for any additional params*/ +} phNfc_sNfcIPCfg_t; + + +/** \ingroup grp_hal_common +* +* \brief Discovery Configuration Mode +* +* This enumeration is used to choose the Discovery Configuration +* Mode :- Configure and Start, Stop or Start with last set +* configuration +* \note None. +*/ +typedef enum phNfc_eDiscoveryConfigMode_t +{ + NFC_DISCOVERY_CONFIG = 0x00U,/**< Configure discovery with values + in phNfc_sADD_Cfg_t and start + discovery */ + NFC_DISCOVERY_START, /**< Start Discovery with previously set + configuration */ + NFC_DISCOVERY_STOP, /**< Stop the Discovery */ + NFC_DISCOVERY_RESUME /**< Resume the Discovery with previously + * set configuration. + * This is valid only when the Target + * is not connected. + */ +}phNfc_eDiscoveryConfigMode_t; + +/** \ingroup grp_hal_common +* +* \brief Target or Tag Release Mode +* +* This enumeration defines various modes of releasing an acquired target +* or tag. +* \note None. +*/ +typedef enum phNfc_eReleaseType_t +{ + NFC_INVALID_RELEASE_TYPE =0x00U,/** Poll configuration structure holds information about the +* enabling the the type of discovery required by the application. This +* structure is the input parameter for the discovery call +* +* \note All members of this structure are input parameters [out]. +* +* \sa \ref phNfc_eP2PMode_t +* +*/ +typedef struct phNfc_sADD_Cfg_t +{ + union + { + phNfc_sPollDevInfo_t PollCfgInfo; /**< Enable/Disable Specific + Reader Functionality and + Card Emulation */ + unsigned PollEnabled; /** Can be used to set polling 'Off' + by setting PollEnabled to zero */ + + } PollDevInfo; + uint32_t Duration; /**< Duration of virtual or idle + period in microseconds in the step size + of 48 microseconds.If duration is set less + than 48 microseconds then default value is + used.For more details please refer PN 544 + user manual*/ + uint8_t NfcIP_Mode ; /**< Select the P2P + speeds using phNfc_eP2PMode_t type. + This is used to enable NFC-IP Discovery + The related Reader Type will be implicitly + selected */ + uint8_t NfcIP_Target_Mode ; + uint8_t NfcIP_Tgt_Disable; /**< Flag to + disable the NFCIP1 TARGET */ +} phNfc_sADD_Cfg_t; + +/*@}*/ + +#endif /* PHNFCTYPES */ + diff --git a/libnfc-nxp/phOsalNfc.h b/libnfc-nxp/phOsalNfc.h new file mode 100644 index 0000000..e522263 --- /dev/null +++ b/libnfc-nxp/phOsalNfc.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/* + * \file phOsalNfc.h + * \brief OSAL Implementation. + * + * Project: NFC-FRI 1.1 + * $Date: Fri Jun 26 14:41:31 2009 $ + * $Author: ing04880 $ + * $Revision: 1.21 $ + * $Aliases: NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ +#ifndef PHOSALNFC_H +#define PHOSALNFC_H + + +/** \defgroup grp_osal_nfc OSAL Component + * + *\note: API listed here encompasses Operating System Abstraction Layer interfaces required to be mapped to underlying OS platforms. + * + */ +#include + +#ifdef PH_NFC_CUSTOMINTEGRATION +#include +#else +#include + +/**< OSAL Message Type */ +#ifdef WIN32 +//#define PH_OSALNFC_MESSAGE_BASE (WM_USER+0x3FF) +#define PH_OSALNFC_MESSAGE_BASE PH_LIBNFC_MESSAGE_BASE +#endif + +/*! + * \ingroup grp_osal_nfc + * + * OSAL Message structure contains message specific details like + * message type, message specific data block details, etc. + */ +//typedef struct phOsalNfc_Message +//{ +// uint32_t eMsgType;/**< Type of the message to be posted*/ +// void * pMsgData;/**< Pointer to message specific data block in case any*/ +// uint16_t Size;/**< Size of the datablock*/ +//} phOsalNfc_Message_t,*pphOsalNfc_Message_t; +typedef phLibNfc_Message_t phOsalNfc_Message_t; +typedef pphLibNfc_Message_t pphOsalNfc_Message_t; + +/*! + * \ingroup grp_osal_nfc + * + * Enum definition contains supported exception types + */ +typedef enum +{ + phOsalNfc_e_NoMemory, /** +#else +#ifdef __linux__ +#include +#else +#include +#endif +#endif + +#endif /* PHOSALNFC_MSG_H */ diff --git a/libnfc-nxp/phOsalNfc_Timer.h b/libnfc-nxp/phOsalNfc_Timer.h new file mode 100644 index 0000000..a245a0d --- /dev/null +++ b/libnfc-nxp/phOsalNfc_Timer.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * 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. + */ + +/** + * \file phOsalNfc_Timer.h + * \brief Timer Implementation. + * + * Project: NFC-FRI 1.1 + * + * $Date: Mon Mar 16 20:30:44 2009 $ + * $Author: ing01697 $ + * $Revision: 1.19 $ + * $Aliases: NFC_FRI1.1_WK912_R21_1,NFC_FRI1.1_WK914_PREP1,NFC_FRI1.1_WK914_R22_1,NFC_FRI1.1_WK914_R22_2,NFC_FRI1.1_WK916_R23_1,NFC_FRI1.1_WK918_R24_1,NFC_FRI1.1_WK920_PREP1,NFC_FRI1.1_WK920_R25_1,NFC_FRI1.1_WK922_PREP1,NFC_FRI1.1_WK922_R26_1,NFC_FRI1.1_WK924_PREP1,NFC_FRI1.1_WK924_R27_1,NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ +#ifndef PHOSALNFC_TIMER_H +#define PHOSALNFC_TIMER_H + +/* -----------------Include files ---------------------------------------*/ +#include +#ifdef PH_NFC_CUSTOMINTEGRATION +#include +#else +#ifdef NXP_MESSAGING +#include +#endif + +#ifdef NXP_MESSAGING +/** + * \ingroup grp_osal_nfc + *\brief Deferred message specific info declaration. + * This type information packed as WPARAM when \ref PH_OSALNFC_MESSAGE_BASE type windows message + * is posted to message handler thread. + */ +//typedef struct phOsalNfc_DeferedCalldInfo +//{ +// nfc_osal_def_call_t pDeferedCall;/**< pointer to Deferred callback */ +// void *pParam;/**< contains timer message specific details*/ +//}phOsalNfc_DeferedCalldInfo_t; +typedef phLibNfc_DeferredCall_t phOsalNfc_DeferedCalldInfo_t; +#endif + +/* ---------------- Macros ----------------------------------------------*/ +/** +*\ingroup grp_osal_nfc +* OSAL timer message .This message type will be posted to calling application thread. +*/ +//#define PH_OSALNFC_TIMER_MSG (0x315) +#define PH_OSALNFC_TIMER_MSG PH_LIBNFC_DEFERREDCALL_MSG + +/** + * \ingroup grp_osal_nfc + * Invalid timer ID type.This ID used indicate timer creation is failed. + */ +#define PH_OSALNFC_INVALID_TIMER_ID (0xFFFF) + +/*! + * \ingroup grp_osal_nfc + * \brief Timer callback interface which will be called once registered timer + * timeout expires. + * \param[in] TimerId Timer Id for which callback is called. + * \retval None + */ +typedef void (*ppCallBck_t)(uint32_t TimerId, void *pContext); + +/* -----------------Structures and Enumerations -------------------------*/ +/** + * \ingroup grp_osal_nfc + **\brief Timer message structure definition. + * Timer Message Structure contains timer specific informations like timer identifier + * and timer callback. + * + */ +typedef struct phOsalNfc_TimerMsg +{ + uint32_t TimerId;/**< Timer ID*/ + ppCallBck_t pCallBck;/**< pointer to Timer Callback*/ + void* pContext; /**< Timer Callback context*/ +}phOsalNfc_Timer_Msg_t,*pphOsalNfc_TimerMsg_t; + +/* -----------------Exported Functions----------------------------------*/ +/** + * \ingroup grp_osal_nfc + * \brief Allows to create new timer. + * + * This API creates a cyclic timer. In case a valid timer is created returned + * timer ID will be other than \ref PH_OSALNFC_INVALID_TIMER_ID. In case returned + * timer id is \ref PH_OSALNFC_INVALID_TIMER_ID, this indicates timer creation + * has failed. + * + * When a timer is created, it is not started by default. The application has to + * explicitly start it using \ref phOsalNfc_Timer_Start(). + * + * \param[in] void + * \retval Created timer ID. + * \note If timer ID value is PH_OSALNFC_INVALID_TIMER_ID, it indicates + * an error occured during timer creation. + * + * \msc + * Application,phOsalNfc; + * Application=>phOsalNfc [label="phOsalNfc_Timer_Create()",URL="\ref phOsalNfc_Timer_Create"]; + * Application<phOsalNfc [label="phOsalNfc_Timer_Create()", URL="\ref phOsalNfc_Timer_Create"]; + * Application<phOsalNfc [label="phOsalNfc_Timer_Start(TIMERID, TIMEOUT, CB)", URL="\ref phOsalNfc_Timer_Start"]; + * --- [label=" : On timer time out expired "]; + * phOsalNfc=>phOsalNfc [label="CB()"]; + * Application<-phOsalNfc[label="PH_OSALNFC_TIMER_MSG"]; + * \endmsc + */ +void phOsalNfc_Timer_Start(uint32_t TimerId, + uint32_t RegTimeCnt, + ppCallBck_t Application_callback, + void *pContext); + +/** + * \ingroup grp_osal_nfc + * \brief Stop an already started timer. + * + * This API allows to stop running timers. In case the timer is stopped, its callback will not be + * notified any more. + * + * \param[in] TimerId valid timer ID obtained suring timer creation. + * \param[in] Application_callback Application Callback interface to be called when timer expires. + * + * \msc + * Application,phOsalNfc; + * Application=>phOsalNfc [label="phOsalNfc_Timer_Create()",URL="\ref phOsalNfc_Timer_Create"]; + * Application<phOsalNfc [label="phOsalNfc_Timer_Start(TIMERID, TIMEOUT, CB)",URL="\ref phOsalNfc_Timer_Start"]; + * --- [label=" : On timer time out expired "]; + * phOsalNfc=>phOsalNfc [label="CB()"]; + * Application=>phOsalNfc [label="phOsalNfc_Timer_Stop(TIMERID)",URL="\ref phOsalNfc_Timer_Stop"]; + \endmsc + */ +void phOsalNfc_Timer_Stop(uint32_t TimerId); + +/** + * \ingroup grp_osal_nfc + * \brief Allows to delete the timer which is already created. + * + * This API allows to delete a timer. Incase timer is running + * it is stopped first and then deleted. if the given timer ID is invalid, this + * function doesn't return any error. Application has to explicitly ensure + * timer ID sent is valid. + * + * \param[in] TimerId timer identieir to delete the timer. + */ +void phOsalNfc_Timer_Delete(uint32_t TimerId); + +#endif +#endif /* PHOSALNFC_TIMER_H */ diff --git a/manifest.xml b/manifest.xml new file mode 100644 index 0000000..1e7df9c --- /dev/null +++ b/manifest.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/private/__get_tls_internal.h b/private/__get_tls_internal.h index 4a8fa5f..373e939 100644 --- a/private/__get_tls_internal.h +++ b/private/__get_tls_internal.h @@ -51,4 +51,3 @@ #endif #endif /* __BIONIC_PRIVATE_GET_TLS_INTERNAL_H_ */ - diff --git a/private/bionic_tls.h b/private/bionic_tls.h index de086f2..065fd9b 100644 --- a/private/bionic_tls.h +++ b/private/bionic_tls.h @@ -56,12 +56,16 @@ __BEGIN_DECLS enum { TLS_SLOT_SELF = 0, // The kernel requires this specific slot for x86. TLS_SLOT_THREAD_ID, + + TLS_SLOT_STACK_GUARD = 5, // GCC requires this specific slot for x86. + TLS_SLOT_ERRNO, // These two aren't used by bionic itself, but allow the graphics code to // access TLS directly rather than using the pthread API. - TLS_SLOT_OPENGL_API = 3, - TLS_SLOT_OPENGL = 4, + TLS_SLOT_OPENGL_API, + TLS_SLOT_OPENGL, + TLS_SLOT_DLERROR, // This slot is only used to pass information from the dynamic linker to // libc.so when the C library is loaded in to memory. The C runtime init @@ -69,9 +73,6 @@ enum { // we reuse an existing location that isn't needed during libc startup. TLS_SLOT_BIONIC_PREINIT = TLS_SLOT_OPENGL_API, - TLS_SLOT_STACK_GUARD = 5, // GCC requires this specific slot for x86. - TLS_SLOT_DLERROR, - // Fast storage for Thread::Current() in ART. TLS_SLOT_ART_THREAD_SELF, diff --git a/system/audio.h b/system/audio.h index 0097264..13e6f8f 100644 --- a/system/audio.h +++ b/system/audio.h @@ -777,8 +777,8 @@ static inline audio_channel_mask_t audio_channel_out_mask_from_count(uint32_t ch case 2: bits = AUDIO_CHANNEL_OUT_STEREO; break; - case 3: // 2.1 - bits = AUDIO_CHANNEL_OUT_STEREO | AUDIO_CHANNEL_OUT_LOW_FREQUENCY; + case 3: + bits = AUDIO_CHANNEL_OUT_STEREO | AUDIO_CHANNEL_OUT_FRONT_CENTER; break; case 4: // 4.0 bits = AUDIO_CHANNEL_OUT_QUAD; diff --git a/system/camera.h b/system/camera.h index 10acfe6..264d710 100644 --- a/system/camera.h +++ b/system/camera.h @@ -200,6 +200,7 @@ enum { * IMPLEMENTATION_DEFINED, then HALv3 devices will use gralloc usage flags * of SW_READ_OFTEN. */ +#ifndef CAMERA_VENDOR_L_COMPAT CAMERA_CMD_SET_VIDEO_FORMAT = 11, CAMERA_CMD_VENDOR_START = 20, @@ -219,6 +220,20 @@ enum { CAMERA_CMD_METADATA_ON = CAMERA_CMD_VENDOR_START + 6, CAMERA_CMD_METADATA_OFF = CAMERA_CMD_VENDOR_START + 7, CAMERA_CMD_VENDOR_END = 200, +#else + /** + * Values used by older HALs, provided as an option for compatibility + */ + CAMERA_CMD_HISTOGRAM_ON = 11, + CAMERA_CMD_HISTOGRAM_OFF = 12, + CAMERA_CMD_HISTOGRAM_SEND_DATA = 13, + CAMERA_CMD_LONGSHOT_ON = 14, + CAMERA_CMD_LONGSHOT_OFF = 15, + CAMERA_CMD_STOP_LONGSHOT = 16, + CAMERA_CMD_METADATA_ON = 100, + CAMERA_CMD_METADATA_OFF = 101, + CAMERA_CMD_SET_VIDEO_FORMAT = 102, +#endif }; /** camera fatal errors */ diff --git a/vndk/hardware_buffer.h b/vndk/hardware_buffer.h index 7a4b31f..6c9ec34 100644 --- a/vndk/hardware_buffer.h +++ b/vndk/hardware_buffer.h @@ -26,6 +26,28 @@ __BEGIN_DECLS const native_handle_t* AHardwareBuffer_getNativeHandle(const AHardwareBuffer* buffer); +enum CreateFromHandleMethod { + // enum values chosen to match internal GraphicBuffer::HandleWrapMethod + AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_REGISTER = 2, + AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE = 3, +}; + +/** + * Create a AHardwareBuffer from a native handle. + * + * This function wraps a native handle in a AHardwareBuffer suitable for use by applications or + * other parts of the system. The contents of desc will be returned by AHardwareBuffer_describe(). + * + * If method is AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_REGISTER, the handle is assumed to be + * unregistered, and it will be registered/imported before being wrapped in the AHardwareBuffer. + * If successful, the AHardwareBuffer will own the handle. + * + * If method is AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE, the handle will be cloned and the + * clone registered. The AHardwareBuffer will own the cloned handle but not the original. + */ +int AHardwareBuffer_createFromHandle(const AHardwareBuffer_Desc* desc, + const native_handle_t* handle, int32_t method, + AHardwareBuffer** outBuffer); /** * Buffer pixel formats.