Ejemplo n.º 1
0
        public static int nfc_initiator_select_passive_target(nfc_device pnd, nfc_modulation nm, byte[] pbtInitData, int szInitData, /*out*/ nfc_target pnt)
        {
            byte[] abtInit = new byte[Math.Max(12, pbtInitData.Length)];
            // byte abtTmpInit[MAX(12, szInitData)];
            int szInit = 0;

            if (pbtInitData == null || szInitData == 0)
            {
                // Provide default values, if any
                abtInit = prepare_initiator_data(nm);
                szInit  = abtInit.Length;
            }
            else if (nm.nmt == nfc_modulation_type.NMT_ISO14443A)
            {
                //abtInit = abtTmpInit;
                iso14443_cascade_uid(pbtInitData, szInitData, ref abtInit, out szInit);
            }
            else
            {
                abtInit = pbtInitData;
                szInit  = szInitData;
            }

            //HAL(initiator_select_passive_target, pnd, nm, abtInit, szInit, pnt);
            pnd.last_error = 0;
            return(pnd.driver.initiator_select_passive_target(pnd, nm, abtInit, szInit, /*out*/ pnt));
        }
Ejemplo n.º 2
0
 /** @ingroup initiator
  * @brief Transceive raw bit-frames to a target
  * @return Returns received bits count on success, otherwise returns libnfc's error code
  *
  * This function is similar to nfc_initiator_transceive_bits() with the following differences:
  * - A precise cycles counter will indicate the number of cycles between emission & reception of frames.
  * - It only supports mode with \a NP_EASY_FRAMING option disabled and CRC must be handled manually.
  * - Overall communication with the host is heavier and slower.
  *
  * Timer control:
  * By default timer configuration tries to maximize the precision, which also limits the maximum
  * cycles count before saturation/timeout.
  * E.g. with PN53x it can count up to 65535 cycles, so about 4.8ms, with a precision of about 73ns.
  * - If you're ok with the defaults, set *cycles = 0 before calling this function.
  * - If you need to count more cycles, set *cycles to the maximum you expect but don't forget
  *   you'll loose in precision and it'll take more time before timeout, so don't abuse!
  *
  * @warning The configuration option \a NP_EASY_FRAMING must be set to \c false.
  * @warning The configuration option \a NP_HANDLE_CRC must be set to \c false.
  * @warning The configuration option \a NP_HANDLE_PARITY must be set to \c true (the default value).
  */
 public static int nfc_initiator_transceive_bits_timed(nfc_device pnd, byte[] pbtTx, int szTxBits, byte[] pbtTxPar, byte[] pbtRx, int szRx, byte[] pbtRxPar, ref UInt32 cycles)
 {
     if (0 == szRx)
     {
         throw new Exception("Invalid argument: szRx=0");
     }
     pnd.last_error = 0;
     return(pnd.driver.initiator_transceive_bits_timed(pnd, pbtTx, szTxBits, pbtTxPar, pbtRx, szRx, pbtRxPar, ref cycles));
 }
Ejemplo n.º 3
0
        /* NFC Device/Hardware manipulation */
        /// <summary>
        /// nfc_open
        /// </summary>
        /// <param name="context"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public static nfc_device nfc_open(nfc_context context, string port)
        {
            nfc_device dev = pn532_uart.getInstance().open(context, port);

            if (null == dev)
            {//log error handle
            }
            else
            {
            }
            return(dev);
        }
Ejemplo n.º 4
0
        /* NFC initiator: act as "reader" */
        public static int nfc_initiator_init(nfc_device pnd)
        {
            int res = 0;

            // Drop the field for a while
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_ACTIVATE_FIELD, false)) < 0)
            {
                return(res);
            }
            // Enable field so more power consuming cards can power themselves up
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_ACTIVATE_FIELD, true)) < 0)
            {
                return(res);
            }
            // Let the device try forever to find a target/tag
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_INFINITE_SELECT, true)) < 0)
            {
                return(res);
            }
            // Activate auto ISO14443-4 switching by default
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_AUTO_ISO14443_4, true)) < 0)
            {
                return(res);
            }
            // Force 14443-A mode
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_FORCE_ISO14443_A, true)) < 0)
            {
                return(res);
            }
            // Force speed at 106kbps
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_FORCE_SPEED_106, true)) < 0)
            {
                return(res);
            }
            // Disallow invalid frame
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_ACCEPT_INVALID_FRAMES, false)) < 0)
            {
                return(res);
            }
            // Disallow multiple frames
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_ACCEPT_MULTIPLE_FRAMES, false)) < 0)
            {
                return(res);
            }
            //HAL
            pnd.last_error = 0;
            return(pnd.driver.initiator_init(pnd));
        }
Ejemplo n.º 5
0
        /* NFC target: act as tag (i.e. MIFARE Classic) or NFC target device. */

        /** @ingroup target
         * @brief Initialize NFC device as an emulated tag
         * @return Returns received bytes count on success, otherwise returns libnfc's error code
         *
         * @param pnd \a nfc_device struct pointer that represent currently used device
         * @param pnt pointer to \a nfc_target struct that represents the wanted emulated target
         *
         * @note \a pnt can be updated by this function: if you set NBR_UNDEFINED
         * and/or NDM_UNDEFINED (ie. for DEP mode), these fields will be updated.
         *
         * @param[out] pbtRx Rx buffer pointer
         * @param[out] szRx received bytes count
         * @param timeout in milliseconds
         *
         * This function initializes NFC device in \e target mode in order to emulate a
         * tag using the specified \a nfc_target_mode_t.
         * - Crc is handled by the device (NP_HANDLE_CRC = true)
         * - Parity is handled the device (NP_HANDLE_PARITY = true)
         * - Cryto1 cipher is disabled (NP_ACTIVATE_CRYPTO1 = false)
         * - Auto-switching in ISO14443-4 mode is enabled (NP_AUTO_ISO14443_4 = true)
         * - Easy framing is disabled (NP_EASY_FRAMING = false)
         * - Invalid frames are not accepted (NP_ACCEPT_INVALID_FRAMES = false)
         * - Multiple frames are not accepted (NP_ACCEPT_MULTIPLE_FRAMES = false)
         * - RF field is dropped
         *
         * @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.
         *
         * If timeout equals to 0, the function blocks indefinitely (until an error is raised or function is completed)
         * If timeout equals to -1, the default timeout will be used
         */
        public static int nfc_target_init(nfc_device pnd, nfc_target pnt, ref byte[] pbtRx, int szRx, int timeout)
        {
            int res = 0;

            // Disallow invalid frame
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_ACCEPT_INVALID_FRAMES, false)) < 0)
            {
                return(res);
            }
            // Disallow multiple frames
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_ACCEPT_MULTIPLE_FRAMES, false)) < 0)
            {
                return(res);
            }
            // Make sure we reset the CRC and parity to chip handling.
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_HANDLE_CRC, true)) < 0)
            {
                return(res);
            }
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_HANDLE_PARITY, true)) < 0)
            {
                return(res);
            }
            // Activate auto ISO14443-4 switching by default
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_AUTO_ISO14443_4, true)) < 0)
            {
                return(res);
            }
            // Activate "easy framing" feature by default
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_EASY_FRAMING, true)) < 0)
            {
                return(res);
            }
            // Deactivate the CRYPTO1 cipher, it may could cause problems when still active
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_ACTIVATE_CRYPTO1, false)) < 0)
            {
                return(res);
            }
            // Drop explicitely the field
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_ACTIVATE_FIELD, false)) < 0)
            {
                return(res);
            }
            pnd.last_error = 0;
            return(pnd.driver.target_init(pnd, pnt, ref pbtRx, szRx, timeout));
        }
