I have barcode scanner, attached to Linux computer via USB. The scanner emulates a keyboard device.
I have to write a program that to read the scanned barcodes and process them. The program runs on background as a service and should read the barcode scanner regardless of the current X focus.
How this can be made in Linux?
Some lower level solution/explanation is preferred.
It sounds like you want to capture the data from a specified device,
In which case the method described in this post should help:
(EDIT: original link dead, Archive link provided)
https://web.archive.org/web/20190101053530/http://www.thelinuxdaily.com/2010/05/grab-raw-keyboard-input-from-event-device-node-devinputevent/
That will listen out for keyboard events stemming from only the specified source.
A word of caution though, as far as I know, that won't stop it from propagating to whatever your current window focus is.
To start with solution, I guess a daemon would perfect choice.
You can write a daemon code, which will open device node (for scanner) and read the data buffer.
Now you have received data in user space, you are free to handle it as per your requirement.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm making a Command-Line Operating system (command line interpreter). How to I get a line of input from the user?
I'm making a Command-Line Operating system. How to I get a line of input form a user?
The first things you'll need are some boot code (to get things like a memory map from firmware), physical memory management, virtual memory management, a scheduler and some kind of inter-process communication (IPC).
The next things you'll need is some kind of device enumeration framework, to help make a tree of devices to keep track of everything; followed by scanning PCI buses to add them to the tree of devices.
Next you'll want to tackle device resources - determining IO port ranges, memory mapped IO ranges and managing IRQs. This can be messy (e.g. AML interpreter for ACPI to determine IO APIC inputs, and "interrupt vector allocator" to handle MSI).
The next thing is USB controller drivers, USB hub driver and maybe (for obsolete hardware) a PS/2 controller driver. These all find devices connected to them (e.g. USB keyboard) and add them to the tree of devices, and then communicate with the drivers for those devices. At some point you might also want to worry about fault tolerance, power management and hot-plug (e.g. if a USB controller driver crashes, is put to sleep or is removed/unplugged; then you'd use the "tree of devices" to figure out which other drivers are effected).
Next, you'll want keyboard drivers. Specifically, a driver for "USB HID" (which is a single specification that covers all human input devices - keyboard, mouse, touchpad, joystick, ..), and maybe (for obsolete hardware) a PS/2 keyboard driver. Note that you'll probably also want an on-screen keyboard for touch-screen users, and input method editor/s to assist with input of some languages (Chinese, Japanese, Korean, etc).
Next, you'll want something for video output. Typically early boot code uses minimal "just enough to display boot log" code (if it's not hidden by a pretty splash image); but you'll want something that's actually good instead (likely including a font engine with Unicode support).
The end result of all of the above is that you'll have a set of (hopefully "standardised for your OS" and documented) device driver interfaces and all of the things that device drivers depend on; a way (the inter-process communication I mentioned near the start) to send "events" (key-presses) to a process and a way for processes to display output (draw things on the screen).
Once all that is done you can write a terminal emulation layer. This is a thing (process?) that hides all the nice modern stuff (e.g. OpenGL, events) under a layer of historic memorabilia (so that the end user's computer, which is likely to be capable of emulating realistic virtual reality environments, can be used as a glorified teleprinter from early last century). This also uses the inter-process communication I mentioned near the start (e.g. maybe pipes - stdin, stdout) to communicate with a child process.
Finally, you can begin writing some sort of command shell. This is just a process that communicates with its parent (e.g. with the terminal emulation layer) via. whatever you're using for inter-process communication (e.g. stdin, stdout) that allows users to start other processes and handles a little "forwarding" (e.g. while a child process is running, keyboard input that shell receives from terminal emulation layer gets forwarded by shell to its child process, and output the shell receives from its child gets forwarded by shell back to shell's parent/terminal emulator).
Note that as part of writing the command shell, or before writing the command shell, you might want to write some libraries to handle simple chores (e.g. getting a whole line of user input and handling things like "home", "end", "delete", "backspace", etc) so that these libraries can be used by all programs including the command shell itself.
It seems doubtful that you are truly implementing an operating system, but if you simply mean a command shell, then it might follow the following structure:
int main()
{
char command_line[1024] ;
char* input = NULL ;
int errorlevel = 0 ;
do
{
// Show command prompt
putchar( '>' ) ;
fflush( stdout ) ;
// Get command line
input = fgets( command_line, stdin, sizeof(command_line) ) ;
if( input != NULL )
{
// Process command line
errorlevel = parseCommand( input, &errorlevel ) ;
}
} while( input != NULL ) ;
return errorlevel ;
}
where parse parseCommand() is a function with the following interface:
int parseCommand( const char* cmd_line, const int* current_errorlevel ) ;
Here the answer to your question of how to get a line of user input is the fgets() function.
The complex part perhaps is in the implementation of parseCommand(); user input is the easy part, but make a start - have fun.
Unlike everyone I appreciate you thinking big but focus on the basics first as it is good to start small. Also, what you are doing is making a command line interpreter and not an OS. There's a big difference between the two. For an OS, you need a kernel, GUI, etc. However here's the solution to your query:
You can use gets, but you might receive a warning in this one
char *gets(char *str)
To overcome above limitation, we can use fgets as :
char *fgets(char *str, int size, FILE *stream)
Using %[^\n]%*c inside scanf
scanf(ā%[^\n]%*cā, str);
This one comes quite in handy when using for loop.
You have a bright future if you think innovatively (people lack this).
But it's always better to brush your base before going big. Welcome to stackoverflow :)
I'm trying to write a Linux daemon that needs to take input from a keyboard-like (HID) device - it's not the console keyboard, but a second device (it's actually a 1D barcode scanner if it makes any difference). The daemon will process the data it receives ("keystrokes" from alphanumeric barcodes).
I know the daemon can use ioctl(EVIOCGRAB) to grab that device from /dev/input/eventx and then read() events (struct input_event from <linux/input.h>), that works, but it's too low level for my needs. I don't need to know about every up and down key event and I would rather not have to decode/handle simultaneous keys, i.e. I don't want to know KEY_DOWN+KEY_RTSHIFT, KEY_DOWN+KEY_A, KEY_UP+KEY_RTSHIFT, KEY_UP+KEY_A, I just want to receive "A".
Using the input events needs a whole pile of extra code to be written, just to get "A" out of it - and that seems a waste of time and effort when there are almost certainly existing keyboard handlers (or something like that) that will do a far better job than me hacking code together - I just can't find them!
Is there any way to put an existing layer of (keyboard?) software onto /dev/input/eventx that the daemon can then exclusively read a stream of simple ascii from?
For this device, /proc/bus/input/devices reports ...
H: Handlers=sysrq kbd leds event9
... which might suggest that something has already put a "kbd" layer on it, but how to access it?
If I don't EVIOCGRAB, then when I scan a barcode I see syslogs about "failed login on /dev/tty1", so that keyboard input is clearly trying to login to a terminal/shell somewhere :-/ (There's no X, desktop etc on this machine either.)
I am not aware of such library or daemon.
However, writing a daemon to do exactly that is not nearly as hard as you think. In my opinion/experience, if you do not need to implement autorepeat (that is, only do autorepeat if the keyboard-like device sends autorepeat keypresses), the daemon is surprisingly simple.
In particular, the main loop is just a blocking read followed by zero or more blocking writes, with an array look-up in the middle.
You can use either a named pipe (in which case you open the pipe before opening the device, because the open succeeds only after another process opens the named pipe or FIFO for reading), or a socket; either Unix Domain socket, or a TCP or UDP socket (on the loopback interface). I'd probably use a named pipe, /var/run/barcode-scanner.
I would use a separate configuration file for the input mapping, and I'd support the preprocessor macro names (KEY_) from /usr/include/linux/input-event-codes.h, parsed to an array using a helper awk script. The key mapping file would probably live in /etc/barcode-scanner/keymap, and contain definitions similar to
KEY_1 = 1
KEY_NUMERIC_1 = 1
KEY_E = e
shift KEY_E = E
ctrl KEY_E = \5
altgr KEY_E = ā¬
KEY_UP = \033[A
and so on. Events not listed in the definition file would be ignored or optionally logged.
You can use an array, because there are up to 768 (0 to KEY_MAX, inclusive; although 0 is KEY_RESERVED) different keyboard events; as a two-dimensional array, you'll probably want something like 16 arrays, for supporting all kombinations of Shift, Ctrl, Alt, and AltGr (or right alt key), when each key is pressed. Internally, you'll just need to handle KEY_LEFTSHIFT, KEY_RIGHTSHIFT, KEY_CAPSLOCK (to manage the shift state); KEY_LEFTALT (to manage the alt state); KEY_RIGHTALT (to manage the altgr state); and KEY_LEFTCTRL and KEY_RIGHTCTRL (to manage the ctrl state). If you use a bit mask to indicate the current states, you can use it as an index to the outer dimension of the lookup array. It really is very straightforward.
Note that each array element is then a string, that is emitted when a key of that state is pressed (ev.value == 1 for keypress, ev.value == 2 for autorepeat). Aside from the above special keys, you do not need to handle key releases at all.
Hm. I wonder if there are others who would need such a daemon? Would you use a GPL3-licensed one, if the sources were at GitHub?
The libevdev library is not exactly what you ask for. But it is widely used (e.g. by the Xorg server evdev and libinput drivers).
As state on the home page:
libevdev is essentially a read(2) on steroids for /dev/input/eventX devices.
It manages ioctl calls for you, handles an events queue, etc.
One additional feature you didn't ask for, but it is really helpful: it can handles events from multiple devices at once. It allows you to listen on multiple devices located in /dev/input and handle the same event type in a single thread.
I have to write a linux kernel module, which change character printed on the screen after pressing a key (let's say - I want 'a' to be printed when I press 'b' on keyboard). What is the best way to do it? I'he thought that good idea is to create module for keyboard. I did some research, i saw few keyloggers (as kernel modules) but all of them where able only to listen what key was pressed, and any change of scancode was imposible (which is pretty obvious in keyloggers). I read 3rd chapter from Linux Device Drivers, and i started to read 6th, but they are talking only about virtual devices, when i want to connect my module with the real device. I saw also this https://stackoverflow.com/questions/33836541/linux-kernel-how-to-capture-a-key-press-and-replace-it-with-another-key, but it wasn't working. My teacher said there is much eaysier way than using interrupts, but I have no idea how to do it (neither using interrupts and any other way).
What should I do? just read next chapters of LDD? Or any other book? Or maybe just lie down and cry?
Here's a very simple example of keyboard driver kernel module: https://github.com/raleighlittles/Olympus-MAJ-1428-Keyboard-Linux-driver/blob/main/hid-olympus-maj1428.c
I had a keyboard that generated weird scancodes for certain non-character keys (read the file, it explains more). Instead of using those scancodes, I wrote code to remap them to the extended function keys (F13, F14, etc.). You could use the code and instead simply switch the scan codes that you want by changing the key_mapping variable.
I have been playing with creating sounds using mathematical wave functions in C. The next step in my project is getting user input from a MIDI keyboard controller in order to modulate the waves to different pitches.
My first notion was that this would be relatively simple and that Linux, being Linux, would allow me to read the raw data stream from my device like I would any other file.
However, research overwhelmingly advises that I write a device driver for the MIDI controller. The general idea is that even though the device file may be present, the kernel will not know what system calls to execute when my application calls functions like read() and write().
Despite these warnings, I did an experiment. I plugged in the MIDI controller and cat'ed the "/dev/midi1" device file. A steady stream of null characters appeared, and when I pressed a key on the MIDI controller several bytes appeared corresponding to the expected Message Chunks that a MIDI device should output. MIDI Protocol Info
So my questions are:
Why does the cat'ed stream behave this way?
Does this mean that there is a plug and play device driver already installed on my system?
Should I still go ahead and write a device driver, or can I get away with reading it like a file?
Thank you in advanced for sharing your wisdom in these areas.
Why does the cat'ed stream behave this way?
Because that is presumably the raw MIDI data that is being received by the controller. The null bytes are probably some sort of sync tick.
Does this mean that there is a plug and play device driver already installed on my system?
Yes.
However, research overwhelmingly advises that I write a device driver for the MIDI controller. The general idea is that even though the device file may be present, the kernel will not know what system calls to execute when my application calls functions like read() and write().
<...>
Should I still go ahead and write a device driver, or can I get away with reading it like a file?
I'm not sure what you're reading or how you're coming to this conclusion, but it's wrong. :) You've already got a perfectly good driver installed for your MIDI controller -- go ahead and use it!
Are you sure you are reading NUL bytes? And not 0xf8 bytes? Because 0xf8 is the MIDI time tick status and is usually sent periodically to keep the instruments in sync. Try reading the device using od:
od -vtx1 /dev/midi1
If you're seeing a bunch of 0xf8, it's okay. If you don't need the tempo information sent by your MIDI controller, either disable it on your controller or ignore those 0xf8 status bytes.
Also, for MIDI, keep in mind that the current MIDI status is usually sent once (to save on bytes) and then the payload bytes follow for as long as needed. For example, the pitch bend status is byte 0xeK (where K is the channel number, i.e. 0 to 15) and its payload is 7 bits of the least significant byte followed by 7 bits of the most significant bytes. Thus, maybe you got a weird controller and you're seeing only repeated payloads of some status, but any controller that's not stupid won't repeat what it doesn't need to.
Now for the driver: have a look at dmesg when you plug in your MIDI controller. Now if your OSS /dev/midi1 appears when you plug in your device (udev is doing this job), and dmesg doesn't shoot any error, you don't need anything else. The MIDI protocol is yet-another-serial-protocol that has a fixed baudrate and transmits/receives bytes. There's nothing complicated about that... just read from or write to the device and you're done.
The only issue is that queuing at some place could result in bad audio latency (if you're using the MIDI commands to control live audio, which I believe is what you're doing). It seems like those devices are mostly made for system exclusive messages, that is, for example, downloading some patch/preset for a synthesizer online and uploading it to the device using MIDI. Latency doesn't really matter in this situation.
Also have a look at the ALSA way of playing with MIDI on Linux.
If you are not developing a new MIDI controller hardware, you shouldn't worry about writing a driver for it. It's the user's concern installing their hardware, and the vendor's obligation to supply the drivers.
Under Linux, you just read the file. Now to interpret and make useful things with the data.
I have a encoder which encodes a speech file(.wav) that i give as input. Now what i want to do is to write a program such that i can speak in the mic and at the same time the encoder can process it. Basically i want to record and process a speech signal in real time (a small delay can be tolerated). To do this i was thinking of making a loop inside which i would first record the speech for say 1 sec in a file say speech.in, then i would copy this file to temp and pass this temp to the encoder. In the meantime the recorder should overwrite the speech.in file and save the next 1 sec of data in it.And continue this loop...
The problem i am having is i cant write a program to control the recorder to do the thing i want. Is there any recorder which can be easily controlled or any code to do it ?
This is the only way i could think of to implement this. Any other(hopefully better) solution is also welcome.
*edit: I am working on Ubuntu 10.04 but i have used the same program on windows as well so any suggestion on either platform is welcome
Your proposed way is not the way to go. At least, this is not how it's done on Windows and Mac. (I don't know how linux flavoured machines would do it but I'm guessing the methodology is the same)
You'll have to open the audio device, and allocate a set of (say 4) internal memorybuffers (length of 100ms sound would suffice, but you'll have to experiment how small you can get the buffer (the smaller, the less latency, but the more chances on audio glitches)).
You attach these to the audio device and ask for a callback when any of these buffers are filled. When you get the first call back, make sure you encode the buffer quickly enough before the 1st buffer is used again by the audiodevice and is overwritten with new data.
You could simultaneously output the encoded sound to the audiodevice again. The latency would be similar to the length of 1 of the buffers.
Sounds like this would be best served by threading.
Here is a MSDN link