Turning off (or otherwise manipulating) the LCD in Linux - c

I just tried the "2. Starting Steps" section on this page as my first code interacting with devices in Linux. I was curious to know if same things can be done with the display, and if so, how. I only know so much about ioctl() and I don't know if it applies here, and I'm not sure if the device is available in /dev or, rather say, not sure if all the things I'm getting from the example from the link are really relevant here. Where should I begin?
Just to be more clear about what I'm after, as an example to start with, I would like to write a code which would turn the display off and wait for a moment and turn it back on. Hints?

That varies greatly on the device. Generally, there will be a kernel module for the device, sometimes the single module can support many devices. You can look at the source code to see the ioctl handler. You can find the file_operations structure in the driver and look at the function in the ioctl position. There you can see what parameters an ioctl command on the device driver will do.
There's no guarantee that ioctl will do anything. The kernel drivers can be implemented in many different ways. But for turning off an LCD screen, ioctl sounds very likely.
I think what you first need to find out is what kernel module supports the device. Then you need to make sure a device file exists for it. You can create the device file using the mknod command. After that, you should look through the module's source (probably the header is most relevant), to see what ioctl command you need to use to turn the LCD backlight on and off.

Related

Is accessing a device driver in Linux only possible using its device file?

Let's say I have a webcam, and I installed the device driver for this webcam in my Linux OS, now a device file will be created for the device driver (for example: /dev/video0).
Now say I want to create a program in C that wants to access this webcam. How can my program access the device driver for the webcam, should my program use the device file (/dev/video0) to access the device driver, or is there another way?
You asked a general question, and then gave a specific example. I'll try to address both.
When you load a driver, the way to communicate with it from user space is by whatever means this driver defined. Typically, this is through a /dev device created for the driver. If that's the case, yes, that's the only way to communicate with it.
This is not universally true. Many drivers also have entries under the /sys sysfs pseudo file system, and some aspects can be modified through there. In fact, there are whole classes of drivers that are only accessible through the /sys fs. Prominent examples are GPIO and Led devices, that can be turned on and off via access to /sys/class/gpio and similar paths.
Another option, considered deprecated but still sometimes used, is to use the /proc pseudo file system. Again, this is up to the driver to define its communication method. As the user, you will have to follow whatever protocol the driver defined.
Also, some drivers don't have any file system presence at all. The most obvious standard example are network interfaces. The only way to communicate with them is via the networking system calls.
In the particular example you provided, you talked about a video camera that appears as /dev/video0. Such a camera is, usually, a Video4Linux (or v4l) camera, and those are accessed via their character devices.
With that said, the protocol for communicating with the camera might have wrappers that makes life easier. If you open the actual device, you might have to implement a rather complicated handshake with it. Instead, you can use the v4l library to wrap the details of the access.
Make no mistake. You're still talking to the character device in /dev. It's just that it's not your code that does it, but the library's.

Writing a FreeBSD kernel module that handles arbitrary interrupt and output to device

I would like to write a FreeBSD kernel module that could accept some arbitrary interrupts and upon receiving these interrupt, output some data to an arbitrary device. Currently, I'm facing several issues:
How would I acquire interrupts through a specific IRQ? On Linux there is the request_irq() call but it seems there's no similar API for FreeBSD... Say, I want to be able to detect all the keyboard interrupt through my kernel module (the keyboard is on irq1), how would I do that? (On Linux it is possible through calling free_irq(1, NULL) and request_irq(1, ...), correct me if I'm wrong though).
Is it possible at all to write to a device file under /dev through a kernel module? I've read the question Example for reading text files in FreeBSD kernel module; following this example I was able to do read/write on regular files, but not a device file under /dev (the "device" was a pseudo "echo device", the classical one used in char device examples). I was able to open the file though.
I do understand that it is considered as a bad practice to do file I/O's in kernel, but I could not think any other way... If anyone has a better solution please tell me. (i.e. write to a device through its device_t node?)
The reason I was doing this in a kernel is that I really need all interrupts to be hit, and running it in the user space has the risk of missing interrupts due to kernel threads preempting user threads (the interrupts could come very frequent).
I would also appreciate if anyone could provide me with some other ideas on how to implement this program (basically, the idea is a kernel module that could do the job of a microcontroller...)
You can register an IRQ handler with bus_setup_intr.
Normally, what one would do in this situation is to have a driver collect the interrupts and any other useful data, and export it through a device, and then a (real-time maybe?) process in user-space can read from one device, do whatever it needs to do, and write to the other device.

How to enumerate USB devices *and* read/write to them?