Ejemplo n.º 6
0
        nfc_initiator_poll_dep_target(nfc_device pnd, nfc_dep_mode ndm, nfc_baud_rate nbr, nfc_dep_info pndiInitiator, nfc_target pnt, int timeout)
        {
            const int period         = 300;
            int       remaining_time = timeout;
            int       res;
            int       result          = 0;
            bool      bInfiniteSelect = pnd.bInfiniteSelect;

            pnt = null;
            if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_INFINITE_SELECT, true)) < 0)
            {
                return(res);
            }
            while (remaining_time > 0)
            {
                if ((res = nfc_initiator_select_dep_target(pnd, ndm, nbr, pndiInitiator, ref pnt, period)) < 0)
                {
                    if (res != NFC_ETIMEOUT)
                    {
                        result = res;
                        break;
                    }
                }
                if (res == 1)
                {
                    result = res;
                    break;
                }
                remaining_time -= period;
            }
            if (!bInfiniteSelect)
            {
                if ((res = nfc_device_set_property_bool(pnd, nfc_property.NP_INFINITE_SELECT, false)) < 0)
                {
                    return(res);
                }
            }
            return(result);
        }
Ejemplo n.º 7
0
        public static nfc_device nfc_device_new(nfc_context context, string connstring)
        {
            nfc_device res = new nfc_device();

            // Store associated context
            res.context = context;

            // Variables initiatialization
            // Note: Actually, these initialization will be overwritten while the device
            // will be setup. Putting them to _false_ while the default is _true_ ensure we
            // send the command to the chip
            res.bCrc            = false;
            res.bPar            = false;
            res.bEasyFraming    = false;
            res.bInfiniteSelect = false;
            res.bAutoIso14443_4 = false;
            res.last_error      = 0;
            res.connstring      = connstring;
            res.driver_data     = null;
            res.chip_data       = null;
            return(res);
        }
Ejemplo n.º 8
0
 public static int nfc_device_get_last_error(nfc_device pnd)
 {
     return(pnd.last_error);
 }
Ejemplo n.º 9
0
 /* Special data accessors */
 public static string nfc_device_get_name(nfc_device pnd)
 {
     return(pnd.name);
 }
Ejemplo n.º 10
0
 public static int nfc_strerror_r(nfc_device pnd, string buf, int buflen)
 {
     return(1);
 }
Ejemplo n.º 11
0
 public static void nfc_perror(nfc_device pnd, string s)
 {
 }
Ejemplo n.º 12
0
 /** @ingroup target
  * @brief Receive bit-frames
  * @return Returns received bits count on success, otherwise returns libnfc's error code
  *
  * @param pnd \a nfc_device struct pointer that represent currently used device
  * @param pbtRx pointer to Rx buffer
  * @param szRx size of Rx buffer
  * @param[out] pbtRxPar parameter contains a byte array of the corresponding parity bits
  *
  * This function makes it possible to receive (raw) bit-frames.  It returns all
  * the messages that are stored in the FIFO buffer of the \e PN53x chip.  It
  * does not require to send any frame and thereby could be used to snoop frames
  * that are transmitted by a nearby \e initiator.  @note Check out the
  * NP_ACCEPT_MULTIPLE_FRAMES configuration option to avoid losing transmitted
  * frames.
  */
 public static int nfc_target_receive_bits(nfc_device pnd, ref byte[] pbtRx, int szRx, byte[] pbtRxPar)
 {
     pnd.last_error = 0;
     return(pnd.driver.target_receive_bits(pnd, ref pbtRx, szRx, pbtRxPar));
 }
Ejemplo n.º 13
0
        /* Error reporting */

        /** @ingroup error
         * @brief Return the last error string
         * @return Returns a string
         *
         * @param pnd \a nfc_device struct pointer that represent currently used device
         */
        public static string nfc_strerror(nfc_device pnd)
        {
            return(NFC.ErrorMessage(pnd.last_error));
        }
Ejemplo n.º 14
0
 /** @ingroup misc
  * @brief Print information about NFC device
  * @return Upon successful return, this function returns the number of characters printed (excluding the null byte used to end output to strings), otherwise returns libnfc's error code (negative value)
  * @param pnd \a nfc_device struct pointer that represent currently used device
  * @param buf pointer where string will be allocated, then information printed
  *
  * @warning *buf must be freed using nfc_free()
  */
 public static int nfc_device_get_information_about(nfc_device pnd, out string buf)
 {
     pnd.last_error = 0;
     return(pnd.driver.device_get_information_about(pnd, out buf));
 }
Ejemplo n.º 15
0
 nfc_initiator_select_dep_target(nfc_device pnd, nfc_dep_mode ndm, nfc_baud_rate nbr, nfc_dep_info pndiInitiator, ref nfc_target pnt, int timeout)
 {
     pnd.last_error = 0;
     return(pnd.driver.initiator_select_dep_target(pnd, ndm, nbr, pndiInitiator, ref pnt, timeout));
 }
Ejemplo n.º 16
0
 /** @ingroup data
  * @brief Get supported baud rates.
  * @return Returns 0 on success, otherwise returns libnfc's error code (negative value)
  * @param pnd \a nfc_device struct pointer that represent currently used device
  * @param nmt \a nfc_modulation_type.
  * @param supported_br pointer of \a nfc_baud_rate array.
  *
  */
 public static int nfc_device_get_supported_baud_rate(nfc_device pnd, nfc_modulation_type nmt, out nfc_baud_rate[] supported_br)
 {
     pnd.last_error = 0;
     return(pnd.driver.get_supported_baud_rate(pnd, nmt, out supported_br));
 }
Ejemplo n.º 17
0
 /** @ingroup dev
  * @brief Abort current running command
  * @return Returns 0 on success, otherwise returns libnfc's error code.
  *
  * @param pnd \a nfc_device struct pointer that represent currently used device
  *
  * Some commands (ie. nfc_target_init()) are blocking functions and will return only in particular conditions (ie. external initiator request).
  * This function attempt to abort the current running command.
  *
  * @note The blocking function (ie. nfc_target_init()) will failed with DEABORT error.
  */
 public static int nfc_abort_command(nfc_device pnd)
 {
     pnd.last_error = 0;
     return(pnd.driver.abort_command(pnd));
 }
Ejemplo n.º 18
0
 public static string nfc_device_get_connstring(nfc_device pnd)
 {
     return(pnd.connstring);
 }
Ejemplo n.º 19
0
 /** @ingroup initiator
  * @brief Check target presence
  * @return Returns 0 on success, otherwise returns libnfc's error code.
  *
  * @param pnd \a nfc_device struct pointer that represent currently used device
  * @param pnt a \a nfc_target struct pointer where desired target information was stored (optionnal, can be \e NULL).
  * This function tests if \a nfc_target (or last selected tag if \e NULL) is currently present on NFC device.
  * @warning The target have to be selected before check its presence
  * @warning To run the test, one or more commands will be sent to target
  */
 public static int nfc_initiator_target_is_present(nfc_device pnd, nfc_target pnt)
 {
     pnd.last_error = 0;
     return(pnd.driver.initiator_target_is_present(pnd, pnt));
 }
Ejemplo n.º 20
0
 nfc_initiator_deselect_target(nfc_device pnd)
 {
     pnd.last_error = 0;
     return(pnd.driver.initiator_deselect_target(pnd));
 }
Ejemplo n.º 21
0
 /** @ingroup initiator
  * @brief Send data to target then retrieve data from target
  * @return Returns received bytes count on success, otherwise returns libnfc's error code.
  *
  * @param pnd \a nfc_device struct pointer that represents currently used device
  * @param pbtTx contains a byte array of the frame that needs to be transmitted.
  * @param szTx contains the length in bytes.
  * @param[out] pbtRx response from the target
  * @param szRx size of \a pbtRx (Will return NFC_EOVFLOW if RX exceeds this size)
  *
  * This function is similar to nfc_initiator_transceive_bytes() with the following differences:
  * - A precise cycles counter will indicate the number of cycles between emission & reception of frames.
  * - It only supports mode with \a NP_EASY_FRAMING option disabled.
  * - Overall communication with the host is heavier and slower.
  *
  * Timer control:
  * By default timer configuration tries to maximize the precision, which also limits the maximum
  * cycles count before saturation/timeout.
  * E.g. with PN53x it can count up to 65535 cycles, so about 4.8ms, with a precision of about 73ns.
  * - If you're ok with the defaults, set *cycles = 0 before calling this function.
  * - If you need to count more cycles, set *cycles to the maximum you expect but don't forget
  *   you'll loose in precision and it'll take more time before timeout, so don't abuse!
  *
  * @warning The configuration option \a NP_EASY_FRAMING must be set to \c false.
  * @warning The configuration option \a NP_HANDLE_PARITY must be set to \c true (the default value).
  */
 public static int nfc_initiator_transceive_bytes_timed(nfc_device pnd, byte[] pbtTx, int szTx, byte[] pbtRx, int szRx, ref UInt32 cycles)
 {
     pnd.last_error = 0;
     return(pnd.driver.initiator_transceive_bytes_timed(pnd, pbtTx, szTx, pbtRx, szRx, ref cycles));
 }
