diff --git a/libnfc/buses/uart.c b/libnfc/buses/uart.c index d7c25fa..0f6ecec 100644 --- a/libnfc/buses/uart.c +++ b/libnfc/buses/uart.c @@ -107,11 +107,10 @@ serial_port uart_open(const char* pcPortName) return sp; } -void uart_set_speed(nfc_device_t* pnd, const uint32_t uiPortSpeed) +void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { - serial_port sp = (serial_port)pnd->nds; DBG("Serial port speed requested to be set to %d bauds.", uiPortSpeed); - // Set port speed (Input and Output) + const serial_port_unix* spu = (serial_port_unix*)sp; // Portability note: on some systems, B9600 != 9600 so we have to do // uint32_t <=> speed_t associations by hand. @@ -142,18 +141,18 @@ void uart_set_speed(nfc_device_t* pnd, const uint32_t uiPortSpeed) default: ERR("Unable to set serial port speed to %d bauds. Speed value must be one of those defined in termios(3).", uiPortSpeed); }; - const serial_port_unix* spu = (serial_port_unix*)sp; - cfsetispeed((struct termios*)&spu->tiNew, stPortSpeed); - cfsetospeed((struct termios*)&spu->tiNew, stPortSpeed); - if( tcsetattr(spu->fd, TCSADRAIN, &spu->tiNew) == -1) + + // Set port speed (Input and Output) + cfsetispeed((struct termios*)&(spu->tiNew), stPortSpeed); + cfsetospeed((struct termios*)&(spu->tiNew), stPortSpeed); + if( tcsetattr(spu->fd, TCSADRAIN, &(spu->tiNew)) == -1) { ERR("%s", "Unable to apply new speed settings."); } } -uint32_t uart_get_speed(const nfc_device_t* pnd) +uint32_t uart_get_speed(serial_port sp) { - serial_port sp = (serial_port)pnd->nds; uint32_t uiPortSpeed = 0; const serial_port_unix* spu = (serial_port_unix*)sp; switch (cfgetispeed(&spu->tiNew)) @@ -194,13 +193,18 @@ void uart_close(const serial_port sp) free(sp); } -bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) +/** + * @brief Receive data from UART and copy data to \a pbtRx + * + * @return 0 on success, otherwise driver error code + */ +int +uart_receive(serial_port sp, byte_t* pbtRx, size_t* pszRxLen) { int res; int byteCount; fd_set rfds; struct timeval tv; - serial_port sp = (serial_port)pnd->nds; // Reset the output count *pszRxLen = 0; @@ -215,8 +219,7 @@ bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) // Read error if (res < 0) { DBG("%s", "RX error."); - pnd->iLastError = DEIO; - return false; + return DEIO; } // Read time-out @@ -224,19 +227,17 @@ bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) if (*pszRxLen == 0) { // Error, we received no data DBG("%s", "RX time-out, buffer empty."); - pnd->iLastError = DETIMEOUT; - return false; + return DETIMEOUT; } else { // We received some data, but nothing more is available - return true; + return 0; } } // Retrieve the count of the incoming bytes res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount); if (res < 0) { - pnd->iLastError = DEIO; - return false; + return DEIO; } // There is something available, read the data @@ -244,24 +245,28 @@ bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen) // Stop if the OS has some troubles reading the data if (res <= 0) { - pnd->iLastError = DEIO; - return false; + return DEIO; } *pszRxLen += res; } while (byteCount); - return true; + return 0; } -bool uart_send(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) +/** + * @brief Send \a pbtTx content to UART + * + * @return 0 on success, otherwise a driver error is returned + */ +int +uart_send(serial_port sp, const byte_t* pbtTx, const size_t szTxLen) { int32_t res; size_t szPos = 0; fd_set rfds; struct timeval tv; - serial_port sp = (serial_port)pnd->nds; while (szPos < szTxLen) { @@ -274,15 +279,13 @@ bool uart_send(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) // Write error if (res < 0) { DBG("%s", "TX error."); - pnd->iLastError = DEIO; - return false; + return DEIO; } // Write time-out if (res == 0) { DBG("%s", "TX time-out."); - pnd->iLastError = DETIMEOUT; - return false; + return DETIMEOUT; } // Send away the bytes @@ -290,13 +293,12 @@ bool uart_send(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen) // Stop if the OS has some troubles sending the data if (res <= 0) { - pnd->iLastError = DEIO; - return false; + return DEIO; } szPos += res; } - return true; + return 0; } #else diff --git a/libnfc/buses/uart.h b/libnfc/buses/uart.h index 483e7a3..35b37d3 100644 --- a/libnfc/buses/uart.h +++ b/libnfc/buses/uart.h @@ -81,12 +81,11 @@ typedef void* serial_port; serial_port uart_open(const char* pcPortName); void uart_close(const serial_port sp); -void uart_set_speed(nfc_device_t* pnd, const uint32_t uiPortSpeed); -uint32_t uart_get_speed(const nfc_device_t* pnd); +void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed); +uint32_t uart_get_speed(const serial_port sp); -bool uart_receive(nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxLen); -bool uart_send(nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen); +int uart_receive(serial_port sp, byte_t* pbtRx, size_t* pszRxLen); +int uart_send(serial_port sp, const byte_t* pbtTx, const size_t szTxLen); #endif // __NFC_BUS_UART_H__ - diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 25861c2..5987dc3 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -69,9 +69,10 @@ const byte_t pncmd_target_get_status [ 2] = { 0xD4,0x8A }; static const byte_t pn53x_ack_frame[] = { 0x00,0x00,0xff,0x00,0xff,0x00 }; static const byte_t pn53x_nack_frame[] = { 0x00,0x00,0xff,0xff,0x00,0x00 }; +// XXX: Is this function correctly named ? bool pn53x_transceive_callback(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))) { DBG("%s", "PN53x ACKed"); return true; diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index ac34129..2bef198 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -100,7 +100,7 @@ pn532_uart_list_devices(nfc_device_desc_t pnddDevices[], size_t szDevices, size_ // 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 "Comunication test" (0x00) - if(!pn532_uart_check_communication((nfc_device_spec_t)sp), &bComOk) + if(!pn532_uart_check_communication((nfc_device_spec_t)sp, &bComOk)) return false; if (!bComOk) continue; @@ -200,16 +200,19 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t #ifdef DEBUG PRINT_HEX("TX", abtTxBuf,szTxLen+7); #endif - if (!uart_send((serial_port)pnd->nds,abtTxBuf,szTxLen+7)) { + int res; + res = uart_send((serial_port)pnd->nds,abtTxBuf,szTxLen+7); + if(res != 0) { ERR("%s", "Unable to transmit data. (TX)"); - pnd->iLastError = DEIO; + pnd->iLastError = res; return false; } szRxBufLen = 6; - if (!uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen)) { + res = uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen); + if (res != 0) { ERR("%s", "Unable to receive data. (RX)"); - pnd->iLastError = DEIO; + pnd->iLastError = res; return false; } @@ -217,18 +220,22 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t 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_transceive_callback(pnd, abtRxBuf, szRxBufLen)) return false; + szRxBufLen -= sizeof(ack_frame); + memmove(abtRxBuf, abtRxBuf+sizeof(ack_frame), szRxBufLen); - szRxBufLen = BUFFER_LENGTH; - - while (!uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen)) { + if (szRxBufLen == 0) { + szRxBufLen = BUFFER_LENGTH; + do { delay_ms(10); - } - + res = uart_receive((serial_port)pnd->nds,abtRxBuf,&szRxBufLen); + } while (res != 0 ); #ifdef DEBUG PRINT_HEX("RX", abtRxBuf,szRxBufLen); #endif + } // When the answer should be ignored, just return a successful result if(pbtRx == NULL || pszRxLen == NULL) return true; @@ -242,9 +249,10 @@ bool pn532_uart_transceive(nfc_device_t* pnd, const byte_t* pbtTx, const size_t #ifdef DEBUG PRINT_HEX("TX", ack_frame,6); #endif - if (!uart_send((serial_port)pnd->nds,ack_frame,6)) { + res = uart_send((serial_port)pnd->nds,ack_frame,6); + if (res != 0) { ERR("%s", "Unable to transmit data. (TX)"); - pnd->iLastError = DEIO; + pnd->iLastError = res; return false; } @@ -268,7 +276,7 @@ pn532_uart_wakeup(const nfc_device_spec_t nds) PRINT_HEX("TX", pncmd_pn532c106_wakeup_preamble,sizeof(pncmd_pn532c106_wakeup_preamble)); #endif uart_send((serial_port)nds, pncmd_pn532c106_wakeup_preamble, sizeof(pncmd_pn532c106_wakeup_preamble)); - if(uart_receive((serial_port)nds,abtRx,&szRxLen)) { + if(0 == uart_receive((serial_port)nds,abtRx,&szRxLen)) { #ifdef DEBUG PRINT_HEX("RX", abtRx,szRxLen); #endif @@ -290,10 +298,10 @@ pn532_uart_check_communication(const nfc_device_spec_t nds, bool* success) #ifdef DEBUG PRINT_HEX("TX", pncmd_communication_test,sizeof(pncmd_communication_test)); #endif - if (!uart_send((serial_port)nds, pncmd_communication_test, sizeof(pncmd_communication_test))) + if (0 != uart_send((serial_port)nds, pncmd_communication_test, sizeof(pncmd_communication_test))) return false; - if(!uart_receive((serial_port)nds,abtRx,&szRxLen)) { + if (0 != uart_receive((serial_port)nds,abtRx,&szRxLen)) { return false; } #ifdef DEBUG