HID устройство не может получить фактическое значение
Я недавно купил модуль сканера штрих-кода из Китая. Согласно их данным, при открытии блокнота все работало нормально, сканируя штрих-коды. Все, что мне нужно сделать, это попробовать использовать libusb и прочитать штрих-код на моем коде c. Я использую Intel Edison с платой Adrunio, которая настроена как USB-хост.
Я установил 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. Мой фактический размер данных штрих-кода (1D) составляет 12 байтов.
Что-то не так в коде или мне нужно добавить больше ядра, чтобы прочитать фактический код барда?
1 ответ
Я понял, что, поскольку он обнаруживает устройство HID с клавиатурой, полученные данные не будут иметь формат ASCII (что я и ожидал). Я изменил код в соответствии с https://www.win.tue.nl/~aeb/linux/kbd/scancodes-14.html
Несмотря на то, что в документе написано 16-битный код ключа, я получал правильные данные, только если прочитал 16 байтов. на основе кода ключа я создал таблицу, которая преобразует код ключа HID в ASCII.
Но все равно это не работает на моей машине с Windows, поскольку говорит, что не может открыть устройство.