Reading NFC Card ID on Ubuntu

27 Sep 2017 / by KhanhIceTea


Install driver

My device is ACS122U :

Kernel modules

# echo "uinput" >> /etc/modules
# echo "install nfc /bin/false" >> /etc/modprobe.d/blacklist.conf
# echo "install pn533 /bin/false" >> /etc/modprobe.d/blacklist.conf

Install packages

sudo apt-get install swig libccid pcscd libpcsclite-dev libpcsclite1 python-dev python-pip gcc linux-headers-$(uname -r)

Run service

sudo service pcscd restart

Install python packages

sudo pip install pyscard python-uinput evdev

Source code

This is source code that read the card ID and simulate keystrokes to type card ID by text then pressing ENTER key.

#! /usr/bin/env python

from __future__ import print_function
from time import sleep

from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver
from smartcard.CardMonitoring import CardMonitor, CardObserver
from smartcard.util import toHexString
from evdev import UInput, ecodes
import uinput

device = uinput.Device([uinput.KEY_0, uinput.KEY_1, uinput.KEY_2, uinput.KEY_3, uinput.KEY_4, uinput.KEY_5, uinput.KEY_6, uinput.KEY_7, uinput.KEY_8, uinput.KEY_9, uinput.KEY_A, uinput.KEY_B, uinput.KEY_C, uinput.KEY_D, uinput.KEY_E, uinput.KEY_F, uinput.KEY_G, uinput.KEY_H, uinput.KEY_I, uinput.KEY_J, uinput.KEY_K, uinput.KEY_L, uinput.KEY_M, uinput.KEY_N, uinput.KEY_O, uinput.KEY_P, uinput.KEY_Q, uinput.KEY_R, uinput.KEY_S, uinput.KEY_T, uinput.KEY_U, uinput.KEY_V, uinput.KEY_W, uinput.KEY_X, uinput.KEY_Y, uinput.KEY_Z, uinput.KEY_TAB])

def card_id_to_keyboards(card_id):
    id = card_id.replace(' ', '')

    return [getattr(uinput, 'KEY_'+x.upper()) for x in id]

# a simple card observer that tries to select DF_TELECOM on an inserted card
class selectDFTELECOMObserver(CardObserver):
    """A simple card observer that is notified
    when cards are inserted/removed from the system and
    prints the list of cards

    def __init__(self): = ConsoleCardConnectionObserver()

    def update(self, observable, actions):
            (addedcards, removedcards) = actions
            for card in addedcards:
                print("+Inserted: ", toHexString(card.atr))
                card.connection = card.createConnection()
                apdu = [0xFF, 0xCA, 0x00, 0x00, 0x00]
                response, sw1, sw2 = card.connection.transmit(apdu)
                keys = card_id_to_keyboards(toHexString(response))
                for key in keys:
                ui = UInput()
                ui.write(ecodes.EV_KEY, ecodes.KEY_ENTER, 0)
                ui.write(ecodes.EV_KEY, ecodes.KEY_ENTER, 1)
            for card in removedcards:
                print("-Removed: ", toHexString(card.atr))

if __name__ == '__main__':
    print("Insert or remove a SIM card in the system.")
    print("This program will exit in 60 seconds")
    cardmonitor = CardMonitor()
    selectobserver = selectDFTELECOMObserver()


    # don't forget to remove observer, or the
    # monitor will poll forever...

    import sys
    if 'win32' == sys.platform:
        print('press Enter to continue')


$ sudo python


This is my demo application that using card ID like a user password, so I can unlock my computer or enter sudo mode :D

It Just Works

If you want a "just-work" solution, checkout this repo. It is built on Java smartcardio.

$ java -jar rfid-reader2keyboard.jar

Good luck ! ;)

Sound good ?