在 Linux 中使用 ACS ACR1252U USB NFC 卡 reader
Using the ACS ACR1252U USB NFC Card reader in Linux
我正在使用通过 USB 连接的 ACS ACR1252U 卡 reader (http://www.acs.com.hk/en/products/342/acr1252u-usb-nfc-reader-iii-nfc-forum-certified-reader/),老实说,我不知道如何让它工作。我用谷歌搜索了很多东西,但没有运气。我正在使用 Debian 的变体。以下或多或少是我所做的:
我使用 dmesg 得到以下信息:
[ 7173.059710] usb 1-1.3: new full-speed USB device number 6 using dwc_otg
[ 7173.160500] usb 1-1.3: not running at top speed; connect to a high speed hub
[ 7173.163114] usb 1-1.3: New USB device found, idVendor=072f, idProduct=223b
[ 7173.163147] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 7173.163168] usb 1-1.3: Product: ACR1252 Dual Reader
[ 7173.163186] usb 1-1.3: Manufacturer: ACS
我使用以下 Python 代码来获取有关设备的更多详细信息:
#!/usr/bin/python
import sys
import usb.core
# find USB devices
dev = usb.core.find(find_all=True)
# loop through devices, printing vendor and product ids in decimal and hex
for cfg in dev:
print cfg
sys.stdout.write('Decimal VendorID=' + str(cfg.idVendor) + ' & ProductID=' + str(cfg.idProduct) + '\n')
sys.stdout.write('Hexadecimal VendorID=' + hex(cfg.idVendor) + ' & ProductID=' + hex(cfg.idProduct) + '\n\n')
这个特定设备的输出是:
DEVICE ID 072f:223b on Bus 001 Address 004 =================
bLength : 0x12 (18 bytes)
bDescriptorType : 0x1 Device
bcdUSB : 0x200 USB 2.0
bDeviceClass : 0x0 Specified at interface
bDeviceSubClass : 0x0
bDeviceProtocol : 0x0
bMaxPacketSize0 : 0x40 (64 bytes)
idVendor : 0x072f
idProduct : 0x223b
bcdDevice : 0x100 Device 1.0
iManufacturer : 0x1 ACS
iProduct : 0x2 ACR1252 Dual Reader
iSerialNumber : 0x0
bNumConfigurations : 0x1
CONFIGURATION 1: 200 mA ==================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0xb1 (177 bytes)
bNumInterfaces : 0x2
bConfigurationValue : 0x1
iConfiguration : 0x0
bmAttributes : 0x80 Bus Powered
bMaxPower : 0x64 (200 mA)
INTERFACE 0: Smart Card ================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x3
bInterfaceClass : 0xb Smart Card
bInterfaceSubClass : 0x0
bInterfaceProtocol : 0x0
iInterface : 0x4 ACR1252 Dual Reader PICC
ENDPOINT 0x1: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x1 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x0
ENDPOINT 0x81: Bulk IN ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x0
ENDPOINT 0x84: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x84 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0xa
INTERFACE 1: Smart Card ================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x1
bAlternateSetting : 0x0
bNumEndpoints : 0x3
bInterfaceClass : 0xb Smart Card
bInterfaceSubClass : 0x0
bInterfaceProtocol : 0x0
iInterface : 0x5 ACR1252 Dual Reader SAM
ENDPOINT 0x2: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x2 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x0
ENDPOINT 0x82: Bulk IN ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x82 IN
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x0
ENDPOINT 0x83: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x83 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0xa
Decimal VendorID=1839 & ProductID=8763
Hexadecimal VendorID=0x72f & ProductID=0x223b
我安装了 PyUSB,我可以使用一些示例代码检测设备,但是当它靠近时读取 NFC 卡(虽然有哔哔声,这让我相信 USB设备本身工作正常)。
我还安装了 libacsccid1 包,它说它支持这个设备 https://github.com/acshk/acsccid,但我不知道如何使用它。
除此之外,我不知道还能做什么。任何帮助将不胜感激。我的项目的目标是根据检测到的 NFC 标签的值来控制 GPIO 输出。
--- 更新 ---
我做了更多的工作,虽然我仍然无法让它工作,但我有更多的数据。具体来说,我正在解决这个问题:http://www.digitalmihailo.com/usb-programming-with-python-on-linux-pyusb-version/
从数据表中我可以确认它是 USB 2.0 全速设备:
为了测试,我只想让蜂鸣器发出声音。这是设备的 API 文档的屏幕截图,用于此功能:
因此,我的设备的 http://www.digitalmihailo.com/usb-programming-with-python-on-linux-pyusb-version/ 的简化版本是:
#!/usr/bin/python
import os
import sys
import time
import usb.core
import usb.util
# According to what I've read, full speed USB is 64 byte packet size.
packet_len = 64
# Packing a request.
# Packets are 64 bytes long, most of the commands are 4 bytes long. So up to 18
# can be batched into a packet. For example command with bytes [0x94, 0x0, 0x0, 0x0] is getting firmware id
def pack_request(*arguments):
packet = [0x0] * packet_len
i = 0
for arg in arguments:
packet[i] = arg
i += 1
#packet[0:4] = [0x94, 0x0, 0x0, 0x0] #get firmware id
return ''.join([chr(c) for c in packet])
def main():
#Updated for the ACS ACR1252U
dev = usb.core.find(idVendor=0x72f, idProduct=0x223b)
# was it found?
if dev is None:
raise ValueError('Device not found')
try:
dev.detach_kernel_driver(0)
except: # this usually mean that kernel driver has already been dettached
pass
# ACS ACR1252U only has 1 configuration
dev.set_configuration()
# Interface 0: Dual Reader PICC. This is what we want
# Interface 1: Dual Reader SAM
try:
dev.set_interface_altsetting(0)
except usb.core.USBError:
print 'Error setting interface!'
pass
# According to the API, to sound the buzzer we must send:
#
# Class: 0xe0
# INS: 0x00
# P1: 0x00
# P2: 0x28
# Lc: 0x01
# DataIn (duration): 0xff (for 255 * 10ms = 2.55 seconds)
raw = pack_request(0xe0, 0x00, 0x00, 0x28, 0x01, 0xff)
#send the packet
# Params are (endpoint, data, timeout)
#
# According to the script output:
# ENDPOINT 0x01: Bulk OUT
dev.write(endpoint=0x01, data=raw)
#done
if __name__ == '__main__':
main()
当我 运行 没有任何反应...没有蜂鸣器,没有错误信息。这里可能有什么问题?
谢谢!
出于好奇,我打开了 Info.plist(在 /usr/lib/pcsc/drivers/ifd-acsccid.bundle/Contents/
中),发现我的设备没有列出。
所以我继续将我的信息添加到 ifdVendorID (0x072F)、ifdProductID (0x223B) 和 ifdFriendlyName (ACS ACR1252U Dual PICC-SAM Reader) 数组和 运行 pcscd - fd.
只有在这一步之后 pcsc_scan 才真正检测到我的设备,其他一切或多或少开始工作。最后我没有直接使用 USB,而是使用了 pyscard (http://pyscard.sourceforge.net/) 库。
这使蜂鸣器工作:
def sound_buzzer(reps):
#NOTE: This function only works if a card is present!
try:
hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
assert hresult == SCARD_S_SUCCESS
hresult, readers = SCardListReaders(hcontext, [])
assert len(readers) > 0
reader = readers[0]
hresult, hcard, dwActiveProtocol = SCardConnect(hcontext, reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
while reps > 0:
buzzer = [0xE0, 0x00, 0x00, 0x28, 0x01, 0x0F] # 0x0F = 15 * 10ms
hresult, response = SCardControl(hcard, SCARD_CTL_CODE(3500), buzzer)
sleep(0.15)
reps = reps - 1
except Exception, e:
#print 'Exception: '+ str(e)
pass
return
我正在使用通过 USB 连接的 ACS ACR1252U 卡 reader (http://www.acs.com.hk/en/products/342/acr1252u-usb-nfc-reader-iii-nfc-forum-certified-reader/),老实说,我不知道如何让它工作。我用谷歌搜索了很多东西,但没有运气。我正在使用 Debian 的变体。以下或多或少是我所做的:
我使用 dmesg 得到以下信息:
[ 7173.059710] usb 1-1.3: new full-speed USB device number 6 using dwc_otg
[ 7173.160500] usb 1-1.3: not running at top speed; connect to a high speed hub
[ 7173.163114] usb 1-1.3: New USB device found, idVendor=072f, idProduct=223b
[ 7173.163147] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 7173.163168] usb 1-1.3: Product: ACR1252 Dual Reader
[ 7173.163186] usb 1-1.3: Manufacturer: ACS
我使用以下 Python 代码来获取有关设备的更多详细信息:
#!/usr/bin/python
import sys
import usb.core
# find USB devices
dev = usb.core.find(find_all=True)
# loop through devices, printing vendor and product ids in decimal and hex
for cfg in dev:
print cfg
sys.stdout.write('Decimal VendorID=' + str(cfg.idVendor) + ' & ProductID=' + str(cfg.idProduct) + '\n')
sys.stdout.write('Hexadecimal VendorID=' + hex(cfg.idVendor) + ' & ProductID=' + hex(cfg.idProduct) + '\n\n')
这个特定设备的输出是:
DEVICE ID 072f:223b on Bus 001 Address 004 =================
bLength : 0x12 (18 bytes)
bDescriptorType : 0x1 Device
bcdUSB : 0x200 USB 2.0
bDeviceClass : 0x0 Specified at interface
bDeviceSubClass : 0x0
bDeviceProtocol : 0x0
bMaxPacketSize0 : 0x40 (64 bytes)
idVendor : 0x072f
idProduct : 0x223b
bcdDevice : 0x100 Device 1.0
iManufacturer : 0x1 ACS
iProduct : 0x2 ACR1252 Dual Reader
iSerialNumber : 0x0
bNumConfigurations : 0x1
CONFIGURATION 1: 200 mA ==================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0xb1 (177 bytes)
bNumInterfaces : 0x2
bConfigurationValue : 0x1
iConfiguration : 0x0
bmAttributes : 0x80 Bus Powered
bMaxPower : 0x64 (200 mA)
INTERFACE 0: Smart Card ================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x3
bInterfaceClass : 0xb Smart Card
bInterfaceSubClass : 0x0
bInterfaceProtocol : 0x0
iInterface : 0x4 ACR1252 Dual Reader PICC
ENDPOINT 0x1: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x1 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x0
ENDPOINT 0x81: Bulk IN ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x0
ENDPOINT 0x84: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x84 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0xa
INTERFACE 1: Smart Card ================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x1
bAlternateSetting : 0x0
bNumEndpoints : 0x3
bInterfaceClass : 0xb Smart Card
bInterfaceSubClass : 0x0
bInterfaceProtocol : 0x0
iInterface : 0x5 ACR1252 Dual Reader SAM
ENDPOINT 0x2: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x2 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x0
ENDPOINT 0x82: Bulk IN ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x82 IN
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x0
ENDPOINT 0x83: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x83 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0xa
Decimal VendorID=1839 & ProductID=8763
Hexadecimal VendorID=0x72f & ProductID=0x223b
我安装了 PyUSB,我可以使用一些示例代码检测设备,但是当它靠近时读取 NFC 卡(虽然有哔哔声,这让我相信 USB设备本身工作正常)。
我还安装了 libacsccid1 包,它说它支持这个设备 https://github.com/acshk/acsccid,但我不知道如何使用它。
除此之外,我不知道还能做什么。任何帮助将不胜感激。我的项目的目标是根据检测到的 NFC 标签的值来控制 GPIO 输出。
--- 更新 ---
我做了更多的工作,虽然我仍然无法让它工作,但我有更多的数据。具体来说,我正在解决这个问题:http://www.digitalmihailo.com/usb-programming-with-python-on-linux-pyusb-version/
从数据表中我可以确认它是 USB 2.0 全速设备:
为了测试,我只想让蜂鸣器发出声音。这是设备的 API 文档的屏幕截图,用于此功能:
因此,我的设备的 http://www.digitalmihailo.com/usb-programming-with-python-on-linux-pyusb-version/ 的简化版本是:
#!/usr/bin/python
import os
import sys
import time
import usb.core
import usb.util
# According to what I've read, full speed USB is 64 byte packet size.
packet_len = 64
# Packing a request.
# Packets are 64 bytes long, most of the commands are 4 bytes long. So up to 18
# can be batched into a packet. For example command with bytes [0x94, 0x0, 0x0, 0x0] is getting firmware id
def pack_request(*arguments):
packet = [0x0] * packet_len
i = 0
for arg in arguments:
packet[i] = arg
i += 1
#packet[0:4] = [0x94, 0x0, 0x0, 0x0] #get firmware id
return ''.join([chr(c) for c in packet])
def main():
#Updated for the ACS ACR1252U
dev = usb.core.find(idVendor=0x72f, idProduct=0x223b)
# was it found?
if dev is None:
raise ValueError('Device not found')
try:
dev.detach_kernel_driver(0)
except: # this usually mean that kernel driver has already been dettached
pass
# ACS ACR1252U only has 1 configuration
dev.set_configuration()
# Interface 0: Dual Reader PICC. This is what we want
# Interface 1: Dual Reader SAM
try:
dev.set_interface_altsetting(0)
except usb.core.USBError:
print 'Error setting interface!'
pass
# According to the API, to sound the buzzer we must send:
#
# Class: 0xe0
# INS: 0x00
# P1: 0x00
# P2: 0x28
# Lc: 0x01
# DataIn (duration): 0xff (for 255 * 10ms = 2.55 seconds)
raw = pack_request(0xe0, 0x00, 0x00, 0x28, 0x01, 0xff)
#send the packet
# Params are (endpoint, data, timeout)
#
# According to the script output:
# ENDPOINT 0x01: Bulk OUT
dev.write(endpoint=0x01, data=raw)
#done
if __name__ == '__main__':
main()
当我 运行 没有任何反应...没有蜂鸣器,没有错误信息。这里可能有什么问题?
谢谢!
出于好奇,我打开了 Info.plist(在 /usr/lib/pcsc/drivers/ifd-acsccid.bundle/Contents/
中),发现我的设备没有列出。
所以我继续将我的信息添加到 ifdVendorID (0x072F)、ifdProductID (0x223B) 和 ifdFriendlyName (ACS ACR1252U Dual PICC-SAM Reader) 数组和 运行 pcscd - fd.
只有在这一步之后 pcsc_scan 才真正检测到我的设备,其他一切或多或少开始工作。最后我没有直接使用 USB,而是使用了 pyscard (http://pyscard.sourceforge.net/) 库。
这使蜂鸣器工作:
def sound_buzzer(reps):
#NOTE: This function only works if a card is present!
try:
hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
assert hresult == SCARD_S_SUCCESS
hresult, readers = SCardListReaders(hcontext, [])
assert len(readers) > 0
reader = readers[0]
hresult, hcard, dwActiveProtocol = SCardConnect(hcontext, reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
while reps > 0:
buzzer = [0xE0, 0x00, 0x00, 0x28, 0x01, 0x0F] # 0x0F = 15 * 10ms
hresult, response = SCardControl(hcard, SCARD_CTL_CODE(3500), buzzer)
sleep(0.15)
reps = reps - 1
except Exception, e:
#print 'Exception: '+ str(e)
pass
return