There is a custom USB device I need to communicate with. There is no particular driver for it. The device doesn't show as /dev/tty*.
I found out how I can use libudev to enumerate the USB devices and let's say I manage to get the corresponding struct udev_device.
What I can't figure out is how I can open(2) the device so I can write(2) to and read(2) from it.
Is it possible to communicate with a generic USB device, setting baudrate and just read/write? If so, what "file" should I open after I find the device with libudev? If not, is writing a kernel-level driver necessary?
libusb is an ideal choice. There are also several examples for such a case as you described.
In your case, you just need to:
Create a default context.
Request the device list.
Search for the device with the desired vendor/product ID.
Open the device, and then communicate via synchronous or asynchronous I/O calls.
Clean up the requested device list.
When done, close off the device handle and destroy the context.
This allows you to write a userspace application/library with relative ease. I've used it with microphones, cameras, and DIY hardware (mini assembly line devices I've built) with considerable success. The devs on the mailing list are also very helpful, though one or two fellows tend to be somewhat caustic to new members if their posts aren't perfectly written.

Block Device driver read/write from user application

I am trying to implement "simple file-system" for my personal experience. For this, I have created a block device driver with which I will perform read/write operations in unit of blocks. Now my question is how should I perform open, read, write and close operation on the block device from the user application.
What I am actually looking for is a function with which I can open the block device /dev/sbd and it returns the struct block_device, if successful. And for the read/write functions, I can issue request to block device struct request with parameters as "buffer, sectore_number, numbe_of_sectors".
Till now I only got block_read() and block_write() functions. But it seems that they are BSD specific. And I am using Debain.
Anyone having idea about it?
Thanks.
I've been doing something similar writing a application level file system that works with files or devices. What you are writing is not really a device driver as device drivers are directly handled/used by the kernel. A user application has no way to access one directly. Regardless, I want to point you to the function calls open(2), read(2), write(2), close(2) (manual page section 2 for all of them). You will need the unistd.h header file to use these. You can set your read/write size as a multiple of your block size when calling read and write. But in the end, you are still going through the kernel.
EDIT: Upon further examination and comments, the device driver really is in the kernel. Normally, there is no direct connection between a driver and an application as there are several layers of code within the kernel to abstract the device so it looks the same like everything else to the application.
There are two ways around this. One is to establish one or more system calls in the system call tree to expose the read/write routines of the device driver to the application. Another idea that I had was to use the ioctl (I/O Control) system call to perform this, but this call is meant to control the actual device. For example, the hard disk uses read and write commands to transfer data, but to talk to the hard drive to get information about it, such as what the last LBA is or get its identity, you would use IOCTL to do that.
Hope this helps.

Detect certain connected USB device

I'm working with a USB device in Linux and have written a library to control this device.
Without going in to TOO many details, the device uses a standard UART protocol, so all I have to do is open a serial connection with open, configure the relevant parameters like baud rate, stop bit, parity, etc, etc, and start bit-banging registers.
The library works fine, however, it its hard coded to assume that this device is /dev/ttyUSB0. That is, this is what I pass to open. If open fails, I exit.
What I would like to do is detect that this device is present, regardless if it's /dev/ttyUSB0, /dev/ttyUSB1, etc. And even detect if there are multiple of these devices connected.
I can write code to poll certain registers on the device that will return serial number, product ID, etc, so I can detect that what is on the other end of the USB is indeed my device... but how can I find a list of connected USB devices, again, in native C?
OR is there a more elegant way of doing this, such as interfacing with it's kernel module, or something? I can provide the USB driver it actually uses, but I'm sort of lost when looking through the code.
Thanks for any insight.
The elegant method is to use udev to create a descriptive symlink for your device when it is connected. Add a line something like this to /etc/udev/rules.d
SUBSYSTEM=="tty",ENV{ID_MODEL}=="My_FlowMeter_Model",ENV{ID_USB_INTERFACE_NUM}=="00",SYMLINK+="flowmeter",RUN+="/bin/su pi -c /home/pi/record-flowmeter.sh
That's a very slightly modified version of an actual udev rule my research group uses to collect data from USB devices connected to battery-powered Raspberry Pi boxes. It also runs a script automatically, which has commands like
stty -F /dev/flowmeter 500000 -ixon -echo -icanon
If you want to know the "real" device filename, you could do readlink /dev/flowmeter. But for most uses you can just use the link: fd = open("/dev/flowmeter"); (or pass it as an argument to your program)
Naturally you should replace flowmeter with a short name for your own device, as well as updating the ID_MODEL based on the output from lsusb.
Multiple devices are a bit more complicated, but there are plenty of examples of udev rules out there.
On Linux, the information you are looking for is in the /sys filesystem, specifically under /sys/bus/usb/devices. From there you will need to search the filesystem to find your device.
For example, I just plugged a USB-serial dongle into my Linux (kernel version 2.6.35) and the device appeared under /sys/bus/usb/devices/2.1-8. Here, I am able to find that this is my device by vendorId:deviceId by checking the files idVendor and idProduct. Here, there is a directory named 2.1-8:1:0 which contains a directory named ttyUSB0.
Obviously, to find your device you will need code (or a shell script using find) to scan the directory tree, looking for the right entries.

Resources