際際滷

際際滷Share a Scribd company logo
Writing char device driver
 Goals
    Anatomy of character device driver
    User interface to driver
        Device files
    Kernel interface to device driver
        File operations structure
        Major and minor number
    Registering/De-registering char device driver
Anatomy of device driver
 A device driver has three sides
    One side talks to the rest of
                                         User
     the kernel
    One talks to the hardware
     and
    One talks to the user              Kernel
                                            損        Device
                                            損        File
                                     Device Driver




                                      Hardware
User interface to the device driver
 A very important Unix design decision was to represent most of the
  system objects as files
 It allows applications to manipulate all system objects with the normal
  file API (open, read, write, close, etc.)
 So, devices had to be represented as files to the applications
 This is done through a special artefact called a device file
 It a special type of file, that associates a file name visible to user space
  applications to the triplet (type, major, minor) that the kernel understands
  All device files are by convention stored in the /dev directory
Device file example
 Device files examples
$ ls -l /dev/ttyS0 /dev/sda1
brw-rw---- 1 root disk 8, 1 2012-11-08 19:52 /dev/sda1
crw-rw---- 1 root dialout 4, 64 2012-11-08 19:52 /dev/ttyS0

Example C code that uses the usual file API to write data to a serial port
int main() {
    int fd;
    fd = open(/dev/ttyS0, O_RDWR);
    write(fd, Hello, 5);
    close(fd);
}
Device files
 In Linux kernel, most of the devices are presented to the user space
  applications through two different abstractions
    Character device
    Block device
 Internally the kernel identifies each device by a triplet of information
    Type (character or block)
    Major number (typically the category of devices)
    Minor number (typically the identifier of the device)
Types of devices
 Block devices
    A device composed of fixed-sized blocks, that can be read and write to
      store data.
    Used for hard disks, SD cards etc.
 Character devices
    An infinite stream of bytes, with no beginning, no end, no size. For e.g.
      serial port.
    Used for serial ports, terminals etc.
    Most of the devices that are not block devices are represented by
      linux kernel as character device.
Creating device files
 On a basic Linux system, the device files can be created manually using the
   mknod command
     mknod /dev/<device> [c|b] major minor
     Needs root privileges
     Coherency between device files and devices handled by the kernel is
       left to the system developer
 On more elaborate Linux systems, mechanisms can be added to
create/remove them automatically when devices appear and
disappear
     devtmpfs virtual filesystem, since kernel 2.6.32
     udev daemon, solution used by desktop and server Linux systems
     mdev program, a lighter solution than udev
Kernel interface to the device driver
 In order to talk to the kernel, the
  driver registers with subsystems          Kernel
  to respond to events. Such an
  event might be the opening of a             Event List
  file, closing a file, a page fault, the         File open        File close
                                               X               X
  plugging in of a new USB device,
  etc.                                               X Interrupt X page
                                                                   fault


                                                        Device Driver
Character drivers
 User-space needs
    The name of a device file in      User Space
     /dev to interact with the
     device driver through regular         Read buffer         Write string
     file operations (open, read,
     write, close...)
 The kernel needs                                    /dev/foo

    To know which driver is in
     charge of device files with a
     given major / minor number        Kernel space      Major/Minor
     pair
   For a given driver, to have
     handlers (file operations) to
     execute when user- space             Read handler        Write handler
     opens, reads, writes or closes
     the device file.
Implementing a character driver
 Four major steps
    Implement operations corresponding to the system calls an
      application can apply to a file: file operations.
    Define a file_operations structure containing function pointers to
      system call functions in your driver.
    Reserve a set of major and minors for your driver
    Tell the kernel to associate the reserved major and minor to your file
      operations
 This is a very common design scheme in the Linux kernel
    A common kernel infrastructure defines a set of operations to be
      implemented by a driver and functions to register your driver
    Your driver only needs to implement this set of well-defined
      operations
