Topic: Call for Windows contributors

Dear NFC-enthusiasts, hackers and developers!

The libnfc team is proud to announce major enhancements for the 1.6 serie, and development is moving forward quickly:
http://code.google.com/p/libnfc/updates/list

However, the core team is composed of GNU/Linux and FreeBSD hackers only, and some architecture changes totally broked the library down on Microsoft Windows. With no particular knowledge not interest in that Operating System, we are unfortunatelly unlikely to resurect it ourself, but we are aware that the Microsoft Windows support is a requirement for the libnfc.
We are therefore kindly requesting your contribution to port the changes we made to the library so that we can ship libnfc-1.6.0 with Microsoft Windows support.

If you like libnfc, use Windows and would like to contribute, feel free to write us a line!

Thanks!

The Libnfc Team

Romuald Conty

Re: Call for Windows contributors

Hi,

just gave it quick try with current trunk (r942).

  • small change to cmake file

  • pipe() does not exist, but this can be solved with a define

  • uart_win32 needs changes, but i'm not able to test this atm because i only have an ACR122 and omnikey 5321

Following patch gets it to compile and nfc-list examples working with ACR122:

Index: cmake_modules/LibnfcDrivers.cmake
===================================================================
--- cmake_modules/LibnfcDrivers.cmake    (revision 936)
+++ cmake_modules/LibnfcDrivers.cmake    (working copy)
@@ -13,13 +13,13 @@
 IF(LIBNFC_DRIVER_PN531_USB)
   FIND_PACKAGE(LIBUSB REQUIRED)
   ADD_DEFINITIONS("-DDRIVER_PN531_USB_ENABLED")
-  SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pn531_usb" "drivers/pn53x_usb.c")
+  SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pn53x_usb.h" "drivers/pn53x_usb.c")
 ENDIF(LIBNFC_DRIVER_PN531_USB)
 
 IF(LIBNFC_DRIVER_PN533_USB)
   FIND_PACKAGE(LIBUSB REQUIRED)
   ADD_DEFINITIONS("-DDRIVER_PN533_USB_ENABLED") 
-  SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pn533_usb" "drivers/pn53x_usb.c")
+  SET(DRIVERS_SOURCES ${DRIVERS_SOURCES} "drivers/pn53x_usb.h" "drivers/pn53x_usb.c")
 ENDIF(LIBNFC_DRIVER_PN533_USB)
 
 IF(LIBNFC_DRIVER_ARYGON)
Index: contrib/windows.h
===================================================================
--- contrib/windows.h    (revision 936)
+++ contrib/windows.h    (working copy)
@@ -30,6 +30,7 @@
 #    define snprintf(S, n, F, ...) sprintf(S, F, __VA_ARGS__)
 #    define MAX(a,b) max(a,b)
 #    define MIN(a,b) min(a,b)
+#    define pipe(fds) _pipe(fds, 5000, _O_BINARY)
 #  else
 #    define snprintf sprintf_s
 #    define strdup _strdup
Index: libnfc/buses/uart_win32.c
===================================================================
--- libnfc/buses/uart_win32.c    (revision 942)
+++ libnfc/buses/uart_win32.c    (working copy)
@@ -140,12 +140,12 @@
 }
 
 int
-uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRx)
+uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx, int iAbortFd)
 {
-  if (!ReadFile (((serial_port_windows *) sp)->hPort, pbtRx, (DWORD)(*pszRx), (LPDWORD) pszRx, NULL)) {
+  if (!ReadFile (((serial_port_windows *) sp)->hPort, pbtRx, (DWORD)(szRx), (LPDWORD) &szRx, NULL)) {
     return DEIO;
   }
-  if (!*pszRx)
+  if (!szRx)
     return DEIO;
   return 0;
 }
@@ -162,3 +162,7 @@
   return 0;
 }
 
+char **
+uart_list_ports (void)
+{
+}

The only problem remains the uart part (i only modified it to please the compiler but it won't work), so if someone owns a serial device and is able to test this under windows i think we can get libnfc 1.6.0 fully working under windows.

Re: Call for Windows contributors

Hello, I made some changes to your patch and apply it in r943.

Romuald Conty

Re: Call for Windows contributors

Build r953

Can't build because sys/select.h cannot be found

Scanning dependencies of target nfc
[  5%] Building C object libnfc/CMakeFiles/nfc.dir/nfc.c.obj
[ 10%] Building C object libnfc/CMakeFiles/nfc.dir/nfc-device.c.obj
H:\libnfc160\libnfc-read-only\libnfc\nfc-device.c: In function 'nfc_device_new':

H:\libnfc160\libnfc-read-only\libnfc\nfc-device.c:13:5: warning: implicit declar
ation of function 'err'
[ 15%] Building C object libnfc/CMakeFiles/nfc.dir/iso14443-subr.c.obj
[ 20%] Building C object libnfc/CMakeFiles/nfc.dir/mirror-subr.c.obj
[ 25%] Building C object libnfc/CMakeFiles/nfc.dir/drivers/acr122.c.obj
[ 30%] Building C object libnfc/CMakeFiles/nfc.dir/drivers/pn53x_usb.c.obj
H:\libnfc160\libnfc-read-only\libnfc\drivers\pn53x_usb.c:35:24: fatal error: sys
/select.h: No such file or directory
compilation terminated.
mingw32-make[2]: *** [libnfc/CMakeFiles/nfc.dir/drivers/pn53x_usb.c.obj] Error 1

mingw32-make[1]: *** [libnfc/CMakeFiles/nfc.dir/all] Error 2
mingw32-make: *** [all] Error 2

Re: Call for Windows contributors

Anon122 wrote:

Can't build because sys/select.h cannot be found

Thanks for reporting.
This problem needs a windows user contribution: under POSIX systems, we use select() and other functions provided by <sys/select.h> to handle abort mecanism.

There are maybe two ways to solve it: use cygwin or simply provide a windows implementation.

Romuald Conty

Re: Call for Windows contributors

Hi,

Windows API has a select() function (http://msdn.microsoft.com/en-us/library … 85%29.aspx), but there is no sys/select.h .

So it is possible to get it to compile using a conditional include. I am not able to test if it is actually working however, since i currently have only an ACR122 reader which does not use the pn53x_usb driver afaik.
I am waiting for an ASK Logo reader to be delivered, so i can test this. It would be good if someone could test this in the mean time ..

Following patch against current trunk fixes the above, and some other problems i had when compiling on windows.
The cmake script is also modified so that the nfc-mfclassic nfc-mfultralight examples are build now (as requested in another thread)

Index: contrib/win32/err.h
===================================================================
--- contrib/win32/err.h    (revision 967)
+++ contrib/win32/err.h    (working copy)
@@ -14,6 +14,6 @@
     exit (code); \
 } while (0)
 
-#define err(code, ...) errx(code, ...)
+#define err errx
 
 #endif /* !_ERR_H_ */
Index: contrib/windows.h
===================================================================
--- contrib/windows.h    (revision 967)
+++ contrib/windows.h    (working copy)
@@ -27,11 +27,14 @@
 #define __WINDOWS_H__
 
 #  include <windows.h>
+#  include <winerror.h>
+#  include "win32/err.h"
 #  if defined (__MINGW32__)
 #    define snprintf(S, n, F, ...) sprintf(S, F, __VA_ARGS__)
 #    define MAX(a,b) max(a,b)
 #    define MIN(a,b) min(a,b)
 #    define pipe(fds) _pipe(fds, 5000, _O_BINARY)
+#    define ETIMEDOUT     WSAETIMEDOUT
 #  else
 #    define snprintf sprintf_s
 #    define strdup _strdup
Index: examples/CMakeLists.txt
===================================================================
--- examples/CMakeLists.txt    (revision 967)
+++ examples/CMakeLists.txt    (working copy)
@@ -1,5 +1,5 @@
-SET(EXAMPLES-SOURCES nfc-anticol nfc-dep-initiator nfc-dep-target nfc-emulate-forum-tag4 nfc-emulate-tag nfc-emulate-uid nfc-list nfc-poll nfc-relay nfc-relay-picc)
-#TODO nfc-mfclassic nfc-mfultralight pn53x-diagnose pn53x-sam pn53x-tamashell
+SET(EXAMPLES-SOURCES nfc-anticol nfc-dep-initiator nfc-dep-target nfc-emulate-forum-tag4 nfc-emulate-tag nfc-emulate-uid nfc-list nfc-poll nfc-relay nfc-relay-picc nfc-mfclassic nfc-mfultralight)
+#TODO  pn53x-diagnose pn53x-sam pn53x-tamashell
 
 # XXX: Examples should not use private API!
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libnfc)
@@ -8,19 +8,19 @@
 LINK_DIRECTORIES(${LIBUSB_LIBRARY_DIRS} ${PCSC_LIBRARY_DIRS})
 
 ADD_LIBRARY(nfc-utils nfc-utils)
-#ADD_LIBRARY(mifare mifare)
 
 # Examples
 FOREACH(source ${EXAMPLES-SOURCES})
-  ADD_EXECUTABLE(${source} ${source}.c)
+  IF((${source} MATCHES "nfc-mfultralight") OR (${source} MATCHES "nfc-mfclassic"))
+    ADD_EXECUTABLE(${source} ${source}.c mifare)
+  ELSE()
+    ADD_EXECUTABLE(${source} ${source}.c)
+  ENDIF((${source} MATCHES "nfc-mfultralight") OR (${source} MATCHES "nfc-mfclassic"))
   TARGET_LINK_LIBRARIES(${source} nfc)
   TARGET_LINK_LIBRARIES(${source} nfc-utils)
   INSTALL(TARGETS ${source} RUNTIME DESTINATION bin COMPONENT examples)
 ENDFOREACH(source)
 
-#TARGET_LINK_LIBRARIES(nfc-mfclassic mifare)
-#TARGET_LINK_LIBRARIES(nfc-mfultralight mifare)
-
 IF(NOT WIN32)
   # Manuals for the examples
   FILE(GLOB manuals "${CMAKE_CURRENT_SOURCE_DIR}/*.1")
Index: examples/nfc-emulate-forum-tag4.c
===================================================================
--- examples/nfc-emulate-forum-tag4.c    (revision 967)
+++ examples/nfc-emulate-forum-tag4.c    (working copy)
@@ -59,6 +59,10 @@
 
 #include "nfc-utils.h"
 
+#ifdef _WIN32
+#  include "contrib/windows.h"
+#  define ENOTSUP 134
+#endif
 
 static nfc_device_t *pnd;
 static bool quiet_output = false;
Index: include/nfc/nfc-emulation.h
===================================================================
--- include/nfc/nfc-emulation.h    (revision 967)
+++ include/nfc/nfc-emulation.h    (working copy)
@@ -22,6 +22,29 @@
 
 #include <sys/types.h>
 
+#  ifdef _WIN32
+  /* Windows platform */
+#    ifndef _WINDLL
+    /* CMake compilation */
+#      ifdef nfc_EXPORTS
+#        define  NFC_EXPORT __declspec(dllexport)
+#      else
+      /* nfc_EXPORTS */
+#        define  NFC_EXPORT __declspec(dllimport)
+#      endif
+       /* nfc_EXPORTS */
+#    else
+      /* _WINDLL */
+    /* Manual makefile */
+#      define NFC_EXPORT
+#    endif
+       /* _WINDLL */
+#  else
+      /* _WIN32 */
+#    define NFC_EXPORT
+#  endif
+       /* _WIN32 */
+
 struct nfc_emulator;
 struct nfc_emulation_state_machine;
 
@@ -37,6 +60,6 @@
   void *data;
 };
 
-int    nfc_emulate_target (nfc_device_t* pnd, struct nfc_emulator *emulator);
+NFC_EXPORT int    nfc_emulate_target (nfc_device_t* pnd, struct nfc_emulator *emulator);
 
 #endif /* __NFC_EMULATION_H__ */
Index: libnfc/buses/uart_win32.c
===================================================================
--- libnfc/buses/uart_win32.c    (revision 967)
+++ libnfc/buses/uart_win32.c    (working copy)
@@ -149,7 +149,7 @@
   if (!ReadFile (((serial_port_windows *) sp)->hPort, pbtRx, dwRxLen, &dwRxLen, NULL)) {
     return DEIO;
   }
-  return (dwRwLen == (DWORD) szRx) ? 0 : DEIO;
+  return (dwRxLen == (DWORD) szRx) ? 0 : DEIO;
 }
 
 int
Index: libnfc/CMakeLists.txt
===================================================================
--- libnfc/CMakeLists.txt    (revision 967)
+++ libnfc/CMakeLists.txt    (working copy)
@@ -22,6 +22,9 @@
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
 ADD_LIBRARY(nfc SHARED ${LIBRARY_SOURCES})
 TARGET_LINK_LIBRARIES(nfc ${LIBUSB_LIBRARIES} ${PCSC_LIBRARIES})
+IF(WIN32)
+  TARGET_LINK_LIBRARIES(nfc wsock32)
+ENDIF(WIN32)
 SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 0)
 
 IF(WIN32)
Index: libnfc/drivers/pn53x_usb.c
===================================================================
--- libnfc/drivers/pn53x_usb.c    (revision 967)
+++ libnfc/drivers/pn53x_usb.c    (working copy)
@@ -32,7 +32,12 @@
 Thanks to d18c7db and Okko for example code
 */
 
-#include <sys/select.h>
+#ifdef _WIN32
+#  include "contrib/windows.h"
+#else
+#  include <sys/select.h>
+#endif
+
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
Index: libnfc/nfc-device.c
===================================================================
--- libnfc/nfc-device.c    (revision 967)
+++ libnfc/nfc-device.c    (working copy)
@@ -26,6 +26,10 @@
 
 #include <stdlib.h>
 
+#ifdef _WIN32
+#  include "contrib/windows.h"
+#endif
+
 #include "nfc-internal.h"
 
 nfc_device_t *

Last edited by glenn (2011-03-31 10:00:36)

Re: Call for Windows contributors

In r968, a dummy sys/select.h file have been added in contrib/win32 directory.

It should allow Windows users to compile the same code than POSIX system users.

Romuald Conty

Re: Call for Windows contributors

I think I should explains a bit how and why we have added the abort mecanism.

While NFC chip is in initiator mode, we send a command and the chip reply within short time. For the host side, we could consider that reply is immediate. But while the NFC chip is in target mode (emulation or P2P), when we ask for a command (from the NFC initiator device) we could wait a very long time before have a reply (sometimes, it never reply). So, we have to be able to cancel the last sent command to re-use the NFC chip.
This is the abort mecanism.

Using PN53x chips, we have to send an ACK frame to the chip to abort the last sent command. So, while the target functions are blocking functions, we have to introduce a way to send a "signal" to the driver to stop waiting reply then send an ACK frame.

Under POSIX systems, we made it with pipes for pn53x_usb and pn532_uart driver.

Note: ACR122 relies on PC/SC and we are not able to stop communication then send ACK as expected, that one of the reasons the ACR122 have a poor support under libnfc.

Romuald Conty

Re: Call for Windows contributors

thanks for the explanation, this really helps me better understanding what is happening

Re: Call for Windows contributors

glenn wrote:

thanks for the explanation, this really helps me better understanding what is happening

Happy to read this smile

Romuald Conty

Re: Call for Windows contributors

Your patch have been modified and applied in r969 (but not tested)
http://code.google.com/p/libnfc/source/detail?r=969

I prefer wrote a clear code (without conditionnal code or conditionnal included headers) so contrib/windows.h header is now included by config.h when we are under Windows platform.
Please read the log message.

Feel free to give some feedback here.

Romuald Conty

Re: Call for Windows contributors

Using this config.h method is indeed much cleaner!
Just tested it and everything still works.
thanks for applying..

Re: Call for Windows contributors

I'm trying to add support for Windows to the development branch. The main issue is supporting the
abort mechanism.

I'm new to sockets programming and serial port programming. Windows provides many choices for supporting asynchronous behavior for sockets. This article has a good run down of the various choices: http://tangentsoft.net/wskfaq/articles/ … egies.html

I'm thinking "Asynchronous sockets" but let me know if that is a bad choice. I'm not sure how these considerations fit in with working with Serial Ports. Another option not mentioned in that article is I/O Completion Ports: http://msdn.microsoft.com/en-us/library … .85).aspx.

Eventually, I'll need this to work over USB but my understanding is that this can work through
serial port emulation. Is this a good assumption?

References:
How to interrupt select call on windows?: http://stackoverflow.com/questions/5289 … on-windows
Serial Comms via IOCP: http://stackoverflow.com/questions/6738 … s-via-iocp

Thanks!

Re: Call for Windows contributors

I'm not sure if it is possible to treat a serial port as a socket on windows, since windows sockets don't work with ordinary file handles. So... I/O Completion ports is the way to go?

Re: Call for Windows contributors

I made the following change to uart_receive in uart_win32.c to allow it to continue to get data when not all data was initially received:

int
uart_receive (serial_port sp, byte_t * pbtRx, const size_t szRx, int iAbortFd)
{
    DWORD dwBytesToGet = szRx;
    DWORD dwBytesReceived = 0;
    int received_bytes_count = 0;
    BOOL succ;
    const int expected_bytes_count = (int)szRx;

    do {
        succ = ReadFile (((serial_port_windows *) sp)->hPort, pbtRx + received_bytes_count,
            dwBytesToGet,
            &dwBytesReceived, NULL);
        if (!succ) {
            DBG("uart_receive: ReadFile returned error\n");
            return DEIO;
        }
        received_bytes_count += dwBytesReceived;
        if (expected_bytes_count > received_bytes_count) {
            dwBytesToGet -= dwBytesReceived;
            //printf("........want %d, just got %d, get %d more\n", expected_bytes_count, dwBytesReceived, dwBytesToGet);
        }
    } while (expected_bytes_count > received_bytes_count);

    PRINT_HEX ("uart_receive: RX", pbtRx, szRx);
    return (received_bytes_count == (DWORD) szRx) ? 0 : DEIO;
}

The nfclist sample is working for me now. For the nfc-emulate-forum-tag4 sample, the phone recognizes the PN532 but it shows up as Unknown tag type. I think there is more work to do but I post this code in case you want to apply a patch now.

Do you think the problem I'm seeing with the tag4 sample is related to the abort mechanism?

Re: Call for Windows contributors

Hey, sometimes it works! But a lot of times I see PN532 error code 0x29 (released by initiator) right after TgGetData. Any idea?

Re: Call for Windows contributors

We need some users contributions to test current development version using various examples and various devices under Windows.

Feel free to post your setup:
* SVN revision
* Operating system (Windows XP, 7, etc; 32 or 64bits)
* Tested devices
* And of course results wink

Romuald Conty

Re: Call for Windows contributors

I cannot compile against #1137 on Windows 7 Pro 32bit:

C:\libnfc-1.2.1-vs2005\svn\libnfc-read-only\bin>mingw32-make
Scanning dependencies of target nfc
[  4%] Building C object libnfc/CMakeFiles/nfc.dir/nfc.c.obj
In file included from C:\libnfc-1.2.1-vs2005\svn\libnfc-read-only\libnfc\nfc-internal.h:32:0,
                 from C:\libnfc-1.2.1-vs2005\svn\libnfc-read-only\libnfc\nfc.c:41:
C:\libnfc-1.2.1-vs2005\svn\libnfc-read-only\libnfc\log.h:21:23: fatal error: semaphore.h: No such file or directory
compilation terminated.
mingw32-make[2]: *** [libnfc/CMakeFiles/nfc.dir/nfc.c.obj] Error 1
mingw32-make[1]: *** [libnfc/CMakeFiles/nfc.dir/all] Error 2
mingw32-make: *** [all] Error 2

Where can I find semaphore.h ?

Re: Call for Windows contributors

rleo79 wrote:

Where can I find semaphore.h ?

When you install MingGW, you are given a list of components to install which by default doesn't include the openmp library which includes pthreads and semaphore.h. So either change it to install all packages or open the gcc component and tick the openmp box.

That'll get you semaphore.h, but I suspect you'll then run into another build error:

c:\mingw64\bin\../lib/gcc/x86_64-w64-mingw32/4.5.2/../../../../include/semaphore.h:149:8: error: expected declaration specifiers or '...' before 'mode_t'

which is what currently has me stumped - on win 7 64bit with the 1.5.0 svn head (rev 1137). I'll try it on a 32 bit xp machine if I get a chance at work tomorrow.

Re: Call for Windows contributors

Many thanks Ging for your hint
I could install openmp library but I get the same error shown in your post...
Windows 7 32bit environment

Re: Call for Windows contributors

Hello all,
I'm trying to compile a nfc.dll, but I have always the error : the same as Ging error about 'mode_t'
Did anybody success to remove this error message?
Thanks in advance for your help

Re: Call for Windows contributors

Hi all!
I'm back to give you news!

I managed to create the nfc.dll on Windows, but not with the 1137 revision.
I succeed with 1122 revision using Mingw 4.5.2 and libusb 1.2.5.0
It seems that some warning are still existing, but the dll is functional and is usable with all given examples.

I keep on working on my SCL3711 to make it work in peer to peer mode with my NFC phone

Re: Call for Windows contributors

Hi Windows users,

Thanks for your contributions!

As I can see, "semaphore.h" is a problem under Windows. After a chat session with Romain, it seems that log4c does already handle threaded cases and by the way the libnfc is not threaded internally. So, the revision r1138 should be more easier to compile under Windows since it does not need "semaphore.h" anymore.

Please report back success or not here.

Thanks!

Romuald Conty

Re: Call for Windows contributors

I downloaded the rev 1138 and the problem is the same, EXACTLY the same...

c:\mingw64\bin\../lib/gcc/x86_64-w64-mingw32/4.5.2/../../../../include/semaphore.h:149:8: error: expected declaration specifiers or '...' before 'mode_t'

Last edited by fantomchris (2011-09-20 15:08:08)

Re: Call for Windows contributors

You're right, my mistake. r1139 should be better.

Romuald Conty