Reading NFC Card ID on Ubuntu

Reading NFC Card ID on Ubuntu

Prerequisites

Install driver

My device is ACS122U : http://www.acs.com.hk/en/products/3/acr122u-usb-nfc-reader/#tab_downloads

Kernel modules

1
2
3
# 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

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

Run service

1
sudo service pcscd restart

Install python packages

1
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#! /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):
self.observer = ConsoleCardConnectionObserver()

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

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

sleep(86400)

# don't forget to remove observer, or the
# monitor will poll forever...
cardmonitor.deleteObserver(selectobserver)

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

Run

1
$ sudo python main.py

Demo

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.

1
$ java -jar rfid-reader2keyboard.jar

Good luck ! ;)

Comments