File operations
 Before registering character devices, you have to define file_operations
  (called fops) for the device files.
 The file_operations structure is generic to all files handled by the Linux
  kernel.
 Here are the most important operations for a character driver. All of them
  are optional. (include/linux/fs.h)
   struct file_operations {
   ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
   ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
   long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
   int (*open) (struct inode *, struct file *);
   int (*release) (struct inode *, struct file *);
   [...]
   };
File operation definition example
#include <linux/fs.h>
static const struct file_operations sample_device_fops = {
     .owner = THIS_MODULE,
     .open = sample_device_open,
     .release = sample_device_release,
     .unlocked_ioctl = sample_device_ioctl,
};
 You need to fill the fops with function your device needs to be supported.
File operations
 open: for opening the device(allocating resources)
 release: for closing the device (releasing resources)
 write: for writing data to the device
 read : for reading data from the device
 ioctl: for query the device statistics and passing configuration parameters
  to device
 mmap: for potentially faster but more complex direct access to the device
Open() and release()
 int open(struct inode *i, struct file *f)
    Called when user-space opens the device file.
    inode is a structure that uniquely represent a file in the system.
    file is a structure created every time a file is opened. Several file
       structures can point to the same inode structure.
          Contains info like the current position, the opening mode, etc.
          Has a void *private_data pointer to store driver specific data
    The open method is provided by the driver to do any initialization in
       preparation to later operations such as allocating memory resources.
 int release(struct inode *i, struct file *f)
    Called when user-space closes the file.
    The role of release is reverse of open(). It performs all the operation to
       undo the tasks done in open() such as de-allocating the memory
       resources allocated at time of open().
read() function
 ssize_t read (struct file *file, __user char *buf, size_t size, loff_t *off)
    Called when user-space uses the read() system call on the device.
    Must read data from the device,
    write at most size bytes in the user-space buffer buf, and
    update the current position in the file off.
    file  is a pointer to the same file structure that was passed in the
      open() operation
    Must return the number of bytes read.
    On UNIX/Linux, read() operations typically block when there isn't
      enough data to read from the device
read() function example
Write()
 ssize_t foo_write(struct file *file, __user const char *buf, size_t size ,loff_t
  *off)
    Called when user-space uses the write() system call on the device
    The opposite of read, must read at most size bytes from buf,
    write it to the device,
    update off and
    return the number of bytes written.
ioctl
 static long ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    Associated with the ioctl system call.
    Allows to extend drivers capabilities beyond read/write API.
    Example:
         changing the speed of a serial port,
         setting video output format,
         querying a device serial number.
    cmd is a number identifying the operation to perform
    arg is the optional argument passed as third argument of the ioctl()
      system call. Can be an integer, an address, etc.
    The semantic of cmd and arg is driver-specific.
dev_t data types
 The kernel data type dev_t represent a major/ minor number pair
    Also called a device number.
    Defined in <linux/kdev_t.h>
   Linux 2.6: 32 bit size (major: 12 bits, minor: 20 bits)
    Macro to compose the device number:
   MKDEV(int major, int minor);
    Macro to extract the minor and major numbers:
   MAJOR(dev_t dev);
   MINOR(dev_t dev);
Registering device numbers
 #include <linux/fs.h>
  int register_chrdev_region(
  dev_t from,                       /* Starting device number */
  unsigned count,                   /* Number of device numbers */
  const char *name);                 /* Registered name */
  Returns 0 if the allocation was successful.
 If you don't have fixed device numbers assigned to your driver
     Better not to choose arbitrary ones. There could be conflicts with
       other drivers.
     The kernel API offers an alloc_chrdev_region function to have the
       kernel allocate free ones for you. You can find the allocated major
       number in /proc/devices.
Information of registered devices
 Registered devices are visible in
  /proc/devices:
 Character devices:                   Block devices:
    1 mem                                1 ramdisk
    4 /dev/vc/0                          259 blkext
    4 tty                                7 loop
    4 ttyS                               8 sd
    5 /dev/tty                           9 md
    5 /dev/console                       11 sr
    5 /dev/ptmx                          65 sd
    6 lp                                 66 sd
                                      Major number Registered name
