13
votes

Hello Linux Kernel Driver Gurus!

I'm writing a v4l2 driver for a camera that uses a serial interface for configuration. I'd like the driver to configure the camera, as it keeps the client code consistent across camera models. The question is: what's the best way to access the camera's serial interface from the driver module?

From what I hear, accessing files from a kernel driver is a big no-no, but it can be done. As such, I'm currently using the following code snippet, but it feels like a hack.

oldfs = get_fs();
set_fs(KERNEL_DS);

fd->f_pos=0;
fd->f_op->write(fd, data, data_len, &fd->f_pos);

set_fs(oldfs);

My question is really: what's the right way to do this?

2

2 Answers

5
votes

I presume that since a serial port is involved, this must be some kind of embedded system. After all, not many PCs even have serial ports. I also assume that the serial port can be considered a permanent connection, at least from the user's perspective. If that is all true, then you don't really want a TTY device. You want to access the device as a private UART.

If you have a look at the Wolfson audio codecs (sound/soc/wm*.c) you will see an example of devices that primarily communicate over I2S but have an auxiliary I2C interface for configuration. This is conceptually what you want, I believe. The driver presents a unified interface to software, and issues commands to whatever hardware is appropriate. Obviously this is much cleaner than having to expose hardware implementation details to userspace.

I couldn't find a good example of a UART driver in the kernel that works this way, but hopefully I've described what to look for. From a practical rather than technical purity point of view, it might just be better to do file I/O from the kernel.

2
votes

First I would advise you to find a way to do this from the userspace if possible: what you try to achieve here really is userspace code in kernel code.

But if you don't find a way to do it, this article shows you how to do userspace calls in kernelspace.

Since you want to access a serial port, you should have calls that tty oriented, for instance for open:

serial_fd = sys_open("/dev/ttyS0",  O_RDWR | O_NOCTTY | O_NONBLOCK))