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

Generalized API and PC/SC support #22

Open
GoogleCodeExporter opened this issue Mar 14, 2015 · 6 comments
Open

Generalized API and PC/SC support #22

GoogleCodeExporter opened this issue Mar 14, 2015 · 6 comments

Comments

@GoogleCodeExporter
Copy link

Thanks to time set apart for this purpose by my employer, I've been working in the month of January on enhancing libfreefare and solving a couple of the existing issues (some of which I previously opened myself :).

The primary goal was decoupling libfreefare from libnfc and allowing other reader subsystems to be used. I implemented that for PC/SC as a first step, other projects that one could think of would be librfid and the new "Linux NFC" stack (https://01.org/linux-nfc).

A secondary goal was making the API easier to use and removing unnecessary -- and libnfc-version specific -- boilerplate code. To this end the new API that I built is reader subsystem agnostic and I spent some effort into making it future-compatible with no API or ABI changes.

I have looked at the work that has been done on the "pcsc" branch and decided that that is not the way to go forward. Creating "-pcsc" versions of everything and replicating a second flurry of boilerplate code among the code examples is exactly what I strive to avoid.

The new API is centered around a new FreefareContext object that holds a library context and references to either automatically acquired or externally provided reader subsystem contexts (e.g. nfc_context) or devices (e.g. nfc_device) and provides an easy to use and unified way to retrieve MifareTag objects. The freefare_get_tags() and freefare_tag_new() methods are still there but marked deprecated (since they are libnfc specific). The latter is superseded by a new freefare_tag_new_ex() function that works with all supported reader subsystems using unions as a way to allow it to accept both libnfc or PC/SC arguments.

The new freefare_init() takes a flags argument that can be a combination of FREEFARE_FLAG_READER_LIBNFC or FREEFARE_FLAG_READER_PCSC to automatically establish a context to the given reader subsystems, or the special value FREEFARE_FLAG_READER_ALL to establish a context with all supported subsystems, even future ones. The latter is the recommended value, which means that a program using the library needs not to be updated to gain access to a future reader subsystem support by the library. The flags can also include FREEFARE_FLAG_DISABLE_ISO14443_4 to disable 14443-4 support where possible (currently only libnfc) to select the -3 version on hybrid cards.

Alternatively, freefare_context/device_add/remove are available to manually manage associating or dissociating reader subsystem contexts or devices with the libfreefare library. A FREEFARE_FLAG_AUTOCLOSE in _add will have libfreefare take over responsibility of the passed in object and automatically call the respective close function (nfc_close()/nfc_exit()) when it is no longer needed.

Once a library context has been retrieved, the freefare_tags_get() method enumerates all supported tags on all on readers on all contexts and returns a list. Alternatively freefare_tag_first() and freefare_tag_next() can be used to iterate over the same set without creating the entire list at once. Both accept an enum mifare_tag_type argument to limit the type of tags eligible (the new type NO_TAG_TYPE means no limit).

The boilerplate code can thus (without error checking) be reduced to:

    FreefareContext ctx = freefare_init(FREEFARE_FLAG_READER_ALL); 
    for(MifareTag tag = freefare_tag_first(ctx, NO_TAG_TYPE); tag; tag = freefare_tag_next(ctx)) { 
        /* Actual code here... */
    }
    freefare_exit(ctx);

The PC/SC support currently is not complete, only DESfire is working. No functional changes to libnfc support should be present (I even added a working FREEFARE_FLAG_DISABLE_ISO14443_4).

Late in the process I added freefare_tag_wait_* which allows non-busy polling for tags (e.g. like the pcsc_scan tool does). This is only implemented for PC/SC and only works on a single context. libnfc has a similar function in nfc_initiator_poll_target() which only works for a single device, implementing support for that is possible. Anything further (waiting for multiple devices/contexts) would require a new threaded approach.

Before I could prepare my code for publication, freefare_selected_tag_is_present() was added in the main libfreefare branch. This was another libnfc specific function, which I choose not to continue supporting (it hasn't been out long, there should be minimal code breakage). Instead I added freefare_tag_is_present() as a reader subsystem agnostic alternative.

I pushed all the code changes to https://code.google.com/r/henryk-libfreefare-extended-reader-support for easy pulling and request inclusion in libfreefare (sadly Google has no pull request support).

Original issue reported on code.google.com by [email protected] on 27 Feb 2014 at 3:19

@GoogleCodeExporter
Copy link
Author

Thanks a lot Henryk for your very valuable contribution!
Sorry we didn't have time yet to review your code, that's not like it can be done in 5 mins ;-)
Thanks for your comprehension.

Original comment by [email protected] on 13 Mar 2014 at 1:03

  • Changed state: Accepted
  • Added labels: Type-Enhancement
  • Removed labels: Type-Defect

@GoogleCodeExporter
Copy link
Author

Henryks PC/SC interface work fine for me. Migrating existing code was quite easy due to the simplifications made.

I want to extend supported_tags from freefare.c with a tag that is recognized by calling its function check_tag_on_reader. I have done this for plain libfreefare by connecting, transceiving bytes and disconnecting from the tag (similar to is_mifare_ultralightc_on_reader). With Henryks implementation, however, I did not find out how to connect to the tag in a non-reader-specific way. AFAICS, the supplied FreefareReaderTag object does not allow to create a usable MifareTag obect (Henryks wrapper mifare_ultralightc_is_on_reader is implemented for libnfc only). Henryk, do you have any hints on that?

Original comment by [email protected] on 2 Jun 2014 at 11:56

@frankmorgner
Copy link

any updates on this?

I saved Henryk's initial approach, which I used, here https://github.com/frankmorgner/libfreefare/tree/pcsc-henryk

@CardContact
Copy link

Any recommended way to move forward with this ?

I'd like to add support for JCOP 2.4.2r2 card, which comes with DESFire and ISO 14443-4 layer APDUs. The current detection code inspects the ATR as returned by the PC/SC subsystem, but does not consider the JCOP ATR as a suitable candidate.

@darconeous
Copy link
Member

Is this related to #71?

@frankmorgner
Copy link

Yes and No. It has the same goal (i.e. run libfreefare over PC/SC), but it's a completely different implementation.

I never got #71 running, whereas https://github.com/frankmorgner/libfreefare/tree/pcsc-henryk worked as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants