RFID API Documentation  1.0
Reference guide for RFID API
Programmer's Guide

RFID API

The programmer's guide is divided into two parts:

The first part pertains to the Generic Reader Interface which covers the API and Usage supported by the reader. This interface is used for routine operations like Reading Tags (Inventory), Programming Tags (Tag Access Operations like Read, Write, Lock, Kill) and configuring the Reader.

The second part pertains to the Reader Management Interface which is used for managing the Reader (Software Update, Reset, Using Config Files, etc).

Generic Reader Interface

Overview

This section provides detailed information on how to develop RFID applications using RFID API generic interface. RFID API allows applications to talk to RFID Readers which support the LLRP Interface. LLRP is a standard specification for the network interface between the reader and its controlling software or hardware.

To develop applications using RFID API follow the steps beneath:

  1. Connecting to RFID Reader
  2. Knowing the Reader Capabilities
  3. Configuring the Reader
  4. Managing Events
  5. Managing Tags
  6. Basic operations
  7. Advanced operations
  8. NXP Custom Tag Support

In general, if the function call succeeds, the function returns RFID_API_SUCCESS else it returns with specific Error code. The RFID_GetErrorDescription functions gets the error description string for the given status code. The RFID_GetLastErrorInfo can be called to find out the error information of the last called function. This function contains timestamp of the error, error description and additional vendor specific error messages if available.

Connecting to RFID Reader

This is the first step to talk to an RFID Reader over the Generic Reader Interface. An application must first acquire a Handle of type RFID_HANDLE32 to the RFID Reader by a call to RFID_Connect or RFID_AcceptConnection. A valid handle will be returned to the application if the function returns RFID_API_SUCCESS. The application can use this handle for all other functions.

The RFID_Connect function is to be used when the RFID Reader is configured in LLRP Server Mode. This function takes the hostname or IP address of the RFID-Reader to connect to, the port number and the response timeout. While connecting on Hand-Held or Device-based Readers, hostname shall be given as "NULL" or "localhost" or "127.0.0.1" so as to connect to the Reader within the device. For Host-based readers, hostname shall be the IP address of the RFID Reader.

The RFID_AcceptConnection function is to be used when the RFID Reader is configured in LLRP Client mode. The application shall create a socket using the win32 API, socket and listen and wait for incoming connection using the win32 API accept, the return value of which shall be passed as socket-handle to RFID_AcceptConnection API. The accept API returns when the connection is initiated from the RFID Reader.

The default LLRP port number is 5084 and the default response timeout is 5 seconds. Specifying zero for port number and timeout uses default values.

The timeout value is also used for configuring the Keep-Alive mechanism which helps in determining if the connection to the reader is alive or not. If the connection to the reader was inactive (i.e. no keep-alive message from the Reader) for a time greater than 10 times the timeout, DISCONNECTION_EVENT will be triggered to the application if the application has registered for the same.

Secured Connection

Secure LLRP mode allows encrypted and optionally authenticated connection to use LLRP service on the reader using SSL/TLS. Please refer "Configure LLRP Settings" and "Certificates" chapter in Reader Integrator Guide for configuring reader in Secure LLRP mode.

RFID API can internally manage secure connection to LLRP service and clients using RFID API can enable secure connection by setting options in SEC_CONNECTION_INFO parameter of CONNECTION_INFO (or SERVER_INFO in case of server mode) parameter to RFID_Connect (or RFID_AcceptConnection call in case of server mode).

Please refer Reader Integrator Guide for documentation on generation of certificates for reader as well as client use.

The example below illustrates use of SEC_CONNECTION_INFO parameter in RFID_Connect to establish a secure to connection to a reader which is configured to operate in Secure LLRP mode.

#ifdef APP_HAS_OPENSSL_HEADERS
#include <openssl/err.h>
#endif
#define MAX_CERT_KEY_FILE_SIZE 4096

RFID_HANDLE32 readerHandle;
CONNECTION_INFO connInfo;
SEC_CONNECTION_INFO secConnInfoExt;
RFID_STATUS rfidStatus = RFID_API_SUCCESS;
BYTE   g_clientCertContent[MAX_CERT_KEY_FILE_SIZE];
UINT32 clientCertSize = 0;
BYTE   g_clientKeyContent[MAX_CERT_KEY_FILE_SIZE];
UINT32 clientKeySize = 0;
BYTE   g_rootCertContent[MAX_CERT_KEY_FILE_SIZE];
UINT32 rootCertSize = 0;
BYTE   g_password[MAX_PATH] = {0};

/* Read client certificate,  client's private key file and root CA certificate file */

GetFileContent("client_crt.pem", &g_clientCertContent, &clientCertSize);
GetFileContent("client_key.pem", &g_clientKeyContent, &clientKeySize);
GetFileContent("cacert.pem", &g_rootCertContent, &rootCertSize);

/* Specify password for private key, if its encrypted (else should be null) */
strcpy(g_password, "abcd12345");

/* Setup secure connection info parameter */
secConnInfoExt.secureMode = true;
secConnInfoExt.validatePeerCert = false; // If true, make sure reader is updated   
                                        // with reader's certificate issued by    
                                        // the same CA that issued to this client
                                        // (see Integrator Guide, "Certificates" chapter)
secConnInfoExt.sizeCertBuff = clientCertSize;
secConnInfoExt.clientCertBuff = g_clientCertContent;
secConnInfoExt.sizeKeyBuff = clientKeySize;
secConnInfoExt.clientKeyBuff = g_clientKeyContent;
secConnInfoExt.sizeRootCertBuff = rootCertSize;
secConnInfoExt.rootCertBuff = g_rootCertContent;
secConnInfoExt.sizePhraseBuff = strlen(g_password);
/* Setup connection info parameter */
connInfo.version = RFID_API3_5_5;
connInfo.lpSecConInfo = &secConnInfoExt;
EstablishSecureConnection()
{
    rfidStatus = RFID_Connect(&readerHandle, TEXT("FX7500ABCDEF"), 0, 0, &connInfo);
    if(RFID_API_SUCCESS == rfidStatus)      
    {
        // Success... Use readerHandle for other API calls
        // ...
        // Disconnect after use
        rfidStatus = RFID_Disconnect(readerHandle);
    }    
    else
    {
        // Failed connection.
        if (RFID_SECURE_CONNECTION_ERROR == rfidStatus)
        {
            // Show error
#ifdef APP_HAS_OPENSSL_HEADERS
            char errStr[1024];
            ERR_error_string(pSecConInfo->connStatus, errStr);
            printf("Secure connection error. Error string: %d\n", errStr);
#else
            printf("Secure connection error. Code: %d\n", secConnInfoExt.connStatus);
#endif          
        }       
    }    
}

int GetFileContent(char* filePath, BYTE *pBuffer, int *pLen)
{
    FILE * pFile;
    size_t result;
    File = fopen ( filePath , "r" );
    if (pFile==NULL) return 0;
    // obtain file size:
    seek (pFile , 0 , SEEK_END);
    pLen = ftell (pFile);
    rewind (pFile);
    // copy the file into the buffer:
    result = fread (pBuffer, 1, *pLen, pFile);
    pLen = result;
    /* the whole file is now loaded in the memory buffer. */
    // terminate
    fclose (pFile);
    return *pLen;
}

Managing API Versions

As new features are developed, reserved fields of existing structures are expanded. So as to ensure backward compatibility, the expanded reserved would not be used for applications compiled using older Dll versions. Applications that require using the new features shall mention the Dll version RFID_VERSION which is being used as part of CONNECTION_INFO or SERVER_INFO for the APIs RFID_Connect and RFID_AcceptConnection respectively.

Please note that when applications upgrade to higher version, it should ensure that those reserved fields in the data structures which have been expanded for use, shall be either NULL or a valid value so as to avoid exceptions due to accessing uninitialized memory.

List of versions versus the features supported

1.RFID_API3_5_0 - This is the basic version of RFID API3, and the Dll defaults to this version RFID_Connect is called with the last parameter LPCONNECTION_INFO as NULL.

2.RFID_API3_5_1 - Dll versions of 5.1.XXX supports the following additional features.

a. Generic Interface

RFID_AcceptConnection

RFID_GetTagStorageSettings

RFID_PurgeTags

Tag Event Reporting - TAG_EVENT_REPORT_INFO in TRIGGER_INFO

RSSI Filtering - RSSI_RANGE_FILTER in POST_FILTER and ACCESS_FILTER

NXP Tag Support

Selecting Tag Fields that is to be reported in TAG_DATA - tagFields in TAG_STORAGE_SETTINGS

Enabling Access reports (disabled by default) - enableAccessReports in TAG_STORAGE_SETTINGS

Reader Exception Event (READER_EXCEPTION_EVENT_DATA)

Truncate Action in Prefilters - TRUNCATE_ACTION in PRE_FILTER

Write Access operation to write to specific fields

b. RM Interface

RFID_GetReaderStats and RFID_ClearReaderStats.

Force login option in fixed readers

RFID_SetActiveProfile and RFID_DeleteProfile

Push model of Software Update in fixed readers

RFID_GetReaderInfo and RFID_SetReaderInfo

RFID_GetTimeZoneList and RFID_SetTimeZone

RFID_GetLocalTime and RFID_SetLocalTime

RFID_GetLLRPConnectionConfig, RFID_SetLLRPConnectionConfig, RFID_InitiateLLRPConnectionFromReader and RFID_DisconnectLLRPConnectionFromReader

RFID_SetUserLED

RFID_GetUSBOperationMode and RFID_SetUSBOperationMode

RFID_GetGPIDebounceTime and RFID_SetGPIDebounceTime

3.RFID_API3_5_5 - Dll versions of 5.5.XXX supports the following additional features

a. Generic Interface

Set/Get Global Antenna Configuration

Call back Mechanism for reporting events

New Event added in RFID_EVENT_TYPE

New Enum added

Periodic Tag Report Duration

TAG_DATA is extended to report phaseInfo

Save LLRP Configuration

b. RM Interface

Idle Mode

User App Deployment

Cable Loss Compensation

Region Configuration

Power Negotiation

User Management

4.RFID_API3_5_6 - Dll versions of 5.6.XXX supports the following additional features:

a. Generic Interface

NXP

Impinj

Tag Storage

RF Survey

b. RM Interface

Antenna Configuration

LLRP Config

Reader Config

Network

Knowing the Reader Capabilities

The capabilities (or Read-Only properties) of the Reader can be known using RFID_GetReaderCaps. The reader capabilities include the following:

General Capabilities

  • Firmware Version
  • Model Name
  • Number of antennas supported
  • Number of GPIs & GPOs
  • UTC Clock supported
  • Receive Sensitivity Table
  • Tag Event Reporting Supported - Indicates the reader's ability to report tag visibility state changes(New Tag, Tag Invisible, or Tag Visibility Changed)
  • RSSI Filter Supported - Indicates the reader's ability to report tags based on the signal strength of the back-scattered signal from the tag.
  • NXP Commands Supported - Indicates whether the reader supports NXP commands like Change EAS,set Quiet, Reset Quiet,Calibrate
  • Tag Locationing Supported - Indicates whether the reader supports Tag Locationing.
  • Duty Cycle Table - if Reader supports setting of Duty Cycle from a list of values as indicated in this table.

Gen2 LLRP Capabilities

  • Block Erase supported
  • Block Write supported
  • State Aware Singulation supported
  • Maximum Number of Operation in Access Sequence
  • Maximum Pre-filters allowable per antenna
  • RF Modes

Regulatory Capabilities

  • Country Code
  • Communication Standard

UHF Band capabilities

  • Transmit Power table
  • Hopping enabled
  • Frequency Hop table if hopping enabled, this table has the frequency information
  • Fixed Frequency table if hopping not enabled, this table contains the frequency list used by the reader.The one-based position of a frequency in this list is its channel index.

Configuring the Reader

Resetting to Factory Defaults

The function RFID_ResetConfigToFactoryDefaults informs the reader to set all configurable values to factory defaults.

GPIO (General Purpose Input and Output)

GPI (General Purpose Input) Port

The function RFID_GetGPIState is used to get the current configuration and state of the specified port number. The RFID_EnableGPIPort function enables the specified port number.It is possible to register for GPI Port state change notification. Before registering, the interested port must be enabled using this RFID_EnableGPIPort.

GPO (General Purpose Output) Port

The function RFID_GetGPOState gets the current state of the specified output port number.To change the state of the specified port, the RFID_SetGPOState can be used.

Radio Power State

This is applicable only for hand held readers and FX7500. The function RFID_GetRadioPowerState gets the current power state of the RFID Radio Module whether it is turned ON or OFF. To modify the radio power state, the function RFID_SetRadioPowerState can be used.

Duty Cycle

This is applicable only for hand held readers. The function RFID_GetReaderCaps can be used to get the list of Duty Cycles supported by the reader in DUTY_CYCLE_TABLE.

Trasnmit Power Level

The function RFID_GetReaderCaps helps to get the transmit power table. This table contains the list of transmit power level supported by the reader. To set appropriate transmit power level, find the power level at appropriate index from the Transmit Power Table and pass the index to the RFID_SetAntennaConfig API for corresponding antenna. The RFID_GetAntennaConfig gets the index of the transmit power level set.

Antenna Specific Configuration

Configuration

The function RFID_SetAntennaConfig is used to set the antenna configuration to individual antenna or all the antennas.

The antenna configuration comprises of Antenna ID, Receive Sensitivity Index, Transmit Power index, Transmit Frequency Index. These indexes are refers to the Receive Sensitivity table, Transmit Power table, Frequency Hop table or Fixed Frequency table respectively. These tables are available in Reader capabilities. If the antenna ID is specified by Zero (0), the configuration is applied to all the available antennas.

RF Configuration

The function RFID_SetAntennaRfConfig is added to configure antenna RF configuration to individual antenna or all the antennas. This function is similar like RFID_SetAntennaConfig but includes additional parameters specific pertaining to antenna.

The configuration includes Receive Sensitivity Index, Transmit Power index, Transmit Frequency Index, RF Mode Table index. These indexes are refers to the Receive Sensitivity table, Transmit Power table, Frequency Hop table or Fixed Frequency table, RF Mode table respectively. These tables are available in Reader capabilities. Also, includes tari, transmit port, receive port and Antenna Stop trigger condition. The stop condition can be 'n' number of attempts, duration based.

If the antenna ID is specified by Zero (0), the configuration is applied to all the available antennas.

Properties

The physical antenna properties of the individual antenna can be known by calling the function RFID_GetPhysicalAntennaProperties. The function gets the gain and the connectivity status of the specified antenna.

Singulation Control

The function RFID_GetSingulationControl retrieves the current settings of the singulation control from the reader for the given Antenna ID.

To set the singulation control settings, the RFID_SetSingulationControl function will be used. The following settings can be configured:

  • Session: Session number to use for inventory operation
  • Tag Population: An estimate of the tag population in view of the RF field of the antenna
  • Tag Transit Time: An estimate of the time a tag will typically remain in the RF field
  • State Aware singulation Action:The action includes the Inventory state and SL flag. The action can be used if only reader supports this capability. The function RFID_GetReaderCaps helps to determine whether state-aware singulation is supported or not.

This function allows setting to individual antenna or all the antennas by specifying the antenna ID as Zero (0).

RF Mode

The reader has one or more set of C1G2 RF mode that the reader is capable of operating. The supported RF mode can be retrieved from RF Mode table using RFID_GetReaderCaps function.

The function RFID_GetRFMode gets the current index to RF Mode table and the Tari from the reader. RFID_SetRFMode function shall be used to change the RF Mode settings in the reader.

Save LLRP Configuration

The function RFID_GetSaveLlrpConfigStatus gets the current saved status of LLRP configurations. The RFID_SaveLlrpConfig function shall be used to save the LLRP configuration in the reader.

Managing Events

The Application can register for one or more events of the enumeration RFID_EVENT_TYPE so as to be notified of the same when it occurs:

