Writing a Linux Driver

The main goal of this article is to learn what a driver is, how to implement a driver for Linux and how to integrate it into the operating system—an article for the experienced C programmer.
An Actual Example of a Driver

The first question we answer is: why use Linux as an example of how to write a driver? The answer is twofold: all the source files are available in Linux, and I have a working example at my lab in UPM-DISAM, Spain.

However, both the directory structure and the driver interface with the kernel are OS dependent. Indeed small changes may appear from one version or release to the next. For example, several things changed from Linux 1.2.x to Linux 2.0.x, such as the prototypes of the driver functions, the kernel configuration method and the Makefiles for kernel compilation.

The device we have selected for our explanation is the MRV-4 Mobile Robot from the U.S. company Denning-Brach International Robotics. Although the robot uses a PC with a specific board for hardware interfacing (a motor/sonar card), the company does not supply a driver for Linux. Nevertheless, all the source files of the software, which control the robot through the motor/sonar card, are available in C language for MS-DOS. The solution is to write a driver for Linux. In the example, we use kernel release 2.0.24, although it will also work in later versions with few modifications.

The mobile platform is composed of a set of wheels coupled with two motors (the drive and the steer), a set of 24 sonars which act as proximity sensors for obstacle detection and a set of bumpers which detect collisions. We need to implement a driver with, at least, the following services (init, open and release are mandatory):

  • write: to send linear and angular velocity commands

  • read: to read sonar measures and encoder values

  • three interrupt handlers: to store sonar measures when a sonar echo is received, to implement an emergency stop when a bumper detects a collision and to stop the steer motor when the wheels are located at 0 (zero) degrees and a go to home flag is active

  • ioctl commands: go to home which sends a constant angular velocity to the wheels and activates the go to home flag; and configuration of motors and sonars

The go to home service allows the user to stop the wheels at an initial position which is always the same (0 degrees). The incoming values from sonars and encoders, as well as the velocity commands, might be part of the main loop of the control program of the robot.

Returning to the initial scheme (Figure 1), the device is the MRV-4 robot, the hardware interface is the motor/sonar card, the source file of the driver will be mrv4.c, the new kernel we will generate will be vmlinuz, the user program for kernel testing will be mrv4test.c and the device will be /dev/mrv4 (see Figure 6).

Figure 6. mrv4hard MRV-4 Scheme

General Programming Considerations

To build a driver, these are the steps to follow:

  1. Program the driver source files, giving special attention to the kernel interface.

  2. Integrate the driver into the kernel, including in the kernel source calls to the driver functions.

  3. Configure and compile the new kernel.

  4. Test the driver, writing a user program.

The directory structure of the Linux source files can be described as follows: the /usr/src contains subdirectories such as /xview and /linux. Inside the /linux directory, the different parts of the kernel are classified into subdirectories: init, kernel, ipc, drivers, etc. The directory /usr/src/linux/drivers/ contains the driver sources, classified into categories such as block, char, net, etc.

Another interesting directory is /usr/include, where the main header files, such as stdio.h, are located. It contains two special subdirectories:

  • /usr/include/system/, which includes system header files, such as types.h

  • /usr/include/linux/, which includes the Linux kernel headers such as lp.h, serial.h, mem.h and mrv4.h.

The first task when programming the source files of a driver is to select a name to identify it uniquely, such as hd, sd, fd, lp, etc. In our case we decided to use mrv4. Our driver is going to be a character driver, so we will write the source into the file /usr/src/linux/drivers/char/mrv4.c, and its header into /usr/include/linux/mrv4.h.

The second task is to implement the driver I/O functions. In our case, mrv4_open(), mrv4_read(), mrv4_write(), mrv4_ioctl() and mrv4_release().

Special care must be taken when programming the driver because of the following limitations:

  • Standard library functions are not available.

  • Some floating-point operations are not available.

  • Stack size is limited.

  • It is not possible to wait for events, because the kernel, and so all the processes, are stopped.

The OS functions supported at kernel level are, of course, only those functions programmed inside it:

  • kmalloc(), kfree(): memory management

  • cli(), sti(): enable/disable interrupts

  • add_timer(), init_timer(), del_timer(): timing management

  • request_irq(), free_irq(): irq management

  • inb_p(), outb_p(): port management

  • memcpy_*fs(): data management

  • printk(): input/output

  • register_*dev(), unregister_*dev(): device management

  • *sleep_on(), wake_up*(): process management

Detailed information on these functions is given in Johnson's Guide (see Resources) or even inside the kernel source files.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

I like this one

Anonymous's picture

Good introduction, I think, for those who is not familiar with Linux drivers at all.
Thanks a lot to the author. I enjoyed the article.

This article twice uses the

Anonymous's picture

This article twice uses the term "protected mode" where it should be using the term "supervisor mode".

Protected mode is a mode of the Intel x86 processor which provides various protection features, such as memory protection and the ability to disable privileged instructions. Under Linux, all software runs in protected mode, but user applications run at a different privilege level to the kernel.

Of course this article is quite out of date (though surprisingly much of it is still relevant) but on this point it was wrong even back when it was written.

sidebar & port table ?

ARJUN's picture

where is the sidebar & port table that were discussed in this article..?

links and sidebars

Keith Daniels's picture

This is not the magazine so there are no "sidebars" Check the links in the articles they have what you are looking for.

"I have always wished that my computer would be as easy to use as my telephone.
My wish has come true. I no longer know how to use my telephone."
-- Bjarne Stroustrup

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix