I have recently bought an 2D barcode scanner module from china. As per their datasheet, it worked fine scanning barcodes when I open a notepad. All i need to do is try using libusb and read the barcode on my c code. I use Intel edison with Adrunio breakout board which is configured as usb host.
I have installed libusb-1.0.20 and unfortunately I couldn't install libusb-1.0.20-devel. Please note I am not using libusbx and libusbx-devel here.
As it is bardcode scanner device, it was supposed to get detected as HID keyboard. Yes it was.
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
And my c code is:
#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;
}
I could able to compile and run the code, scan, open, read the device. But the data what I could read is all zero. Even though it says wMaxPacketSize 0x0008 1x 8 bytes
and bLength 18
it gave me error when I tried with length as 8,16,18. So I changed to 24. My actual barcode (1D) data size is 12bytes.
Is it something wrong on the code or should I need to add more core to read the actual bardcode.
I understood that since it detects as a HID keyboard device, the data which I had received will not be in ASCII format(which is what I was expecting). I have modified the code according to https://www.win.tue.nl/~aeb/linux/kbd/scancodes-14.html
Even though the document says 16-bit keycode, I was getting correct data only if I read 16 bytes. based on the keycode, I have created a table which converts HID keycode to ASCII.
But still this doesn't works on my Windows machine, as it says it cannot open the device.