Character device registration
 The kernel represents character drivers with a cdev structure
 Declare this structure globally (within your module):
   #include <linux/cdev.h>
   static struct cdev char_cdev;

 In the init function, initialize the structure
   void cdev_init(struct cdev *cdev, struct file_operations *fops);
   cdev_init(&char_cdev, &fops);
Character device registration
 Then, now that your structure is ready, add it to the system:
   int cdev_add(
       struct cdev *p,     /* Character device structure */
       dev_t dev,          /* Starting device major / minor number */
       unsigned count); /* Number of devices */
   If (cdev_add(&char_cdev, dev_no, device_count))
       printk(Char device registration failedn);

 After this function call, the kernel knows the association between the
  major/minor numbers and the file operations. Your device is ready to be
  used!.
Character device unregistration
 First delete your character device:
   void cdev_del(struct cdev *p);
 Then, and only then, free the device number:
 void unregister_chrdev_region(dev_t from, unsigned count);
 Example :
   cdev_del(&char_cdev);
   unregister_chrdev_region(char_dev, count);
Char driver example from kernel
                  sources
 Read operation example
    Drivers/char/lp.c
 Ioctl operation example
    drivers/char/lp.c
 Write operation example
    Drivers/char/lp.c
Linux error code
 The kernel convention for error management is
    Return 0 on success
         return 0;
    Return a negative error code on failure
         return -EFAULT;
 Error codes
    include/asm-generic/errno-base.h
    include/asm-generic/errno.h
Misc Drivers
 Misc (or miscellaneous) drivers are simple char drivers that share certain
  common characteristics.
 The kernel abstracts these commonalities into an API (implemented
  in drivers/char/misc.c),
 This simplifies the way these drivers are initialized.
 All misc devices are assigned a major number of 10, but each can choose a
  single minor number.
 Consider the sequence of initialization steps that a char driver performs:
    Allocates major/minor numbers via alloc_chrdev_region() and friends
    Creates /dev and /sys nodes using class_device_create()
    Registers itself as a char driver using cdev_init() and cdev_add()
 A misc driver accomplishes all this with a single call to misc_register()
 #include <linux/miscdevice.h>

struct miscdevice sample_misc_device = {
     .minor = MISC_DYNAMIC_MINOR,
     .name = sample_device",
     .fops = &sample_device_fops,
};
 Registration
misc_register(&sample_misc_device);
 De-registration
misc_deregister(&sample_misc_device)
References
 Third Edition of Linux Device Drivers, by Jonathan Corbet, Alessandro
  Rubini, and Greg Kroah-Hartman.
Ad

Recommended

