ARYGON driver works again and PN532_UART improved :)
drivers/pn532_uart: code clean up chips/pn53x: new fonction to build frames drivers/arygon: use the new way to drive UART (its far more stable)
This commit is contained in:
parent
7ec1080e16
commit
f81138b3c7
8 changed files with 268 additions and 263 deletions
|
@ -217,7 +217,6 @@ static const struct timeval tvTimeout = {
|
||||||
int
|
int
|
||||||
uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx)
|
uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct timeval tv = tvTimeout;
|
struct timeval tv = tvTimeout;
|
||||||
int received_bytes_count = 0;
|
int received_bytes_count = 0;
|
||||||
int available_bytes_count = 0;
|
int available_bytes_count = 0;
|
||||||
|
|
|
@ -94,17 +94,12 @@ pn53x_init(nfc_device_t * pnd)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pn53x_check_ack_frame_callback (nfc_device_t * pnd, const byte_t * pbtRxFrame, const size_t szRxFrameLen)
|
pn53x_check_ack_frame (nfc_device_t * pnd, const byte_t * pbtRxFrame, const size_t szRxFrameLen)
|
||||||
{
|
{
|
||||||
if (szRxFrameLen >= sizeof (pn53x_ack_frame)) {
|
if (szRxFrameLen >= sizeof (pn53x_ack_frame)) {
|
||||||
if (0 == memcmp (pbtRxFrame, pn53x_ack_frame, sizeof (pn53x_ack_frame))) {
|
if (0 == memcmp (pbtRxFrame, pn53x_ack_frame, sizeof (pn53x_ack_frame))) {
|
||||||
// DBG ("%s", "PN53x ACKed");
|
// DBG ("%s", "PN53x ACKed");
|
||||||
return true;
|
return true;
|
||||||
} else if (0 == memcmp (pbtRxFrame, pn53x_nack_frame, sizeof (pn53x_nack_frame))) {
|
|
||||||
DBG ("%s", "PN53x NACKed");
|
|
||||||
// TODO Double check in user manual if no PN53x replies NACK then remove this
|
|
||||||
pnd->iLastError = DENACK;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pnd->iLastError = DEACKMISMATCH;
|
pnd->iLastError = DEACKMISMATCH;
|
||||||
|
@ -117,7 +112,7 @@ pn53x_check_ack_frame_callback (nfc_device_t * pnd, const byte_t * pbtRxFrame, c
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pn53x_check_error_frame_callback (nfc_device_t * pnd, const byte_t * pbtRxFrame, const size_t szRxFrameLen)
|
pn53x_check_error_frame (nfc_device_t * pnd, const byte_t * pbtRxFrame, const size_t szRxFrameLen)
|
||||||
{
|
{
|
||||||
if (szRxFrameLen >= sizeof (pn53x_error_frame)) {
|
if (szRxFrameLen >= sizeof (pn53x_error_frame)) {
|
||||||
if (0 == memcmp (pbtRxFrame, pn53x_error_frame, sizeof (pn53x_error_frame))) {
|
if (0 == memcmp (pbtRxFrame, pn53x_error_frame, sizeof (pn53x_error_frame))) {
|
||||||
|
@ -364,6 +359,36 @@ pn53x_unwrap_frame (const byte_t * pbtFrame, const size_t szFrameBits, byte_t *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pn53x_build_frame(byte_t * pbtFrame, size_t * pszFrame, const byte_t * pbtData, const size_t szData)
|
||||||
|
{
|
||||||
|
if (szData <= PN53x_NORMAL_FRAME__DATA_MAX_LEN) {
|
||||||
|
// LEN - Packet length = data length (len) + checksum (1) + end of stream marker (1)
|
||||||
|
pbtFrame[3] = szData + 1;
|
||||||
|
// LCS - Packet length checksum
|
||||||
|
pbtFrame[4] = 256 - (szData + 1);
|
||||||
|
// TFI
|
||||||
|
pbtFrame[5] = 0xD4;
|
||||||
|
// DATA - Copy the PN53X command into the packet buffer
|
||||||
|
memcpy (pbtFrame + 6, pbtData, szData);
|
||||||
|
|
||||||
|
// DCS - Calculate data payload checksum
|
||||||
|
byte_t btDCS = (256 - 0xD4);
|
||||||
|
for (size_t szPos = 0; szPos < szData; szPos++) {
|
||||||
|
btDCS -= pbtData[szPos];
|
||||||
|
}
|
||||||
|
pbtFrame[6 + szData] = btDCS;
|
||||||
|
|
||||||
|
// 0x00 - End of stream marker
|
||||||
|
pbtFrame[szData + 7] = 0x00;
|
||||||
|
|
||||||
|
(*pszFrame) = szData + PN53x_NORMAL_FRAME__OVERHEAD;
|
||||||
|
} else {
|
||||||
|
// FIXME: Build extended frame
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pn53x_decode_target_data (const byte_t * pbtRawData, size_t szRawData, pn53x_type type, nfc_modulation_type_t nmt,
|
pn53x_decode_target_data (const byte_t * pbtRawData, size_t szRawData, pn53x_type type, nfc_modulation_type_t nmt,
|
||||||
nfc_target_info_t * pnti)
|
nfc_target_info_t * pnti)
|
||||||
|
|
|
@ -196,10 +196,6 @@ typedef enum {
|
||||||
} pn53x_target_mode_t;
|
} pn53x_target_mode_t;
|
||||||
|
|
||||||
bool pn53x_init(nfc_device_t * pnd);
|
bool pn53x_init(nfc_device_t * pnd);
|
||||||
bool pn53x_check_ack_frame_callback (nfc_device_t * pnd, const byte_t * pbtRxFrame,
|
|
||||||
const size_t szRxFrameLen);
|
|
||||||
bool pn53x_check_error_frame_callback (nfc_device_t * pnd, const byte_t * pbtRxFrame,
|
|
||||||
const size_t szRxFrameLen);
|
|
||||||
bool pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t *pszRx);
|
bool pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t *pszRx);
|
||||||
bool pn53x_read_register (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t * ui8Value);
|
bool pn53x_read_register (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t * ui8Value);
|
||||||
bool pn53x_write_register (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t ui8SymbolMask, uint8_t ui8Value);
|
bool pn53x_write_register (nfc_device_t * pnd, uint16_t ui16Reg, uint8_t ui8SymbolMask, uint8_t ui8Value);
|
||||||
|
@ -270,5 +266,9 @@ bool pn53x_TgInitAsTarget (nfc_device_t * pnd, pn53x_target_mode_t ptm,
|
||||||
const byte_t * pbtNFCID3t, const byte_t * pbtGB, const size_t szGB,
|
const byte_t * pbtNFCID3t, const byte_t * pbtGB, const size_t szGB,
|
||||||
byte_t * pbtRx, size_t * pszRx, byte_t * pbtModeByte);
|
byte_t * pbtRx, size_t * pszRx, byte_t * pbtModeByte);
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
bool pn53x_check_ack_frame (nfc_device_t * pnd, const byte_t * pbtRxFrame, const size_t szRxFrameLen);
|
||||||
|
bool pn53x_check_error_frame (nfc_device_t * pnd, const byte_t * pbtRxFrame, const size_t szRxFrameLen);
|
||||||
|
void pn53x_build_frame(byte_t * pbtFrame, size_t * pszFrame, const byte_t * pbtData, const size_t szData);
|
||||||
|
|
||||||
#endif // __NFC_CHIPS_PN53X_H__
|
#endif // __NFC_CHIPS_PN53X_H__
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* Public platform independent Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009, Roel Verdult
|
* Copyright (C) 2009, Roel Verdult
|
||||||
|
* Copyright (C) 2010, Romuald Conty
|
||||||
|
* Copyright (C) 2011, Romain Tartière, Romuald Conty
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -24,28 +26,26 @@
|
||||||
* This driver can handle ARYGON readers that use UART as bus.
|
* This driver can handle ARYGON readers that use UART as bus.
|
||||||
* UART connection can be direct (host<->arygon_uc) or could be provided by internal USB to serial interface (e.g. host<->ftdi_chip<->arygon_uc)
|
* UART connection can be direct (host<->arygon_uc) or could be provided by internal USB to serial interface (e.g. host<->ftdi_chip<->arygon_uc)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include "../drivers.h"
|
#include "arygon.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#ifdef HAVE_STRINGS_H
|
#include <sys/param.h>
|
||||||
# include <strings.h>
|
#include <string.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "arygon.h"
|
|
||||||
|
|
||||||
|
#include <nfc/nfc.h>
|
||||||
#include <nfc/nfc-messages.h>
|
#include <nfc/nfc-messages.h>
|
||||||
|
|
||||||
// Bus
|
#include "libnfc/drivers.h"
|
||||||
|
#include "libnfc/nfc-internal.h"
|
||||||
|
#include "libnfc/chips/pn53x.h"
|
||||||
|
#include "libnfc/chips/pn53x-internal.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
/** @def DEV_ARYGON_PROTOCOL_ARYGON_ASCII
|
/** @def DEV_ARYGON_PROTOCOL_ARYGON_ASCII
|
||||||
* @brief High level language in ASCII format. (Common µC commands and Mifare® commands)
|
* @brief High level language in ASCII format. (Common µC commands and Mifare® commands)
|
||||||
*/
|
*/
|
||||||
|
@ -63,10 +63,12 @@
|
||||||
*/
|
*/
|
||||||
#define DEV_ARYGON_PROTOCOL_TAMA_WAB '3'
|
#define DEV_ARYGON_PROTOCOL_TAMA_WAB '3'
|
||||||
|
|
||||||
#define SERIAL_DEFAULT_PORT_SPEED 9600
|
#define ARYGON_SERIAL_DEFAULT_PORT_SPEED 9600
|
||||||
|
|
||||||
|
struct arygon_data {
|
||||||
|
serial_port port;
|
||||||
|
};
|
||||||
|
|
||||||
// TODO Move this one level up for libnfc-1.6
|
|
||||||
static const byte_t pn53x_ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
|
|
||||||
// XXX It seems that sending arygon_ack_frame to cancel current command is not allowed by ARYGON µC (see arygon_ack())
|
// XXX It seems that sending arygon_ack_frame to cancel current command is not allowed by ARYGON µC (see arygon_ack())
|
||||||
// static const byte_t arygon_ack_frame[] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
|
// static const byte_t arygon_ack_frame[] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
|
||||||
|
|
||||||
|
@ -75,39 +77,15 @@ static const byte_t arygon_error_incomplete_command[] = "FF0C0000\x0d\x0a";
|
||||||
static const byte_t arygon_error_unknown_mode[] = "FF060000\x0d\x0a";
|
static const byte_t arygon_error_unknown_mode[] = "FF060000\x0d\x0a";
|
||||||
|
|
||||||
// void arygon_ack (const nfc_device_spec_t nds);
|
// void arygon_ack (const nfc_device_spec_t nds);
|
||||||
bool arygon_reset_tama (const nfc_device_spec_t nds);
|
bool arygon_reset_tama (nfc_device_t * pnd);
|
||||||
void arygon_firmware (const nfc_device_spec_t nds, char * str);
|
void arygon_firmware (nfc_device_t * pnd, char * str);
|
||||||
|
bool arygon_check_communication (nfc_device_t * pnd);
|
||||||
bool arygon_check_communication (const nfc_device_spec_t nds);
|
|
||||||
|
|
||||||
nfc_device_desc_t *
|
|
||||||
arygon_pick_device (void)
|
|
||||||
{
|
|
||||||
nfc_device_desc_t *pndd;
|
|
||||||
|
|
||||||
if ((pndd = malloc (sizeof (*pndd)))) {
|
|
||||||
size_t szN;
|
|
||||||
|
|
||||||
if (!arygon_list_devices (pndd, 1, &szN)) {
|
|
||||||
DBG ("%s", "arygon_list_devices failed");
|
|
||||||
free (pndd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (szN == 0) {
|
|
||||||
DBG ("%s", "No device found");
|
|
||||||
free (pndd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pndd;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
arygon_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
|
arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
|
||||||
{
|
{
|
||||||
/** @note: Due to UART bus we can't know if its really a pn532 without
|
/** @note: Due to UART bus we can't know if its really an ARYGON without
|
||||||
* sending some PN53x commands. But using this way to probe devices, we can
|
* sending some commands. But using this way to probe devices, we can
|
||||||
* have serious problem with other device on this bus */
|
* have serious problem with other device on this bus */
|
||||||
#ifndef SERIAL_AUTOPROBE_ENABLED
|
#ifndef SERIAL_AUTOPROBE_ENABLED
|
||||||
(void) pnddDevices;
|
(void) pnddDevices;
|
||||||
|
@ -125,22 +103,31 @@ arygon_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *
|
||||||
|
|
||||||
while ((pcPort = pcPorts[iDevice++])) {
|
while ((pcPort = pcPorts[iDevice++])) {
|
||||||
sp = uart_open (pcPort);
|
sp = uart_open (pcPort);
|
||||||
DBG ("Trying to find ARYGON device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED);
|
DBG ("Trying to find ARYGON device on serial port: %s at %d bauds.", pcPort, ARYGON_SERIAL_DEFAULT_PORT_SPEED);
|
||||||
|
|
||||||
if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
|
if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
|
||||||
uart_set_speed (sp, SERIAL_DEFAULT_PORT_SPEED);
|
uart_set_speed (sp, ARYGON_SERIAL_DEFAULT_PORT_SPEED);
|
||||||
|
|
||||||
if (!arygon_reset_tama((nfc_device_spec_t) sp))
|
nfc_device_t nd;
|
||||||
continue;
|
nd.driver = &arygon_driver;
|
||||||
|
nd.driver_data = malloc(sizeof(struct arygon_data));
|
||||||
|
((struct arygon_data*)(nd.driver_data))->port = sp;
|
||||||
|
nd.chip_data = malloc(sizeof(struct pn53x_data));
|
||||||
|
((struct pn53x_data*)(nd.chip_data))->type = PN532;
|
||||||
|
((struct pn53x_data*)(nd.chip_data))->state = NORMAL;
|
||||||
|
|
||||||
|
bool res = arygon_reset_tama(&nd);
|
||||||
|
free(nd.driver_data);
|
||||||
|
free(nd.chip_data);
|
||||||
uart_close (sp);
|
uart_close (sp);
|
||||||
|
if(!res)
|
||||||
|
continue;
|
||||||
|
|
||||||
// ARYGON reader is found
|
// ARYGON reader is found
|
||||||
strncpy (pnddDevices[*pszDeviceFound].acDevice, "ARYGON", DEVICE_NAME_LENGTH - 1);
|
snprintf (pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", pcPort);
|
||||||
pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0';
|
|
||||||
pnddDevices[*pszDeviceFound].pcDriver = ARYGON_DRIVER_NAME;
|
pnddDevices[*pszDeviceFound].pcDriver = ARYGON_DRIVER_NAME;
|
||||||
pnddDevices[*pszDeviceFound].pcPort = strdup (pcPort);
|
pnddDevices[*pszDeviceFound].pcPort = strdup (pcPort);
|
||||||
pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED;
|
pnddDevices[*pszDeviceFound].uiSpeed = ARYGON_SERIAL_DEFAULT_PORT_SPEED;
|
||||||
DBG ("Device found: %s (%s)", pnddDevices[*pszDeviceFound].acDevice, pcPort);
|
|
||||||
(*pszDeviceFound)++;
|
(*pszDeviceFound)++;
|
||||||
|
|
||||||
// Test if we reach the maximum "wanted" devices
|
// Test if we reach the maximum "wanted" devices
|
||||||
|
@ -177,140 +164,202 @@ arygon_connect (const nfc_device_desc_t * pndd)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
uart_set_speed (sp, pndd->uiSpeed);
|
uart_set_speed (sp, pndd->uiSpeed);
|
||||||
if (!arygon_reset_tama((nfc_device_spec_t) sp)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG ("Successfully connected to: %s", pndd->pcPort);
|
|
||||||
|
|
||||||
// We have a connection
|
// We have a connection
|
||||||
pnd = malloc (sizeof (nfc_device_t));
|
pnd = malloc (sizeof (nfc_device_t));
|
||||||
char acFirmware[10];
|
strncpy (pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1);
|
||||||
arygon_firmware((nfc_device_spec_t) sp, acFirmware);
|
|
||||||
snprintf (pnd->acName, DEVICE_NAME_LENGTH - 1, "%s %s (%s)", pndd->acDevice, acFirmware, pndd->pcPort);
|
|
||||||
pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0';
|
pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0';
|
||||||
pnd->nds = (nfc_device_spec_t) sp;
|
|
||||||
pnd->bActive = true;
|
|
||||||
|
|
||||||
|
pnd->driver_data = malloc(sizeof(struct arygon_data));
|
||||||
|
((struct arygon_data*)(pnd->driver_data))->port = sp;
|
||||||
|
pnd->chip_data = malloc(sizeof(struct pn53x_data));
|
||||||
|
((struct pn53x_data*)(pnd->chip_data))->type = PN532;
|
||||||
|
((struct pn53x_data*)(pnd->chip_data))->state = SLEEP;
|
||||||
|
pnd->driver = &arygon_driver;
|
||||||
|
|
||||||
|
// Check communication using "Reset TAMA" command
|
||||||
|
if (!arygon_reset_tama(pnd)) {
|
||||||
|
free(pnd->driver_data);
|
||||||
|
free(pnd->chip_data);
|
||||||
|
free(pnd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pn53x_init(pnd);
|
||||||
return pnd;
|
return pnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
arygon_disconnect (nfc_device_t * pnd)
|
arygon_disconnect (nfc_device_t * pnd)
|
||||||
{
|
{
|
||||||
uart_close ((serial_port) pnd->nds);
|
uart_close (((struct arygon_data*)(pnd->driver_data))->port);
|
||||||
|
free(pnd->driver_data);
|
||||||
|
free(pnd->chip_data);
|
||||||
free (pnd);
|
free (pnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TX_BUFFER_LENGTH (300)
|
#define ARYGON_TX_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD + 1)
|
||||||
#define RX_BUFFER_LENGTH (PN53x_EXTENDED_FRAME_MAX_LEN + PN53x_EXTENDED_FRAME_OVERHEAD + sizeof(pn53x_ack_frame))
|
#define ARYGON_RX_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
|
||||||
bool
|
bool
|
||||||
arygon_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx)
|
arygon_tama_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData)
|
||||||
{
|
{
|
||||||
byte_t abtTxBuf[TX_BUFFER_LENGTH] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff }; // Every packet must start with "0x32 0x00 0x00 0xff"
|
byte_t abtFrame[ARYGON_TX_BUFFER_LEN] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff }; // Every packet must start with "0x32 0x00 0x00 0xff"
|
||||||
byte_t abtRxBuf[RX_BUFFER_LENGTH];
|
|
||||||
size_t szRxBufLen;
|
|
||||||
size_t szReplyMaxLen = MIN(RX_BUFFER_LENGTH, *pszRx);
|
|
||||||
size_t szPos;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
// Packet length = data length (len) + checksum (1) + end of stream marker (1)
|
pnd->iLastCommand = pbtData[0];
|
||||||
abtTxBuf[4] = szTx;
|
size_t szFrame = 0;
|
||||||
// Packet length checksum
|
pn53x_build_frame (abtFrame + 1, &szFrame, pbtData, szData);
|
||||||
abtTxBuf[5] = 256 - abtTxBuf[4];
|
|
||||||
// Copy the PN53X command into the packet buffer
|
|
||||||
memmove (abtTxBuf + 6, pbtTx, szTx);
|
|
||||||
|
|
||||||
// Calculate data payload checksum
|
int res = uart_send (((struct arygon_data*)(pnd->driver_data))->port, abtFrame, szFrame + 1);
|
||||||
abtTxBuf[szTx + 6] = 0;
|
|
||||||
for (szPos = 0; szPos < szTx; szPos++) {
|
|
||||||
abtTxBuf[szTx + 6] -= abtTxBuf[szPos + 6];
|
|
||||||
}
|
|
||||||
|
|
||||||
// End of stream marker
|
|
||||||
abtTxBuf[szTx + 7] = 0;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
PRINT_HEX ("TX", abtTxBuf, szTx + 8);
|
|
||||||
#endif
|
|
||||||
res = uart_send ((serial_port) pnd->nds, abtTxBuf, szTx + 8);
|
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
ERR ("%s", "Unable to transmit data. (TX)");
|
ERR ("%s", "Unable to transmit data. (TX)");
|
||||||
pnd->iLastError = res;
|
pnd->iLastError = res;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
memset (abtRxBuf, 0x00, sizeof (abtRxBuf));
|
byte_t abtRxBuf[6];
|
||||||
#endif
|
res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRxBuf, 6);
|
||||||
szRxBufLen = szReplyMaxLen;
|
|
||||||
res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
|
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
ERR ("%s", "Unable to receive data. (RX)");
|
ERR ("%s", "Unable to read ACK");
|
||||||
pnd->iLastError = res;
|
pnd->iLastError = res;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// WARN: UART is a per byte reception, so you usually receive ACK and next frame the same time
|
if (pn53x_check_ack_frame (pnd, abtRxBuf, sizeof(abtRxBuf))) {
|
||||||
if (!pn53x_check_ack_frame_callback (pnd, abtRxBuf, szRxBufLen))
|
((struct pn53x_data*)(pnd->chip_data))->state = EXECUTE;
|
||||||
|
} else if (0 == memcmp(arygon_error_unknown_mode, abtRxBuf, sizeof(abtRxBuf))) {
|
||||||
|
ERR( "Bad frame format." );
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
szRxBufLen -= sizeof (pn53x_ack_frame);
|
|
||||||
memmove (abtRxBuf, abtRxBuf + sizeof (pn53x_ack_frame), szRxBufLen);
|
|
||||||
szReplyMaxLen -= sizeof (pn53x_ack_frame);
|
|
||||||
|
|
||||||
if (szRxBufLen == 0) {
|
|
||||||
do {
|
|
||||||
delay_ms (10);
|
|
||||||
szRxBufLen = szReplyMaxLen;
|
|
||||||
res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
|
|
||||||
} while (res != 0);
|
|
||||||
#ifdef DEBUG
|
|
||||||
PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pn53x_check_error_frame_callback (pnd, abtRxBuf, szRxBufLen))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// When the answer should be ignored, just return a successful result
|
|
||||||
if (pbtRx == NULL || pszRx == NULL)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
|
|
||||||
if (szRxBufLen < 9)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
|
|
||||||
*pszRx = szRxBufLen - 9;
|
|
||||||
memcpy (pbtRx, abtRxBuf + 7, *pszRx);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen)
|
||||||
|
{
|
||||||
|
byte_t abtRxBuf[5];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
int res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRxBuf, 5);
|
||||||
|
if (res != 0) {
|
||||||
|
ERR ("%s", "Unable to receive data. (RX)");
|
||||||
|
pnd->iLastError = res;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
|
||||||
|
if (0 != (memcmp (abtRxBuf, pn53x_preamble, 3))) {
|
||||||
|
ERR ("%s", "Frame preamble+start code mismatch");
|
||||||
|
pnd->iLastError = DEIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((0x01 == abtRxBuf[3]) && (0xff == abtRxBuf[4])) {
|
||||||
|
// Error frame
|
||||||
|
uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRxBuf, 3);
|
||||||
|
ERR ("%s", "Application level error detected");
|
||||||
|
pnd->iLastError = DEISERRFRAME;
|
||||||
|
return -1;
|
||||||
|
} else if ((0xff == abtRxBuf[3]) && (0xff == abtRxBuf[4])) {
|
||||||
|
// Extended frame
|
||||||
|
// FIXME: Code this
|
||||||
|
abort ();
|
||||||
|
} else {
|
||||||
|
// Normal frame
|
||||||
|
if (256 != (abtRxBuf[3] + abtRxBuf[4])) {
|
||||||
|
// TODO: Retry
|
||||||
|
ERR ("%s", "Length checksum mismatch");
|
||||||
|
pnd->iLastError = DEIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// abtRxBuf[3] (LEN) include TFI + (CC+1)
|
||||||
|
len = abtRxBuf[3] - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > szDataLen) {
|
||||||
|
ERR ("Unable to receive data: buffer too small. (szDataLen: %zu, len: %zu)", szDataLen, len);
|
||||||
|
pnd->iLastError = DEIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TFI + PD0 (CC+1)
|
||||||
|
res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRxBuf, 2);
|
||||||
|
if (res != 0) {
|
||||||
|
ERR ("%s", "Unable to receive data. (RX)");
|
||||||
|
pnd->iLastError = res;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abtRxBuf[0] != 0xD5) {
|
||||||
|
ERR ("%s", "TFI Mismatch");
|
||||||
|
pnd->iLastError = DEIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abtRxBuf[1] != pnd->iLastCommand + 1) {
|
||||||
|
ERR ("%s", "Command Code verification failed");
|
||||||
|
pnd->iLastError = DEIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, pbtData, len);
|
||||||
|
if (res != 0) {
|
||||||
|
ERR ("%s", "Unable to receive data. (RX)");
|
||||||
|
pnd->iLastError = res;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRxBuf, 2);
|
||||||
|
if (res != 0) {
|
||||||
|
ERR ("%s", "Unable to receive data. (RX)");
|
||||||
|
pnd->iLastError = res;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_t btDCS = (256 - 0xD5);
|
||||||
|
btDCS -= pnd->iLastCommand + 1;
|
||||||
|
for (size_t szPos = 0; szPos < len; szPos++) {
|
||||||
|
btDCS -= pbtData[szPos];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btDCS != abtRxBuf[0]) {
|
||||||
|
ERR ("%s", "Data checksum mismatch");
|
||||||
|
pnd->iLastError = DEIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0x00 != abtRxBuf[1]) {
|
||||||
|
ERR ("%s", "Frame postamble mismatch");
|
||||||
|
pnd->iLastError = DEIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
((struct pn53x_data*)(pnd->chip_data))->state = NORMAL;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
arygon_firmware (const nfc_device_spec_t nds, char * str)
|
arygon_firmware (nfc_device_t * pnd, char * str)
|
||||||
{
|
{
|
||||||
const byte_t arygon_firmware_version_cmd[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'v' };
|
const byte_t arygon_firmware_version_cmd[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'v' };
|
||||||
byte_t abtRx[RX_BUFFER_LENGTH];
|
byte_t abtRx[16];
|
||||||
size_t szRx = 16;
|
size_t szRx = sizeof(abtRx);
|
||||||
int res;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
PRINT_HEX ("TX", arygon_firmware_version_cmd, sizeof (arygon_firmware_version_cmd));
|
|
||||||
#endif
|
|
||||||
uart_send ((serial_port) nds, arygon_firmware_version_cmd, sizeof (arygon_firmware_version_cmd));
|
|
||||||
|
|
||||||
res = uart_receive ((serial_port) nds, abtRx, &szRx);
|
int res = uart_send (((struct arygon_data*)(pnd->driver_data))->port, arygon_firmware_version_cmd, sizeof (arygon_firmware_version_cmd));
|
||||||
|
if (res != 0) {
|
||||||
|
DBG ("Unable to send ARYGON firmware command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRx, szRx);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
DBG ("Unable to retrieve ARYGON firmware version.");
|
DBG ("Unable to retrieve ARYGON firmware version.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
PRINT_HEX ("RX", abtRx, szRx);
|
|
||||||
#endif
|
|
||||||
if ( 0 == memcmp (abtRx, arygon_error_none, 6)) {
|
if ( 0 == memcmp (abtRx, arygon_error_none, 6)) {
|
||||||
byte_t * p = abtRx + 6;
|
byte_t * p = abtRx + 6;
|
||||||
unsigned int szData;
|
unsigned int szData;
|
||||||
|
@ -321,43 +370,32 @@ arygon_firmware (const nfc_device_spec_t nds, char * str)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
arygon_reset_tama (const nfc_device_spec_t nds)
|
arygon_reset_tama (nfc_device_t * pnd)
|
||||||
{
|
{
|
||||||
const byte_t arygon_reset_tama_cmd[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'r' };
|
const byte_t arygon_reset_tama_cmd[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'r' };
|
||||||
byte_t abtRx[RX_BUFFER_LENGTH];
|
byte_t abtRx[10]; // Attempted response is 10 bytes long
|
||||||
size_t szRx = 10; // Attempted response is 10 bytes long
|
size_t szRx = sizeof(abtRx);
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
// Sometimes the first byte we send is not well-transmited (ie. a previously sent data on a wrong baud rate can put some junk in buffer)
|
uart_send (((struct arygon_data*)(pnd->driver_data))->port, arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd));
|
||||||
#ifdef DEBUG
|
|
||||||
PRINT_HEX ("TX", arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd));
|
|
||||||
#endif
|
|
||||||
uart_send ((serial_port) nds, arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd));
|
|
||||||
|
|
||||||
// Two reply are possible from ARYGON device: arygon_error_none (ie. in case the byte is well-sent)
|
// Two reply are possible from ARYGON device: arygon_error_none (ie. in case the byte is well-sent)
|
||||||
// or arygon_error_unknown_mode (ie. in case of the first byte was bad-transmitted)
|
// or arygon_error_unknown_mode (ie. in case of the first byte was bad-transmitted)
|
||||||
res = uart_receive ((serial_port) nds, abtRx, &szRx);
|
res = uart_receive (((struct arygon_data*)(pnd->driver_data))->port, abtRx, szRx);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
DBG ("No reply to 'reset TAMA' command.");
|
DBG ("No reply to 'reset TAMA' command.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#if 0
|
||||||
PRINT_HEX ("RX", abtRx, szRx);
|
if ( 0 == memcmp (abtRx, arygon_error_unknown_mode, sizeof (arygon_error_unknown_mode))) {
|
||||||
#endif
|
|
||||||
if ( 0 == memcmp (abtRx, arygon_error_unknown_mode, sizeof (arygon_error_unknown_mode) - 1)) {
|
|
||||||
// HACK Here we are... the first byte wasn't sent as expected, so we resend the same command
|
// HACK Here we are... the first byte wasn't sent as expected, so we resend the same command
|
||||||
#ifdef DEBUG
|
|
||||||
PRINT_HEX ("TX", arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd));
|
|
||||||
#endif
|
|
||||||
uart_send ((serial_port) nds, arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd));
|
uart_send ((serial_port) nds, arygon_reset_tama_cmd, sizeof (arygon_reset_tama_cmd));
|
||||||
res = uart_receive ((serial_port) nds, abtRx, &szRx);
|
res = uart_receive ((serial_port) nds, abtRx, &szRx);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
PRINT_HEX ("RX", abtRx, szRx);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (0 != memcmp (abtRx, arygon_error_none, sizeof (arygon_error_none) - 1)) {
|
if (0 != memcmp (abtRx, arygon_error_none, sizeof (arygon_error_none) - 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -387,41 +425,14 @@ arygon_ack (const nfc_device_spec_t nds)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
|
||||||
arygon_check_communication (const nfc_device_spec_t nds)
|
|
||||||
{
|
|
||||||
byte_t abtRx[RX_BUFFER_LENGTH];
|
|
||||||
size_t szRx = sizeof(abtRx);
|
|
||||||
const byte_t attempted_result[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, // ACK
|
|
||||||
0x00, 0x00, 0xff, 0x09, 0xf7, 0xd5, 0x01, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbc, 0x00 }; // Reply
|
|
||||||
int res;
|
|
||||||
|
|
||||||
/** To be sure that PN532 is alive, we have put a "Diagnose" command to execute a "Communication Line Test" */
|
const struct nfc_driver_t arygon_driver = {
|
||||||
const byte_t pncmd_communication_test[] =
|
.name = ARYGON_DRIVER_NAME,
|
||||||
{ DEV_ARYGON_PROTOCOL_TAMA, // Header to passthrough front ARYGON µC (== directly talk to PN53x)
|
.probe = arygon_probe,
|
||||||
0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbe, 0x00 };
|
.connect = arygon_connect,
|
||||||
|
.send = arygon_tama_send,
|
||||||
|
.receive = arygon_tama_receive,
|
||||||
|
.disconnect = arygon_disconnect,
|
||||||
|
.strerror = pn53x_strerror,
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
PRINT_HEX ("TX", pncmd_communication_test, sizeof (pncmd_communication_test));
|
|
||||||
#endif
|
|
||||||
res = uart_send ((serial_port) nds, pncmd_communication_test, sizeof (pncmd_communication_test));
|
|
||||||
if (res != 0) {
|
|
||||||
ERR ("%s", "Unable to transmit data. (TX)");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = uart_receive ((serial_port) nds, abtRx, &szRx);
|
|
||||||
if (res != 0) {
|
|
||||||
ERR ("%s", "Unable to receive data. (RX)");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
|
||||||
PRINT_HEX ("RX", abtRx, szRx);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (0 != memcmp (abtRx, attempted_result, sizeof (attempted_result))) {
|
|
||||||
DBG ("%s", "Communication test failed, result doesn't match to attempted one.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* Public platform independent Near Field Communication (NFC) library
|
* Public platform independent Near Field Communication (NFC) library
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009, Roel Verdult
|
* Copyright (C) 2009, Roel Verdult
|
||||||
|
* Copyright (C) 2010, Romuald Conty
|
||||||
|
* Copyright (C) 2011, Romuald Conty, Romain Tartière
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -28,15 +30,13 @@
|
||||||
|
|
||||||
# define ARYGON_DRIVER_NAME "ARYGON"
|
# define ARYGON_DRIVER_NAME "ARYGON"
|
||||||
|
|
||||||
// Functions used by developer to handle connection to this device
|
bool arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||||
nfc_device_desc_t *arygon_pick_device (void);
|
|
||||||
bool arygon_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
|
||||||
|
|
||||||
nfc_device_t *arygon_connect (const nfc_device_desc_t * pndd);
|
nfc_device_t *arygon_connect (const nfc_device_desc_t * pndd);
|
||||||
void arygon_disconnect (nfc_device_t * pnd);
|
void arygon_disconnect (nfc_device_t * pnd);
|
||||||
|
bool arygon_tama_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData);
|
||||||
|
int arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szData);
|
||||||
|
|
||||||
// Callback function used by libnfc to transmit commands to the PN53X chip
|
extern const struct nfc_driver_t arygon_driver;
|
||||||
bool arygon_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx,
|
|
||||||
size_t * pszRx);
|
|
||||||
|
|
||||||
#endif // ! __NFC_DRIVER_ARYGON_H__
|
#endif // ! __NFC_DRIVER_ARYGON_H__
|
||||||
|
|
|
@ -29,20 +29,19 @@
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include "libnfc/drivers.h"
|
#include "pn532_uart.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "pn532_uart.h"
|
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
#include <nfc/nfc-messages.h>
|
#include <nfc/nfc-messages.h>
|
||||||
|
|
||||||
#include "uart.h"
|
#include "libnfc/drivers.h"
|
||||||
#include "libnfc/nfc-internal.h"
|
#include "libnfc/nfc-internal.h"
|
||||||
#include "libnfc/chips/pn53x.h"
|
#include "libnfc/chips/pn53x.h"
|
||||||
#include "libnfc/chips/pn53x-internal.h"
|
#include "libnfc/chips/pn53x-internal.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
#define SERIAL_DEFAULT_PORT_SPEED 115200
|
#define SERIAL_DEFAULT_PORT_SPEED 115200
|
||||||
|
|
||||||
|
@ -99,16 +98,14 @@ pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * ps
|
||||||
bool res = pn532_uart_check_communication (&nd);
|
bool res = pn532_uart_check_communication (&nd);
|
||||||
free(nd.driver_data);
|
free(nd.driver_data);
|
||||||
free(nd.chip_data);
|
free(nd.chip_data);
|
||||||
|
uart_close (sp);
|
||||||
if(!res)
|
if(!res)
|
||||||
continue;
|
continue;
|
||||||
uart_close (sp);
|
|
||||||
|
|
||||||
snprintf (pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", pcPort);
|
snprintf (pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", pcPort);
|
||||||
pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0';
|
|
||||||
pnddDevices[*pszDeviceFound].pcDriver = PN532_UART_DRIVER_NAME;
|
pnddDevices[*pszDeviceFound].pcDriver = PN532_UART_DRIVER_NAME;
|
||||||
pnddDevices[*pszDeviceFound].pcPort = strdup (pcPort);
|
pnddDevices[*pszDeviceFound].pcPort = strdup (pcPort);
|
||||||
pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED;
|
pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED;
|
||||||
DBG ("Device found: %s.", pnddDevices[*pszDeviceFound].acDevice);
|
|
||||||
(*pszDeviceFound)++;
|
(*pszDeviceFound)++;
|
||||||
|
|
||||||
// Test if we reach the maximum "wanted" devices
|
// Test if we reach the maximum "wanted" devices
|
||||||
|
@ -159,11 +156,12 @@ pn532_uart_connect (const nfc_device_desc_t * pndd)
|
||||||
pnd->driver = &pn532_uart_driver;
|
pnd->driver = &pn532_uart_driver;
|
||||||
|
|
||||||
// Check communication using "Diagnose" command, with "Communication test" (0x00)
|
// Check communication using "Diagnose" command, with "Communication test" (0x00)
|
||||||
if (!pn532_uart_check_communication (pnd))
|
if (!pn532_uart_check_communication (pnd)) {
|
||||||
|
pn532_uart_disconnect(pnd);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
DBG ("Successfully connected to: %s", pndd->pcPort);
|
pn53x_init(pnd);
|
||||||
|
|
||||||
return pnd;
|
return pnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,13 +178,10 @@ pn532_uart_disconnect (nfc_device_t * pnd)
|
||||||
bool
|
bool
|
||||||
pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData)
|
pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData)
|
||||||
{
|
{
|
||||||
DBG ("state: %d (SLEEP: %d, NORMAL: %d, EXECUTE: %d)", ((struct pn53x_data*)(pnd->chip_data))->state, SLEEP, NORMAL, EXECUTE);
|
|
||||||
if (((struct pn53x_data*)(pnd->chip_data))->state == SLEEP) {
|
if (((struct pn53x_data*)(pnd->chip_data))->state == SLEEP) {
|
||||||
// if (1) {
|
|
||||||
/** PN532C106 wakeup. */
|
/** PN532C106 wakeup. */
|
||||||
/** High Speed Unit (HSU) wake up consist to send 0x55 and wait a "long" delay for PN532 being wakeup. */
|
/** High Speed Unit (HSU) wake up consist to send 0x55 and wait a "long" delay for PN532 being wakeup. */
|
||||||
const byte_t pn532_wakeup_preamble[] = { 0x55, 0x55, 0x00, 0x00, 0x00 };
|
const byte_t pn532_wakeup_preamble[] = { 0x55, 0x55, 0x00, 0x00, 0x00 };
|
||||||
//, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
||||||
uart_send (((struct pn532_uart_data*)(pnd->driver_data))->port, pn532_wakeup_preamble, sizeof (pn532_wakeup_preamble));
|
uart_send (((struct pn532_uart_data*)(pnd->driver_data))->port, pn532_wakeup_preamble, sizeof (pn532_wakeup_preamble));
|
||||||
((struct pn53x_data*)(pnd->chip_data))->state = NORMAL; // PN532 should now be awake
|
((struct pn53x_data*)(pnd->chip_data))->state = NORMAL; // PN532 should now be awake
|
||||||
// According to PN532 application note, C106 appendix: to go out Low Vbat mode and enter in normal mode we need to send a SAMConfiguration command
|
// According to PN532 application note, C106 appendix: to go out Low Vbat mode and enter in normal mode we need to send a SAMConfiguration command
|
||||||
|
@ -195,38 +190,13 @@ pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
byte_t abtTxBuf[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
byte_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
||||||
|
|
||||||
pnd->iLastCommand = pbtData[0];
|
pnd->iLastCommand = pbtData[0];
|
||||||
size_t szFrame = 0;
|
size_t szFrame = 0;
|
||||||
|
|
||||||
if (szData <= PN53x_NORMAL_FRAME__DATA_MAX_LEN) {
|
pn53x_build_frame (abtFrame, &szFrame, pbtData, szData);
|
||||||
// LEN - Packet length = data length (len) + checksum (1) + end of stream marker (1)
|
|
||||||
abtTxBuf[3] = szData + 1;
|
|
||||||
// LCS - Packet length checksum
|
|
||||||
abtTxBuf[4] = 256 - (szData + 1);
|
|
||||||
// TFI
|
|
||||||
abtTxBuf[5] = 0xD4;
|
|
||||||
// DATA - Copy the PN53X command into the packet buffer
|
|
||||||
memcpy (abtTxBuf + 6, pbtData, szData);
|
|
||||||
|
|
||||||
// DCS - Calculate data payload checksum
|
int res = uart_send (((struct pn532_uart_data*)(pnd->driver_data))->port, abtFrame, szFrame);
|
||||||
byte_t btDCS = (256 - 0xD4);
|
|
||||||
for (size_t szPos = 0; szPos < szData; szPos++) {
|
|
||||||
btDCS -= pbtData[szPos];
|
|
||||||
}
|
|
||||||
abtTxBuf[6 + szData] = btDCS;
|
|
||||||
|
|
||||||
// 0x00 - End of stream marker
|
|
||||||
abtTxBuf[szData + 7] = 0x00;
|
|
||||||
|
|
||||||
szFrame = szData + PN53x_NORMAL_FRAME__OVERHEAD;
|
|
||||||
} else {
|
|
||||||
// FIXME: Build extended frame
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
int res = uart_send (((struct pn532_uart_data*)(pnd->driver_data))->port, abtTxBuf, szFrame);
|
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
ERR ("%s", "Unable to transmit data. (TX)");
|
ERR ("%s", "Unable to transmit data. (TX)");
|
||||||
pnd->iLastError = res;
|
pnd->iLastError = res;
|
||||||
|
@ -241,7 +211,7 @@ pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pn53x_check_ack_frame_callback (pnd, abtRxBuf, sizeof(abtRxBuf))) {
|
if (pn53x_check_ack_frame (pnd, abtRxBuf, sizeof(abtRxBuf))) {
|
||||||
((struct pn53x_data*)(pnd->chip_data))->state = EXECUTE;
|
((struct pn53x_data*)(pnd->chip_data))->state = EXECUTE;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -29,16 +29,12 @@
|
||||||
# include <sys/param.h>
|
# include <sys/param.h>
|
||||||
# define PN532_UART_DRIVER_NAME "PN532_UART"
|
# define PN532_UART_DRIVER_NAME "PN532_UART"
|
||||||
|
|
||||||
// Functions used by developer to handle connection to this device
|
|
||||||
nfc_device_desc_t *pn532_uart_pick_device (void);
|
|
||||||
bool pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
bool pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound);
|
||||||
|
|
||||||
nfc_device_t *pn532_uart_connect (const nfc_device_desc_t * pndd);
|
nfc_device_t *pn532_uart_connect (const nfc_device_desc_t * pndd);
|
||||||
void pn532_uart_disconnect (nfc_device_t * pnd);
|
void pn532_uart_disconnect (nfc_device_t * pnd);
|
||||||
|
|
||||||
// Callback function used by libnfc to transmit commands to the PN53X chip
|
|
||||||
bool pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData);
|
bool pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData);
|
||||||
int pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen);
|
int pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szData);
|
||||||
|
|
||||||
extern const struct nfc_driver_t pn532_uart_driver;
|
extern const struct nfc_driver_t pn532_uart_driver;
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "nfc-internal.h"
|
#include "nfc-internal.h"
|
||||||
|
|
||||||
#include <nfc/nfc-messages.h>
|
#include <nfc/nfc-messages.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
nfc_device_desc_t *nfc_pick_device (void);
|
nfc_device_desc_t *nfc_pick_device (void);
|
||||||
|
|
||||||
|
@ -53,6 +54,9 @@ const struct nfc_driver_t *nfc_drivers[] = {
|
||||||
# if defined (DRIVER_PN532_UART_ENABLED)
|
# if defined (DRIVER_PN532_UART_ENABLED)
|
||||||
&pn532_uart_driver,
|
&pn532_uart_driver,
|
||||||
# endif /* DRIVER_PN532_UART_ENABLED */
|
# endif /* DRIVER_PN532_UART_ENABLED */
|
||||||
|
# if defined (DRIVER_ARYGON_ENABLED)
|
||||||
|
&arygon_driver,
|
||||||
|
# endif /* DRIVER_ARYGON_ENABLED */
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue