Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
10 views46 pages

Chapter 1-c Devicedrivers

A device driver is a software program that enables higher-level computer programs to communicate with hardware devices, acting as a translator between the hardware and applications. In Linux, device drivers can be categorized into character, block, and network devices, each with specific functionalities and access methods. The document also discusses the processes for loading and removing drivers in both user and kernel spaces, as well as the structure and implementation of a simple character device driver.

Uploaded by

ikush.misc
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views46 pages

Chapter 1-c Devicedrivers

A device driver is a software program that enables higher-level computer programs to communicate with hardware devices, acting as a translator between the hardware and applications. In Linux, device drivers can be categorized into character, block, and network devices, each with specific functionalities and access methods. The document also discusses the processes for loading and removing drivers in both user and kernel spaces, as well as the structure and implementation of a simple character device driver.

Uploaded by

ikush.misc
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 46

DEVICE

DRIVER
Introducti
• Defination :-on
Device driver or software driver
is a computer program allowing higher-level
computer programs to interact with a hardware
device.

• A driver typically communicates with the


device through the computer bus or
communications subsystem to which the
hardware connects.

• Drivers are hardware-dependent and operating


- system-specific. They usually provide the
interrupt handling required for any necessary
Why a Device
• A device driver is usually part of the OS
Driver?
kernel( a computer program at the core of a computer's operating system and generally has

complete control over everything in the system.disks,devices,memory,cpu)


o C ompiled with the OS
o Dynamically loaded into the OS during execution.

• Each device driver handles


o one device type (e.g., mouse)
o one class of closely related devices (e.g., SCSI disk driver to
multiple disks of different sizes and different
handle
speeds.).
• A device driver simplifies programming by acting
as translator between a hardware device and
the applications or operating systems that use it.

• Programmers can write the higher-level


application code independently of whatever
specific hardware device.
Locatio
n
Device Drivers in
Linux
Processes in
• When a Linux
user process executes a system call, it
does not transfer c ontrol to another process,

• but changes its execution mode from user to


kernel mode.

• In kernel mode, while executing the system call,


the
process has a c c ess to the kernel address space,
and

• Through supporting functions it has access to


the address space of the user executing the
c all.
Functions of Device
• Drivers
Ac c ept abstract read and write requests from
the device-independent layer above.
• Initialize the device.
• Manage power requirements and log events.
• Check input parameters if they are valid.
• Translate valid input from abstract to concrete
terms
o e.g., convert linear block number into the head, track, sector and
cylinder number for disk access.
• Check the device if it is in use (i.e., check the status
bit).
• Control the device by issuing a sequence of
commands. The driver determines what commands
will be issued.
Loadable Kernel
Module
• In computing, a loadable kernel module (or LKM) is an
object file that contains code to extend the running kernel,
or so- called base kernel, of an operating system.
• Most current Unix-like systems, and Microsoft Windows,
support
loadable kernel modules.
• Without loadable kernel modules, an operating system
would have to have all possible anticipated functionality
already compiled directly into the base kernel.
• Much of that functionality would reside in memory
without being used, wasting memory, and would require
that users rebuild and reboot the base kernel every
time new functionality is desired.
• Most operating systems supporting loadable kernel
modules will include modules to support most desired
functionality.
Classes of Devices and
•Modules
The Linux way of looking at devices
distinguishes between three fundamental
device types.

• Each module usually implements one of these


types,
and thus is classifiable as

1.char module

2.block

module