Machine-Learning-A-Z-Course-Downloadable-際際滷s-V1.5.pdf
Machine-Learning-A-Z-Course-Downloadable-際際滷s-V1.5.pdf
Maris R
linux device driver
linux device driver
Rahul Batra
Introduction Linux Device Drivers
Introduction Linux Device Drivers
NEEVEE Technologies
Diabetes Mellitus
Diabetes Mellitus
MD Abdul Haleem
Power Point Presentation on Artificial Intelligence
Power Point Presentation on Artificial Intelligence
Anushka Ghosh
Republic Act No. 11313 Safe Spaces Act (Bawal Bastos Law).pptx
Republic Act No. 11313 Safe Spaces Act (Bawal Bastos Law).pptx
maricelabaya1
Hypertension
Hypertension
Ratheeshkrishnakripa
Nursing process
Nursing process
Dr. Binu Babu Nursing Lectures Incredibly Easy
Linux device drivers
Linux device drivers
Emertxe Information Technologies Pvt Ltd
Uboot startup sequence
Uboot startup sequence
Houcheng Lin
U-Boot - An universal bootloader
U-Boot - An universal bootloader
Emertxe Information Technologies Pvt Ltd
Bootloaders
Bootloaders
Anil Kumar Pugalia
U-Boot Porting on New Hardware
U-Boot Porting on New Hardware
RuggedBoardGroup
Embedded_Linux_Booting
Embedded_Linux_Booting
Rashila Rr
Embedded Linux Kernel - Build your custom kernel
Embedded Linux Kernel - Build your custom kernel
Emertxe Information Technologies Pvt Ltd
Linux file system
Linux file system
Md. Tanvir Hossain
Spi drivers
Spi drivers
pradeep_tewani
U-Boot presentation 2013
U-Boot presentation 2013
Wave Digitech
Linux commands
Linux commands
Balakumaran Arunachalam
Basic Linux Internals
Basic Linux Internals
mukul bhardwaj
Embedded linux network device driver development
Embedded linux network device driver development
Amr Ali (ISTQB CTAL Full, CSM, ITIL Foundation)
Linux Kernel Booting Process (1) - For NLKB
Linux Kernel Booting Process (1) - For NLKB
shimosawa
Linux Internals - Part II
Linux Internals - Part II
Emertxe Information Technologies Pvt Ltd
Bootloaders (U-Boot)
Bootloaders (U-Boot)
Omkar Rane
Shell programming
Shell programming
Moayad Moawiah
U boot porting guide for SoC
U boot porting guide for SoC
Macpaul Lin
Linux command ppt
Linux command ppt
kalyanineve
Jagan Teki - U-boot from scratch
Jagan Teki - U-boot from scratch
linuxlab_conf
Writing Character driver (loadable module) in linux
Writing Character driver (loadable module) in linux
RajKumar Rampelli
Char Drivers And Debugging Techniques
Char Drivers And Debugging Techniques
YourHelper1

More Related Content

What's hot (20)

Linux device drivers
Linux device drivers
Emertxe Information Technologies Pvt Ltd
Uboot startup sequence
Uboot startup sequence
Houcheng Lin
U-Boot - An universal bootloader
U-Boot - An universal bootloader
Emertxe Information Technologies Pvt Ltd
Bootloaders
Bootloaders
Anil Kumar Pugalia
U-Boot Porting on New Hardware
U-Boot Porting on New Hardware
RuggedBoardGroup
Embedded_Linux_Booting
Embedded_Linux_Booting
Rashila Rr
Embedded Linux Kernel - Build your custom kernel
Embedded Linux Kernel - Build your custom kernel
Emertxe Information Technologies Pvt Ltd
Linux file system
Linux file system
Md. Tanvir Hossain
Spi drivers
Spi drivers
pradeep_tewani
U-Boot presentation 2013
U-Boot presentation 2013
Wave Digitech
Linux commands
Linux commands
Balakumaran Arunachalam
Basic Linux Internals
Basic Linux Internals
mukul bhardwaj
Embedded linux network device driver development
Embedded linux network device driver development
Amr Ali (ISTQB CTAL Full, CSM, ITIL Foundation)
Linux Kernel Booting Process (1) - For NLKB
Linux Kernel Booting Process (1) - For NLKB
shimosawa
Linux Internals - Part II
Linux Internals - Part II
Emertxe Information Technologies Pvt Ltd
Bootloaders (U-Boot)
Bootloaders (U-Boot)
Omkar Rane
Shell programming
Shell programming
Moayad Moawiah
U boot porting guide for SoC
U boot porting guide for SoC
Macpaul Lin
Linux command ppt
Linux command ppt
kalyanineve
Jagan Teki - U-boot from scratch
Jagan Teki - U-boot from scratch
linuxlab_conf

Similar to Introduction to char device driver (20)

Writing Character driver (loadable module) in linux
Writing Character driver (loadable module) in linux
RajKumar Rampelli
Char Drivers And Debugging Techniques
Char Drivers And Debugging Techniques
YourHelper1
Part 03 File System Implementation in Linux
Part 03 File System Implementation in Linux
Tushar B Kute
Device Drivers
Device Drivers
Kushal Modi
Linux Char Device Driver
Linux Char Device Driver
Gary Yeh
Ganesh naik linux_kernel_internals
Ganesh naik linux_kernel_internals
nullowaspmumbai
Ganesh naik linux_kernel_internals
Ganesh naik linux_kernel_internals
Ganesh Naik
Ch1 linux basics
Ch1 linux basics
chandranath06
Unix fundamentals
Unix fundamentals
Bimal Jain
Device drivers tsp
Device drivers tsp
Pradeep Kumar TS
Linux 4 you
Linux 4 you
Shashwat Shriparv
Edubooktraining
Edubooktraining
norhloudspeaker
Linux filesystemhierarchy
Linux filesystemhierarchy
Dr. C.V. Suresh Babu
Lecture1 Introduction
Lecture1 Introduction
Mohammed Farrag
Lamp1
Lamp1
Nadhi ya
Lamp
Lamp
Reka
Lamp1
Lamp1
Reka
Introduction to Operating Systems.pptx
Introduction to Operating Systems.pptx
MohamedSaied877003
Device_drivers_copy_to_user_copy_from_user.pptx
Device_drivers_copy_to_user_copy_from_user.pptx
siddu85
Linux System Programming - File I/O
Linux System Programming - File I/O
YourHelper1
Writing Character driver (loadable module) in linux
Writing Character driver (loadable module) in linux
RajKumar Rampelli
Char Drivers And Debugging Techniques
Char Drivers And Debugging Techniques
YourHelper1
Part 03 File System Implementation in Linux
Part 03 File System Implementation in Linux
Tushar B Kute
Device Drivers
Device Drivers
Kushal Modi
Linux Char Device Driver
Linux Char Device Driver
Gary Yeh
Ganesh naik linux_kernel_internals
Ganesh naik linux_kernel_internals
nullowaspmumbai
Ganesh naik linux_kernel_internals
Ganesh naik linux_kernel_internals
Ganesh Naik
Unix fundamentals
Unix fundamentals
Bimal Jain
Lecture1 Introduction
Lecture1 Introduction
Mohammed Farrag
Lamp
Lamp
Reka
Lamp1
Lamp1
Reka
Introduction to Operating Systems.pptx
Introduction to Operating Systems.pptx
MohamedSaied877003
Device_drivers_copy_to_user_copy_from_user.pptx
Device_drivers_copy_to_user_copy_from_user.pptx
siddu85
Linux System Programming - File I/O
Linux System Programming - File I/O
YourHelper1
Ad

