static int pn532_uart_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout) { int res = 0; // Before sending anything, we need to discard from any junk bytes uart_flush_input(DRIVER_DATA(pnd)->port); switch (CHIP_DATA(pnd)->power_mode) { case LOWVBAT: { /** PN532C106 wakeup. */ if ((res = pn532_uart_wakeup(pnd)) < 0) { return res; } // 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 ((res = pn532_SAMConfiguration(pnd, PSM_NORMAL, 1000)) < 0) { return res; } } break; case POWERDOWN: { if ((res = pn532_uart_wakeup(pnd)) < 0) { return res; } } break; case NORMAL: // Nothing to do :) break; }; uint8_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff" size_t szFrame = 0; if ((res = pn53x_build_frame(abtFrame, &szFrame, pbtData, szData)) < 0) { pnd->last_error = res; return pnd->last_error; } res = uart_send(DRIVER_DATA(pnd)->port, abtFrame, szFrame, timeout); if (res != 0) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)"); pnd->last_error = res; return pnd->last_error; } uint8_t abtRxBuf[6]; res = uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, 6, 0, timeout); if (res != 0) { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "Unable to read ACK"); pnd->last_error = res; return pnd->last_error; } if (pn53x_check_ack_frame(pnd, abtRxBuf, sizeof(abtRxBuf)) == 0) { // The PN53x is running the sent command } else { return pnd->last_error; } return NFC_SUCCESS; }
bool pn532_uart_list_devices (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 * sending some PN53x commands. But using this way to probe devices, we can * have serious problem with other device on this bus */ #ifndef SERIAL_AUTOPROBE_ENABLED (void) pnddDevices; (void) szDevices; *pszDeviceFound = 0; DBG ("%s", "Serial auto-probing have been disabled at compile time. Skipping autoprobe."); return false; #else /* SERIAL_AUTOPROBE_ENABLED */ *pszDeviceFound = 0; serial_port sp; const char *pcPorts[] = DEFAULT_SERIAL_PORTS; const char *pcPort; int iDevice = 0; while ((pcPort = pcPorts[iDevice++])) { sp = uart_open (pcPort); DBG ("Trying to find PN532 device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED); if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) { bool bComOk; // Serial port claimed but we need to check if a PN532_UART is connected. uart_set_speed (sp, SERIAL_DEFAULT_PORT_SPEED); // PN532 could be powered down, we need to wake it up before line testing. pn532_uart_wakeup ((nfc_device_spec_t) sp); // Check communication using "Diagnose" command, with "Communication test" (0x00) if (!pn532_uart_check_communication ((nfc_device_spec_t) sp, &bComOk)) continue; if (!bComOk) continue; uart_close (sp); 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].pcPort = strdup (pcPort); pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED; DBG ("Device found: %s.", pnddDevices[*pszDeviceFound].acDevice); (*pszDeviceFound)++; // Test if we reach the maximum "wanted" devices if ((*pszDeviceFound) >= szDevices) break; } # ifdef DEBUG if (sp == INVALID_SERIAL_PORT) DBG ("Invalid serial port: %s", pcPort); if (sp == CLAIMED_SERIAL_PORT) DBG ("Serial port already claimed: %s", pcPort); # endif /* DEBUG */ } #endif /* SERIAL_AUTOPROBE_ENABLED */ return true; }
int pn532_uart_ack(nfc_device *pnd) { int res = 0; if (POWERDOWN == CHIP_DATA(pnd)->power_mode) { if ((res = pn532_uart_wakeup(pnd)) < 0) { return res; } } return (uart_send(DRIVER_DATA(pnd)->port, pn53x_ack_frame, sizeof(pn53x_ack_frame), 0)); }
nfc_device_t * pn532_uart_connect (const nfc_device_desc_t * pndd) { serial_port sp; nfc_device_t *pnd = NULL; bool bComOk; DBG ("Attempt to connect to: %s at %d bauds.", pndd->pcPort, pndd->uiSpeed); sp = uart_open (pndd->pcPort); if (sp == INVALID_SERIAL_PORT) ERR ("Invalid serial port: %s", pndd->pcPort); if (sp == CLAIMED_SERIAL_PORT) ERR ("Serial port already claimed: %s", pndd->pcPort); if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) return NULL; uart_set_speed (sp, pndd->uiSpeed); // PN532 could be powered down, we need to wake it up before line testing. pn532_uart_wakeup ((nfc_device_spec_t) sp); // Check communication using "Diagnose" command, with "Communication test" (0x00) if (!pn532_uart_check_communication ((nfc_device_spec_t) sp, &bComOk)) return NULL; if (!bComOk) return NULL; DBG ("Successfully connected to: %s", pndd->pcPort); // We have a connection pnd = malloc (sizeof (nfc_device_t)); strncpy (pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1); pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0'; pnd->nc = NC_PN532; pnd->nds = (nfc_device_spec_t) sp; pnd->bActive = true; return pnd; }