Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix PN532 UART support + macOS support #633

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ Readers known to work:

These readers are support by CCID since v1.4.25, make sure your CCID driver version higher or equal to 1.4.25.

On MacOS, you can check your CCID version with the following command, and if required, you can install latest CCID driver from [https://github.com/martinpaljak/osx-ccid-installer/releases](https://github.com/martinpaljak/osx-ccid-installer/releases)
On macOS, you can check your CCID version with the following command, and if required, you can install latest CCID driver from [https://github.com/martinpaljak/osx-ccid-installer/releases](https://github.com/martinpaljak/osx-ccid-installer/releases)

```
grep -A 1 CFBundleShortVersionString /usr/local/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist
Expand Down
20 changes: 20 additions & 0 deletions contrib/win32/libnfc/buses/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,26 @@ uart_send(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout)
return 0;
}

/**
* @brief Send \a pbtTx content to UART one byte at a time
*
* @return 0 on success, otherwise a driver error is returned
*/
int
uart_send_single(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout)
{
(void) timeout;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this I guess

int error = 0;
for (int i = 0; i < szTx; i++)
{
error |= uart_send(sp, pbtTx+i, 1, timeout);
delay_ms(1); // ceil(1_000_000us / 115200baud) = 9us but no usleep on windows
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sleeping in userland seems terrible… Timing should be managed at the underlying level (UART driver of the OS?)

}

return error ? NFC_EIO : 0;
}


BOOL is_port_available(int nPort)
{
TCHAR szPort[15];
Expand Down
4 changes: 4 additions & 0 deletions libnfc/buses/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#ifdef __APPLE__
#include <sys/termios.h>
#else
#include <termios.h>
#endif
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
Expand Down
4 changes: 4 additions & 0 deletions libnfc/buses/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#ifdef __APPLE__
#include <sys/termios.h>
#else
#include <termios.h>
#endif
#include <unistd.h>

#include <nfc/nfc.h>
Expand Down
37 changes: 37 additions & 0 deletions libnfc/buses/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#ifdef __APPLE__
#include <sys/termios.h>
#else
#include <termios.h>
#endif
#include <unistd.h>
#include <stdlib.h>

Expand Down Expand Up @@ -95,6 +99,19 @@ const char *serial_ports_device_radix[] = { "ttyUSB", "ttyS", "ttyACM", "ttyAMA"
// Work-around to claim uart interface using the c_iflag (software input processing) from the termios struct
# define CCLAIMED 0x80000000

// If macOS and still haven't detected required baud rates, set them as we do have support for some
#ifdef __APPLE__
#ifndef B57600
#define B57600 57600
#endif
#ifndef B115200
#define B115200 115200
#endif
#ifndef B230400
#define B230400 230400
#endif
#endif

struct serial_port_unix {
int fd; // Serial port file descriptor
struct termios termios_backup; // Terminal info before using the port
Expand Down Expand Up @@ -367,6 +384,26 @@ uart_receive(serial_port sp, uint8_t *pbtRx, const size_t szRx, void *abort_p, i
return NFC_SUCCESS;
}

/**
* @brief Send \a pbtTx content to UART one byte at a time
*
* @return 0 on success, otherwise a driver error is returned
*/
int
uart_send_single(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout)
{
(void) timeout;
int error = 0;
for (int i = 0; i < szTx; i++)
{
error |= uart_send(sp, pbtTx+i, 1, timeout);
samyk marked this conversation as resolved.
Show resolved Hide resolved
usleep(9);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sleeping in userland seems terrible… Timing should be managed at the underlying level (UART driver of the OS?)

}


return error ? NFC_EIO : NFC_SUCCESS;
}

/**
* @brief Send \a pbtTx content to UART
*
Expand Down
1 change: 1 addition & 0 deletions libnfc/buses/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ uint32_t uart_get_speed(const serial_port sp);

int uart_receive(serial_port sp, uint8_t *pbtRx, const size_t szRx, void *abort_p, int timeout);
int uart_send(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout);
int uart_send_single(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout);

char **uart_list_ports(void);

Expand Down
6 changes: 3 additions & 3 deletions libnfc/drivers/pn532_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ pn532_uart_wakeup(nfc_device *pnd)
{
/* High Speed Unit (HSU) wake up consist to send 0x55 and wait a "long" delay for PN532 being wakeup. */
const uint8_t pn532_wakeup_preamble[] = { 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
int res = uart_send(DRIVER_DATA(pnd)->port, pn532_wakeup_preamble, sizeof(pn532_wakeup_preamble), 0);
int res = uart_send_single(DRIVER_DATA(pnd)->port, pn532_wakeup_preamble, sizeof(pn532_wakeup_preamble), 0);
CHIP_DATA(pnd)->power_mode = NORMAL; // PN532 should now be awake
return res;
}
Expand Down Expand Up @@ -348,7 +348,7 @@ pn532_uart_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, in
return pnd->last_error;
}

res = uart_send(DRIVER_DATA(pnd)->port, abtFrame, szFrame, timeout);
res = uart_send_single(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;
Expand Down Expand Up @@ -507,7 +507,7 @@ pn532_uart_ack(nfc_device *pnd)
return res;
}
}
return (uart_send(DRIVER_DATA(pnd)->port, pn53x_ack_frame, sizeof(pn53x_ack_frame), 0));
return (uart_send_single(DRIVER_DATA(pnd)->port, pn53x_ack_frame, sizeof(pn53x_ack_frame), 0));
}

static int
Expand Down