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

Get Serialnumber/UID from reader? #130

Open
atterdal opened this issue Jun 3, 2022 · 2 comments
Open

Get Serialnumber/UID from reader? #130

atterdal opened this issue Jun 3, 2022 · 2 comments

Comments

@atterdal
Copy link

atterdal commented Jun 3, 2022

I have four 1252u readers connected and it works great. However I need to know what card is read from what reader even after reboot or some usb-devices are plug out/in and the name is changed depending on the order they are booted.

Is there a way to solve this?

Cheers,
Stefan

@kur0s4ki
Copy link

Did you solve this ? I have the same issue.

@vaaski
Copy link

vaaski commented Sep 14, 2024

Might be a little late, but I found a way that seems to be reliable so far. I have two readers plugged into my Raspberry Pi 4.

First I check what the addresses are with lsusb, which looks like this:

lsusb

# Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
# Bus 001 Device 010: ID 072f:2200 Advanced Card Systems, Ltd ACR122U
# Bus 001 Device 011: ID 072f:2200 Advanced Card Systems, Ltd ACR122U
# Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
# Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Then I use udevadm info to get more info about each device, the relevant bits look like this:

udevadm info -a -n /dev/bus/usb/001/010

# [...]
# looking at device '/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.2':
#   KERNEL=="1-1.2"
#   [...]
#   ATTR{power/active_duration}=="798352"
#   [...]

With the info provided by the udevadm info -a -n ${address} command I can check the physical port and the duration they've been connected for. Then I just map those to the names that nfc-pcsc provides, which seem to be in the order they connected, in my case they look like this:

  • ACS ACR122U PICC Interface 00 00
  • ACS ACR122U PICC Interface 01 00
Here's my code to do all that
// usb.ts

import { execaCommand } from "execa"

const LSUSB_MATCHER = /^Bus (\d+) Device (\d+).+ACR122U/
const KERNEL_MATCHER = /KERNEL=="(.+)"$/m
const TIME_MATCHER = /ATTR{power\/active_duration}=="(.+)"$/m
const DEVICE_MATCHER = /ACS ACR122U PICC Interface (\d+) 00/m

const PORTS = {
  "1-1.1": "upper",
  "1-1.2": "lower",
} as const

type USBDevice = {
  kernel: string
  time: string
}

export const parseUSBData = async () => {
  const output = await execaCommand("lsusb")

  const devices: USBDevice[] = []

  for (const line of output.stdout.split("\n")) {
    const match = LSUSB_MATCHER.exec(line)
    if (!match) continue

    const [, bus, device] = match
    const address = `/dev/bus/usb/${bus}/${device}`

    const info = await execaCommand(`udevadm info -a -n ${address}`)

    const kernelMatch = KERNEL_MATCHER.exec(info.stdout)
    if (!kernelMatch) throw new Error("no kernel match")

    const [, kernel] = kernelMatch

    const timeMatcher = TIME_MATCHER.exec(info.stdout)
    if (!timeMatcher) throw new Error("no time match")

    const [, time] = timeMatcher

    devices.push({ kernel, time })
  }

  return devices.sort((a, b) => Number.parseInt(b.time) - Number.parseInt(a.time))
}

export const getPort = async (deviceName: string) => {
  const deviceIndexMatch = DEVICE_MATCHER.exec(deviceName)
  if (!deviceIndexMatch) throw new Error("no device index match")

  const [, deviceIndex] = deviceIndexMatch

  const devices = await parseUSBData()
  const device = devices[Number.parseInt(deviceIndex)]
  if (!device) throw new Error("no device found")

  const port = PORTS[device.kernel as keyof typeof PORTS]
  if (!port) throw new Error("no port found")

  return port as (typeof PORTS)[keyof typeof PORTS]
}

With that I just get the port like this:

import { NFC } from "nfc-pcsc"
import { getPort } from "./usb"

const nfc = new NFC()

nfc.on("reader", async reader => {
  const port = await getPort(reader.reader.name)
  console.log("connected reader", port)
})

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

No branches or pull requests

3 participants