Fix ARYGON driver:

- Does not send any ACK frame at start: my ARYGON does get happy with this frame (see code comments)
 - Send a TAMA reset (for PN532) instead of ACK frame
 - Remove bzero use: its a deprecated function
This commit is contained in:
Romuald Conty 2010-10-22 14:29:44 +00:00
parent ca8c5cabe1
commit 8798f6bbcd
3 changed files with 81 additions and 26 deletions

View file

@ -35,7 +35,7 @@ AC_PATH_PROG(PKG_CONFIG, pkg-config, [AC_MSG_ERROR([pkg-config not found.])])
AC_HEADER_STDC AC_HEADER_STDC
AC_HEADER_STDBOOL AC_HEADER_STDBOOL
AC_CHECK_HEADERS([fcntl.h limits.h stdio.h stdlib.h stdint.h stddef.h stdbool.h sys/ioctl.h sys/param.h sys/time.h termios.h]) AC_CHECK_HEADERS([fcntl.h limits.h stdio.h stdlib.h stdint.h stddef.h stdbool.h sys/ioctl.h sys/param.h sys/time.h termios.h])
AC_CHECK_FUNCS([bzero memmove memset select strdup strerror strstr strtol usleep], AC_CHECK_FUNCS([memmove memset select strdup strerror strstr strtol usleep],
[AC_DEFINE([_XOPEN_SOURCE], [600], [Enable POSIX extensions if present])]) [AC_DEFINE([_XOPEN_SOURCE], [600], [Enable POSIX extensions if present])])
AC_DEFINE(_NETBSD_SOURCE, 1, [Define on NetBSD to activate all library features]) AC_DEFINE(_NETBSD_SOURCE, 1, [Define on NetBSD to activate all library features])

View file

@ -170,7 +170,7 @@ pn53x_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, b
} }
*pszRx = MAX_FRAME_LEN; *pszRx = MAX_FRAME_LEN;
// Call the tranceive callback function of the current device // Call the transceive callback function of the current device
if (!pnd->pdc->transceive (pnd, pbtTx, szTx, pbtRx, pszRx)) if (!pnd->pdc->transceive (pnd, pbtTx, szTx, pbtRx, pszRx))
return false; return false;
// TODO Put all these hex-coded command behind a human-readable #define (1.6.x) // TODO Put all these hex-coded command behind a human-readable #define (1.6.x)

View file

@ -37,10 +37,6 @@
# include <strings.h> # include <strings.h>
#endif #endif
#ifdef _WIN32
# define bzero(a, b) memset(a, 0x00, b)
#endif
#include "arygon.h" #include "arygon.h"
#include <nfc/nfc-messages.h> #include <nfc/nfc-messages.h>
@ -70,16 +66,22 @@
#define SERIAL_DEFAULT_PORT_SPEED 9600 #define SERIAL_DEFAULT_PORT_SPEED 9600
// TODO Move this one level up for libnfc-1.6 // TODO Move this one level up for libnfc-1.6
static const byte_t ack_frame[] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 }; 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())
// static const byte_t arygon_ack_frame[] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
void arygon_ack (const nfc_device_spec_t nds); static const byte_t arygon_error_none[] = "FF000000\x0d\x0a";
static const byte_t arygon_error_incomplete_command[] = "FF0C0000\x0d\x0a";
static const byte_t arygon_error_unknown_mode[] = "FF060000\x0d\x0a";
// void arygon_ack (const nfc_device_spec_t nds);
bool arygon_reset_tama (const nfc_device_spec_t nds);
bool arygon_check_communication (const nfc_device_spec_t nds); bool arygon_check_communication (const nfc_device_spec_t nds);
/** /**
* @note ARYGON-ADRA (PN531): ???,n,8,1 * @note ARYGON-ADRA (PN531): ???,n,8,1
* @note ARYGON-ADRB (PN532): 9600,n,8,1 * @note ARYGON-ADRB (PN532): 9600,n,8,1
* @note ARYGON-APDA (PN531): 9600,n,8,1 * @note ARYGON-APDA (PN531): 9600,n,8,1
* @note ARYGON-APDB1UA33N (PN532): 115200,n,8,1
* @note ARYGON-APDB2UA33 (PN532 + ARYGON µC): 9600,n,8,1 * @note ARYGON-APDB2UA33 (PN532 + ARYGON µC): 9600,n,8,1
*/ */
nfc_device_desc_t * nfc_device_desc_t *
@ -131,10 +133,7 @@ arygon_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t *
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, SERIAL_DEFAULT_PORT_SPEED);
// Send ACK frame to cancel a previous command if (!arygon_reset_tama((nfc_device_spec_t) sp))
arygon_ack ((nfc_device_spec_t) sp);
if (!arygon_check_communication ((nfc_device_spec_t) sp))
continue; continue;
uart_close (sp); uart_close (sp);
@ -180,9 +179,9 @@ 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)) {
// Send ACK frame to cancel a previous command return NULL;
arygon_ack ((nfc_device_spec_t) sp); }
DBG ("Successfully connected to: %s", pndd->pcPort); DBG ("Successfully connected to: %s", pndd->pcPort);
@ -240,7 +239,7 @@ arygon_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx,
return false; return false;
} }
#ifdef DEBUG #ifdef DEBUG
bzero (abtRxBuf, sizeof (abtRxBuf)); memset (abtRxBuf, 0x00, sizeof (abtRxBuf));
#endif #endif
res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen); res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
if (res != 0) { if (res != 0) {
@ -256,8 +255,8 @@ arygon_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx,
if (!pn53x_check_ack_frame_callback (pnd, abtRxBuf, szRxBufLen)) if (!pn53x_check_ack_frame_callback (pnd, abtRxBuf, szRxBufLen))
return false; return false;
szRxBufLen -= sizeof (ack_frame); szRxBufLen -= sizeof (pn53x_ack_frame);
memmove (abtRxBuf, abtRxBuf + sizeof (ack_frame), szRxBufLen); memmove (abtRxBuf, abtRxBuf + sizeof (pn53x_ack_frame), szRxBufLen);
if (szRxBufLen == 0) { if (szRxBufLen == 0) {
szRxBufLen = BUFFER_LENGTH; szRxBufLen = BUFFER_LENGTH;
@ -288,29 +287,85 @@ arygon_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx,
return true; return true;
} }
bool
arygon_reset_tama(const nfc_device_spec_t nds)
{
const byte_t arygon_reset_tama[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'r' };
byte_t abtRx[BUFFER_LENGTH];
size_t szRx;
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)
#ifdef DEBUG
PRINT_HEX ("TX", arygon_reset_tama, sizeof (arygon_reset_tama));
#endif
uart_send ((serial_port) nds, arygon_reset_tama, sizeof (arygon_reset_tama));
// 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)
res = uart_receive ((serial_port) nds, abtRx, &szRx);
if (res != 0) {
return false;
}
#ifdef DEBUG
PRINT_HEX ("RX", abtRx, szRx);
#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
#ifdef DEBUG
PRINT_HEX ("TX", arygon_reset_tama, sizeof (arygon_reset_tama));
#endif
uart_send ((serial_port) nds, arygon_reset_tama, sizeof (arygon_reset_tama));
res = uart_receive ((serial_port) nds, abtRx, &szRx);
if (res != 0) {
return false;
}
#ifdef DEBUG
PRINT_HEX ("RX", abtRx, szRx);
#endif
}
if (0 != memcmp (abtRx, arygon_error_none, sizeof (arygon_error_none) - 1)) {
return false;
}
return true;
}
/*
void void
arygon_ack (const nfc_device_spec_t nds) arygon_ack (const nfc_device_spec_t nds)
{ {
byte_t abtRx[BUFFER_LENGTH];
size_t szRx;
#ifdef DEBUG #ifdef DEBUG
PRINT_HEX ("TX", ack_frame, sizeof (ack_frame)); PRINT_HEX ("TX", arygon_ack_frame, sizeof (arygon_ack_frame));
#endif #endif
uart_send ((serial_port) nds, ack_frame, sizeof (ack_frame)); uart_send ((serial_port) nds, arygon_ack_frame, sizeof (arygon_ack_frame));
uart_receive ((serial_port) nds, abtRx, &szRx);
#ifdef DEBUG
PRINT_HEX ("RX", abtRx, szRx);
#endif
// ARYGON device will send an arygon_error_incomplete_command when sending an
// ACK frame, and I (Romuald) don't know if the command is sent to PN or not
if (0 != memcmp (abtRx, arygon_error_incomplete_command, sizeof (arygon_error_incomplete_command) - 1)) {
return false;
}
} }
*/
bool bool
arygon_check_communication (const nfc_device_spec_t nds) arygon_check_communication (const nfc_device_spec_t nds)
{ {
byte_t abtRx[BUFFER_LENGTH]; byte_t abtRx[BUFFER_LENGTH];
size_t szRx; size_t szRx;
const byte_t attempted_result[] = const byte_t attempted_result[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, // ACK
{ 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd5, 0x01, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd5, 0x01, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbc, 0x00 }; // Reply
0xbc, 0x00 };
int res; int res;
/** To be sure that PN532 is alive, we have put a "Diagnose" command to execute a "Communication Line Test" */ /** To be sure that PN532 is alive, we have put a "Diagnose" command to execute a "Communication Line Test" */
const byte_t pncmd_communication_test[] = const byte_t pncmd_communication_test[] =
{ DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbe, { DEV_ARYGON_PROTOCOL_TAMA, // Header to passthrough front ARYGON µC (== directly talk to PN53x)
0x00 }; 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbe, 0x00 };
#ifdef DEBUG #ifdef DEBUG
PRINT_HEX ("TX", pncmd_communication_test, sizeof (pncmd_communication_test)); PRINT_HEX ("TX", pncmd_communication_test, sizeof (pncmd_communication_test));