From 9cc3dca98b65d6db531c517561634ad239220137 Mon Sep 17 00:00:00 2001 From: Romuald Conty Date: Sun, 10 Jan 2010 18:14:26 +0000 Subject: [PATCH] Improve Doxygen generation. Move doxygen comment from header to source (make installed header more cleaner). --- Doxyfile.in | 10 +- Makefile.am | 4 +- src/include/nfc/nfc.h | 201 ++------------------------------------- src/lib/drivers/acr122.c | 1 - src/lib/nfc.c | 198 ++++++++++++++++++++++++++++++++++---- 5 files changed, 195 insertions(+), 219 deletions(-) diff --git a/Doxyfile.in b/Doxyfile.in index dca9399..b4a483e 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -56,9 +56,9 @@ EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = YES HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES @@ -76,7 +76,7 @@ GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES -SHOW_DIRECTORIES = NO +SHOW_DIRECTORIES = YES SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = @@ -114,7 +114,7 @@ FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- -SOURCE_BROWSER = NO +SOURCE_BROWSER = YES INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO diff --git a/Makefile.am b/Makefile.am index 9e777e9..84090ce 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,8 +12,8 @@ if DOC_ENABLED clean-local: rm -rf doc -html-am : Doxyfile +doc : Doxyfile @DOXYGEN@ $(builddir)/Doxyfile -.PHONY: html +.PHONY: doc endif diff --git a/src/include/nfc/nfc.h b/src/include/nfc/nfc.h index 6563f47..8051617 100644 --- a/src/include/nfc/nfc.h +++ b/src/include/nfc/nfc.h @@ -17,8 +17,8 @@ * along with this program. If not, see * * - * @file libnfc.h - * @brief libnfc interface + * @file nfc.h + * @brief nfc interface * * Provide all usefull functions (API) to handle NFC devices. */ @@ -36,229 +36,40 @@ extern "C" { #endif // __cplusplus -/** - * @fn void nfc_list_devices(nfc_device_desc_t *pnddDevices[], size_t szDevices, size_t *pszDeviceFound) - * @brief Probe for discoverable supported devices (ie. only available for some drivers) - * @param pnddDevices Array of nfc_device_desc_t previously allocated by the caller. - * @param szDevices size of the pnddDevices array. - * @param pszDeviceFound number of devices found. - */ void nfc_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound); -/** - * @fn nfc_device_t* nfc_connect(nfc_device_desc_t* pndd) - * @brief Connect to a NFC device - * @param pndd Device description if specific device is wanted, NULL otherwise - * @return Returns pointer to a nfc_device_t struct if successfull; otherwise returns NULL value. - * - * If \a pndd is NULL, the first available NFC device is claimed by libnfc. - * It will automatically search the system using all available drivers to determine a device is free. - * - * If \a pndd is passed then libnfc will try to claim the right device using information provided by this struct. - * - * When it has successfully claimed a NFC device, memory is allocated to save the device information. It will return a pointer to a nfc_device_t struct. - * This pointer should be supplied by every next function of libnfc that should perform an action with this device. - */ nfc_device_t* nfc_connect(nfc_device_desc_t* pndd); -/** - * @fn void nfc_disconnect(nfc_device_t* pnd) - * @brief Disconnect from a NFC device - * @param pnd nfc_device_t struct pointer that represent currently used device - * - * Initiator is disconnected and the device, including allocated nfc_device_t struct, is released. - */ void nfc_disconnect(nfc_device_t* pnd); -/** - * @fn nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, const bool bEnable) - * @brief Configure advanced NFC device settings - * @return Returns true if action was successfully performed; otherwise returns false. - * @param pnd nfc_device_t struct pointer that represent currently used device - * @param ndo nfc_device_option_t struct that contains options to set to device - * @param bEnable boolean - * - * Configures parameters and registers that control for example timing, modulation, frame and error handling. - * There are different categories for configuring the PN53X chip features (handle, activate, infinite and accept). - * These are defined to organize future settings that will become available when they are needed. - */ bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t ndo, const bool bEnable); - -/** - * @fn nfc_initiator_init(const nfc_device_t* pnd) - * @brief Initialize NFC device as initiator (reader) - * @return Returns true if action was successfully performed; otherwise returns false. - * @param pnd nfc_device_t struct pointer that represent currently used device - * - * The NFC device is configured to function as RFID reader. After initialization it can be used to communicate to passive RFID tags and active NFC devices. The reader will act as initiator to communicate peer 2 peer (NFCIP) to other active NFC devices. - */ bool nfc_initiator_init(const nfc_device_t* pnd); -/** - * @fn nfc_initiator_select_tag(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtInitData, const size_t szInitDataLen, nfc_target_info_t* pti) - * @brief Select a passive or emulated tag - * @return Returns true if action was successfully performed; otherwise returns false. - * @param pnd nfc_device_t struct pointer that represent currently used device - * @param im Desired modulation - * @param pbtInitData Optional initiator data used for Felica, ISO14443B, Topaz Polling or for ISO14443A selecting a specific UID. - * @param szInitDataLen Length of initiator data \a pbtInitData. - * - * The NFC device will try to find the available passive tags. Some NFC devices are capable to emulate passive tags. The standards (ISO18092 and ECMA-340) describe the modulation that can be used for reader to passive communications. The chip needs to know with what kind of tag it is dealing with, therefore the initial modulation and speed (106, 212 or 424 kbps) should be supplied. - * @note For every initial modulation type there is a different collection of information returned (in nfc_target_info_t pointer pti) They all fit in the data-type which is called nfc_target_info_t. This is a union which contains the tag information that belongs to the according initial modulation type. - */ bool nfc_initiator_select_tag(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtInitData, const size_t szInitDataLen, nfc_target_info_t* pti); -/** - * @fn nfc_initiator_select_dep_target(const nfc_device_t *pnd, const nfc_modulation_t nmInitModulation, const byte_t *pbtPidData, const size_t szPidDataLen, const byte_t *pbtNFCID3i, const size_t szNFCID3iDataLen, const byte_t *pbtGbData, const size_t szGbDataLen, nfc_target_info_t * pti); - * @brief Select a target and request active or passive mode for DEP (Data Exchange Protocol) - * @return Returns true if action was successfully performed; otherwise returns false. - * @param pnd nfc_device_t struct pointer that represent currently used device - * @param im Desired modulation (NM_ACTIVE_DEP or NM_PASSIVE_DEP for active, respectively passive mode) - * @param pbtPidData passive initiator data, 4 or 5 bytes long, (optional, only for NM_PASSIVE_DEP, can be NULL) - * @param pbtNFCID3i the NFCID3, 10 bytes long, of the initiator (optional, can be NULL) - * @param pbtGbData generic data of the initiator, max 48 bytes long, (optional, can be NULL) - * - * The NFC device will try to find the available target. The standards (ISO18092 and ECMA-340) describe the modulation that can be used for reader to passive communications. - * @note nfc_target_info_t_dep will be returned when the target was acquired successfully. - */ bool nfc_initiator_select_dep_target(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtPidData, const size_t szPidDataLen, const byte_t* pbtNFCID3i, const size_t szNFCID3iDataLen, const byte_t *pbtGbData, const size_t szGbDataLen, nfc_target_info_t* pti); -/** - * @fn nfc_initiator_deselect_tag(const nfc_device_t* pnd); - * @brief Deselect a selected passive or emulated tag - * @return Returns true if action was successfully performed; otherwise returns false. - * @param pnd nfc_device_t struct pointer that represent currently used device - * - * After selecting and communicating with a passive tag, this function could be used to deactivate and release the tag. This is very useful when there are multiple tags available in the field. It is possible to use the nfc_initiator_select_tag() function to select the first available tag, test it for the available features and support, deselect it and skip to the next tag until the correct tag is found. - */ bool nfc_initiator_deselect_tag(const nfc_device_t* pnd); -/** - * @fn nfc_initiator_transceive_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar) - * @brief Transceive raw bit-frames - * @return Returns true if action was successfully performed; otherwise returns false. - * @param pbtTx contains a byte array of the frame that needs to be transmitted. - * @param szTxBits contains the length in bits. - * @note For example the REQA (0x26) command (first anti-collision command of ISO14443-A) must be precise 7 bits long. This is not possible by using nfc_initiator_transceive_bytes(). With that function you can only communicate frames that consist of full bytes. When you send a full byte (8 bits + 1 parity) with the value of REQA (0x26), a tag will simply not respond. More information about this can be found in the anti-colision example. - * @param pbtTxPar parameter contains a byte array of the corresponding parity bits needed to send per byte. - * @note For example if you send the SELECT_ALL (0x93, 0x20) = [ 10010011, 00100000 ] command, you have to supply the following parity bytes (0x01, 0x00) to define the correct odd parity bits. This is only an example to explain how it works, if you just are sending two bytes with ISO14443-A compliant parity bits you better can use the nfc_initiator_transceive_bytes() function. - * @returns The received response from the tag will be stored in the parameters (pbtRx, pszRxBits and pbtRxPar). They work the same way as the corresponding parameters for transmission. - * - * The NFC reader will transmit low-level messages where only the modulation is handled by the PN53X chip. Construction of the frame (data, CRC and parity) is completely done by libnfc. This can be very useful for testing purposes. Some protocols (e.g. MIFARE Classic) require to violate the ISO14443-A standard by sending incorrect parity and CRC bytes. Using this feature you are able to simulate these frames. - */ bool nfc_initiator_transceive_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar); -/** - * @fn nfc_initiator_transceive_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) - * @brief Transceive byte and APDU frames - * @return Returns true if action was successfully performed; otherwise returns false. - * - * The reader will transmit the supplied bytes in pbtTx to the target (tag). It waits for the response and stores the received bytes in the pbtRx byte array. The parity bits are handled by the PN53X chip. The CRC can be generated automatically or handled manually. Using this function, frames can be communicated very fast via the NFC reader to the tag. Tests show that on average this way of communicating is much faster than using the regular driver/middle-ware (often supplied by manufacturers). - * @warning The configuration option NDO_HANDLE_PARITY must be set to true (the default value). - */ bool nfc_initiator_transceive_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); - -/** - * @fn nfc_initiator_transceive_dep_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) - * @brief Transceive data - * @return Returns true if action was successfully performed; otherwise returns false. - * - * The reader will transmit the supplied (data) bytes in pbtTx to the target (tag). It waits for the response and stores the received bytes in the pbtRx byte array. The difference between this function and nfc_initiator_transceive_bytes is that here pbtTx and pbtRx contain *only* the data sent and received and not any additional commands, that is all handled internally by the PN53X. - */ bool nfc_initiator_transceive_dep_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); -/** - * @fn nfc_initiator_mifare_cmd(const nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp) - * @brief Execute a MIFARE Classic Command - * @return Returns true if action was successfully performed; otherwise returns false. - * @param pmp Some commands need additional information. This information should be supplied in the mifare_param union. - * - * The specified MIFARE command will be executed on the tag. There are different commands possible, they all require the destination block number. - * @note There are three different types of information (Authenticate, Data and Value). - * - * First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID. They are both used to initialize the internal cipher-state of the PN53X chip (http://libnfc.org/hardware/pn53x-chip). After a successful authentication it will be possible to execute other commands (e.g. Read/Write). The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process. - */ bool nfc_initiator_mifare_cmd(const nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp); - -/** - * @fn nfc_target_init(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits) - * @brief Initialize NFC device as an emulated tag - * @return Returns true if action was successfully performed; otherwise returns false. - * - * This functionality allows the NFC device to act as an emulated tag. There seems to be quite some options available for this feature. Not all of the PN53X modulations are tested and documented at the moment. At the moment it could best be seen as a preliminary functionality. - * - * @warning Be aware that this function will wait (hang) until a command is received that is not part of the anti-collision. The RATS command for example would wake up the emulator. After this is received, the send and receive functions can be used. - */ bool nfc_target_init(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits); - -/** - * @fn nfc_target_receive_bits(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar) - * @brief Receive bit-frames - * @return Returns true if action was successfully performed; otherwise returns false. - * - * This function makes it possible to receive (raw) bit-frames. It returns all the messages that are stored in the FIFO buffer of the PN53X chip. It does not require to send any frame and thereby could be used to snoop frames that are transmitted by a nearby reader. Check out the NDO_ACCEPT_MULTIPLE_FRAMES configuration option to avoid losing transmitted frames. - */ bool nfc_target_receive_bits(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar); - -/** - * @fn nfc_target_receive_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) - * @brief Receive bytes and APDU frames - * @return Returns true if action was successfully performed; otherwise returns false. - * - * The main receive function that returns the received frames from a nearby reader. - */ bool nfc_target_receive_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen); - -/** - * @fn nfc_target_receive_dep_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) - * @brief Receive data - * @return Returns true if action was successfully performed; otherwise returns false. - * - * The main receive function that returns the received data from a nearby reader. The difference between this function and nfc_target_receive_bytes is that here pbtRx contains *only* the data received and not any additional commands, that is all handled internally by the PN53X. - */ bool nfc_target_receive_dep_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen); - -/** - * @fn nfc_target_send_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar) - * @brief Send raw bit-frames - * @return Returns true if action was successfully performed; otherwise returns false. - * - * This function can be used to transmit (raw) bit-frames to the reader. - */ bool nfc_target_send_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar); - -/** - * @fn nfc_target_send_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) - * @brief Send bytes and APDU frames - * @return Returns true if action was successfully performed; otherwise returns false. - * - * To communicate byte frames and APDU responses to the reader, this function could be used. - */ bool nfc_target_send_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen); - -/** - * @fn nfc_target_send_dep_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) - * @brief Send data - * @return Returns true if action was successfully performed; otherwise returns false. - * - * To communicate data to the reader, this function could be used. The difference between this function and nfc_target_send_bytes is that here pbtTx contains *only* the data sent and not any additional commands, that is all handled internally by the PN53X. - */ bool nfc_target_send_dep_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen); -/** - * @fn const char* nfc_version(void) - * @brief Returns the library version - * @return Returns a string with the library version - */ -const char* nfc_version(void); - -/** - * @fn const char*nfc_device_name(nfc_device_t* pnd) - * @brief Returns the device name - * @return Returns a string with the device name - */ - +/* Special data accessors */ const char* nfc_device_name(nfc_device_t* pnd); +/* Misc. functions */ +const char* nfc_version(void); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/src/lib/drivers/acr122.c b/src/lib/drivers/acr122.c index b805901..580b8b2 100644 --- a/src/lib/drivers/acr122.c +++ b/src/lib/drivers/acr122.c @@ -118,7 +118,6 @@ acr122_pick_device (void) } /** - * @fn bool acr122_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound) * @brief List connected devices * * Probe PCSC to find NFC capable hardware. diff --git a/src/lib/nfc.c b/src/lib/nfc.c index 7bb2c82..4cbfba3 100644 --- a/src/lib/nfc.c +++ b/src/lib/nfc.c @@ -1,4 +1,4 @@ -/** +/*- * Public platform independent Near Field Communication (NFC) library * * Copyright (C) 2009, Roel Verdult @@ -15,13 +15,14 @@ * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see - * - * + * + */ + +/** * @file nfc.c * @brief NFC library implementation */ - #include #include #include @@ -83,6 +84,12 @@ nfc_pick_device (void) return NULL; } +/** + * @brief Probe for discoverable supported devices (ie. only available for some drivers) + * @param pnddDevices Array of nfc_device_desc_t previously allocated by the caller. + * @param szDevices size of the pnddDevices array. + * @param pszDeviceFound number of devices found. + */ void nfc_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszDeviceFound) { @@ -108,6 +115,19 @@ nfc_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *pszD } } +/** + * @brief Connect to a NFC device + * @param pndd Device description if specific device is wanted, NULL otherwise + * @return Returns pointer to a nfc_device_t struct if successfull; otherwise returns NULL value. + * + * If \a pndd is NULL, the first available NFC device is claimed by libnfc. + * It will automatically search the system using all available drivers to determine a device is free. + * + * If \a pndd is passed then libnfc will try to claim the right device using information provided by this struct. + * + * When it has successfully claimed a NFC device, memory is allocated to save the device information. It will return a pointer to a nfc_device_t struct. + * This pointer should be supplied by every next function of libnfc that should perform an action with this device. + */ nfc_device_t* nfc_connect(nfc_device_desc_t* pndd) { nfc_device_t* pnd = NULL; @@ -191,6 +211,12 @@ nfc_device_t* nfc_connect(nfc_device_desc_t* pndd) return NULL; } +/** + * @brief Disconnect from a NFC device + * @param pnd nfc_device_t struct pointer that represent currently used device + * + * Initiator is disconnected and the device, including allocated nfc_device_t struct, is released. + */ void nfc_disconnect(nfc_device_t* pnd) { // Release and deselect all active communications @@ -201,6 +227,17 @@ void nfc_disconnect(nfc_device_t* pnd) pnd->pdc->disconnect(pnd); } +/** + * @brief Configure advanced NFC device settings + * @return Returns true if action was successfully performed; otherwise returns false. + * @param pnd nfc_device_t struct pointer that represent currently used device + * @param ndo nfc_device_option_t struct that contains options to set to device + * @param bEnable boolean + * + * Configures parameters and registers that control for example timing, modulation, frame and error handling. + * There are different categories for configuring the PN53X chip features (handle, activate, infinite and accept). + * These are defined to organize future settings that will become available when they are needed. + */ bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t dco, const bool bEnable) { byte_t btValue; @@ -267,6 +304,14 @@ bool nfc_configure(nfc_device_t* pnd, const nfc_device_option_t dco, const bool return true; } + +/** + * @brief Initialize NFC device as initiator (reader) + * @return Returns true if action was successfully performed; otherwise returns false. + * @param pnd nfc_device_t struct pointer that represent currently used device + * + * The NFC device is configured to function as RFID reader. After initialization it can be used to communicate to passive RFID tags and active NFC devices. The reader will act as initiator to communicate peer 2 peer (NFCIP) to other active NFC devices. + */ bool nfc_initiator_init(const nfc_device_t* pnd) { // Make sure we are dealing with a active device @@ -281,6 +326,18 @@ bool nfc_initiator_init(const nfc_device_t* pnd) return true; } +/** + * @brief Select a target and request active or passive mode for DEP (Data Exchange Protocol) + * @return Returns true if action was successfully performed; otherwise returns false. + * @param pnd nfc_device_t struct pointer that represent currently used device + * @param im Desired modulation (NM_ACTIVE_DEP or NM_PASSIVE_DEP for active, respectively passive mode) + * @param pbtPidData passive initiator data, 4 or 5 bytes long, (optional, only for NM_PASSIVE_DEP, can be NULL) + * @param pbtNFCID3i the NFCID3, 10 bytes long, of the initiator (optional, can be NULL) + * @param pbtGbData generic data of the initiator, max 48 bytes long, (optional, can be NULL) + * + * The NFC device will try to find the available target. The standards (ISO18092 and ECMA-340) describe the modulation that can be used for reader to passive communications. + * @note nfc_target_info_t_dep will be returned when the target was acquired successfully. + */ bool nfc_initiator_select_dep_target(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtPidData, const size_t szPidDataLen, const byte_t* pbtNFCID3i, const size_t szNFCID3iDataLen, const byte_t *pbtGbData, const size_t szGbDataLen, nfc_target_info_t* pnti) { byte_t abtRx[MAX_FRAME_LEN]; @@ -330,6 +387,18 @@ bool nfc_initiator_select_dep_target(const nfc_device_t* pnd, const nfc_modulati return true; } +/** + * @fn nfc_initiator_select_tag(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtInitData, const size_t szInitDataLen, nfc_target_info_t* pti) + * @brief Select a passive or emulated tag + * @return Returns true if action was successfully performed; otherwise returns false. + * @param pnd nfc_device_t struct pointer that represent currently used device + * @param im Desired modulation + * @param pbtInitData Optional initiator data used for Felica, ISO14443B, Topaz Polling or for ISO14443A selecting a specific UID. + * @param szInitDataLen Length of initiator data \a pbtInitData. + * + * The NFC device will try to find the available passive tags. Some NFC devices are capable to emulate passive tags. The standards (ISO18092 and ECMA-340) describe the modulation that can be used for reader to passive communications. The chip needs to know with what kind of tag it is dealing with, therefore the initial modulation and speed (106, 212 or 424 kbps) should be supplied. + * @note For every initial modulation type there is a different collection of information returned (in nfc_target_info_t pointer pti) They all fit in the data-type which is called nfc_target_info_t. This is a union which contains the tag information that belongs to the according initial modulation type. + */ bool nfc_initiator_select_tag(const nfc_device_t* pnd, const nfc_modulation_t nmInitModulation, const byte_t* pbtInitData, const size_t szInitDataLen, nfc_target_info_t* pnti) { byte_t abtInit[MAX_FRAME_LEN]; @@ -467,11 +536,32 @@ bool nfc_initiator_select_tag(const nfc_device_t* pnd, const nfc_modulation_t nm return true; } +/** + * @fn nfc_initiator_deselect_tag(const nfc_device_t* pnd); + * @brief Deselect a selected passive or emulated tag + * @return Returns true if action was successfully performed; otherwise returns false. + * @param pnd nfc_device_t struct pointer that represent currently used device + * + * After selecting and communicating with a passive tag, this function could be used to deactivate and release the tag. This is very useful when there are multiple tags available in the field. It is possible to use the nfc_initiator_select_tag() function to select the first available tag, test it for the available features and support, deselect it and skip to the next tag until the correct tag is found. + */ bool nfc_initiator_deselect_tag(const nfc_device_t* pnd) { return (pn53x_transceive(pnd,pncmd_initiator_deselect,3,NULL,NULL)); } +/** + * @fn nfc_initiator_transceive_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar) + * @brief Transceive raw bit-frames + * @return Returns true if action was successfully performed; otherwise returns false. + * @param pbtTx contains a byte array of the frame that needs to be transmitted. + * @param szTxBits contains the length in bits. + * @note For example the REQA (0x26) command (first anti-collision command of ISO14443-A) must be precise 7 bits long. This is not possible by using nfc_initiator_transceive_bytes(). With that function you can only communicate frames that consist of full bytes. When you send a full byte (8 bits + 1 parity) with the value of REQA (0x26), a tag will simply not respond. More information about this can be found in the anti-colision example. + * @param pbtTxPar parameter contains a byte array of the corresponding parity bits needed to send per byte. + * @note For example if you send the SELECT_ALL (0x93, 0x20) = [ 10010011, 00100000 ] command, you have to supply the following parity bytes (0x01, 0x00) to define the correct odd parity bits. This is only an example to explain how it works, if you just are sending two bytes with ISO14443-A compliant parity bits you better can use the nfc_initiator_transceive_bytes() function. + * @returns The received response from the tag will be stored in the parameters (pbtRx, pszRxBits and pbtRxPar). They work the same way as the corresponding parameters for transmission. + * + * The NFC reader will transmit low-level messages where only the modulation is handled by the PN53X chip. Construction of the frame (data, CRC and parity) is completely done by libnfc. This can be very useful for testing purposes. Some protocols (e.g. MIFARE Classic) require to violate the ISO14443-A standard by sending incorrect parity and CRC bytes. Using this feature you are able to simulate these frames. + */ bool nfc_initiator_transceive_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar) { byte_t abtRx[MAX_FRAME_LEN]; @@ -530,6 +620,12 @@ bool nfc_initiator_transceive_bits(const nfc_device_t* pnd, const byte_t* pbtTx, return true; } +/** + * @brief Transceive data + * @return Returns true if action was successfully performed; otherwise returns false. + * + * The reader will transmit the supplied (data) bytes in pbtTx to the target (tag). It waits for the response and stores the received bytes in the pbtRx byte array. The difference between this function and nfc_initiator_transceive_bytes is that here pbtTx and pbtRx contain *only* the data sent and received and not any additional commands, that is all handled internally by the PN53X. + */ bool nfc_initiator_transceive_dep_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; @@ -561,6 +657,13 @@ bool nfc_initiator_transceive_dep_bytes(const nfc_device_t* pnd, const byte_t* p return true; } +/** + * @brief Transceive byte and APDU frames + * @return Returns true if action was successfully performed; otherwise returns false. + * + * The reader will transmit the supplied bytes in pbtTx to the target (tag). It waits for the response and stores the received bytes in the pbtRx byte array. The parity bits are handled by the PN53X chip. The CRC can be generated automatically or handled manually. Using this function, frames can be communicated very fast via the NFC reader to the tag. Tests show that on average this way of communicating is much faster than using the regular driver/middle-ware (often supplied by manufacturers). + * @warning The configuration option NDO_HANDLE_PARITY must be set to true (the default value). + */ bool nfc_initiator_transceive_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; @@ -591,6 +694,16 @@ bool nfc_initiator_transceive_bytes(const nfc_device_t* pnd, const byte_t* pbtTx return true; } +/** + * @brief Execute a MIFARE Classic Command + * @return Returns true if action was successfully performed; otherwise returns false. + * @param pmp Some commands need additional information. This information should be supplied in the mifare_param union. + * + * The specified MIFARE command will be executed on the tag. There are different commands possible, they all require the destination block number. + * @note There are three different types of information (Authenticate, Data and Value). + * + * First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID. They are both used to initialize the internal cipher-state of the PN53X chip (http://libnfc.org/hardware/pn53x-chip). After a successful authentication it will be possible to execute other commands (e.g. Read/Write). The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process. + */ bool nfc_initiator_mifare_cmd(const nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp) { byte_t abtRx[MAX_FRAME_LEN]; @@ -651,6 +764,14 @@ bool nfc_initiator_mifare_cmd(const nfc_device_t* pnd, const mifare_cmd mc, cons return true; } +/** + * @brief Initialize NFC device as an emulated tag + * @return Returns true if action was successfully performed; otherwise returns false. + * + * This functionality allows the NFC device to act as an emulated tag. There seems to be quite some options available for this feature. Not all of the PN53X modulations are tested and documented at the moment. At the moment it could best be seen as a preliminary functionality. + * + * @warning Be aware that this function will wait (hang) until a command is received that is not part of the anti-collision. The RATS command for example would wake up the emulator. After this is received, the send and receive functions can be used. + */ bool nfc_target_init(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits) { byte_t abtRx[MAX_FRAME_LEN]; @@ -704,6 +825,12 @@ bool nfc_target_init(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits) return true; } +/** + * @brief Receive bit-frames + * @return Returns true if action was successfully performed; otherwise returns false. + * + * This function makes it possible to receive (raw) bit-frames. It returns all the messages that are stored in the FIFO buffer of the PN53X chip. It does not require to send any frame and thereby could be used to snoop frames that are transmitted by a nearby reader. Check out the NDO_ACCEPT_MULTIPLE_FRAMES configuration option to avoid losing transmitted frames. + */ bool nfc_target_receive_bits(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar) { byte_t abtRx[MAX_FRAME_LEN]; @@ -736,6 +863,12 @@ bool nfc_target_receive_bits(const nfc_device_t* pnd, byte_t* pbtRx, size_t* psz return true; } +/** + * @brief Receive data + * @return Returns true if action was successfully performed; otherwise returns false. + * + * The main receive function that returns the received data from a nearby reader. The difference between this function and nfc_target_receive_bytes is that here pbtRx contains *only* the data received and not any additional commands, that is all handled internally by the PN53X. + */ bool nfc_target_receive_dep_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; @@ -754,6 +887,12 @@ bool nfc_target_receive_dep_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t return true; } +/** + * @brief Receive bytes and APDU frames + * @return Returns true if action was successfully performed; otherwise returns false. + * + * The main receive function that returns the received frames from a nearby reader. + */ bool nfc_target_receive_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) { byte_t abtRx[MAX_FRAME_LEN]; @@ -772,6 +911,12 @@ bool nfc_target_receive_bytes(const nfc_device_t* pnd, byte_t* pbtRx, size_t* ps return true; } +/** + * @brief Send raw bit-frames + * @return Returns true if action was successfully performed; otherwise returns false. + * + * This function can be used to transmit (raw) bit-frames to the reader. + */ bool nfc_target_send_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar) { size_t szFrameBits = 0; @@ -809,6 +954,12 @@ bool nfc_target_send_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const si } +/** + * @brief Send bytes and APDU frames + * @return Returns true if action was successfully performed; otherwise returns false. + * + * To communicate byte frames and APDU responses to the reader, this function could be used. + */ bool nfc_target_send_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) { byte_t abtCmd[sizeof(pncmd_target_send)]; @@ -827,6 +978,12 @@ bool nfc_target_send_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const s return true; } +/** + * @brief Send data + * @return Returns true if action was successfully performed; otherwise returns false. + * + * To communicate data to the reader, this function could be used. The difference between this function and nfc_target_send_bytes is that here pbtTx contains *only* the data sent and not any additional commands, that is all handled internally by the PN53X. + */ bool nfc_target_send_dep_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) { byte_t abtCmd[sizeof(pncmd_target_set_data)]; @@ -845,20 +1002,29 @@ bool nfc_target_send_dep_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, con return true; } -const char* nfc_version(void) -{ -#ifdef SVN_REVISION - return PACKAGE_VERSION" (r"SVN_REVISION")"; -#else - return PACKAGE_VERSION; -#endif // SVN_REVISION -} +/* Special data accessors */ -// functions to provide external hooks to python (or other languages) - that cannot -// handle structures in return values when used as a DLL - -// function to return device name of device that has already been configured/claimed +/** + * @brief Returns the device name + * @return Returns a string with the device name ( MUST be freed with free() ) + */ const char* nfc_device_name(nfc_device_t* pnd) { return pnd->acName; } + +/* Misc. functions */ + +/** + * @brief Returns the library version + * @return Returns a string with the library version + */ +const char* nfc_version(void) +{ + #ifdef SVN_REVISION + return PACKAGE_VERSION" (r"SVN_REVISION")"; + #else + return PACKAGE_VERSION; + #endif // SVN_REVISION +} +