Events Description
GPI_EVENT A GPI event (state change from high to low, or low to high) has occurred on a GPI port. When this event is signaled, RFID_GetEventData can be called to know the GPI port and the event that has occurred. The Dll can store a maximum of 2000 GPI_EVENT_DATA, which if not retrieved using RFID_GetEventData, results in dropping of further events.
TAG_DATA_EVENT Tag(s) are available for the Application to read. When this event is signaled RFID_GetReadTag can be called till all Tags are read from the Dll's Queue. The Dll can store a maximum of 4096 TAG_DATA by default, which if not retrieved using RFID_GetEventData, results in dropping of further events. The maximum Tag Storage count can be altered using the function RFID_SetTagStorageSettings.
BUFFER_FULL_WARNING_EVENT When the internal buffers are 90% full, this event will be signaled.
ANTENNA_EVENT A particular Antenna has been Connected/Disconnected. When this event is signaled, RFID_GetEventData can be called to know the Antenna and the Connection Status that has occurred. The Dll can store a maximum of 2000 ANTENNA_EVENT_DATA, which if not retrieved using RFID_GetEventData, results in dropping of further events.
INVENTORY_START_EVENT Inventory Operation has started. In case of periodic trigger this event will be triggered for each period.
INVENTORY_STOP_EVENT Inventory Operation has stopped. In case of periodic trigger this event will be triggered for each period.
ACCESS_START_EVENT Access Operation has started.
ACCESS_STOP_EVENT Access Operation has stopped.
DISCONNECTION_EVENT Event notifying disconnection from the Reader. When this event is signaled, RFID_GetEventData can be called to know the reason for the disconnection. The Application can call RFID_Reconnect periodically to attempt re-connection or call RFID_Disconnect to cleanup and exit.
BUFFER_FULL_EVENT When the internal buffers are 100% full, this event will be signaled and tags are discarded in FIFO manner.
NXP_EAS_ALARM_EVENT This Event is generated when Reader finds a(NXP)tag with it's EAS System bit still set to true.
READER_EXCEPTION_EVENT Event notifying that an exception has occured in the Reader. When this event is signaled, RFID_GetEventData can be called to know the reason for the exception. The Application can continue to use the connection if the reader renders is usable.
TEMPERATURE_ALARM_EVENT When Temperature reaches Threshold level, this will be generated. RFID_GetEventData can be called to get the event details like source name (PA/Ambient), current Temperature and alarm Level (Low, High or Critical)

The Application can use either win32 event based mechanism or call back mechanism to register for event notification.

Win32 Event Mechanism

The following steps have to be followed for getting event notifications:

1. The Application shall create an Event using the WIN32 API CreateEvent and pass it as the parameter for RFID_RegisterEventNotification.

  HANDLE hTagArrived = CreateEvent(NULL, FALSE, FALSE, NULL);
  rfidStatus = RFID_RegisterEventNotification(readerHandle, TAG_DATA_EVENT, hTagArrived);

  // Perform operations and wait for the Event to be signaled

2. Wait for the event to be notified or signaled.

  WaitForSingleObject(hTagArrived, INFINITE);

3. When the event is signaled, the Application shall call the function RFID_GetEventData to fetch the data associated with the respective event.

4. For de-registering an event, the Application shall call RFID_DeregisterEventNotification and close the event handle as follows:

  rfidStatus = RFID_DeregisterEventNotification(readerHandle, TAG_DATA_EVENT);
  CloseHandle(hTagArrived);

Call back Mechanism

This section describes new API that enable a Linux user to manage RFID events using a mechanism native to Linux, which is a Callback function.

The user can register a callback function for all the events he is interested in using the new API RFID_RegisterEventNotificationCallback.

1. Registering Event:

    The application shall register the call back function along with interested events.
    The call back function will be invoked when the event is raised.

    RFID_EVENT_TYPE rfidEvents[12] =
    {
        GPI_EVENT, TAG_READ_EVENT, BUFFER_FULL_EVENT, BUFFER_FULL_WARNING_EVENT,ANTENNA_EVENT, DISCONNECTION_EVENT,
        INVENTORY_START_EVENT, INVENTORY_STOP_EVENT, ACCESS_START_EVENT, ACCESS_STOP_EVENT, READER_EXCEPTION_EVENT
    };
    rfidStatus = RFID_RegisterEventNotificationCallback (readerHandle, rfidEvents,  12, (RfidEventCallbackFunction) rfidEventCallback, NULL, NULL);

2. De-register Event

    The application shall call RFID_RegisterEventNotificationCallback with parameter pFnRfidEventCallbackFunction as NULL to de-register.

Call back Mechanism and win32 Event based event handlings are mutually exclusive. Hence application shall stick to one mechanism and not attempt combination of two event handling mechanisms.

Managing Tags

Application needs to get the Tags from the Dll which are reported by Reader. Tags can be reported as part of an Inventory operation RFID_PerformInventory or a Read Access operation RFID_Read.

Starting from version RFID_API3_5_1 onwards, applications can configure to receive Tag reports that indicate the results of access operations as shown beneath.

TAG_STORAGE_SETTINGS tagStorageSettings;
RFID_GetTagStorageSettings(readerHandle,&tagStorageSettings);
tagStorageSettings.enableAccessReports = true;
RFID_SetTagStorageSettings(readerHandle,&tagStorageSettings);

Each Tag has a set of associated information along with it. During Inventory operation the Reader reports the EPC-ID of the Tag, where as during Read-Access operation the requested Memory Bank Data is also reported apart from EPC-ID. In either case, there is additional information like PC-bits, RSSI, last time seen, tag seen count, etc that will be available for each Tag. This information is reported to the Application as TAG_DATA for each Tag reported by the Reader.

Applications can also choose to enable/disable reporting of certain fields in TAG_DATA. Disabling certain fields can sometimes improve the performance as the Reader and the Dll shall not be processing that information. It can also result in specific behavior. For e.g. disabling reporting of Antenna Id can result in application receiving as single unique tag even though they were multiple entries of the same tag reported from different Antennas. The following snippet shows enabling the reporting of PeakRSSI, Tag Seen count, PC and CRC only and disabling other fields like Antenna ID, time stamps and XPC.

TAG_STORAGE_SETTINGS tagStorageSettings;
RFID_GetTagStorageSettings(readerHandle,&tagStorageSettings);
tagStorageSettings.tagFields = (UINT16)(PEAK_RSSI | TAG_SEEN_COUNT | PC |CRC);
RFID_SetTagStorageSettings(readerHandle,&tagStorageSettings);

Before the application can start getting/reading tags it has to allocate and initialize the memory for the Tag (EPC-ID and Memory-Bank) using the function RFID_AllocateTag. The Application can specify its customized memory bank data size using the function RFID_SetTagStorageSettings. The Application shall initialize the tag storage settings prior to allocating memory for TAG_DATA so that all Tag allocations reflect the applications customized memory requirement.

TAG_STORAGE_SETTINGS tagStorageSettings;
LPTAG_DATA pTagData;
tagStorageSettings.maxMemoryBankByteCount = 32; // for 256 bit Memory Bank Data
tagStorageSettings.maxTagCount = 100;
tagStorageSettings.maxTagIdByteCount = 12; // Default 96 bit EPC-Id
rfidStatus = RFID_SetTagStorageSettings(readerHandle, &tagStorageSettings);
pTagData = RFID_AllocateTag(readerHandle);

The applications can purge all tags present in Dll and Reader queues using the API RFID_PurgeTags.

Inventory operation: When RFID_PerformInventory is invoked, the application will get notified of TAG_DATA_EVENT if tags are reported back from the Reader. When notified of the same, application can call RFID_GetReadTag to fetch tags from the Dll one by one. The TAG_DATA will contain the EPC-ID (pTagID) and other information related to the tag; Being reported as part of an inventory operation, TAG_DATA's opCode will be ACCESS_OPERATION_NONE and opStatus to be ignored.

rfidStatus = RFID_PerformInventory(readerHandle, NULL, NULL, NULL, NULL);
// Lets wait for 3 seconds to see if a Tag arrives
if(WaitForSingleObject(hTagArrived, 3000) == WAIT_OBJECT_0)
{
   // You can read Tag using RFID_GetEventData
   while(RFID_API_SUCCESS == RFID_GetEventData(readerHandle, TAG_DATA_EVENT, pTagData))
       printTagData(pTagData->pTagID, pTagData->tagIDLength);
}
rfidStatus = RFID_StopInventory(readerHandle);

Single Tag - Read Access: When the application calls the function RFID_Read to read data from a specific memory bank of a particular tag, the function returns the TAG_DATA as its out-parameter shown beneath. The TAG_DATA will contain the EPC-ID (pTagID) and its opStatus will indicate the status of Access operation; Access Operation for which the TAG_DATA pertains to is indicated by the opCode [ACCESS_OPERATION_READ for Read Access]. If opStatus is ACCESS_SUCCESS pMemoryBankData will have valid data, which is the requested Memory Bank data.

// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D};
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
READ_ACCESS_PARAMS readAccessParams;
LPTAG_DATA pTagData;
readAccessParams.accessPassword = 0; // Access Password for this memory bank is zero
readAccessParams.memoryBank = MEMORY_BANK_USER; // Read from User memory bank
readAccessParams.byteCount = 64; // Read 64 Bytes
readAccessParams.byteOffset = 0; // Start reading from Offset 0
pTagData = RFID_AllocateTag(readerHandle);
rfidStatus = RFID_Read(readerHandle, specificTag, specificTagIdLength, &readAccessParams, NULL, NULL, pTagData, NULL);

Multiple Tags : Read Access: When the application calls the function RFID_Read to read data from a specific memory bank of multiple tags, the function RFID_Read returns immediately, and reports the Tags asynchronously as done in Inventory operation. The TAG_DATA reported will contain the EPC-ID (pTagID) and its opStatus will indicate the status of Access operation [opCode will be ACCESS_OPERATION_READ for Read Access]. If opStatus is ACCESS_SUCCESS pMemoryBankData will have valid data, which is the requested Memory Bank data.

rfidStatus = RFID_Read(readerHandle, NULL, 0, &readAccessParams, NULL, NULL, NULL, NULL);
WaitForSingleObject(accessComplete, INFINITE);
// Fetch the tags
while(RFID_API_SUCCESS == RFID_GetReadTag(readerHandle, pTagData))
{
    If(pTagData->opStatus == ACCESS_SUCCESS)
    {
       // print the Tag ID and Memory Bank
    }
}

Access Operation Sequence : Read Access: When the application calls the function RFID_PerformAccessSequence further to adding operations for Read (using RFID_AddOperationToAccessSequence of type ACCESS_OPERATION_READ), the function RFID_PerformAccessSequence returns immediately, and reports tags asynchronously, as shown in use-case no 3.

It depends on the Application requirement to determine how many TAG_DATA needs to be allocated. A typical example of a simple UI application that just displays a list of inventoried tags would allocate one TAG_DATA and use it repeatedly in further calls to RFID_GetReadTag.

When the application is done with using the TAG_DATA allocated using RFID_AllocateTag, it shall call RFID_DeallocateTag. The Application shall not deallocate the TAG_DATA or its internal members (pTagID, pMemoryBankData) by itself, doing which shall result in unexpected behavior.

Basic operations

This section covers the basic/simple operations that an application would need to be performed on an RFID Reader which includes Inventory and single tag access operations.

Simple Inventory (Continuous)

A simple continuous inventory operation would read all tags in the field of view of all antennas of the connected RFID Reader. It will use NO filters (pre-filters or post-filters) and the start and stop trigger for the inventory would be default, i.e. start immediately when RFID_PerformInventory is called, and stop immediately when RFID_StopInventory is called.

rfidStatus = RFID_PerformInventory(readerHandle, NULL, NULL, NULL, NULL);
// Wait as long as needed to perform a continuous inventory.
// Keep getting tags using RFID_GetReadTag when TAG_DATA_EVENT is signaled.
// getting Tags can also be done on a separate Read-Thread
rfidStatus = RFID_StopInventory(readerHandle);

Simple Access Operations - On Single Tag

Tag Access operations can be performed on a specific tag or can be applied on tags that match a specific Access-Filter. If no Access-filter is specified the Access Operation will be performed on all Tags in the field of view of chosen Antennas.

This section covers simple tag access operation on a specific tag which could be in the field of view of any of the antenna of the connected RFID Reader.

Read

The application can call RFID_Read to read data from a specific memory bank.

// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D}; 
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
READ_ACCESS_PARAMS readAccessParams;
LPTAG_DATA pTagData;
readAccessParams.accessPassword = 0; // Access Password for accessing this memory bank is zero
readAccessParams.memoryBank = MEMORY_BANK_USER; // Read from User memory bank
readAccessParams.byteCount = 64; // Read 64 Bytes
readAccessParams.byteOffset = 0; // Start reading from Offset 0
pTagData = RFID_AllocateTag(readerHandle);
rfidStatus = RFID_Read(readerHandle, specificTag, specificTagIdLength, &readAccessParams, NULL, NULL, pTagData, NULL);

Write, Block-Write

The application can call RFID_Write or RFID_BlockWrite to write data to a specific memory bank.

// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D}; 
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
WRITE_ACCESS_PARAMS writeAccessParams;
UINT8 writeUserData[64];
writeAccessParams.accessPassword = 0; // Access Password for accessing this memory bank is zero
writeAccessParams.memoryBank = MEMORY_BANK_USER; // Write to User memory bank
writeAccessParams.byteOffset = 0; // Start writing from Offset 0
writeAccessParams.writeDataLength = 64; // Write 64 Bytes
//Fill in the Data to be written into writeUserData
writeAccessParams.pWriteData = writeUserData;
rfidStatus = RFID_Write(readerHandle, specificTag, specificTagIdLength, &writeAccessParams, NULL, NULL, NULL);

Lock

The application can call RFID_Lock to perform lock operation on one or more memory banks with specific privileges.

// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D}; 
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
LOCK_ACCESS_PARAMS lockAccessParams;
lockAccessParams.accessPassword = 0xAAAAAAAA; // Access Password to be applied.
lockAccessParams.privilege[LOCK_USER_MEMORY] = LOCK_PRIVILEGE_READ_WRITE;
lockAccessParams.privilege[LOCK_TID_MEMORY] = LOCK_PRIVILEGE_READ_WRITE;
rfidStatus = RFID_Lock(readerHandle, specificTag, specificTagIdLength, &lockAccessParams, &accessFilter, NULL, NULL);

Kill

The application can call RFID_Kill to kill a tag.

// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D}; 
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
KILL_ACCESS_PARAMS killAccessParams;
killAccessParams.killPassword = 0xAAAAAAAA;
rfidStatus = RFID_Kill(readerHandle, specificTag, specificTagIdLength,&killAccessParams, NULL, NULL, NULL);

Block-Erase

The application can call RFID_BlockErase to erase the contents of a tag.

// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D}; 
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
BLOCK_ERASE_ACCESS_PARAMS blockEraseAccessParams;
blockEraseAccessParams.accessPassword = 0;
blockEraseAccessParams.memoryBank = MEMORY_BANK_USER;
blockEraseAccessParams.byteCount = 100; // Number of bytes to be erased
blockEraseAccessParams.byteOffset = 0; // Start erasing from Offset 0
rfidStatus = RFID_BlockErase(readerHandle, specificTag, specificTagIdLength,&blockEraseAccessParams, NULL, NULL, NULL);

Block-Permalock

The application can call RFID_BlockPermalock to block permalock the contents of a tag. The TAG_DATA will contain the EPC-ID (pTagID) and its opStatus will indicate the status of Access operation; Access Operation for which the TAG_DATA pertains to is indicated by the opCode [ACCESS_OPERATION_BLOCK_PERMALOCK for BlockPermalock Access]. If opStatus is ACCESS_SUCCESS pMemoryBankData will have valid data, which is the Block-Permalock Mask Data.

// EPC-Id of the Tag on which the Access operation is to be performed.
UINT8 specificTag[12] = {0xFD, 0x02, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0X23, 0X7D}; 
UINT32 specificTagIdLength = 12; // Length of the Tag-Id (EPC-Id) Array
UINT8 lockMask[4] = {0xF0, 0x00, 0x00, 0x00};
BLOCK_PERMALOCK_ACCESS_PARAMS Block-PermalockAccessParams;
Block-PermalockAccessParams.accessPassword = 0xAAAAAAAA; // Access Password
Block-PermalockAccessParams.readLock = TRUE;
Block-PermalockAccessParams.memoryBank = MEMORY_BANK_USER
Block-PermalockAccessParams.byteOffset = 0;
Block-PermalockAccessParams.byteCount = 4;
Block-PermalockAccessParams.mask = lockMask;
Block-PermalockAccessParams.maskLength = 4;
rfidStatus = RFID_Block-Permalock(readerHandle, specificTag, specificTagIdLength, &Block-PermalockAccessParams, NULL, NULL, NULL, NULL);

Access Operations on specific memory field of Single Tag

