HID 设备无法获取实际值
HID device cannot able to get actual value
我最近从中国买了一个二维条码扫描模块。根据他们的数据表,当我打开记事本时,它可以很好地扫描条形码。我需要做的就是尝试使用 libusb 并读取我的 c 代码上的条形码。我将英特尔爱迪生与配置为 USB 主机的 Ad运行io 分线板一起使用。
我已经安装了 libusb-1.0.20,不幸的是我无法安装 libusb-1.0.20-devel。请注意,我在这里没有使用 libusbx 和 libusbx-devel。
因为它是条形码扫描仪设备,所以它应该被检测为 HID 键盘。是的。
Bus 001 Device 003: ID 1eab:8203
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x1eab
idProduct 0x8203
bcdDevice 1.00
iManufacturer 1 NewLand
iProduct 2 HidKeyBoard
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 200mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 1 Boot Interface Subclass
bInterfaceProtocol 1 Keyboard
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 63
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x84 EP 4 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 1
Device Status: 0x0001
Self Powered
而我的 C 代码是:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
//gcc -o usbtest usbtest.c -lusb-1.0
//libusbx-devel, libusbx
#include <libusb-1.0/libusb.h>
void print_devices(libusb_device *dev)
{
struct libusb_device_descriptor desc;
struct libusb_config_descriptor *config;
const struct libusb_interface *inter;
const struct libusb_interface_descriptor *interdesc;
const struct libusb_endpoint_descriptor *endpointdesc;
int ret;
int i,j,k;
ret = libusb_get_device_descriptor(dev, & desc);
if(ret < 0)
{
fprintf(stderr, "error in getting device descriptor\n");
return;
}
printf("Number of possible configs is %d\n",desc.bNumConfigurations);
printf("Vendor ID : 0x%x\n", desc.idVendor);
printf("Product ID : 0x%x\n", desc.idProduct);
libusb_get_config_descriptor(dev, 0, &config);
printf("Interface %d\n", config->bNumInterfaces);
for(i=0; i < config->bNumInterfaces; i++)
{
inter = &config->interface[i];
printf("Number of alternate settings : %d\n", inter->num_altsetting);
for(j=0; j < inter->num_altsetting; j++)
{
interdesc = &inter->altsetting[j];
printf(" Interface number : %d, ", interdesc->bInterfaceNumber);
printf(" Num of endpoints : %d\n", interdesc->bNumEndpoints);
for(k=0; k < interdesc->bNumEndpoints; k++)
{
endpointdesc = &interdesc->endpoint[k];
printf(" Desc type : %d ",endpointdesc->bDescriptorType);
printf(" EP Addr: %d\n", endpointdesc->bEndpointAddress);
}
}
}
printf("\n\n");
libusb_free_config_descriptor(config);
}
int main(int argc, char *argv[])
{
libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
libusb_context *context = NULL; //a libusb session
libusb_device_handle *dev_handle; //a device handle
size_t list;
size_t iter;
int retVal;
int kernelDriverDetached = 0; /* Set to 1 if kernel driver detached */
retVal = libusb_init(&context);
if(retVal < 0)
{
perror("libusb_init");
exit(1);
}
libusb_set_debug(context, 3); //set verbosity level to 3, as suggested in the documentation
list = libusb_get_device_list(context, &devs);
if(list < 0){
fprintf(stderr, "Error in getting device list\n");
libusb_free_device_list(devs, 1);
libusb_exit(context);
exit(1);
}
printf("There are %d devices found\n",list);
for(iter = 0; iter < list; iter++)
{
/* print devices specs */
print_devices(devs[iter]);
}
dev_handle = libusb_open_device_with_vid_pid(context, 0x1eab, 0x8203/*0x1d6b,0x0002*/); //these are vendorID and productID I found for my usb device
if(dev_handle == NULL) {
fprintf(stderr, "Unable to open device.\n");
return 1;
}
/* Check whether a kernel driver is attached to interface #0. If so, we'll
* need to detach it.
*/
if (libusb_kernel_driver_active(dev_handle, 0))
{
retVal = libusb_detach_kernel_driver(dev_handle, 0);
if (retVal == 0)
{
kernelDriverDetached = 1;
}
else
{
fprintf(stderr, "Error detaching kernel driver.\n");
return 1;
}
}
/* Claim interface #0. */
retVal = libusb_claim_interface(dev_handle, 0);
if (retVal != 0)
{
fprintf(stderr, "Error claiming interface.\n");
return 1;
}
printf("Scanner Device Opened\n");
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
char buf[24];
int actualbytes;
retVal = libusb_interrupt_transfer(dev_handle, /*0x84*/(4 | LIBUSB_ENDPOINT_IN), buf, 24, &actualbytes, 0);
if(retVal == 0) {
printf("Received %d bytes\n",actualbytes);
}
else
{
fprintf(stderr, "Error Receiving message. retVal : %d, Actual : %d\n",retVal,actualbytes);
}
for(iter = 0; iter < actualbytes; iter++){
printf("Data[%d] = %d\n",iter,buf[iter]);
}
/* Release interface #0. */
retVal = libusb_release_interface(dev_handle, 0);
if (0 != retVal)
{
fprintf(stderr, "Error releasing interface.\n");
}
/* If we detached a kernel driver from interface #0 earlier, we'll now
* need to attach it again. */
if (kernelDriverDetached)
{
libusb_attach_kernel_driver(dev_handle, 0);
}
/* Shutdown libusb. */
libusb_free_device_list(devs, 1); //free the list, unref the devices in it
libusb_exit(context);
return 0;
}
我可以编译和 运行 代码、扫描、打开、读取设备。但是我能读到的数据都是零。尽管它说 wMaxPacketSize 0x0008 1x 8 bytes
和 bLength 18
当我尝试将长度设置为 8,16,18 时它给了我错误。所以我改为24。我的实际条码(一维)数据大小是12bytes。
代码有问题吗?还是我需要添加更多核心才能读取实际的 bardcode。
我知道因为它检测为 HID 键盘设备,所以我收到的数据不会是 ASCII 格式(这是我所期望的)。我根据https://www.win.tue.nl/~aeb/linux/kbd/scancodes-14.html
修改了代码
尽管文档说的是 16 位键码,但我只有在读取 16 字节时才能获得正确的数据。基于键码,我创建了一个 table 将 HID 键码转换为 ASCII。
但这在我的 Windows 机器上仍然不起作用,因为它说它无法打开设备。
我最近从中国买了一个二维条码扫描模块。根据他们的数据表,当我打开记事本时,它可以很好地扫描条形码。我需要做的就是尝试使用 libusb 并读取我的 c 代码上的条形码。我将英特尔爱迪生与配置为 USB 主机的 Ad运行io 分线板一起使用。
我已经安装了 libusb-1.0.20,不幸的是我无法安装 libusb-1.0.20-devel。请注意,我在这里没有使用 libusbx 和 libusbx-devel。
因为它是条形码扫描仪设备,所以它应该被检测为 HID 键盘。是的。
Bus 001 Device 003: ID 1eab:8203
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x1eab
idProduct 0x8203
bcdDevice 1.00
iManufacturer 1 NewLand
iProduct 2 HidKeyBoard
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 200mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 1 Boot Interface Subclass
bInterfaceProtocol 1 Keyboard
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 63
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x84 EP 4 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 1
Device Status: 0x0001
Self Powered
而我的 C 代码是:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
//gcc -o usbtest usbtest.c -lusb-1.0
//libusbx-devel, libusbx
#include <libusb-1.0/libusb.h>
void print_devices(libusb_device *dev)
{
struct libusb_device_descriptor desc;
struct libusb_config_descriptor *config;
const struct libusb_interface *inter;
const struct libusb_interface_descriptor *interdesc;
const struct libusb_endpoint_descriptor *endpointdesc;
int ret;
int i,j,k;
ret = libusb_get_device_descriptor(dev, & desc);
if(ret < 0)
{
fprintf(stderr, "error in getting device descriptor\n");
return;
}
printf("Number of possible configs is %d\n",desc.bNumConfigurations);
printf("Vendor ID : 0x%x\n", desc.idVendor);
printf("Product ID : 0x%x\n", desc.idProduct);
libusb_get_config_descriptor(dev, 0, &config);
printf("Interface %d\n", config->bNumInterfaces);
for(i=0; i < config->bNumInterfaces; i++)
{
inter = &config->interface[i];
printf("Number of alternate settings : %d\n", inter->num_altsetting);
for(j=0; j < inter->num_altsetting; j++)
{
interdesc = &inter->altsetting[j];
printf(" Interface number : %d, ", interdesc->bInterfaceNumber);
printf(" Num of endpoints : %d\n", interdesc->bNumEndpoints);
for(k=0; k < interdesc->bNumEndpoints; k++)
{
endpointdesc = &interdesc->endpoint[k];
printf(" Desc type : %d ",endpointdesc->bDescriptorType);
printf(" EP Addr: %d\n", endpointdesc->bEndpointAddress);
}
}
}
printf("\n\n");
libusb_free_config_descriptor(config);
}
int main(int argc, char *argv[])
{
libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
libusb_context *context = NULL; //a libusb session
libusb_device_handle *dev_handle; //a device handle
size_t list;
size_t iter;
int retVal;
int kernelDriverDetached = 0; /* Set to 1 if kernel driver detached */
retVal = libusb_init(&context);
if(retVal < 0)
{
perror("libusb_init");
exit(1);
}
libusb_set_debug(context, 3); //set verbosity level to 3, as suggested in the documentation
list = libusb_get_device_list(context, &devs);
if(list < 0){
fprintf(stderr, "Error in getting device list\n");
libusb_free_device_list(devs, 1);
libusb_exit(context);
exit(1);
}
printf("There are %d devices found\n",list);
for(iter = 0; iter < list; iter++)
{
/* print devices specs */
print_devices(devs[iter]);
}
dev_handle = libusb_open_device_with_vid_pid(context, 0x1eab, 0x8203/*0x1d6b,0x0002*/); //these are vendorID and productID I found for my usb device
if(dev_handle == NULL) {
fprintf(stderr, "Unable to open device.\n");
return 1;
}
/* Check whether a kernel driver is attached to interface #0. If so, we'll
* need to detach it.
*/
if (libusb_kernel_driver_active(dev_handle, 0))
{
retVal = libusb_detach_kernel_driver(dev_handle, 0);
if (retVal == 0)
{
kernelDriverDetached = 1;
}
else
{
fprintf(stderr, "Error detaching kernel driver.\n");
return 1;
}
}
/* Claim interface #0. */
retVal = libusb_claim_interface(dev_handle, 0);
if (retVal != 0)
{
fprintf(stderr, "Error claiming interface.\n");
return 1;
}
printf("Scanner Device Opened\n");
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
char buf[24];
int actualbytes;
retVal = libusb_interrupt_transfer(dev_handle, /*0x84*/(4 | LIBUSB_ENDPOINT_IN), buf, 24, &actualbytes, 0);
if(retVal == 0) {
printf("Received %d bytes\n",actualbytes);
}
else
{
fprintf(stderr, "Error Receiving message. retVal : %d, Actual : %d\n",retVal,actualbytes);
}
for(iter = 0; iter < actualbytes; iter++){
printf("Data[%d] = %d\n",iter,buf[iter]);
}
/* Release interface #0. */
retVal = libusb_release_interface(dev_handle, 0);
if (0 != retVal)
{
fprintf(stderr, "Error releasing interface.\n");
}
/* If we detached a kernel driver from interface #0 earlier, we'll now
* need to attach it again. */
if (kernelDriverDetached)
{
libusb_attach_kernel_driver(dev_handle, 0);
}
/* Shutdown libusb. */
libusb_free_device_list(devs, 1); //free the list, unref the devices in it
libusb_exit(context);
return 0;
}
我可以编译和 运行 代码、扫描、打开、读取设备。但是我能读到的数据都是零。尽管它说 wMaxPacketSize 0x0008 1x 8 bytes
和 bLength 18
当我尝试将长度设置为 8,16,18 时它给了我错误。所以我改为24。我的实际条码(一维)数据大小是12bytes。
代码有问题吗?还是我需要添加更多核心才能读取实际的 bardcode。
我知道因为它检测为 HID 键盘设备,所以我收到的数据不会是 ASCII 格式(这是我所期望的)。我根据https://www.win.tue.nl/~aeb/linux/kbd/scancodes-14.html
修改了代码尽管文档说的是 16 位键码,但我只有在读取 16 字节时才能获得正确的数据。基于键码,我创建了一个 table 将 HID 键码转换为 ASCII。
但这在我的 Windows 机器上仍然不起作用,因为它说它无法打开设备。