-
Notifications
You must be signed in to change notification settings - Fork 442
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
base: master
Are you sure you want to change the base?
Conversation
libnfc/buses/uart.c
Outdated
for (int i = 0; i < szTx; i++) | ||
{ | ||
error |= uart_send(sp, pbtTx+i, 1, timeout); | ||
usleep(9); |
There was a problem hiding this comment.
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?)
contrib/win32/libnfc/buses/uart.c
Outdated
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 |
There was a problem hiding this comment.
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?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not looks right: can you please describe the issues you are trying to fix?
contrib/win32/libnfc/buses/uart.c
Outdated
int | ||
uart_send_single(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout) | ||
{ | ||
(void) timeout; |
There was a problem hiding this comment.
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
The MacOS changes are unrelated, so I guess they would better fit in another PR? |
Actually, I do not understand what this PR is supposed to fix. |
@smortex @neomilium Hey all, I'm finding that I get significant failure rates on nfc_open() with the PN532 via UART (FTDI) by default. It failed every time with the default apps like I tried a logic analyzer and found the chip wasn't responding at all to initial commands. Oddly, I also noticed not all of the consecutive 0x00's were being sent. Perhaps this is an issue with the libusb version used. At quick glance of the data coming out, I assumed stop bits were missing and that the commands were being sent in one shot so I split out the UART TX to write on byte at a time (for pn53x only), and it started working intermittently. I added an additional delay equal to one bit and now I have 100% success rate with If pn532 was already working successfully for other people then I'm guessing varying libusb's may be the culprit, though if this works successfully on other user systems, I'd suggest we keep it to increase compatibility with systems. |
And here's the debug output using the original version (still patched to support baud 115200 on macOS)
|
Using UART devices, we pass through
IMHO, we should rely on kernel to do these things. We probably need to tweak the way we send data to serial port (ie. maybe improve configuration we made on port opening). Your detailed comment is really appreciated, even the implementation could help to target the problem but IMHO the final implementation should rely on kernel good-usage, not on a userland workaround. |
Makes sense. I'm investigating why termios isn't sending all the bytes. For example you can see I'm not sure what's required for Windows; I can investigate but I may not be able to test properly and would be concerned with making driver-specific changes without ability to test. |
Think I found a culprit. What ends up happening is when I tried a int
uart_send(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout)
{
(void) timeout;
LOG_HEX(LOG_GROUP, "TX", pbtTx, szTx);
if ((int) szTx == write(UART_DATA(sp)->fd, pbtTx, szTx))
{
tcdrain(UART_DATA(sp)->fd);
return NFC_SUCCESS;
}
else
return NFC_EIO;
} |
🤔 have you tried adding |
Just tried, looks like macOS doesn't have // set blocking mode
int flags = fcntl(UART_DATA(sp)->fd, F_GETFL);
fcntl(UART_DATA(sp)->fd, F_SETFL, flags & ~O_NONBLOCK);
// write out
int bytes = write(UART_DATA(sp)->fd, pbtTx, szTx);
// return old mode (may or may not be nonblocking)
// i tested with the next line both enabled commented out
fcntl(UART_DATA(sp)->fd, F_SETFL, flags); |
AFAICR, MacOS is supposed to be POSIX. If it still says that |
Ah, thanks! O_SYNC compiles (odd that it's not in |
Warning: The following could drive you crazy :-) The serial port handling, in C, compliant with more-or-less POSIX platforms (e.g. Linux, FreeBSD, macOS), compliant with Windows, working with bad hardware, working through RS232, USB, Bluetooth, etc. was, is and will source of headache... Maybe, we could try to use a library that already handle these corner-cases like: https://sigrok.org/wiki/Libserialport I know it could be a big turn, but could be at least the right moment to test it, and see if the macOS support is better than ours. |
Adding libserialport is likely a much larger undertaking than I'm interested in at the moment; I just wanted to try out libnfc and have it work natively on my mac :) and send a reasonable patch back so that others could do the same. I think for now I'll adjust my UART changes to I'm happy to contribute more if I have other projects in the area but at the moment I just wanted to try out the example apps to see how they worked, and it always feels nicer to get things working natively! |
No description provided.