Block Device driver read/write from user application - c

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.

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.

Can I change file permissions from within a program?

When writing a device driver, I use the function device_create(), which creates a file in /dev linked to the functions registered through fops.
The problem is, once I insmod this module, I can't fprintf to write to the /dev file. A page domain fault occurs. I can still write to a normal file, so I imagine that I don't have permission to write to the file in /dev. Is there anything I can do to set the file as writable within the kernel module while calling device_create() so I wouldn't need to externally set it?
If I read this right, you have a userspace program doing fopen + fprintf on a device file backed by your custom driver. On use, the kernel crashes.
First of all the use of FILE abstraction (given with fopen and fprintf) is extremely sketchy when applied to device drivers. Since it does internal buffering, you never know for sure what data actually hits the driver and in what chunks. Use the standard file descriptors directly instead (open + write).
Now, the suspicion that there is a permission problem cannot be right. If the open routine of your driver is reached, the kernel already determined you have necessary privileges. Similarly, if the write routine is reached the file was already opened, so we know you have permissions to use it. But even if there was a permission problem of some kind, a page domain fault is definitely not valid for the kernel to encounter in response.
Given the quality of the question I would argue you are too new to programming to play with this stuff and would recommend sticking to userspace for the time being.
Take a look at init/initramfs.c where there are sample uses of syscalls by the kernel. Include linux/syscalls.h and just use sys_chmod. It works like the userspace variant. This can be applied to pretty much any system call.(Not that it's a good idea to use socket in the kernel)

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.

Linux device driver for a RS232 device in embedded system

I have recently started learning to write Linux device drivers for a specific project that I am working on. Previously most of the work I have done has been with devices running no OS so Linux drivers and development is somewhat new to me.
For the project I am working on I have an embedded system running a Linux based operating system. I have an external device with is controlled via RS232 that I need to write a driver for.
Questions:
1) Is there a way to access serial ports from withing kernel space (and possibly use serial.h, serial_core.h, etc.), how is this usually done, any good examples?
2) From what I found it seems like it would be much easier to access the serial ports in user space by just opening dev/ttyS* and writing to it. When writing a driver for a device like this (RS232 device) is it preferred to do it in user space or is there a way to write a kernel module? How does one decide to write a driver as a kernel module over user space or vise versa?
Are drivers only for generic devices such as UART/serial and then above that is userspace or should this driver be written as a kernel module? I appreciate the help, I have been unable to find much information to answer my questions.
There are a few times when a module that communicates over a serial port may be in the kernel. The pppd (point to point protocol daemon) is one example as Linux has some kernel code devoted to that since it is a high traffic use of serial and it also needs to turn around and put the IP packets into kernel space.
Most other uses would work better from user space since you have a good API that already takes care of a lot of the errors that can happen. This also lessens the chance that your errors will result in massive system failure.
Doing things like this from user space does result in some latency. Reads and writes are buffered, and it's often difficult to tell where in the write operations the hardware actually is, and canceling an already succeeded write call isn't really doable from user space, even if the hardware hasn't yet received the bytes.
I would suggest attempting to do it from user space first and then move to OS driver if necessary. Even if it is necessary to move this into an OS level driver, you'll likely be able to get some progress made from user space.

Implementing a file descriptor

How would I go about implementing my own file descriptor?
Say if I have a kernel module controlling some hardware and I want to expose the ability to communicate with this hardware to the userspace via read() and write(). Don't want to use IOCTL or netlink or other userspace-kernelspace methods. Would I need to recompile the kernel or can I do it just by writing a kernel module.
I understand that creating the file descriptor will require a mechanism for userspace to tell the kernelspace to create an entry in the task's files struct (ie a function equivalent to open(), eventfd() timerfd(), socket()). That I can implement via IOCTL (so that I wont have to recompile the kernel), but how do I hack into read() and write() - I have patched them using LD_PRELOAD before, is that the only way? Don't want to recompile the kernel!
I am not sure I understand all of your questions. Nonetheless:
you can definitely have this as a kernel module;
you probably want to create a character device (second part of your question);
for the char device you can implement the system calls you need; if you only want to have read and write - no problem;
Look at the chapter three (and others) of this book.
konrad.kruczynski is right!
use a character device as the userspace mechanism to communicate with your hardware, and create a device in /dev filesystem such as /dev/hardware_type_A.
then compile && load your module in the kernel, then if all your code is good, then the kernel will create a character device in /dev/ with name /dev/hardware_type_A.
then you can use read, write, open, close calls just like you use with the other devices or the files to control your hardware.
IF you really say that you dont want to control it over ioctl, then you must need a new protocol that sends data using write and your driver unpacks that data and controls the hardware on behalf of your program in user.

Resources