Windows 上 rusb write_interrupt 中的输入/输出错误
我正在使用 rust、STM32 芯片、usb-device 和 < 构建一个小型“宏”风格键盘a href="https://docs.rs/usbd-hid" rel="nofollow noreferrer">usbd-hid。我的电脑正确检测到该设备,并且制造商字符串等在设备管理器中可见。我可以将该设备用作键盘。
但是,当我尝试使用 rusb 或 hidapi,它因 IO 错误而失败。当我调试 C 代码时,当它尝试 WriteFile
到 USB 设备时,会出现“访问被拒绝”错误。经过进一步研究,这似乎是一个 限制Windows,因为我无法访问 HID 鼠标和键盘,因为它们是系统保留的:
libusb 支持原生 Windows HID 驱动,但有一些限制,例如无法访问 HID 鼠标和键盘,因为它们是系统保留的
但是我找不到任何文档或示例来说明如何解决此问题 - 它似乎我应该能够在我的 USB 描述符中添加不完全由 Windows 持有的另一个配置、接口或端点。有人对从哪里开始有任何提示吗?
我当前的 USB 设备配置(使用 usbd-hid 的宏,如果需要的话我很乐意放弃)如下所示:
#[gen_hid_descriptor(
(collection = APPLICATION, usage_page = GENERIC_DESKTOP, usage = KEYBOARD) = {
(usage_page = KEYBOARD, usage_min = 0xE0, usage_max = 0xE7) = {
#[packed_bits 8] #[item_settings data,variable,absolute] modifier=input;
};
(usage_min = 0x00, usage_max = 0xFF) = {
#[item_settings constant,variable,absolute] reserved=input;
};
(usage_page = LEDS, usage_min = 0x01, usage_max = 0x05) = {
#[packed_bits 5] #[item_settings data,variable,absolute] leds=output;
};
(usage_page = KEYBOARD, usage_min = 0x00, usage_max = 0xDD) = {
#[item_settings data,array,absolute] keycodes=input;
};
(usage_page = 0xFF17, usage_min = 0x01, usage_max = 0xFF) = {
#[item_settings data,variable,absolute] command=output;
};
(usage_page = 0xFF17, usage_min = 0x01, usage_max = 0xFF) = {
#[item_settings data,variable,absolute] data=output;
};
}
)]
#[allow(dead_code)]
pub struct CustomKeyboardReport {
pub modifier: u8,
pub reserved: u8,
pub leds: u8,
pub keycodes: [u8; 6],
pub command: u8,
pub data: u8,
}
生成的描述符如下所示
0x05 0x01 0x09 0x06 0xA1 0x01 0x05 0x07
0x19 0xE0 0x29 0xE7 0x15 0x00 0x25 0x01
0x75 0x01 0x95 0x08 0x81 0x02 0x19 0x00
0x29 0xFF 0x26 0xFF 0x00 0x75 0x08 0x95
0x01 0x81 0x03 0x05 0x08 0x19 0x01 0x29
0x05 0x25 0x01 0x75 0x01 0x95 0x05 0x91
0x02 0x95 0x03 0x91 0x03 0x05 0x07 0x19
0x00 0x29 0xDD 0x26 0xFF 0x00 0x75 0x08
0x95 0x06 0x81 0x00 0x06 0x17 0xFF 0x19
0x01 0x29 0xFF 0x95 0x01 0x91 0x02 0x06
0x17 0xFF 0x19 0x01 0x29 0xFF 0x91 0x02
0xC0
相关: 1
I'm building a small "macro" style keyboard using rust, STM32 chips, usb-device and usbd-hid. The device is correctly detected by my PC and the manufacturer strings etc are visible in device manager. I can use the device as a keyboard.
However when I try to write from host to device using rusb or hidapi, it fails with an IO error. When I debug the C code it gives an "Access Denied" error when it tries to WriteFile
to the USB device. It seems on further research that this is a limitation of Windows, in that I can't access HID mice and keyboards as they're system reserved:
the native Windows HID driver is supported by libusb, but there are some limitations, such as not being able to access HID mice and keyboards since they are system reserved
However I can't find any documentation or examples of how to work around this - it seems I should be able to add another configuration, interface or endpoint in my USB descriptors that isn't exclusively held by Windows. Anybody have any hints on where to start?
My current USB device configuration (using usbd-hid's macro, which I'm happy to abandon if I need to) looks like this:
#[gen_hid_descriptor(
(collection = APPLICATION, usage_page = GENERIC_DESKTOP, usage = KEYBOARD) = {
(usage_page = KEYBOARD, usage_min = 0xE0, usage_max = 0xE7) = {
#[packed_bits 8] #[item_settings data,variable,absolute] modifier=input;
};
(usage_min = 0x00, usage_max = 0xFF) = {
#[item_settings constant,variable,absolute] reserved=input;
};
(usage_page = LEDS, usage_min = 0x01, usage_max = 0x05) = {
#[packed_bits 5] #[item_settings data,variable,absolute] leds=output;
};
(usage_page = KEYBOARD, usage_min = 0x00, usage_max = 0xDD) = {
#[item_settings data,array,absolute] keycodes=input;
};
(usage_page = 0xFF17, usage_min = 0x01, usage_max = 0xFF) = {
#[item_settings data,variable,absolute] command=output;
};
(usage_page = 0xFF17, usage_min = 0x01, usage_max = 0xFF) = {
#[item_settings data,variable,absolute] data=output;
};
}
)]
#[allow(dead_code)]
pub struct CustomKeyboardReport {
pub modifier: u8,
pub reserved: u8,
pub leds: u8,
pub keycodes: [u8; 6],
pub command: u8,
pub data: u8,
}
Which produces a descriptor that looks like this
0x05 0x01 0x09 0x06 0xA1 0x01 0x05 0x07
0x19 0xE0 0x29 0xE7 0x15 0x00 0x25 0x01
0x75 0x01 0x95 0x08 0x81 0x02 0x19 0x00
0x29 0xFF 0x26 0xFF 0x00 0x75 0x08 0x95
0x01 0x81 0x03 0x05 0x08 0x19 0x01 0x29
0x05 0x25 0x01 0x75 0x01 0x95 0x05 0x91
0x02 0x95 0x03 0x91 0x03 0x05 0x07 0x19
0x00 0x29 0xDD 0x26 0xFF 0x00 0x75 0x08
0x95 0x06 0x81 0x00 0x06 0x17 0xFF 0x19
0x01 0x29 0xFF 0x95 0x01 0x91 0x02 0x06
0x17 0xFF 0x19 0x01 0x29 0xFF 0x91 0x02
0xC0
Related: 1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我通过创建一个单独的报告解决了这个问题:
然后我创建了一个单独的 HID 接口,只有一个
OUT
端点:在我的
poll
函数中,我检查了两个:然后我可以读取通过提取原始输出来获取数据:
由于只有 1 个报告 ID,因此我不必在使用
libusb
从主机发送的数据中添加reportId
。I resolved this by creating a separate report:
Then I created a separate HID interface with only an
OUT
endoint:In my
poll
function I check both:And then I can read the data by pulling raw output:
As there is only 1 report ID, I did not have to prepend the
reportId
in the data I sent from the host usinglibusb
.