read from a USB barcode scanner that simulates a keyboard
I have a USB barcode scanner that acts like a keyboard: whenever a barcode is read it sends the code where the keyboard would normally write. I would like to write some code (preferably in C) to modify this behavior and to be able to listen to the scanner from a program, just like I would read from a socket or a serial port for instance.
I am writing code to control a robot, the barcode scanner is used for localization. So I need the control code to be able to listen to the scanner. Maybe you don't know the solution but can give some ideas that would put me on the way. I have the feeling that I could use the ioctl function, but I am not familiar with the underlying concepts, and it's a pretty complex function. Thanks Brice National University of Singapore |
Maybe you could have a look at phidgets - these are usb devices for controlling and sensing various things. Lots of robotics applications. Anyway they have libraries in C, C#, VB and others, that you could look at the source of to see how they talk through the usb bus. There's sure to be a way to define a particular device (all devices are defined by a vendor:device identifier so can be specifically targeted) and to stop the keyboard driver from using it.
Phidgets are here: http://www.phidgets.com/index.php |
Hi
There was a similar thread, which had never received any answer. http://www.linuxquestions.org/questi...errerid=260969 So I posted the topic again here hoping I would get more chance (and I did, thanks bernied), but in the meantime I contacted this guy to see if he had managed to find a solution. Here is the answer he kindly gave me. I post it here for reference: They normally configure as a keyboard, though in Linux, by default, some of the COM ports may not be accessible. Add "8250.nr_uarts=8" to the end of your kernel line to have it configure past COM4.I am going to work on those two ideas, and post my results here. In the meantime, more suggestions are welcome. |
I managed to read from the USB barcode scanner using libhid. However I have the feeling that there should be some way to redirect whatever comes from that barcode to a file without using libhid. My ultimate goal is to redirect it to a FIFO (/dev/rtfX).
What MardukKurios (the guy I quoted in previous post) suggested sounds like a good idea, but unfortunately 8250.nr_uarts is not an option recognized by my kernel. However, this suggests that what I want to do should be possible. I've always thought that the main advantage of Linux is that everything is possible, provided that you have enough knowledge. Does anybody here has enough knowledge to help me? At least some ideas I could start with. PS: dmesg shows this usb 2-1: new full speed USB device using uhci_hcd and address 3 input: � Symbol Technologies, Inc, 2000 Symbol Bar Code Scanner as /class/input/input3 input: USB HID v1.10 Keyboard [� Symbol Technologies, Inc, 2000 Symbol Bar Code Scanner ] on usb-0000:00:1d.0-1 |
read from a USB barcode scanner that simulates a keyboard
Quote:
I am also facing the same problem using a usb device which simulates keyboard types. I am able to get the device information like (vendor name, product name etc.) using libhid. But I am facing problem in reading the output from the usb-device. it is simply sending the reads to the cursor location of the native terminal. As you solved this problem and able to read the usb device using libhid, could you please give me a guide or send me a sample code to me. my email id is dhrubajyoti.deka@gmail.com . Thanks in advance. Dhruba |
I am no longer using libusb/libhid, but I am using the input layer of the kernel instead. The idea is to read from the /dev/input/event device associated with your device. To know which /dev/input/event node is associated with my device, I open all of them, get vendor ID and product ID and compare. If you don't have /dev/input, you must enable it in your kernel.
Btw, I got all this information from Vojtech Pavlik, the guy who wrote the input layer of the kernel. I haven't found how to deal with capital letter though (shift key), and not all characters are in my conversion table... but that should get you started. Here is my code: Code:
#include <stdio.h> |
And here is some (older) code that uses libhid.
Code:
#include <stdio.h> |
Thanks a lot!!!
Quote:
Thanks a lot!!! your idea really worked. Its amazing. Thanks a lot... Dhruba |
Quote:
Hi.. Thank a lot pls can you help where exactly i need to insert this code to read from barcode scanner? |
in main() call initScanner once and then call readScanner in a loop.
|
Hi,
Thanks a lot..I have done the changes already...your code and explanation really helped me....thanks a lot again.... Please can you help me ..Now my problem is how to detect the device when it is inserted or removed. Becuase once i remove the device and if i insert again new event is assigned to the device. Please can you help me how to detect device of it is insertion and removal? |
An idea would be to detect when device is removed as when a reading error occurs. Then you would have to call initialize() again, which will scan the devices again to find your scanner.
|
Little Changes And Run Ok!
#include <stdio.h>
#include <string.h> #include <dirent.h> #include <fcntl.h> #include <unistd.h> #include <linux/input.h> #include <stdlib.h> #define VENDORID 0xc2e #define PRODUCTID 0x200 #define SCN_BCD_SZ 15 int scan_fd = -1; int initScanner(){ int count; char path[32]; struct dirent **files; struct input_id id; printf("Inicializa \n"); count = scandir("/dev/input", &files, NULL, alphasort); printf("Archivos: %i \n", count); while( count>0 ){ count--; if( scan_fd==-1 && strncmp(files[count]->d_name,"event",5)==0 ){ sprintf(path,"/dev/input/%s",files[count]->d_name); scan_fd = open(path,O_RDONLY); if( scan_fd>=0 ){ if( ioctl(scan_fd,EVIOCGID,(void *)&id)<0 ) perror("ioctl EVIOCGID"); else{ if( id.vendor==VENDORID && id.product==PRODUCTID ) printf("scanner attached to %s\n",path); else{ close(scan_fd); scan_fd = -1; } } } else{ fprintf(stderr,"Error opening %s",path); perror(""); } } free(files[count--]); } free(files); if( scan_fd>=0 ) ioctl(scan_fd,EVIOCGRAB); else{ printf("scanner not found or couldn't be opened\n"); return 0;} return 1; } int closeScanner(){ close(scan_fd); scan_fd = -1; return 1; } char keycodelist(int scancode){ char ret = '-'; //return (unsigned char)scancode; switch(scancode){ case 0x02: ret ='1';break; case 0x03: ret ='2';break; case 0x04: ret ='3';break; case 0x05: ret ='4';break; case 0x06: ret ='5';break; case 0x07: ret ='6';break; case 0x08: ret ='7';break; case 0x09: ret ='8';break; case 0x0a: ret ='9';break; case 0x0b: ret ='0';break; case 0x0c: ret ='-';break; case 0x10: ret ='q';break; case 0x11: ret ='w';break; case 0x12: ret ='e';break; case 0x13: ret ='r';break; case 0x14: ret ='t';break; case 0x15: ret ='y';break; case 0x16: ret ='u';break; case 0x17: ret ='i';break; case 0x18: ret ='o';break; case 0x19: ret ='p';break; case 0x1e: ret ='a';break; case 0x1f: ret ='s';break; case 0x20: ret ='d';break; case 0x21: ret ='f';break; case 0x22: ret ='g';break; case 0x23: ret ='h';break; case 0x24: ret ='j';break; case 0x25: ret ='k';break; case 0x26: ret ='l';break; case 0x2c: ret ='z';break; case 0x2d: ret ='x';break; case 0x2e: ret ='c';break; case 0x2f: ret ='v';break; case 0x30: ret ='b';break; case 0x31: ret ='n';break; case 0x32: ret ='m';break; default: break; } return ret; } //read a barcode from the scanner. //reads as long as *loopcond!=0 (if loopcond is NULL then read //forever). If termination condition is met, returns NULL. //read all characters from barcode untill we read 0x28 (carriage //return). char* readScanner(int *loopcond){ static char barcode[SCN_BCD_SZ]; char code[SCN_BCD_SZ]; int i=0; struct input_event ev; while( loopcond==NULL?1:*loopcond ){ read(scan_fd,&ev,sizeof(struct input_event)); if( ev.type==1 && ev.value==1 ){ if( ev.code==28 ){ //carriage return //printf("Carriage Return Read \n"); code[i] = 0; strcpy(barcode,code); return barcode; } else{ if( ev.code!=0 ){ code[i++] = keycodelist(ev.code); //printf("Char: %i-%i \n", keycodelist(ev.code), ev.code); if( i==SCN_BCD_SZ-1 ){ printf("Barcode buffer full\n"); return NULL;} } } } } return NULL; } main(){ initScanner(); printf("Escaner Ok \n"); while(1){ printf("%s \n", readScanner(NULL)); printf("Sigiente Código... \n"); } } |
All times are GMT -5. The time now is 07:40 PM. |