Ejemplo n.º 22
0
        /** @ingroup initiator
         * @brief Send data to target then retrieve data from target
         * @return Returns received bytes count on success, otherwise returns libnfc's error code
         *
         * @param pnd \a nfc_device struct pointer that represents currently used device
         * @param pbtTx contains a byte array of the frame that needs to be transmitted.
         * @param szTx contains the length in bytes.
         * @param[out] pbtRx response from the target
         * @param szRx size of \a pbtRx (Will return NFC_EOVFLOW if RX exceeds this size)
         * @param timeout in milliseconds
         *
         * The NFC device (configured as initiator) will transmit the supplied bytes (\a pbtTx) to the target.
         * It waits for the response and stores the received bytes in the \a pbtRx byte array.
         *
         * If \a NP_EASY_FRAMING option is disabled the frames will sent and received in raw mode: \e PN53x will not handle input neither output data.
         *
         * The parity bits are handled by the \e PN53x chip. The CRC can be generated automatically or handled manually.
         * Using this function, frames can be communicated very fast via the NFC initiator 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 \a NP_HANDLE_PARITY must be set to \c true (the default value).
         *
         * @note When used with MIFARE Classic, NFC_EMFCAUTHFAIL error is returned if authentication command failed. You need to re-select the tag to operate with.
         *
         * If timeout equals to 0, the function blocks indefinitely (until an error is raised or function is completed)
         * If timeout equals to -1, the default timeout will be used
         */

        public static int nfc_initiator_transceive_bytes(nfc_device pnd, byte[] pbtTx, int szTx, byte[] pbtRx, int szRx, int timeout)
        {
            pnd.last_error = 0;
            return(pnd.driver.initiator_transceive_bytes(pnd, pbtTx, szTx, pbtRx, szRx, timeout));
        }
Ejemplo n.º 23
0
 /** @ingroup data
  * @brief Get supported modulations.
  * @return Returns 0 on success, otherwise returns libnfc's error code (negative value)
  * @param pnd \a nfc_device struct pointer that represent currently used device
  * @param mode \a nfc_mode.
  * @param supported_mt pointer of \a nfc_modulation_type array.
  *
  */
 public static int nfc_device_get_supported_modulation(nfc_device pnd, nfc_mode mode, out nfc_modulation_type[] supported_mt)
 {
     pnd.last_error = 0;
     return(pnd.driver.get_supported_modulation(pnd, mode, out supported_mt));
 }
Ejemplo n.º 24
0
 /// <summary>
 /// nfc_close
 /// </summary>
 /// <param name="pnd"></param>
 public static void nfc_close(nfc_device pnd)
 {
     pn532_uart.dispose();
     pnd.last_error = 0;
     pnd.driver.close(pnd);
 }
Ejemplo n.º 25
0
        /* Properties accessors */

        /** @ingroup properties
         * @brief Set a device's integer-property value
         * @return Returns 0 on success, otherwise returns libnfc's error code (negative value)
         * @param pnd \a nfc_device struct pointer that represent currently used device
         * @param property \a nfc_property which will be set
         * @param value integer value
         *
         * Sets integer property.
         *
         * @see nfc_property enum values
         */
        public static int nfc_device_set_property_int(nfc_device pnd, nfc_property property, int value)
        {
            pnd.last_error = 0;
            return(pnd.driver.device_set_property_int(pnd, property, value));
        }
Ejemplo n.º 26
0
 /** @ingroup target
  * @brief Send bytes and APDU frames
  * @return Returns sent bytes count on success, otherwise returns libnfc's error code
  *
  * @param pnd \a nfc_device struct pointer that represent currently used device
  * @param pbtTx pointer to Tx buffer
  * @param szTx size of Tx buffer
  * @param timeout in milliseconds
  *
  * This function make the NFC device (configured as \e target) send byte frames
  * (e.g. APDU responses) to the \e initiator.
  *
  * If timeout equals to 0, the function blocks indefinitely (until an error is raised or function is completed)
  * If timeout equals to -1, the default timeout will be used
  */
 public static int nfc_target_send_bytes(nfc_device pnd, byte[] pbtTx, int szTx, int timeout)
 {
     pnd.last_error = 0;
     return(pnd.driver.target_send_bytes(pnd, pbtTx, szTx, timeout));
 }
Ejemplo n.º 27
0
 /** @ingroup properties
  * @brief Set a device's boolean-property value
  * @return Returns 0 on success, otherwise returns libnfc's error code (negative value)
  * @param pnd \a nfc_device struct pointer that represent currently used device
  * @param property \a nfc_property which will be set
  * @param bEnable boolean to activate/disactivate the property
  *
  * Configures parameters and registers that control for example timing,
  * modulation, frame and error handling.  There are different categories for
  * configuring the \e PN53X chip features (handle, activate, infinite and
  * accept).
  */
 public static int nfc_device_set_property_bool(nfc_device pnd, nfc_property property, bool bEnable)
 {
     pnd.last_error = 0;
     return(pnd.driver.device_set_property_bool(pnd, property, bEnable));
 }
Ejemplo n.º 28
0
 /** @ingroup target
  * @brief Receive bytes and APDU frames
  * @return Returns received bytes count on success, otherwise returns libnfc's error code
  *
  * @param pnd \a nfc_device struct pointer that represent currently used device
  * @param pbtRx pointer to Rx buffer
  * @param szRx size of Rx buffer
  * @param timeout in milliseconds
  *
  * This function retrieves bytes frames (e.g. ADPU) sent by the \e initiator to the NFC device (configured as \e target).
  *
  * If timeout equals to 0, the function blocks indefinitely (until an error is raised or function is completed)
  * If timeout equals to -1, the default timeout will be used
  */
 public static int nfc_target_receive_bytes(nfc_device pnd, ref byte[] pbtRx, int szRx, int timeout)
 {
     pnd.last_error = 0;
     return(pnd.driver.target_receive_bytes(pnd, ref pbtRx, szRx, timeout));
 }
Ejemplo n.º 29
0
        //public static int nfc_list_devices(nfc_context context, nfc_connstring connstrings[], int connpublic static strings_len){}

        /** @ingroup dev
         * @brief Turn NFC device in idle mode
         * @return Returns 0 on success, otherwise returns libnfc's error code.
         *
         * @param pnd \a nfc_device struct pointer that represent currently used device
         *
         * This function switch the device in idle mode.
         * In initiator mode, the RF field is turned off and the device is set to low power mode (if avaible);
         * In target mode, the emulation is stoped (no target available from external initiator) and the device is set to low power mode (if avaible).
         */
        public static int nfc_idle(nfc_device pnd)
        {
            pnd.last_error = 0;
            return(pnd.driver.idle(pnd));
        }
Ejemplo n.º 30
0
 /** @ingroup target
  * @brief Send raw bit-frames
  * @return Returns sent bits count on success, otherwise returns libnfc's error code.
  *
  * @param pnd \a nfc_device struct pointer that represent currently used device
  * @param pbtTx pointer to Tx buffer
  * @param szTxBits size of Tx buffer
  * @param pbtTxPar parameter contains a byte array of the corresponding parity bits needed to send per byte.
  * This function can be used to transmit (raw) bit-frames to the \e initiator
  * using the specified NFC device (configured as \e target).
  */
 public static int nfc_target_send_bits(nfc_device pnd, byte[] pbtTx, int szTxBits, byte[] pbtTxPar)
 {
     pnd.last_error = 0;
     return(pnd.driver.target_send_bits(pnd, pbtTx, szTxBits, pbtTxPar));
 }