The following functions are wrappers around RFID_Write API and assists in writing to specific memory fields of a specific Tag.

  • RFID_WriteTagID - This function writes to TagID of a specific tag and adjusts the PC bits according to the length of the TagID. When the TagID is modified, this API ensures that the Tag shall subsequently backscatter the modified EPC, for which it also writes the length of the new or updated (PC + EPC) into the first 5 bits of the Tag's PC.
  • RFID_WriteKillPassword - This function writes the kill password of a specific tag.
  • RFID_WriteAccessPassword - This function writes the access password of the a specific tag.

Advanced operations

Tag Event Reporting

This feature can be used to enable reporting tag visibility changes. If a reader supports this feature it reports the Reader Capability tagEventReportingSupported as true. The following code snippet enabled reporting tags when a Tag is visible/Gone out of Visibility/Back to visibility for at least 100 ms TRIGGER_INFO triggerInfo;

TAG_EVENT_REPORT_INFO tagEventReportInfo;
triggerInfo.lpTagEventReportInfo = &tagEventReportInfo;
triggerInfo.tagReportTrigger = 1;
tagEventReportInfo.reportNewTagEvent = MODERATED;
tagEventReportInfo.reportTagBackToVisibilityEvent = MODERATED;
tagEventReportInfo.reportTagInvisibleEvent = MODERATED;
tagEventReportInfo.newTagEventModeratedTimeoutMilliseconds = 100;
tagEventReportInfo.tagBackToVisibilityModeratedTimeoutMilliseconds = 100;
tagEventReportInfo.tagInvisibleEventModeratedTimeoutMilliseconds = 100;
triggerInfo.startTrigger.type = START_TRIGGER_TYPE_IMMEDIATE;
triggerInfo.stopTrigger.type = STOP_TRIGGER_TYPE_IMMEDIATE;
rfidStatus = RFID_PerformInventory(readerHandle, NULL, NULL, &triggerInfo, NULL);

TAG_EVENT reported as part of TAG_DATA indicates the visibility state of the Tag.

Using Pre-Filters

Pre-filters are same as the Select command of C1G2 specification. Once applied, pre-filters are applied prior to Inventory and Access operations.

Introduction

Singulation

Singulation refers to the method of identifying an individual Tag in a multiple-Tag environment. RFID Readers could support State-Aware or State-Unaware pre-filtering (or singulation) which is indicated by the boolean flag stateAwareSingulationSupported in the READER_CAPS and can be known using the function RFID_GetReaderCaps.

In order to filter tags that match a specific condition, it is necessary to use the tag-sessions and their states (setting the tags to different states based on match criteria- RFID_AddPreFilter) so that while performing inventory, tags can be instructed to participate (singulation - RFID_SetSingulationControl) or not participate in the inventory based on their states.

Sessions and Inventoried Flags

Tags provide 4 sessions (denoted S0, S1, S2, and S3) and maintain an independent inventoried flag for each session. Each of the four inventoried flags has two values, denoted A and B. These inventoried flag of each session can be set to A or B based on match criteria using function RFID_AddPreFilter.

Selected Flag

Tags provide a selected flag, SL, which can be asserted or deasserted based on match criteria using function RFID_AddPreFilter.

State-Unaware Singulation

In state-unaware singulation the Reader permits 6 options (as enumerated by STATE_UNAWARE_ACTION) of filtering tags. This is more simplified than state-aware singulation.

State-Aware Singulation

In state-aware singulation the Application can specify detailed controls for singulation: Action and Target. Action indicates whether matching Tags assert or deassert SL (Selected Flag), or set their inventoried flag to A or to B. Tags conforming to the match criteria specified using the function RFID_AddPreFilter are considered matching and the remaining are non-matching. Target indicates whether to modify a Tag's SL flag or its inventoried flag, and in the case of inventoried it further specifies one of four sessions.

Truncate Action

Truncate action specifies whether a Tag backscatters its entire EPC, or only that portion of the EPC immediately following Mask. During truncated replies a Tag substitutes 00000 for the PC bits. Truncated replies are always followed by the CRC-16 in EPC memory 00h to 0Fh; a Tag does not recompute this CRC for a truncated reply.

Applying Pre-Filters

The following are the steps to use pre-filters:

  • Add pre-filters
  • Set appropriate singulation controls
  • Perform Inventory or Access operation

Add Pre-filters

Each RFID Reader supports a maximum number of Pre-Filters per Antenna as indicated by maxNumPreFilters in the READER_CAPS which can be known using the function RFID_GetReaderCaps. The application can set pre-filters using RFID_AddPreFilter and remove using RFID_DeletePreFilter. To set pre-filter for all antennas, use zero for antennaID.

State-Unaware Singulation

PRE_FILTER prefilter;
UINT8 tagMask[2] = {0x12, 0x11};
prefilter.filterAction = FILTER_ACTION_STATE_UNAWARE; // use state unaware singulation
//do not select tags that match the criteria in this pre-filter (Tags whose EPC-ID starts with 0x1211)
prefilter.filterActionParams.stateUnawareAction = STATE_UNAWARE_ACTION_UNSELECT; 
prefilter.memoryBank = MEMORY_BANK_EPC;
prefilter.bitOffset = 32; // skip the PC bits
prefilter.tagPatternBitCount = 2 * 8;
prefilter.pTagPattern = tagMask; // Tags whose EPC-ID starts with 0x1211
//Set this filter for Antenna Number 3
rfidStatus = RFID_AddPreFilter(readerHandle, 3, &prefilter, &filterIndex); // filterIndex can be used later to Delete pre-filters

State-Aware Singulation

PRE_FILTER prefilter;
UINT8 tagMask[2] = {0x12, 0x11};
prefilter.filterAction = FILTER_ACTION_STATE_AWARE;
prefilter.filterActionParams.stateAwareParams.target = TARGET_INVENTORIED_STATE_S1;
prefilter.filterActionParams.stateAwareParams.stateAwareAction = STATE_AWARE_ACTION_INV_B;
// So as not to select tags that match the criteria in this pre-filter (Tags whose EPC-ID starts with 0x1211) 
    // lets put inventoried flag of session S1 of matching tags to B; We will also have to set appropriate singulation control
    // not to get tags with inventoried flag B for session S1.
prefilter.memoryBank = MEMORY_BANK_EPC;
prefilter.bitOffset = 32; // skip the PC bits
prefilter.tagPatternBitCount = 2 * 8;
prefilter.pTagPattern = tagMask; // Tags whose EPC-ID starts with 0x1211
//Set this filter for Antenna Number 3
rfidStatus = RFID_AddPreFilter(readerHandle, 3, &prefilter, &filterIndex); // filterIndex can be used later to Delete pre-filters

Set appropriate Singulation Controls

Now that the pre-filters are set (i.e. Tags are classified into matching or non-matching criteria), the Application needs to specify which tags should participate in the Inventory using RFID_SetSingulationControl. Singulation Control also can be specified with respect to each Antenna like Pre-Filters. To set singulation for all antennas, use zero for antennaID.

State-Unaware Singulation

//Set all required values in Singualtion Control
// Set Session to operate as S1. If not specified Reader uses its own way of implementing the State-unaware singulation.
singulationControl.session = SESSION_S1;    
rfidStatus = RFID_SetSingulationControl(readerHandle, 3, &singulationControl);

State-Aware Singulation

//Set all required values in Singualtion Control
singulationControl.session = SESSION_S1;
singulationControl.stateAwareSingulationAction.perform = true;
singulationControl.stateAwareSingulationAction.inventoryState = INVENTORY_STATE_B;
singulationControl.stateAwareSingulationAction.slFlag = SL_FLAG_DEASSERTED;
rfidStatus = RFID_SetSingulationControl(readerHandle, 3, &singulationControl);

Perform Inventory or Access Operation

Inventory or Access operation when performed after setting pre-filters, will use the tags filtered out of pre-filters for their operation.

Using Triggers

Triggers are the conditions that should be satisfied in order to start or stop an operation (Inventory or AccessSequence). This information can be specified using TRIGGER_INFO. The application can also configure the Tag-Report trigger which indicates when to receive 'n' unique Tag-Reports from the Reader. Refer to TRIGGER_INFO for more information.

The following are some use-cases of using TRIGGER_INFO

GPI based Inventory - Start inventory when GPI port 'n' changes state to TRUE and stop inventory when GPI port n changes state to FALSE.

TRIGGER_INFO triggerInfo;
triggerInfo.tagReportTrigger = 1; // Report back each tag report as and when its read by the reader
triggerInfo.startTrigger.type = START_TRIGGER_TYPE_GPI;
triggerInfo.startTrigger.value.gpi.eventInfo = TRUE;
triggerInfo.startTrigger.value.gpi.portNumber =  1;
triggerInfo.stopTrigger.type = STOP_TRIGGER_TYPE_GPI_WITH_TIMEOUT;
triggerInfo.stopTrigger.value.gpi.eventInfo = FALSE;
triggerInfo.stopTrigger.value.gpi.portNumber =  1;
triggerInfo.stopTrigger.value.gpi.timeoutMilliseconds =  1000;

Periodic Inventory - Start inventory at a specified time for a specified duration repeatedly.

// This trigger starts Inventory on 12th of this month, and 12AM,
// and runs for 200 milliseconds every second.

TRIGGER_INFO triggerInfo;
triggerInfo.tagReportTrigger = 0; // Report back all read tags after completion of one round of inventory (i.e. one period).
triggerInfo.startTrigger.type = START_TRIGGER_TYPE_PERIODIC;
triggerInfo.startTrigger.value.periodic.periodMilliseconds = 1000; /*perform inventory for 1 sec*/
SYSTEMTIME startTime;
GetSystemTime(&startTime);
startTime.wDay = 12;
startTime.wHour = 12;
triggerInfo.startTrigger.value.periodic.startTime = &startTime;
triggerInfo.stopTrigger.type = STOP_TRIGGER_TYPE_DURATION;
triggerInfo.stopTrigger.value.durationMilliseconds = 200;/*Stop after 200 milliseconds*/

Perform 'n' Rounds of Inventory with a timeout - Start condition could be any; Stop condition is to perform 'n' rounds of inventory and then stop or stop inventory after the specified timeout.

TRIGGER_INFO triggerInfo;
triggerInfo.tagReportTrigger = 0; // Report back all read tags after 3 rounds of inventory).
triggerInfo.startTrigger.type = START_TRIGGER_TYPE_IMMEDIATE;
triggerInfo.stopTrigger.type = STOP_TRIGGER_TYPE_N_ATTEMPTS_WITH_TIMEOUT;
triggerInfo.stopTrigger.value.numAttempts.n = 3; // perform 3 rounds of inventory
triggerInfo.stopTrigger.value.numAttempts.timeoutMilliseconds = 3000; // timeout after 3 seconds

Read 'n' Tags with a timeout - Start condition could be any; Stop condition is to stop after reading 'n' tags or stop inventory after the specified timeout.

TRIGGER_INFO triggerInfo;
triggerInfo.tagReportTrigger = 100; // Report back all read tags after getting 100 unique tags or after 3 seconds).
triggerInfo.startTrigger.type = START_TRIGGER_TYPE_IMMEDIATE;
triggerInfo.stopTrigger.type = STOP_TRIGGER_TYPE_TAG_OBSERVATION_WITH_TIMEOUT;
triggerInfo.stopTrigger.value.tagObservation.n = 100; // Stop inventory after reading 100 Tags
triggerInfo.stopTrigger.value.tagObservation.timeoutMilliseconds = 3000;

Inventory

Inventory with Triggers

There are various situations that act as conditions (triggers) for performing inventory.

Refer section "Using Triggers" to configure Triggers.

The following shows an example of performing 1 round of Inventory on Antennas 1 and 3.

ANTENNA_INFO antennaInfo;
UINT16 antennaIDList[2] = {1,3};// Antennas for the operation are 1 and 3.
antennaInfo.pAntennaList = antennaIDList;
antennaInfo.length = 2;
TRIGGER_INFO triggerInfo;
triggerInfo.tagReportTrigger = 0; // Report back all read tags after 3 rounds of inventory).
triggerInfo.startTrigger.type = START_TRIGGER_TYPE_IMMEDIATE;
triggerInfo.stopTrigger.type = STOP_TRIGGER_TYPE_N_ATTEMPTS_WITH_TIMEOUT;
triggerInfo.stopTrigger.value.numAttempts.n = 1; // perform 1 round of inventory
triggerInfo.stopTrigger.value.numAttempts.timeoutMilliseconds = 0; // Reader's default timeout
rfidStatus = RFID_PerformInventory(readerHandle, NULL, &antennaInfo, &triggerInfo, NULL);

Using Post-Filters

Post-filters are those filters which are applied on the Tags that the reader received after prefiltering (if any).

Post-filters allow the application to set one or two tag patterns and to specify a condition as a combination of the patterns.

The following snippet shows setting a post-filter that does not get tags starting with 0x1111 and 0x2222.

POST_FILTER postFilter;
TAG_PATTERN tagPatternA;
TAG_PATTERN tagPatternB;
UINT8 tagMask[64] = {0xFF};
UINT8 tagData[2];
/* Populate two post-filter patterns */
memset(tagMask, 0xFF, 64);
tagPatternA.memoryBank = MEMORY_BANK_EPC;
tagPatternA.bitOffset = 0x20;// Skip the PC bits
tagData[0] = tagData[1] = 0x11;
tagPatternA.pTagPattern = tagData;
tagPatternA.tagPatternBitCount = tagPatternA.tagMaskBitCount = 2 * 8;
tagPatternA.tagMaskBitCount = tagPatternA.tagPatternBitCount;
tagPatternA.pTagMask = tagMask;
tagPatternB.memoryBank = MEMORY_BANK_EPC;
tagPatternB.bitOffset = 0x20; // Skip the PC bits
tagData[0] = tagData[1] = 0x22;
tagPatternB.pTagPattern = tagData;
tagPatternB.tagPatternBitCount = tagPatternB.tagMaskBitCount = 2 * 8;
tagPatternB.tagMaskBitCount = tagPatternB.tagPatternBitCount;
tagPatternB.pTagMask = tagMask;
postFilter.lpTagPatternA = &tagPatternA;
postFilter.lpTagPatternB = &tagPatternB;
postFilter.matchPattern = NOTA_AND_NOTB;
RFID_API_SUCCESS == RFID_PerformInventory(readerHandle, &postFilter, NULL,NULL, NULL)

Using RSSI Filtering in Post Filters Starting from version RFID_API3_5_1 onwards, applications can use RSSI based filtering if supported by the reader. This is indicated by the field rssiFilterSupported of READER_CAPS. The following code snippet does filtering of tags which have RSSI value in range -40 to -10.

POST_FILTER postFilter;
RSSI_RANGE_FILTER rssiRangeFilter;
postFilter.lpTagPatternA = NULL;
postFilter.lpTagPatternB = NULL;
postFilter.lpRSSIRangeFilter = &rssiRangeFilter;
rssiRangeFilter.peakRSSILowerLimit = -40;
rssiRangeFilter.peakRSSIUpperLimit = -10;
rssiRangeFilter.matchRange = WITHIN_RANGE;
rfidStatus = RFID_PerformInventory(readerHandle, &postFilter, NULL, &triggerInfo, NULL);

Access

Using Access-Filters

In order to perform an access operation on multiple tags, the Application can set ACCESS_FILTER to filter the required tags. If ACCESS_FILTER is not specified, the operation will be performed on all Tags. In any case, the PRE_FILTER(s) if any is set will apply prior to ACCESS_FILTER.

The following Access-filter gets all tags that have zeroed Reserved memory bank.

ACCESS_FILTER accessFilter;
UINT8 tagData[8];
UINT8 tagMask[8];
memset(tagMask, 0xFF, 8);
memset(tagData, 0, 8);
tagPatternA.memoryBank = MEMORY_BANK_RESERVED;
tagPatternA.bitOffset = 0;
tagPatternA.pTagPattern = tagData;
tagPatternA.tagPatternBitCount = tagPatternA.tagMaskBitCount = 8 * 8;
tagPatternA.pTagMask = tagMask;
accessFilter.lpTagPatternA = &tagPatternA;
accessFilter.lpTagPatternB = NULL;

Access Operation on Multiple Tags

Performing a single Access operation on multiple tags is an asynchronous operation. The function issues the access-operation and returns. The Reader performs one round of inventory using pre-filters if any, and then applies the access-filters and the resultant tags are subject to the access-operation. When the access operation is complete, the Dll signals the event ACCESS_STOP_EVENT. The Application can call the function RFID_GetLastAccessResult to know the result. In case of Read access operation RFID_Read the event TAG_DATA_EVENT is signalled when Tags are reported.

The following snippet shows a sample write-access operation:

WRITE_ACCESS_PARAMS writeAccessParams;
UINT8 writeUserData[64];
UINT32 accessSuccessCount, accessFailureCount;
HANDLE accessComplete = CreateEvent(NULL, FALSE, FALSE, NULL);
RFID_RegisterEventNotification(readerHandle, ACCESS_STOP_EVENT, accessComplete);
writeAccessParams.accessPassword = 0;
writeAccessParams.memoryBank = MEMORY_BANK_USER;
writeAccessParams.byteOffset = 0;
writeAccessParams.writeDataLength = 64;
writeAccessParams.pWriteData = writeUserData;
memset(writeAccessParams.pWriteData, 0xAA, writeAccessParams.writeDataLength);
rfidStatus = RFID_Write(readerHandle, NULL, 0, &writeAccessParams, &accessFilter, NULL, NULL);
if(RFID_API_SUCCESS == rfidStatus)
{
    accessSuccessCount = accessFailureCount = 0;
    WaitForSingleObject(accessComplete, INFINITE);
    rfidStatus =  RFID_GetLastAccessResult(readerHandle,
    &accessSuccessCount, &accessFailureCount);
}

Using Access Sequence

The Application can issue multiple access operations on a single go using Access-Sequence API. This is useful when each tag from a set of (access-filtered) tags is to be subject to an order of access operations. The maximum number of access-operations that can be specified in an access sequence is specified in maxNumOperationsInAccessSequence of READER_CAPS. The Application shall first initialize the access-sequence using RFID_InitializeAccessSequence before adding operations to it using RFID_AddOperationToAccessSequence. The operations will be performed in the same order in which it is added to it sequence. An operation can be removed from the sequence using RFID_DeleteOperationFromAccessSequence and finally deinitialized if no more needed by calling the function RFID_DeinitializeAccessSequence.

rfidStatus = RFID_InitializeAccessSequence(readerHandle);
UINT32 opCode = 0;
readAccessParams.accessPassword = 0;
readAccessParams.memoryBank = MEMORY_BANK_EPC;
readAccessParams.byteCount = 6;
readAccessParams.byteOffset = 4;
opCodeParams.opCode = ACCESS_OPERATION_READ;
opCodeParams.opParams = &readAccessParams;
rfidStatus = RFID_AddOperationToAccessSequence(readerHandle, &opCodeParams, &opCode);
// Add multiple access-operations.
HANDLE accessStopped = CreateEvent(NULL, FALSE, FALSE, NULL);
RFID_RegisterEventNotification(readerHandle, ACCESS_STOP_EVENT, accessStopped);
status = RFID_PerformAccessSequence(readerHandle, NULL, NULL, &triggerInfo, NULL);
DWORD thisEvent = WaitForSingleObject(accessStopped, INFINITE);
// If the access operation is to be terminated without meeting
// the stop trigger ( if specified), RFID_StopAccessSequence can be called.
rfidStatus =  RFID_StopAccessSequence(readerHandle);

NXP Custom Tag Support

Readers which support NXP commands report the same in the field NXPCommandsSupported of READER_CAPS as true. The following operations can be performed on NXPTags:

1) RFID_NXPSetEAS - This API can be used to set/reset the EAS (Electronic Article Surveillance) Bit. Tags can be monitored for EAS bit for the purpose of theft detection. For E.g Tags with EAS enabled moving out could be an indication of unbilled item or theft. The API RFID_NXPSetEAS lets you set or reset the EAS bits on one or more NXP tags. An NXP tag with EAS bit set will raise an NXP_EAS_ALARM_EVENT when running EAS SCAN NXP_EAS_SCAN on the reader.

2) RFID_NXPReadProtect and RFID_NXPResetReadProtect - The API RFID_NXPReadProtect sets the Quiet bit on one or more NXP tags. As a result, these tags trace-back a string of zeroes during Inventory and don't respond to access-operations, there by preventing unsecure access to Tag information. To put them back into normal mode, one has to call RFID_NXPResetReadProtect API.

3) Performing NXP Scan - To track NXP tags in which the EAS bit is set, an NXP_EAS_SCAN can be initiated on the reader by calling RFID_PerformNXPEASScan or RFID_PerformInventory API with its AntennaInfo parameter specifying NXP_EAS_SCAN as the OPERATION_QUALIFIER for at least one of the Antenna IDs in the AntennaList array.

4) Perform NXP BrandID check (supported only on NXP U-Code 8 and above tags that supports this functionality). Brand ID check can be initiated by API RFID_NXPBrandCheck. Reader performs an inventory operation with additional verification on whether or not tag inventoried matches the BrandID specified as parameter in RFID_NXPBrandCheck. Tags inventoried and matching the Brand ID will be reported with brandValid field of TAG_DATA for that tag set to 1 if there is a match else 0. Ongoing Brand ID check operation can be explicitly stopped using RFID_NXPStopBrandCheck.

Impinj TagFocus Feature

Impinj's Monza 4, Monza 5, and Monza R6 tag chips offer a feature called TagFocus. This feature enables a reader to instruct tags to continue to refresh their A/B flag setting such that they remain in a non-responsive state. By instructing tags that have already been inventoried to remain silent while inventorying other tags, reader has a far greater chance of finding difficult-to-read tags. This feature can be enabled by configuring antenna's singulation settings and applying a pre-filter (same as the Select command of C1G2 specification) with specific parameter values. This feature can be disabled by deleting the pre-filter with specific parameter values from the API.

Note: This feature is applicable only for FX7500 ,FX9600 and RE40.

// Get the Reader Capability

READER_CAPS readerCaps;
RFID_GetReaderCaps(readerHandle, &readerCaps);
// configure antenna's singulation settings using Session 1 with Flag A
for(UINT16 nIndex = 1; nIndex <= readerCaps.numAntennas; nIndex++)
{
    SINGULATION_CONTROL SingulationControl;
    RFID_GetSingulationControl(readerHandle, nIndex, &SingulationControl);
    SingulationControl.stateAwareSingulationAction.perform = true;
    SingulationControl.session = SESSION_S1;
    SingulationControl.stateAwareSingulationAction.inventoryState = INVENTORY_STATE_A;
    SingulationControl.stateAwareSingulationAction.slFlag = SL_FLAG_DEASSERTED;
    RFID_SetSingulationControl(readerHandle, nIndex, &SingulationControl);
}
//apply a pre-filter to the reader with specific parameter values
RFID_DeletePreFilter(readerHandle, 0, 0); // delete all existing pre-filters first

UINT32 tagFocusFilterIndex = 0;
PRE_FILTER tagFocusFilter;
UINT8 tagMask[3] = {0x80, 0x06, 0x00};
tagFocusFilter.bitOffset = 6;
tagFocusFilter.pTagPattern = tagMask;
tagFocusFilter.tagPatternBitCount = 20;
tagFocusFilter.memoryBank = MEMORY_BANK_TID;
tagFocusFilter.filterAction = FILTER_ACTION_STATE_AWARE;
tagFocusFilter.filterActionParams.stateAwareParams.target = TARGET_INVENTORIED_STATE_S1;
tagFocusFilter.filterActionParams.stateAwareParams.stateAwareAction = STATE_AWARE_ACTION_INV_B;

RFID_AddPreFilter(readerHandle, 0, &tagFocusFilter, &tagFocusFilterIndex);
//perform simple inventory 
RFID_PerformInventory(readerHandle, NULL, NULL, NULL, NULL);
//disable TagFocus feature
RFID_DeletePreFilter(readerHandle, 0, tagFocusFilterIndex);

Clean-up and Disconnect

When the application is done with the connection and with the operations on the RFID-Reader, it shall call RFID_Disconnect to close the connection and to release and clean up the resources.

rfidStatus = RFID_Disconnect(readerHandle);

Reader Management Interface

Overview

The reader allows set of reader management functionality via reader management interface. The reader requires login authentication prior to perform any other management functions. The management functions such as software/firmware upgrade, set the antenna mode, enable or disable the read point (Antenna) and set the radio power state can be performed through the management interface.

The RFID_Login function returns the handle to the reader management interface. The other functions must use this handle to perform the required operation.

After application is done with the reader management operations, the RFID_Logout function must be called for cleaning up the resources allocated during the RFID_Login function.

Connecting to the Reader

The RFID_Login must be called first to perform any reader management functions.

In case of fixed readers, the login information such as user name, password and secured mode are required for performing login operation. The secure mode parameter specifies that whether the mode of communication is HTTP or HTTPS. Based on this parameter, the internal communication between the client and the reader uses the specified transport interface. If supported by the Reader, there is an option to override an existing login session using the forceLogin option of LOGIN_INFO. This is currently supported on FX 7400 Version 1.1.0 and higher.

The login Info is not required for the Hand held readers. But it is must to call the RFID_Login function first prior to other reader management functions.

Updating Firmware or Software of the Reader

Fixed Reader

The reader allows to update software includes the OS, applications from the given FTP Server location. Starting from version RFID_API3_5_1 onwards, the API also supports the "push model" software update, which allows updating software from non-FTP locations (E.g. D:\NewSoftware) also. This is currently supported on FX 7400 Version 1.1.0 and higher.

The function RFID_UpdateSoftware helps to perform the software update functionality.

Read Points

The function RFID_EnableReadPoint allows enabling or disabling the read point (Antenna) for the specified antenna ID.

To know the connection status of the antenna, the RFID_GetReadPointConnectStatus can be called.

Antenna Modes

The fixed reader supports the two modes of operation namely Mono-static and Bi-Static. The RFID_GetAntennaMode gets the current configured mode. The function RFID_SetAntennaMode allows changing the mode to either mono-static or bi-static.

Getting System Info

The function RFID_GetSystemInfo helps to get the reader system information. This includes Radio Firmware version, FPGA version, Up time, reader name, location, RAM available & Flash memory available.

This API also gets the device Information which includes Hostname, Manufacturer, Model, Hardware version, Boot Loader version, and Number of Physical antennas supported.

Managing Reader Configuration

The reader supports managing the reader configuration files, called profiles. The reader configuration is typically managed as XML files.

The list of configurations supported by a reader can be obtained from API RFID_GetProfileList. This API is supported only on FX SERIES.

The upload of configuration file can be performed using RRFID_ExportProfileToReader. The absolute file path of the source file must be specified. For example, "C:\Profiles"

The function RFID_DeleteProfile deletes the profile from the reader. To activate a profile in the reader, the function RFID_SetActiveProfile can be used.

The function RFID_SetSysLogServer allows to route the syslogs to remote syslog server. This API takes remote syslog server host name, port number & minimum severity as parameters. The API RFID_GetSysLogServer gets the current syslog configuration.

This function RFID_FactoryReset does the reset to factory defaults configuration. This wipes out region configuration, reader information, cable loss, Time related configuration and all other user configurations.

Managing LLRP Connection and Configuration

The RFID Reader can be configured in LLRP client or server mode using the function RFID_SetLLRPConnectionConfig and current setting can be retrieved using RFID_GetLLRPConnectionConfig. While acting in client mode, the function RFID_InitiateLLRPConnectionFromReader can be used to initiate an LLRP Connection from the reader to the port on the Server-IP as configured in LLRP_CONNECTION_CONFIG. RFID_DisconnectLLRPConnectionFromReader disconnects the current LLRP Connection from the reader.

The function RFID_GetLLRPConnectionStatus gets the current connected status of LLRP connection and the client IP address who is connected to LLRP server.

USB Operation Mode

This feature is supported only on FX series readers. The FX Reader's USB connection can be configured to be either ActiveSync or Network. While in ActiveSync mode, the ActiveSync application running on host gets connected as soon as the USB cable connected to the Reader is plugged in to the host. While in Network mode, the Reader and the host gets connected as a network, reader being 169.254.10.1. This acts as a fallback mechanism to login to the Reader's web console to know its primary IP. The APIs RFID_GetUSBOperationMode and RFID_SetUSBOperationMode can be used for this.

GPI DeBounce Time

This feature is supported only on FX series readers. The debounce time is used to filter out unwanted GPI signals. If the debounce time is greater than that GPI's on time, then the GPI will be ignored. If the debounce time is less that the GPI on time, then the GPI will be detected. The APIs RFID_GetGPIDebounceTime and RFID_SetGPIDebounceTime can be used for this.

Local Time

API support for Getting and Setting the local time of the Reader is provided only on FX series readers. The APIs RFID_GetLocalTime and RFID_SetLocalTime can be used for this.

Time Zone

API support for this feature is supported only on FX series readers. Getting the Time zone list, current time zone and setting the time zone of the can be done using the APIs RFID_GetTimeZoneList and RFID_SetTimeZone.

Network

This feature is supported only on FX series readers. The API support for getting and setting the Network settings such as DHCP or Static IP Address configuration for Ethernet, Wi-Fi and Bluetooth interface. The APIs RFID_GetNetworkInterfaceSettings and RFID_SetNetworkInterfaceSettings can be used for this.

For getting or setting NTP server, the APIs RFID_SetNTPServer and RFID_GetNTPServer can be used this. The reader time (UTC) is synchronized with the NTP Server configured.

To establish connection Wi-Fi access point, the API RFID_SetWirelessNetwork can be used to configure ESS ID, Passkey and auto connect on reboot. RFID_GetWirelessConfigParameters gets the current Wireless configuration.

User LED

Setting the user LED is supported only on FX series readers. The API RFID_SetUserLED can be used for this.

Reader Statistics

Getting per antenna Reader Statistics and clearing off the statistics is supported only on FX series readers. The API RFID_GetReaderStats and RFID_ClearReaderStats can be used for this. This API gets the inventory and access operation successful and failure counts. Also, includes Ambient/PA temperature critical, high & low alarm counts, forward/reverse power high, low alarm counts, echo threshold alarm counts, and GPIO information counts.

Reader and System Information

Getting the Reader's System Info like Firmware version, uptime, ram-available, flash-available, etc can be done using RFID_GetSystemInfo. Getting and Setting the Reader Information like name, description, location and contact information can be done using RFID_GetReaderInfo and RFID_SetReaderInfo.

Idle Mode

This feature is supported only in FX7500 reader. The Idle Mode Timeout allows the reader to switch off the radio module power, after a specified timer interval elapsed only if reader is in idle state (Not performing any radio related operation like inventory or access). Radio will be powered on if any inventory/access operation is initiated from client application.

The APIs RFID_TurnOffRadioWhenIdle and RFID_GetRadioIdleTimeout can be used for this.

Cable Loss Compensation

This feature is supported only in FX7500 reader. Typically RF power transmitted at the antenna is lesser than transmit power at the port due to loss in cable. Once the cable loss in dB per 100 feet and cable length in feet are configured per antenna, the reader sets new upper limit for the transmit power after accounting for the specified loss in cable.

The APIs RFID_SetCableLossCompensation and RFID_GetCableLossCompensation can be used for this.

User App Deployment

This feature is supported only in FX7500 reader. The following functionalities are supported for facilitating embedded user application on the FX7500.

  • Installation and un-installation of the user application
  • Listing the set of currently installed user applications
  • Starting and Stopping the user application
  • Getting the current Run status
  • Auto start of the upper application on reader reboot

The APIs that are exposed in RFID3 to support of deployment of user application are:

Region Configuration

The following APIs are exposed to configure region:

Power Negotiation

This feature is supported only in FX7500 reader and applicable only when the reader is connected to LLDP enabled POE+ switch. This feature enables the reader to negotiate power with switch. On granting power, the reader power source switches to POE+ mode.

The following APIs are exposed:

Restarting the Reader

The reader can be rebooted or restarted by calling the function RFID_Restart. This functionality is not supported on hand-held readers.

Disconnecting the Reader

The RFID_Logout function does the clean-up activity for the reader management interface. This must be called once the application has done with Reader management functions.

64-bit Support

The 64 bit Dll for RFID API is rfidapi32PC.dll. The name of the Dll is same as the 32-bit counterpart. 32-bit Applications can be recompiled to 64-bit applications as mentioned in section beneath.

Compiling EMDK Sample Applications for 64-bit support Existing RFID Samples (BasicRFIDHost1 & RFIDHostSample1) can be compiled for 64-bit machine by the following steps:

1) Ensure that Visual Studio 2005 or Visual Studio 2008 is installed for 64-bit support so that 64-bit applications can be compiled.

2) Open the solution file which is to be compiled.

3) Open Configuration Manager and add New Solution Platform and New Project Platform 'x64' if it is not present.

4) Set the active platform for the current project as 'x64'.

5) Add _WIN64 to the preprocessor definitions of the project to be compiled.

6) In the project properties, open Linker -> Advanced -> Target Machine. Set this as  MachineX64 (/MACHINE:X64)

7) Now the environment is ready to build a 64-bit application.