3.network
1. Character
• devices
A character (char) device is one that can be
accessed as a stream of bytes (like a file); a
char driver is in charge of implementing this
behavior.
• Such a driver usually implements at least the
open, close, read, and write system calls.
• The text console (/dev/console) and the serial ports
(/dev/ttyS0 and friends) are examples of char
devices, as they are well represented by the stream
abstraction.
• Char devices are a c c essed by means of
filesystem nodes, such as /dev/tty1 and
/dev/lp0.
• The only relevant difference between a char
device and a regular file is that you can always
move back and forth in the regular file, whereas
2.Block
• Like char devices,devices
block devices are accessed
by filesystem nodes in the /dev directory.
• A block device is a device (e.g., a disk) that can host
a filesystem.
• In most Unix systems, a block device can only handle
I/O operations that transfer one or more whole blocks,
which are usually 512 bytes (or a larger power of two)
bytes in length.
• Linux, instead, allows the application to read and
write a block device like a char device—it permits
the transfer of any number of bytes at a time.
• As a result, block and char devices differ only in the
way data is managed internally by the kernel, and
thus in the kernel/driver software interface.
• Like a char device, each block device is accessed
through a filesystem node, and the difference
between them is transparent to the user.
3. Network
• Any networkinterfaces
transaction is made through an interface,
that is, a device that is able to exchange data with
other hosts.
• Usually, an interface is a hardware device, but it
might also be a pure software device, like the
loopback interface.
• A network interface is in charge of sending and
receiving data packets, driven by the network
subsystem of the kernel, without knowing how individual
transactions map to the a ctual packets being
transmitted.
• Many network connections (especially those using TCP)
are stream-oriented, but network devices are, usually,
designed around the transmission and receipt of
packets.
• A network driver knows nothing about individual
connections; it only handles packets.
Major Minor
Numbers
• Major device numbers are used by the Linux
system to map I/O requests to the driver code,
thereby deciding which device driver to execute,
when a user reads from or writes to the special
file.

• The minor numbers are entirely under the control


of the driver writer, and usually refer to sub-
devices of the device.

• These sub-devices may be separate units


attached to a controller. Thus, a disk device
driver may, for example, communicate with a
hardware controller (the device) which has
several disk drives (sub- devices) attached.
Device Driver
oProtocol
After driver knows which commands to issue,
it starts to write them into controller's device
registers .
o After writing each command, it checks to see
if the controller accepted the c ommand and
is prepared to a c c ept the next one.
o After commands have been issued, either (a)
the device waits until the c ontroller does some
work and it blocks itself until interrupt comes
to unblock it; or (b) the device doesn't wait
because the c ommand finished without any
delay.
Applicatio
ns
• Because of the diversity of modern hardware and operating
systems, drivers operate in many different environments.
Drivers may interface with:

• Printers
• video adapters
• network cards
• sound cards
• local buses of various sorts — in particular, for bus mastering
on
modern systems
• low-bandwidth I/O buses of various sorts (for pointing
devices such as mice, keyboards, USB, etc.)
• computer storage devices such as hard disk, CD-ROM
and floppy disk buses (ATA, SATA, SCSI)
• implementing support for different file systems
• image scanners
• digital cameras
Character Device
Driver
• User Space and Kernel Space
• Loading and Removing the
driver in user space
• Loading and Removing the
driver in kernel space
• The complete driver “memory”
User space and kernel
• space
When you write device drivers, it’s important
to make the distinction between “user space”
and “kernel space”.
• Kernel Space : Linux (which is a kernel)
manages the machine's hardware in a simple
and effic ient manner, offering the user a
simple and uniform programming interface.
• In the same way, the kernel, and in particular its
device drivers, form a bridge or interface
between the end-user/programmer and the
hardware.
• Any subroutines or functions forming part of
the kernel (modules and device drivers, for
example) are considered to be part of kernel
space.
• User space : End-user programs, like the UNIX
shell or other GUI based applications (kpresenter
for example), are part of the user space.
• Obviously, these applications need to interact
with the system's hardware . However, they
don’t do so directly, but through the kernel
supported functions.
Device driver events and their associated interfacing functions between kernel space and user space.
Events User functions Kernel functions
Load module insmod module_init()
Open device fopen file_operations: open
Close device fread file_operations: read
Write device fwrite file_operations: write
Close device fclose file_operations: release
Remove module rmmod module_exit()

