Skip to main content

Supported Readers

VIDPIDDescription
0x0C270x3BFAStandard multi-technology reader
0x0C270x3B4CLEGIC enabled reader
0x0C270x3B1EBluetooth Low Energy (BLE) reader
N/AN/ASerial Interface (RS-232)

Connection Strategies

RIK provides three ways to identify which USB reader to connect to. The strategy is determined by which DeviceId fields you populate.

1. VID/PID Only

The simplest approach. RIK opens the first device matching the given Vendor ID and Product ID.

ReaderDefinition readerDef{};
readerDef.DeviceId.VendorId = 0x0C27;
readerDef.DeviceId.ProductId = 0x3BFA;
readerDef.ProtocolType = PROTOCOL_TYPE_FEATURE_REPORT;

auto handle = AbstractReader::CreateReaderInstance(readerDef, 3);
warning

If multiple readers with the same VID/PID are connected, this opens whichever one the OS enumerates first. The result is non-deterministic. Use serial number or USB path to target a specific device.

2. VID/PID + Serial Number

Adding a serial number narrows the match to a specific device. The USB serial number is part of the USB Device Descriptor -- on newer rf IDEAS readers it matches the reader's ESN (Electronic Serial Number), but on older readers it may be empty or non-unique.

ReaderDefinition readerDef{};
readerDef.DeviceId.VendorId = 0x0C27;
readerDef.DeviceId.ProductId = 0x3BFA;
std::strncpy(readerDef.DeviceId.SerialNumber, "ABC123",
sizeof(readerDef.DeviceId.SerialNumber) - 1);
readerDef.ProtocolType = PROTOCOL_TYPE_FEATURE_REPORT;

auto handle = AbstractReader::CreateReaderInstance(readerDef, 3);
Finding serial numbers

Connect one reader at a time and read its ESN from the metadata (GetMetadataStruct().ESN in C++, GetMetadata().ESN in C#, get_metadata()["ESN"] in Python). On newer readers, this ESN matches the USB serial number in the device descriptor.

note

VID/PID should be provided alongside the serial number. Both are passed to the underlying USB library as match criteria. Providing VID/PID narrows the search and avoids accidentally matching a non-reader device that happens to share a serial number.

3. USB Path

The USB path is a topological identifier for a physical USB port. When set, VID/PID and serial number are ignored entirely -- the connection is made purely by port location. This is the most deterministic strategy and is ideal for fixed installations with multiple identical readers.

Path formats:

  • Linux: "B-P" or "B-P.P.P" (e.g., "1-7", "1-7.2") where B = bus number, P = port number
  • Windows: Location path string (e.g., "PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(7)")
  • macOS: Hexadecimal USB location ID (e.g., "0x14100000"); decimal format is also accepted
ReaderDefinition readerDef{};
readerDef.ProtocolType = PROTOCOL_TYPE_FEATURE_REPORT;

// USB path -- VID/PID are not required in this mode
std::strncpy(readerDef.DeviceId.UsbPath, "1-7", // Linux bus-port path
sizeof(readerDef.DeviceId.UsbPath) - 1);

auto handle = AbstractReader::CreateReaderInstance(readerDef, 3);
note

The USB path identifies a physical port, not a device. If you move a reader to a different port, its path changes. If you swap two readers between ports, each will take on the other's path.

See Discovering USB Readers for how to discover connected readers programmatically or find topological paths on Linux, Windows, and macOS.

Strategy Summary

StrategyDeviceId FieldsBehavior
VID/PIDVendorId + ProductIdOpens the first matching device. Simple, but non-deterministic with duplicates.
VID/PID + SerialVendorId + ProductId + SerialNumberFilters by USB serial number. Reliable when readers have unique serial numbers.
USB PathUsbPath (VID/PID ignored)Opens by physical port location. Most deterministic. Ideal for fixed multi-reader setups.

Finding Your Reader's VID/PID

Windows: Device Manager > Universal Serial Bus devices > Properties > Details > Hardware Ids

Linux:

lsusb | grep -i rfideas
# Or for all USB devices:
lsusb

Reader Capabilities

rf IDEAS readers (Reader) support:

  • Card data reading
  • Beeper control (volume, beep count, duration)
  • LED configuration
  • Reader configuration (get/set)
  • Extended configuration
  • Keystroking enable/disable
  • Transparent mode (capability check, enable/disable)
  • Module state control (LF radio, HF radio, BLE)
  • LUID get/set
  • BLE configuration read/write
  • HWG file import/export
  • Smart card configuration
  • Supported card type enumeration

Serial Readers

Serial readers use SerialBinary protocol with Reader. Configure the serial port:

ReaderDefinition readerDef{};
readerDef.ProtocolType = PROTOCOL_TYPE_SERIAL_BINARY;
std::strcpy(readerDef.SerialPortSettings.PortName, "COM3"); // Windows
// std::strcpy(readerDef.SerialPortSettings.PortName, "/dev/ttyACM0"); // Linux
// std::strcpy(readerDef.SerialPortSettings.PortName, "/dev/cu.usbserial-1410"); // macOS
readerDef.SerialPortSettings.BaudRate = SERIAL_PORT_BAUD_9600;
readerDef.SerialPortSettings.Parity = SERIAL_PORT_PARITY_NONE;
readerDef.SerialPortSettings.DataBits = SERIAL_PORT_DATA_BITS_8;
readerDef.SerialPortSettings.StopBits = SERIAL_PORT_STOP_BITS_ONE;

Linux USB Permissions

Create a udev rule for reader access. This rule covers all known rf IDEAS reader VID/PID combinations:

/etc/udev/rules.d/99-rfideas.rules
sudo tee /etc/udev/rules.d/99-rfideas.rules << 'EOF'
# rf IDEAS readers (VID 0x0C27)
SUBSYSTEM=="usb", ATTR{idVendor}=="0c27", MODE="0660", GROUP="plugdev"
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0c27", MODE="0660", GROUP="plugdev"
EOF

sudo udevadm control --reload-rules && sudo udevadm trigger
tip

The rf IDEAS rules above use a vendor-wide match (ATTR{idVendor}=="0c27") instead of per-PID rules. This covers all current and future rf IDEAS readers without needing rule updates.

Ensure your user is in the plugdev group:

sudo usermod -aG plugdev $USER
warning

You must log out and back in (or reboot) for group membership changes to take effect.

For serial readers, add your user to dialout:

sudo usermod -aG dialout $USER

macOS USB Permissions

On macOS 12.0 (Monterey) and later, RIK accesses USB HID readers through IOKit and HIDAPI. No root / sudo and no App Sandbox HID/USB entitlements are required for CLI or non-sandboxed apps.

Privilege model

You do not need to run your application with sudo, and you do not need App Sandbox HID/USB entitlements on CLI or non-sandboxed binaries. Reader discovery does not require Input Monitoring. Opening a keyboard-class HID collection (typical for current rf IDEAS readers) may require an Input Monitoring (kTCCServiceListenEvent) grant on the responsible process — often the host app such as Terminal.app, not the RIK binary itself. Headless or LaunchDaemon hosts can discover readers but still fail to open them when no console TCC identity is available.

Keystroking while connected

Some rf IDEAS readers can operate in keystroking mode, where the reader sends card data as keyboard input to the focused application. RIK opens the HID device non-exclusively by design: a reader in keystroking mode continues to send keystrokes to the focused application while RIK is connected and reading.

This behavior is intentional. When designing your application:

  • If keystroking must be suppressed during programmatic reads, disable it with EnableKeystroking(false) (C++/C#) or enable_keystroking(False) (Python) before connecting, or configure the reader to disable keystroking at startup. See Enable/Disable Keystroking.
  • Ensure no sensitive input field (password box, PIN entry) is focused when a card is presented while RIK is active.

App Sandbox entitlements

com.apple.security.device.hid and com.apple.security.device.usb are App Sandbox entitlements. They apply only to sandboxed .app bundles (Mac App Store submissions or apps with the App Sandbox entitlement enabled). CLI binaries and non-sandboxed applications do not use entitlements for HID access.

Do not add sandbox entitlements to CLI projects

Declaring these entitlements in a CLI binary or non-sandboxed application has no effect and is misleading. Do not copy App Sandbox entitlements from sample projects into a RIK CLI or non-sandboxed integration.

Troubleshooting

If a reader is not detected on macOS:

  1. Verify the reader appears in System Information.app under USB. If it does not appear, the issue is hardware or cable, not permissions.
  2. If macOS Gatekeeper blocks libReaderIntegrationKit.dylib, see Gatekeeper.
  3. If the reader is enumerated in System Information.app but still fails to open:
    • Confirm the process is not running inside an App Sandbox without the appropriate entitlement.
    • For keyboard-class collections, grant Input Monitoring to the responsible app (for example Terminal.app when running from a terminal) in System Settings > Privacy & Security > Input Monitoring.