%Character Devices %Thadeu Cascardo # Introduction Devices in POSIX Systems are files in /dev directory. As with any files in POSIX, they may be opened, closed, read from, written to, seeked, ioctl'd, and others. Examples of device files: * /dev/sda - A SCSI block device * /dev/ttyS0 - A Serial terminal device # POSIX I/O calls POSIX systems have some standard calls for I/O. Since devices are files, these same system calls are used to work with devices. We are gonna work with the following calls: * open * read * write * close * lseek * ioctl # Device types and numbers Linux devices may be of different types, including character devices, block devices or network devices. Both character and block devices have identifying numbers, a major and a minor number. # VFS # Introduction The virtual file system is the hub for almost all operations in a Linux-based system. It allows IPC with pipes, access to devices, including storage through regular files and organization with directories. # Everything is a file In Unix, there's a say: "everything is a file, if it's not a file, it's a process". Well, most things are really files, and that's why the VFS is at the center of the system, including for device drivers. # Special files, procfs and others When handling with special files (character and block device nodes), procfs files and others, we'll use some common structures. These include the *struct file\\_operations*, *struct file* and *struct inode*. Do not forget to include linux/fs.h. # File Operations * owner * open * release * flush * read * write * ioctl * unlocked\\_ioctl * llseek * poll * mmap * many others # Opened File * f\\_mode * f\\_flags * f\\_pos * f\\_op * private\\_data # Filesystem File: inode The inode is a representation of the file as in its filesystem, including its major/minor numbers and pointers to the corresponding device representation. # Character Devices # Device Number Macros Nowadays, major number is 12 bits and minor number is 20 bits. This may change in the future, so macros should be used. * include linux/kdev\\_t.h * MAJOR * MINOR * MKDEV # Character devices allocation In Linux, major and minor numbers have to be requested or allocated. The calls to do that for character devices are: * int register\\_chrdev\\_region (dev\\_t first, unsigned int count, char *name); * int alloc\\_chrdev\\_region (dev\\_t *dev, unsigned int firstminor, unsigned int count, char *name); * void unregister\\_chrdev\\_region (dev\\_t dev, unsigned int count); # cdev structure Use *cdev\\_alloc* or *cdev\\_init* to allocate or initalize a cdev structure. Use *cdev\\_add* and *cdev\\_del* to register and unregister it. # Open/Release Implementing open and release should be very simple for many devices. They usually allocate data, and multiplex devices by minor number. # Inode structure Use *imajor* and *iminor* to get the major and minor number from an inode structure. # Read Read may write to user space less bytes than requested. # Write Write is very similar to read. Only problem is that many applications misbehave when driver writes less bytes than requested.