Device driver events and their associated functions between kernel space and the hardware device.
Events Kernel functions
Read data inb
Write data outb
Loading and Removing the driver in user
space
• To implement simple chara cter device driver in user
space make one file named “demo.c” and content of
file is :
#include <linux/module.h>
MODULE_LICENSE("Dual
BSD/GPL");

• Next, you need to generate a makefile. The makefile


for this example, which should be named Makefile,
will be:
obj-m := demo.o

• Unlike with previous versions of the kernel, it’s now also


necessary to compile the module using the same
kernel that you’re going to load and use the module
with. To compile it, you can type:
make -C /usr/src/kernel-source-2.6.8 M=`pwd`
modules
In user space, you can load the module as root by typing the
following
into the command line:
# insmod demo.ko

The insmod command allows the installation of the module in


the kernel. However, this particular module isn’t of much use.

It is possible to check that the module has been installed


correctly by looking at all installed modules:
# lsmod

Finally, the module can be removed from the kernel using the
command: # rmmod demo

By issuing the lsmod command again, you can verify that the
module is no longer in the kernel.
Loading and Removing the driver in kernel
space
• When a module device driver is loaded into the
kernel, some preliminary tasks are usually
performed like resetting the device, reserving
RAM, reserving interrupts, and reserving
input/output ports, etc.
• These tasks are performed, in kernel space, by
two functions which need to be present (and
explicitly declared): module_init and module_exit;
they correspond to the user space commands
insmod and rmmod , which are used when
installing or removing a module.
• To sum up, the user commands insmod and
rmmod use the kernel space functions
module_init and module_exit.
#include <linux/init.h>
#include
<linux/module.h>
#include
<linux/kernel.h>
MODULE_LICENSE("Dual
BSD/GPL");
static int hello_init(void)
{
printk("<1> Hello world!\
n"); return 0;
}
static void hello_exit(void)
{
printk("<1> Bye,
cruelworld\ n");
}
• The a ctual functions hello_init and hello_exit ca n be
given any name desired. However, in order for them to
be identified as the corresponding loading and
removing functions, they have to be passed as
parameters to the functions module_init and
module_exit.

• The printk function has also been introduced. It is very


similar to the well known printf apart from the fact that it
only works inside the kernel. The <1> symbol shows
the high priority of the message (low number). In this
way, besides getting the message in the kernel system
log files, you should also receive this message in the
system console.

• This module can be compiled using the same


command as before, after adding its name into the
Makefile and content of it is : “obj-m := demo.o
The complete driver “memory”: initial part of
the driver
• I’ll now show how to build a complete device driver: memory.c.
This device will allow a character to be read from or written into
it. This device, while normally not very useful, provides a very
illustrative example since it is a complete driver; it's also easy to
implement,since it doesn’t interface to a real hardware device.

• After the #include files, the functions that will be defined later
are declared.
• The common functions which are typically used to
manipulate files are declared in the definition of the
file_operations structure. These will also be explained in detail
later. Next, the initialization and exit functions—used when
loading and removing the module—are declared to the
kernel.
• Finally, the global variables of the driver are declared: one of
them is the major number of the driver, the other is a pointer
to a region in memory, memory_buffer, which will be used as
storage for the driver data.
/* Necessary includes for device drivers */
#include <linux/init.h>
<linux/config.h>
#include <linux/module.h>
<linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
<linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
<linux/types.h> /* size_t */
#include <linux/proc_fs.h>
<linux/fcntl.h> /* O_ACCMODE */
#include <asm/system.h> /* cli(), *_flags */
<asm/uaccess.h> /* copy_from/to_user */
#include
MODULE_LICENSE("Dual BSD/GPL");
#include
/* Declaration of memory.c functions */
#n
i itncl muedmeory_open(struct inode *inode, struct file *filp);
int memory_release(struct inode *inode, struct file *filp);
#s
s iinzcel_utde memory_read(struct file *filp, char *buf,
size_t count, loff_t
#f
s
* i_
s np
i co
z ls
e u)
_ d;
t e memory_write(struct file *filp, char *buf, size_t count, loff_t
*f_pos);
#o
v iindclm uedmeory_exit(void);
int memory_init(void);

/* Structure that declares the usual file */


/* access functions */
struct file_operations memory_fops = {
read: memory_read,
write: memory_write,
open: memory_open,
release: memory_release
};

/* Declaration of the init and exit functions */


module_init(memory_init);
module_exit(memory_exit);

/* Global variables of the driver */


/* Major number */
int memory_major = 60;
/* Buffer to store data */
char *memory_buffer;
The “memory” driver: connection of the device
• with
In UNIXits
andfiles
Linux, devices are accessed from user space in exactly
the same way as files are accessed. These device files are normally
subdirectories of the /dev directory.
• To link normal files with a kernel module two numbers are used: major
number and minor number. The major number is the one the kernel
uses to link a file with its driver. The minor number is for internal use of
the device and for simplicity it won’t be covered in this article.

• To achieve this, a file (which will be used to access the device


driver) must be created, by typing the following command as root:
• # mknod /dev/memory c 60 0

• In the above, c means that a char device is to be created, 60 is


the
major number and 0 is the minor number.
• Within the driver, in order to link it with its corresponding /dev file in
kernel space, the register_chrdev function is used. It is called with
three arguments: major number, a string of characters showing the
module name, and a file_operations structure which links the call with
the file functions it defines. It is invoked, when installing the module,
in this way:
• Also, note the use of the kmalloc function. This function is used for
memory allocation of the buffer in the device driver which resides
in kernel space. Its use is very similar to the well known malloc
int memory_init(void) {
int result;

/* Registering device
*/
result = register_chrdev(memory_major, "memory", &memory_fops);
if (result < 0) {
printk(
"<1>memory: cannot obtain major number %d\n", memory_major);
return result;
}

/* Allocating memory for the buffer


*/ memory_buffer = kmalloc(1,
GFP_KERNEL); if (!memory_buffer) {
result = -ENOMEM;
goto fail;
}
memset(memory_buffer, 0, 1);

printk("<1>Inserting memory module\


n"); return 0;

fail:
memory_exit(
); return
result;

}
The “memory” driver: removing
• the driver
In order to remove the module inside the memory_exit
function, the function unregsiter_chrdev needs to be
present. This will free the major number for the kernel.

• The buffer memory is also freed in this function, in order


to leave a clean kernel when removing the device
driver.

void memory_exit(void) {
/* Freeing the major number */
unregister_chrdev(memory_major, "memory");

/* Freeing buffer memory */


if (memory_buffer) {
kfree(memory_buffer);
}

printk("<1>Removing memory
module\n");

}
The “memory” driver: opening the
device as a file
• The kernel space function, which corresponds to opening a file
in user space (fopen), is the member open: of the file_operations
structure in the call to register_chrdev. In this case, it is the
memory_open function. It takes as arguments: an inode structure,
which sends information to the kernel regarding the major number
and minor number; and a file structure with information relative
to the different operations that can be performed on a file.
Neither of these functions will be covered in depth within this
article.
• When a file is opened, it’s normally necessary to initialize driver
variables or reset the device. In this simple example, though,
these operations are not performed.
• The memory_open function can be seen below:

int memory_open(struct inode *inode, struct file *filp)


{
/* Success */ return 0;
}
The “memory” driver: closing the
•device as a file
The corresponding function for closing a file in user space
(fclose) is the release: member of the file_operations
structure in the call to register_chrdev. In this particular case,
it is the function memory_release, which has as arguments
an inode structure and a file structure, just like before.
• When a file is closed, it’s usually necessary to free the used
memory and any variables related to the opening of the
device. But, once again, due to the simplicity of this
example, none of these operations are performed.
• The memory_release function is shown below:
int memory_release(struct inode *inode, struct file *filp)
{
/* Success */ return 0;
}
The “memory” driver: reading
• the device
To read a device with the user function fread or
similar, the member read: of the file_operations
structure is used in the call to register_chrdev. This
time, it is the function memory_read. Its
arguments are: a type file structure; a buffer
(buf), from which the user space function (fread)
will read; a counter with the number of bytes to
transfer (count), which has the same value as the
usual counter in the user space function (fread);
and finally, the position of where to start reading
the file (f_pos).

• In this simple case, the memory_read function


transfers a single byte from the driver buffer
(memory_buffer) to user space with the
function copy_to_user:
ssize_t memory_read(struct file *filp, char *buf,
size_t count, loff_t *f_pos) {

/* Transfering data to user space */


copy_to_user(buf,memory_buffer,1);

/* Changing reading position as best suits */


if (*f_pos == 0) {
*f_pos+=1;
return 1;
} else
{ return
0;
}
}

• The reading position in the file (f_pos) is also changed.


If the position is at the beginning of the file, it is
increased by one and the number of bytes that have
been properly read is given as a return value, 1. If
not at the beginning of the file, an end of file (0) is
returned since the file only stores one byte.
The “memory” driver: writing to
• aTo device
write to a device with the user function fwrite or similar,
the member write: of the file_operations structure is used in
the call to register_chrdev.
• It is the function memory_write, in this particular example,
which has the following as arguments: a type file structure;
buf, a buffer in which the user space function (fwrite) will
write; count, a counter with the number of bytes to transfer,
which has the same values as the usual counter in the user
space function (fwrite); and finally, f_pos, the position of
where to start writing in the file.

ssize_t memory_write( struct file *filp, char *buf,


size_t count, loff_t *f_pos)
{

char *tmp;

tmp=buf+count-1;
copy_from_user(memory_buffer,tmp,1);
return 1;
}
The complete “memory”
driver
• By joining all of the previously shown code, the complete driver is achieved:
<memory.c> =

<memory initial>
<memory init module>
<memory exit module>
<memory open>
<memory release>
<memory read>

<memory write>
• Before this module can be used, you will need to compile it in the same way as
with previous modules. The module can then be loaded with:
• # insmod memory.ko
• It’s also convenient to unprotect the device:
• # chmod 666 /dev/memory
• If everything went well, you will have a device /dev/memory to which you can
write a string of characters and it will store the last one of them. You can perform
the operation like this:
• $ echo -n abcdef >/dev/memory
• To check the content of the device you can use a simple cat:
• $ cat /dev/memory
• The stored character will not change until it is overwritten or the module is
removed.
USB
connection Drivers
• The universal serial bus (USB) is a
between a host c omputer
and a number of peripheral devices.
• It was originally created to replace a wide range
of slow and different buses—the parallel, serial,
and keyboard connections—with a single bus
type that all devices could connect to.
• USB has grown beyond these slow connections
and now supports almost every type of device
that can be connected to a PC.
• The latest revision of the USB specification
added high-speed connections with a
theoretical speed limit of 480 MBps.
• Topologically, a USB subsystem is not laid out as a
bus; it is rather a tree built out of several point-to-
point links. The links are four-wire c ables (ground,
power, and two signal wires) that connect a
device and a hub, just like twisted-pair Ethernet.
• The USB host c ontroller is in charge of asking
every USB device if it has any data to send.
• Because of this topology, a USB device can never
start sending data without first being asked to by
the host controller.
• This configuration allows for a very easy plugand-
play type of system, whereby devices can be
automatically configured by the host computer.
• The USB protocol specifica tions define a set of
standards that any device of a specific type
can follow.
• If a device follows that standard, then a
special driver for that device is not
necessary.
• These different types are called classes and
consist of things like storage devices, keyboards,
mice, joysticks, network devices, and modems.
• Other types of devices that do not fit into these
classes require a special vendor-specific driver to
be written for that specific device.
• Video devices and USB-to-serial devices are a
good example where there is no defined
standard, and a driver is needed for every
different device from different manufacturers.
USB Device
Basics
• A USB device is a very complex thing, as
described in the offic ial USB documentation
(available at http://www.usb.org).
• Fortunately, the Linux kernel provides a
subsystem called the USB c ore to handle most
of the complexity. This chapter describes the
interaction between a driver and the USB
core.
• USB devices consist of configurations,
interfaces, and endpoints and how USB drivers
bind to USB interfaces, not the entire USB
device.
1.
• The most basic form of USB communication is
Endpoints
through something called an endpoint.
• A USB endpoint can carry data in only one direction,
either from the host computer to the device (called
an OUT endpoint) or from the device to the host
computer (called an IN endpoint).
• Endpoints can be thought of as unidirectional pipes.
• A USB endpoint can be one of four different types
that describe how the data is transmitted:
• CONTROL:
• Control endpoints are used to allow access to
different parts of the USB device.
• They are commonly used for configuring the device,
retrieving information about the device, sending
commands to the device, or retrieving status reports
about the device. These endpoints are usually small in
size.
• Every USB device has a control endpoint called
“endpoint 0” that is used by the USB core to configure
the device at insertion time.
• These transfers are guaranteed by the USB protocol
to always have enough reserved bandwidth to
make it through to the device.
• INTERRUPT:
• Interrupt endpoints transfer small amounts of data at a
fixed rate every time the USB host asks the device for
data.
• These endpoints are the primary transport method for
USB keyboards and mice.
• They are also commonly used to send data to USB
devices to control the device, but are not generally used
to transfer large amounts of data.
• These transfers are guaranteed by the USB protocol
to always have enough reserved bandwidth to
make it through.
• BULK:
• Bulk endpoints transfer large amounts of data. These endpoints
are usually much larger (they can hold more characters at
once) than interrupt endpoints.
• They are common for devices that need to transfer any data
that must get through with no data loss.
• These transfers are not guaranteed by the USB protocol to
always
make it through in a specific amount of time.
• If there is not enough room on the bus to send the whole BULK
packet, it is split up across multiple transfers to or from the
device. These endpoints are common on printers, storage, and
network devices.
• ISOCHRONOUS:
• Isochronous endpoints also transfer large amounts of data,
but the data is not always guaranteed to make it through.
• These endpoints are used in devices that can handle loss of
data, and rely more on keepinga constant stream of data
flowing.
• Real-time data collections, such as audio and video
2.
• USB endpoints are bundled up into interfaces.
Interfaces
USB interfaces handle only one type of a USB
logical connection, such as a mouse, a
keyboard, or a audio stream.
• Some USB devices have multiple interfaces, such
as a USB speaker that might consist of two
interfaces: a USB keyboard for the buttons and a
USB audio stream.
• Because a USB interface represents basic
functionality, each USB driver controls an
interface; so, for the speaker example, Linux
needs two different drivers for one hardware
device.
3.
• USB interfaces are themselves bundled up into
Configurations
configurations.
• A USB device can have multiple configurations
and might switch between them in order to
change the state of the device.
• For example, some devices that allow firmware to
be downloaded to them contain multiple
configurations to accomplish this.
• A single configuration can be enabled only at
one point in time.
• Linux does not handle multiple configuration
USB devices very well, but, thankfully, they are
rare.
• USB devices are quite complex and are made up
of lots of different logical units.
• The relationships among these units can be
simply described as follows:
A. Devices usually have one or more
configurations.
B. Configurations often have one or more
interfaces.
C. Interfaces usually have one or more settings.
D. Interfaces have zero or more endpoints.
Referenc
• Websites
es
o www.en.wikipedia.org
o www.slideshare.in

• Books
o Linux Device Driver
• By Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman
Thank
You!!!

You might also like