windows – 在不知道VID和PID的情况下读取USB HID条形码扫描器输
我正在尝试为条形码扫描仪开发独立于设备的库,它必须在Windows环境中工作.
我已经在这个领域做了一些研究,afaik这个问题的大部分解决方案都取决于具体的设备VID和PID(RawInput @ filter by vid& pid string),在我的情况下这是不可接受的,因为我正在尝试开发独立于设备的解决方案,该解决方案将与任何USB条形码扫描仪配合使用. 实际上这件事情非常具有挑战性,至少对我来说,这里有确切的要求.此外,我不能要求用户热插拔设备(在这种情况下,我只能检测插入的设备并提取它的视频/ pid).此外,我不能使用设备的VID和PID数据库.一般来说,我实际上根本不能使用vid和pid. 另外我不能以任何方式重新编程条形码扫描仪,除非它是从我的程序完成的(也许我可以发送一些条形码扫描器特定的IOCTL,这将使它回答我?). 目前我将使用此问题中提出的解决方案: 此外,我已经看到商业图书馆(这是一个没有任何来源和任何有关如何实施的信息,但考虑到他们在他们的更改日志中有一些单词“Perfomance counter”,我猜他们在上面的链接中使用了解决方案),实现此功能,但它在x64系统中不起作用.可能是因为代码混乱或因为它可能使用某种过滤器(迷你)驱动程序.这是加密的,我不能重新分配它. 我的确切问题是: 正是我现在正在做的事情: >通过RID_INPUTSINK读取输入. 我目前要做的事情: >通过RID_INPUTSINK读取输入 我在C上开发它,纯WinAPI,它将是一个DLL库,并且可以在x32-86和x32-64架构上的Windows XP,Vista,7,8中工作. 更新0: 根据该文档,USB条形码扫描器具有UsagePage 0x8C和Usage 0x02.不幸的是我没有使用它作为RAWINPUTDEVICE.dwUsage和RAWINPUTDEVICE.dwUsagePage.可能是因为系统安装了它的usb键盘驱动程序,在用户模式下它与真正的USB键盘无法区分.这些值可能在kernelmode环境中可用(其中一个选项是开发hid过滤器驱动程序).
这不能回答你的具体问题,但无论如何……
一年多以前,我在更恶劣的环境下实施了条形码阅读器支持.这是一个报告应用程序,与纯Java(跨平台富客户端,主要是Windows)中的逻辑数据相关联. 因此,该决定针对任何基于JNI的平台特定实施. >前两个字符确定的击键频率(最初/超时后) 输入被缓冲区消耗,直到不满足机器生成的输入的条件,或者已经通过验证,其中将通知条形码监听器.在任何一种情况下,都可以转发输入,就像没有其他事情一样. 这被证明是非常准确的,因为对于人来说,几乎不可能以条形码阅读器的速率输入有效序列(几乎)零抖动. 编辑: 刚挖出Java源代码;我可以为您提供上述实施的早期修订代码示例(无保修,也考虑实施CR): import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * A {@link KeyListener} implementation for barcode readers. This implementation * checks for input rate and jitter to distinguish human and scanner * input sequences by 'precision'. A barcode input sequence from a scanner is * typically terminated with a line break. * * @author Me */ public abstract class AbstractBarcodeInputListener implements KeyListener { public static final int DEFAULT_MIN_PAUSE = 300;// [ms] public static final int DEFAULT_MAX_TIME_DELTA = 200;// [ms] public static final int DEFAULT_MAX_TIME_JITTER = 50;// [ms] public static Integer parseInt(Pattern pattern,int group,String line) { final Matcher matcher = pattern.matcher(line); if (matcher.matches()) return Integer.parseInt(matcher.group(group)); return null; } private String input; private final long minPause; private long maxTimeDelta; private final long maxTimeJitter; private long firstTime; private long firstTimeDelta; private long lastTimeDelta; private long lastTime; public AbstractBarcodeInputListener(long maxTimeDelta,long maxTimeJitter) { this.input = new String(); this.minPause = AbstractBarcodeInputListener.DEFAULT_MIN_PAUSE; this.maxTimeDelta = maxTimeDelta; this.maxTimeJitter = maxTimeJitter; this.firstTime = 0; this.firstTimeDelta = 0; this.lastTimeDelta = 0; this.lastTime = 0; } public AbstractBarcodeInputListener() { this(AbstractBarcodeInputListener.DEFAULT_MAX_TIME_DELTA,AbstractBarcodeInputListener.DEFAULT_MAX_TIME_JITTER); } private boolean checkTiming(KeyEvent e) { final int inputLength = this.input.length(); final long time = e.getWhen(); long timeDelta = time - this.lastTime; long absJitter = 0; long relJitter = 0; boolean inputOK = true; switch (inputLength) { case 0: // pause check inputOK &= (timeDelta > this.minPause); this.firstTime = time; this.firstTimeDelta = timeDelta = 0; break; case 1: // delta check this.firstTimeDelta = timeDelta; inputOK &= (timeDelta < this.maxTimeDelta); break; default:// jitter check & delta check absJitter = Math.abs(timeDelta - this.firstTimeDelta); relJitter = Math.abs(timeDelta - this.lastTimeDelta); inputOK &= (absJitter < this.maxTimeJitter); inputOK &= (relJitter < this.maxTimeJitter); inputOK &= (timeDelta < this.maxTimeDelta); break; } this.lastTime = time; this.lastTimeDelta = timeDelta; return inputOK; } @Override public void keyPressed(KeyEvent e) { } private void clearInput() { this.input = new String(); } private void commitInput(KeyEvent e) { final String code = this.input; if (!code.isEmpty()) { final long avgIntervalTime = e.getWhen() - this.firstTime; this.maxTimeDelta = (avgIntervalTime * 15) / 10; this.clearInput(); this.codeRead(code); } } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { if (this.checkTiming(e)) { final char c = e.getKeyChar(); switch (c) { case 'b': this.clearInput(); break; case 'n': this.commitInput(e); break; default: this.input += c; break; } } else { this.clearInput(); } } public abstract void codeRead(String line); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Windows – 什么是SMS代理主机?
- windows-server-2008-r2 – 如何在不破坏RDP的情况下禁用TL
- 如何使Emacs dired模式在Windows中显示unicode字符?
- 在window环境下挂载mysql数据卷
- 设置服务器以承载所有LAN设备的Windows更新
- 窗口 – 我如何设置巧克力来将应用程序安装到另一个驱动器上
- 32位数据转8位数据和8位数据转32位数据
- f# – fsx脚本引用一个引用很多dll的DLL
- 当驱动器作为“通用”设备呈现时,如何监控Windows中的SSD磨
- windows-server-2012 – 启动徽标后的Windows Server 2012r
- 配置 – 为Windows服务保留用户可编辑设置的最佳
- 蓝牙在2台Windows 7计算机上使用C#进行配对而不进
- windows-server-2008-r2 – 适用于Windows Serve
- 如何将Windows Workflow作为Web服务(.svc)托管?
- Windows批处理文件中的字符串处理:如何用前导零
- Windows 8 – 可重新分发的脱机.NET Framework 3
- api – Windows Live Mesh为程序设置提供同步;我
- 联想拯救者Y7000安装双系统:win10 + ubuntu16.0
- 3dmax2012卸载/安装失败/如何彻底卸载清除干净3d
- Windows上的Web服务搭建