chip/pn53x: handle PN532 "power down" and "low VBat" power mode instead of a simple "sleep" mode. (Fixes Issue 167)

This commit is contained in:
Romuald Conty
2011-04-27 13:16:36 +00:00
parent 09b18bf6b8
commit 1198a71d64
6 changed files with 73 additions and 31 deletions
+1 -1
View File
@@ -220,7 +220,7 @@ acr122_connect (const nfc_device_desc_t * pndd)
// Done, we found the reader we are looking for
snprintf (pnd->acName, sizeof (pnd->acName), "%s / %s", pndd->acDevice, pcFirmware);
CHIP_DATA (pnd)->state = NORMAL;
CHIP_DATA (pnd)->power_mode = NORMAL;
CHIP_DATA (pnd)->io = &acr122_io;
// 50: empirical tuning on Touchatag
// 46: empirical tuning on ACR122U
+4 -6
View File
@@ -112,7 +112,7 @@ arygon_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDev
pnd->driver_data = malloc(sizeof(struct arygon_data));
DRIVER_DATA (pnd)->port = sp;
pnd->chip_data = malloc(sizeof(struct pn53x_data));
CHIP_DATA (pnd)->state = NORMAL;
CHIP_DATA (pnd)->power_mode = NORMAL;
CHIP_DATA (pnd)->io = &arygon_tama_io;
bool res = arygon_reset_tama (pnd);
@@ -172,7 +172,7 @@ arygon_connect (const nfc_device_desc_t * pndd)
pnd->chip_data = malloc(sizeof(struct pn53x_data));
// The PN53x chip connected to ARYGON MCU doesn't seems to be in SLEEP mode
CHIP_DATA (pnd)->state = NORMAL;
CHIP_DATA (pnd)->power_mode = NORMAL;
CHIP_DATA (pnd)->io = &arygon_tama_io;
// empirical tuning
CHIP_DATA (pnd)->timer_correction = 46;
@@ -239,7 +239,7 @@ arygon_tama_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szDat
}
if (pn53x_check_ack_frame (pnd, abtRxBuf, sizeof(abtRxBuf))) {
CHIP_DATA (pnd)->state = EXECUTE;
// The PN53x is running the sent command
} else if (0 == memcmp(arygon_error_unknown_mode, abtRxBuf, sizeof(abtRxBuf))) {
ERR( "Bad frame format." );
// We have already read 6 bytes and arygon_error_unknown_mode is 10 bytes long
@@ -255,8 +255,6 @@ arygon_tama_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szDat
int
arygon_abort (nfc_device_t *pnd)
{
CHIP_DATA (pnd)->state = NORMAL;
// Send a valid TAMA packet to wakup the PN53x (we will not have an answer, according to Arygon manual)
byte_t dummy[] = { 0x32, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 0x6c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0xbe, 0x00 };
@@ -384,7 +382,7 @@ arygon_tama_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLe
pnd->iLastError = DEIO;
return -1;
}
CHIP_DATA (pnd)->state = NORMAL;
// The PN53x command is done and we successfully received the reply
return len;
}
+41 -16
View File
@@ -49,7 +49,7 @@
static const byte_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
int pn532_uart_ack (nfc_device_t * pnd);
// void pn532_uart_wakeup (const nfc_device_spec_t nds);
int pn532_uart_wakeup (nfc_device_t * pnd);
const struct pn53x_io pn532_uart_io;
@@ -94,7 +94,7 @@ pn532_uart_probe (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * ps
DRIVER_DATA (pnd)->port = sp;
pnd->chip_data = malloc(sizeof(struct pn53x_data));
CHIP_DATA (pnd)->type = PN532;
CHIP_DATA (pnd)->state = SLEEP;
CHIP_DATA (pnd)->power_mode = LOWVBAT;
CHIP_DATA (pnd)->io = &pn532_uart_io;
// Check communication using "Diagnose" command, with "Communication test" (0x00)
@@ -158,7 +158,7 @@ pn532_uart_connect (const nfc_device_desc_t * pndd)
DRIVER_DATA(pnd)->port = sp;
pnd->chip_data = malloc(sizeof(struct pn53x_data));
CHIP_DATA(pnd)->type = PN532;
CHIP_DATA(pnd)->state = SLEEP;
CHIP_DATA(pnd)->power_mode = LOWVBAT;
CHIP_DATA(pnd)->io = &pn532_uart_io;
// empirical tuning
CHIP_DATA(pnd)->timer_correction = 48;
@@ -182,21 +182,42 @@ pn532_uart_disconnect (nfc_device_t * pnd)
nfc_device_free (pnd);
}
int
pn532_uart_wakeup (nfc_device_t * pnd)
{
/* 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 };
int res = uart_send (DRIVER_DATA(pnd)->port, pn532_wakeup_preamble, sizeof (pn532_wakeup_preamble));
CHIP_DATA(pnd)->power_mode = NORMAL; // PN532 should now be awake
return res;
}
#define PN532_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
bool
pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData)
{
if (CHIP_DATA(pnd)->state == SLEEP) {
/** PN532C106 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 };
uart_send (DRIVER_DATA(pnd)->port, pn532_wakeup_preamble, sizeof (pn532_wakeup_preamble));
CHIP_DATA(pnd)->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
if (!pn53x_SAMConfiguration (pnd, 0x01)) {
return false;
switch (CHIP_DATA(pnd)->power_mode) {
case LOWVBAT: {
/** PN532C106 wakeup. */
if (-1 == pn532_uart_wakeup(pnd)) {
return false;
}
// 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
if (!pn53x_SAMConfiguration (pnd, 0x01)) {
return false;
}
}
}
break;
case POWERDOWN: {
if (-1 == pn532_uart_wakeup(pnd)) {
return false;
}
}
break;
case NORMAL:
// Nothing to do :)
break;
};
byte_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
CHIP_DATA (pnd)->ui8LastCommand = pbtData[0];
@@ -223,7 +244,7 @@ pn532_uart_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData
}
if (pn53x_check_ack_frame (pnd, abtRxBuf, sizeof(abtRxBuf))) {
CHIP_DATA(pnd)->state = EXECUTE;
// The PN53x is running the sent command
} else {
return false;
}
@@ -353,14 +374,18 @@ pn532_uart_receive (nfc_device_t * pnd, byte_t * pbtData, const size_t szDataLen
pnd->iLastError = DEIO;
return -1;
}
CHIP_DATA(pnd)->state = NORMAL;
// The PN53x command is done and we successfully received the reply
return len;
}
int
pn532_uart_ack (nfc_device_t * pnd)
{
CHIP_DATA(pnd)->state = NORMAL;
if (POWERDOWN == CHIP_DATA(pnd)->power_mode) {
if (-1 == pn532_uart_wakeup(pnd)) {
return -1;
}
}
return (0 == uart_send (DRIVER_DATA(pnd)->port, ack_frame, sizeof (ack_frame))) ? 0 : -1;
}
+3 -3
View File
@@ -285,7 +285,7 @@ pn53x_usb_connect (const nfc_device_desc_t *pndd)
*DRIVER_DATA (pnd) = data;
pnd->chip_data = malloc(sizeof(struct pn53x_data));
CHIP_DATA (pnd)->state = NORMAL;
CHIP_DATA (pnd)->power_mode = NORMAL;
CHIP_DATA (pnd)->io = &pn53x_usb_io;
switch (DRIVER_DATA (pnd)->model) {
@@ -388,7 +388,7 @@ pn53x_usb_send (nfc_device_t * pnd, const byte_t * pbtData, const size_t szData)
}
if (pn53x_check_ack_frame (pnd, abtRxBuf, res)) {
CHIP_DATA(pnd)->state = EXECUTE;
// The PN53x is running the sent command
} else {
return false;
}
@@ -529,7 +529,7 @@ read:
pnd->iLastError = DEIO;
return -1;
}
CHIP_DATA (pnd)->state = NORMAL;
// The PN53x command is done and we successfully received the reply
return len;
}