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, поскольку говорит, что не может открыть устройство.

Другие вопросы по тегам