Introduction to char device driver

  • 1. Writing char device driver Goals Anatomy of character device driver User interface to driver Device files Kernel interface to device driver File operations structure Major and minor number Registering/De-registering char device driver
  • 2. Anatomy of device driver A device driver has three sides One side talks to the rest of User the kernel One talks to the hardware and One talks to the user Kernel 損 Device 損 File Device Driver Hardware
  • 3. User interface to the device driver A very important Unix design decision was to represent most of the system objects as files It allows applications to manipulate all system objects with the normal file API (open, read, write, close, etc.) So, devices had to be represented as files to the applications This is done through a special artefact called a device file It a special type of file, that associates a file name visible to user space applications to the triplet (type, major, minor) that the kernel understands All device files are by convention stored in the /dev directory
  • 4. Device file example Device files examples $ ls -l /dev/ttyS0 /dev/sda1 brw-rw---- 1 root disk 8, 1 2012-11-08 19:52 /dev/sda1 crw-rw---- 1 root dialout 4, 64 2012-11-08 19:52 /dev/ttyS0 Example C code that uses the usual file API to write data to a serial port int main() { int fd; fd = open(/dev/ttyS0, O_RDWR); write(fd, Hello, 5); close(fd); }
  • 5. Device files In Linux kernel, most of the devices are presented to the user space applications through two different abstractions Character device Block device Internally the kernel identifies each device by a triplet of information Type (character or block) Major number (typically the category of devices) Minor number (typically the identifier of the device)
  • 6. Types of devices Block devices A device composed of fixed-sized blocks, that can be read and write to store data. Used for hard disks, SD cards etc. Character devices An infinite stream of bytes, with no beginning, no end, no size. For e.g. serial port. Used for serial ports, terminals etc. Most of the devices that are not block devices are represented by linux kernel as character device.
  • 7. Creating device files On a basic Linux system, the device files can be created manually using the mknod command mknod /dev/<device> [c|b] major minor Needs root privileges Coherency between device files and devices handled by the kernel is left to the system developer On more elaborate Linux systems, mechanisms can be added to create/remove them automatically when devices appear and disappear devtmpfs virtual filesystem, since kernel 2.6.32 udev daemon, solution used by desktop and server Linux systems mdev program, a lighter solution than udev
  • 8. Kernel interface to the device driver In order to talk to the kernel, the driver registers with subsystems Kernel to respond to events. Such an event might be the opening of a Event List file, closing a file, a page fault, the File open File close X X plugging in of a new USB device, etc. X Interrupt X page fault Device Driver
  • 9. Character drivers User-space needs The name of a device file in User Space /dev to interact with the device driver through regular Read buffer Write string file operations (open, read, write, close...) The kernel needs /dev/foo To know which driver is in charge of device files with a given major / minor number Kernel space Major/Minor pair For a given driver, to have handlers (file operations) to execute when user- space Read handler Write handler opens, reads, writes or closes the device file.
  • 10. Implementing a character driver Four major steps Implement operations corresponding to the system calls an application can apply to a file: file operations. Define a file_operations structure containing function pointers to system call functions in your driver. Reserve a set of major and minors for your driver Tell the kernel to associate the reserved major and minor to your file operations This is a very common design scheme in the Linux kernel A common kernel infrastructure defines a set of operations to be implemented by a driver and functions to register your driver Your driver only needs to implement this set of well-defined operations
  • 11. File operations Before registering character devices, you have to define file_operations (called fops) for the device files. The file_operations structure is generic to all files handled by the Linux kernel. Here are the most important operations for a character driver. All of them are optional. (include/linux/fs.h) struct file_operations { ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); [...] };
  • 12. File operation definition example #include <linux/fs.h> static const struct file_operations sample_device_fops = { .owner = THIS_MODULE, .open = sample_device_open, .release = sample_device_release, .unlocked_ioctl = sample_device_ioctl, }; You need to fill the fops with function your device needs to be supported.
  • 13. File operations open: for opening the device(allocating resources) release: for closing the device (releasing resources) write: for writing data to the device read : for reading data from the device ioctl: for query the device statistics and passing configuration parameters to device mmap: for potentially faster but more complex direct access to the device
  • 14. Open() and release() int open(struct inode *i, struct file *f) Called when user-space opens the device file. inode is a structure that uniquely represent a file in the system. file is a structure created every time a file is opened. Several file structures can point to the same inode structure. Contains info like the current position, the opening mode, etc. Has a void *private_data pointer to store driver specific data The open method is provided by the driver to do any initialization in preparation to later operations such as allocating memory resources. int release(struct inode *i, struct file *f) Called when user-space closes the file. The role of release is reverse of open(). It performs all the operation to undo the tasks done in open() such as de-allocating the memory resources allocated at time of open().
  • 15. read() function ssize_t read (struct file *file, __user char *buf, size_t size, loff_t *off) Called when user-space uses the read() system call on the device. Must read data from the device, write at most size bytes in the user-space buffer buf, and update the current position in the file off. file is a pointer to the same file structure that was passed in the open() operation Must return the number of bytes read. On UNIX/Linux, read() operations typically block when there isn't enough data to read from the device
  • 17. Write() ssize_t foo_write(struct file *file, __user const char *buf, size_t size ,loff_t *off) Called when user-space uses the write() system call on the device The opposite of read, must read at most size bytes from buf, write it to the device, update off and return the number of bytes written.
  • 18. ioctl static long ioctl(struct file *file, unsigned int cmd, unsigned long arg) Associated with the ioctl system call. Allows to extend drivers capabilities beyond read/write API. Example: changing the speed of a serial port, setting video output format, querying a device serial number. cmd is a number identifying the operation to perform arg is the optional argument passed as third argument of the ioctl() system call. Can be an integer, an address, etc. The semantic of cmd and arg is driver-specific.
  • 19. dev_t data types The kernel data type dev_t represent a major/ minor number pair Also called a device number. Defined in <linux/kdev_t.h> Linux 2.6: 32 bit size (major: 12 bits, minor: 20 bits) Macro to compose the device number: MKDEV(int major, int minor); Macro to extract the minor and major numbers: MAJOR(dev_t dev); MINOR(dev_t dev);
  • 20. Registering device numbers #include <linux/fs.h> int register_chrdev_region( dev_t from, /* Starting device number */ unsigned count, /* Number of device numbers */ const char *name); /* Registered name */ Returns 0 if the allocation was successful. If you don't have fixed device numbers assigned to your driver Better not to choose arbitrary ones. There could be conflicts with other drivers. The kernel API offers an alloc_chrdev_region function to have the kernel allocate free ones for you. You can find the allocated major number in /proc/devices.
  • 21. Information of registered devices Registered devices are visible in /proc/devices: Character devices: Block devices: 1 mem 1 ramdisk 4 /dev/vc/0 259 blkext 4 tty 7 loop 4 ttyS 8 sd 5 /dev/tty 9 md 5 /dev/console 11 sr 5 /dev/ptmx 65 sd 6 lp 66 sd Major number Registered name
  • 22. Character device registration The kernel represents character drivers with a cdev structure Declare this structure globally (within your module): #include <linux/cdev.h> static struct cdev char_cdev; In the init function, initialize the structure void cdev_init(struct cdev *cdev, struct file_operations *fops); cdev_init(&char_cdev, &fops);
  • 23. Character device registration Then, now that your structure is ready, add it to the system: int cdev_add( struct cdev *p, /* Character device structure */ dev_t dev, /* Starting device major / minor number */ unsigned count); /* Number of devices */ If (cdev_add(&char_cdev, dev_no, device_count)) printk(Char device registration failedn); After this function call, the kernel knows the association between the major/minor numbers and the file operations. Your device is ready to be used!.
  • 24. Character device unregistration First delete your character device: void cdev_del(struct cdev *p); Then, and only then, free the device number: void unregister_chrdev_region(dev_t from, unsigned count); Example : cdev_del(&char_cdev); unregister_chrdev_region(char_dev, count);
  • 25. Char driver example from kernel sources Read operation example Drivers/char/lp.c Ioctl operation example drivers/char/lp.c Write operation example Drivers/char/lp.c
  • 26. Linux error code The kernel convention for error management is Return 0 on success return 0; Return a negative error code on failure return -EFAULT; Error codes include/asm-generic/errno-base.h include/asm-generic/errno.h
  • 27. Misc Drivers Misc (or miscellaneous) drivers are simple char drivers that share certain common characteristics. The kernel abstracts these commonalities into an API (implemented in drivers/char/misc.c), This simplifies the way these drivers are initialized. All misc devices are assigned a major number of 10, but each can choose a single minor number. Consider the sequence of initialization steps that a char driver performs: Allocates major/minor numbers via alloc_chrdev_region() and friends Creates /dev and /sys nodes using class_device_create() Registers itself as a char driver using cdev_init() and cdev_add() A misc driver accomplishes all this with a single call to misc_register()
  • 28. #include <linux/miscdevice.h> struct miscdevice sample_misc_device = { .minor = MISC_DYNAMIC_MINOR, .name = sample_device", .fops = &sample_device_fops, }; Registration misc_register(&sample_misc_device); De-registration misc_deregister(&sample_misc_device)
  • 29. References Third Edition of Linux Device Drivers, by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman.