Java中如何识别输入来自哪台条码扫描器?
区分两台条码扫描器的输入来源
首先明确:条码扫描器常见两种工作模式,模拟键盘(Keyboard Wedge)和USB HID设备。如果是键盘模式,系统会把扫描内容当成普通键盘输入,无法通过usb4java区分来源,需要先将扫描器切换到HID模式(通常用扫描器自带的设置条码完成)。如果已经是HID模式,可按以下步骤用usb4java实现设备区分:
核心步骤
1. 唯一标识设备
同型号的扫描器vendorId和productId会相同,必须用busNumber + deviceAddress作为唯一标识,这两个值你已经在现有代码中获取到了。
2. 打开目标设备并获取句柄
在遍历设备时,匹配到目标扫描器(比如根据vendorId、productId,再结合bus/address)后,打开设备:
DeviceHandle handle = new DeviceHandle(); int openResult = LibUsb.open(device, handle); if (openResult != LibUsb.SUCCESS) { throw new LibUsbException("Failed to open device", openResult); }
3. 配置设备并声明接口
HID设备需要配置后才能通信,先设置配置,再找到对应的HID接口并声明:
// 设置设备配置(通常配置值为1,可从DeviceDescriptor获取bNumConfigurations确认) int configResult = LibUsb.setConfiguration(handle, 1); if (configResult != LibUsb.SUCCESS) { throw new LibUsbException("Failed to set configuration", configResult); } // 获取配置描述符 ConfigurationDescriptor configDescriptor = new ConfigurationDescriptor(); int configDescResult = LibUsb.getConfigDescriptor(device, 0, configDescriptor); if (configDescResult != LibUsb.SUCCESS) { throw new LibUsbException("Failed to get config descriptor", configDescResult); } // 遍历接口,找到HID类接口(bInterfaceClass为0x03) Interface iface = configDescriptor.interface()[0]; for (InterfaceDescriptor ifaceDesc : iface.altsetting()) { if (ifaceDesc.bInterfaceClass() == LibUsb.CLASS_HID) { // 声明接口 int claimResult = LibUsb.claimInterface(handle, ifaceDesc.bInterfaceNumber()); if (claimResult != LibUsb.SUCCESS) { throw new LibUsbException("Failed to claim interface", claimResult); } break; } }
4. 读取设备输入数据
找到HID接口的中断端点(通常是IN端点,bEndpointAddress的最高位为1),然后同步或异步读取数据:
// 找到IN端点 EndpointDescriptor inEndpoint = null; for (EndpointDescriptor epDesc : ifaceDesc.endpoint()) { if ((epDesc.bEndpointAddress() & LibUsb.ENDPOINT_IN) != 0) { inEndpoint = epDesc; break; } } // 同步读取数据(缓冲区大小根据扫描器的报告长度设置,通常64字节) byte[] buffer = new byte[64]; IntBuffer transferred = IntBuffer.allocate(1); int readResult = LibUsb.interruptTransfer(handle, inEndpoint.bEndpointAddress(), ByteBuffer.wrap(buffer), transferred, 5000); // 5秒超时 if (readResult == LibUsb.SUCCESS) { // 处理扫描到的数据,buffer里就是扫描器发送的内容 String barcode = new String(buffer, 0, transferred.get(0)).trim(); System.out.printf("来自设备(Bus %d, Device %d)的条码: %s%n", busNumber, address, barcode); }
5. 资源释放
使用完设备后,要释放接口、关闭设备:
LibUsb.releaseInterface(handle, ifaceDesc.bInterfaceNumber()); LibUsb.close(handle); LibUsb.freeDeviceList(list, true);
关键注意事项
- 如果扫描器是键盘模式,必须先切换到HID模式:参考扫描器的用户手册,扫描对应的设置条码即可切换。
- 权限问题:在Linux/macOS下可能需要设置udev规则,避免权限不足;Windows下通常需要驱动支持。
- 异步读取:如果需要同时监听两台设备,建议使用usb4java的异步传输API(LibUsb.asyncTransfer),避免阻塞主线程。
内容的提问来源于stack exchange,提问作者Ahmed
相关产品推荐
相关产品推荐

