\subsection{Character drivers}

\begin{frame}
  \frametitle{Usefulness of character drivers}
  \begin{itemize}
  \item Except for storage device drivers, most drivers for devices
    with input and output flows are implemented as character drivers.
  \item So, most drivers you will face will be character drivers.
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Creating a Character Driver 1/2}
  \begin{itemize}
  \item User-space needs
    \begin{itemize}
    \item The name of a device file in \code{/dev} to interact with
      the device driver through regular file operations (open, read,
      write, close...)
    \end{itemize}
  \item The kernel needs
    \begin{itemize}
    \item To know which driver is in charge of device files with a
      given major / minor number pair
    \item For a given driver, to have handlers (\emph{file
        operations}) to execute when user-space opens, reads, writes
      or closes the device file.
    \end{itemize}
  \end{itemize}
\end{frame}


\begin{frame}
  \frametitle{Creating a Character Driver 2/2}
  \begin{center}
    \includegraphics[width=\textwidth]{slides/kernel-driver-development-character-drivers/user-kernel-exchanges.pdf}
  \end{center}
\end{frame}

\begin{frame}
  \frametitle{Implementing a character driver}
  \begin{itemize}
  \item Four major steps
    \begin{itemize}
    \item Implement operations corresponding to the system calls an
      application can apply to a file: \emph{file operations}
    \item Define a \code{file_operations} structure associating function
      pointers to their implementation in your driver
    \item Reserve a set of major and minors for your driver
    \item Tell the kernel to associate the reserved major and minor to
      your file operations
    \end{itemize}
  \item This is a very common design scheme in the Linux kernel
    \begin{itemize}
    \item A common kernel infrastructure defines a set of operations
      to be implemented by a driver and functions to register your
      driver
    \item Your driver only needs to implement this set of well-defined
      operations
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{File operations 1/3}
  \begin{itemize}
  \item Before registering character devices, you have to define
    \code{file_operations} (called \emph{fops}) for the device files.
  \item The \code{file_operations} structure is generic to all files
    handled by the Linux kernel. It contains many operations that
    aren't needed for character drivers.
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{File operations 2/3}
  \begin{itemize}
  \item Here are the most important operations for a character
    driver. All of them are optional.
  \end{itemize}
\begin{minted}{c}
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 (*mmap) (struct file *, struct vm_area_struct *);
    int (*open) (struct inode *, struct file *);
    int (*release) (struct inode *, struct file *);
};
\end{minted}
\end{frame}

\begin{frame}[fragile]
  \frametitle{open() and release()}
  \begin{itemize}
  \item \mint{c}+int foo_open(struct inode *i, struct file *f)+
    \begin{itemize}
    \item Called when user-space opens the device file.
    \item \code{inode} is a structure that uniquely represent a file
      in the system (be it a regular file, a directory, a symbolic
      link, a character or block device)
    \item \code{file} is a structure created every time a file is
      opened. Several file structures can point to the same
      \code{inode} structure.
      \begin{itemize}
      \item Contains information like the current position, the
        opening mode, etc.
      \item Has a \code{void *private_data} pointer that one can
        freely use.
      \item A pointer to the file structure is passed to all other
        operations
      \end{itemize}
    \end{itemize}
  \item \mint{c}+int foo_release(struct inode *i, struct file *f)+
    \begin{itemize}
    \item Called when user-space closes the file.
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{read()}
  \begin{itemize}
  \item \mint{c}+ssize_t foo_read(struct file *f, __user char *buf,+
    \mint{c}+size_t sz, loff_t *off)+
    \begin{itemize}
    \item Called when user-space uses the \code{read()} system call on
      the device.
    \item Must read data from the device, write at most \code{sz}
      bytes in the user-space buffer \code{buf}, and update the
      current position in the file \code{off}. \code{f} is a pointer
      to the same file structure that was passed in the \code{open()}
      operation
    \item Must return the number of bytes read.
    \item On UNIX, \code{read()} operations typically block when there
      isn't enough data to read from the device
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{write()}
  \begin{itemize}
  \item \mint{c}+ssize_t foo_write(struct file *f,+
    \mint{c}+__user const char *buf, size_t sz, loff_t *off)+
    \begin{itemize}
    \item Called when user-space uses the \code{write()} system call
      on the device
    \item The opposite of \code{read}, must read at most \code{sz}
      bytes from \code{buf}, write it to the device, update \code{off}
      and return the number of bytes written.
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Exchanging data with user-space 1/3}
  \begin{itemize}
  \item Kernel code isn't allowed to directly access user-space
    memory, using \code{memcpy} or direct pointer dereferencing
    \begin{itemize}
    \item Doing so does not work on some architectures
    \item If the address passed by the application was invalid, the
      application would segfault.
    \end{itemize}
  \item To keep the kernel code portable and have proper error
    handling, your driver must use special kernel functions to
    exchange data with user-space.
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Exchanging data with user-space 2/3}
  \begin{itemize}
  \item A single value
    \begin{itemize}
    \item \code{get_user(v, p);}
      \begin{itemize}
      \item The kernel variable \code{v} gets the value pointed by the
        user-space pointer \code{p}
      \end{itemize}
    \item \code{put_user(v, p);}
      \begin{itemize}
      \item The value pointed by the user-space pointer \code{p} is
        set to the contents of the kernel variable \code{v}.
      \end{itemize}
    \end{itemize}
  \item A buffer
    \begin{itemize}
    \item \mint{c}+unsigned long copy_to_user(void __user *to,+
      \mint{c}+const void *from, unsigned long n);+
    \item \mint{c}+unsigned long copy_from_user(void *to,+
      \mint{c}+const void __user *from, unsigned long n);+
    \end{itemize}
  \item The return value must be checked. Zero on success, non-zero on
    failure. If non-zero, the convention is to return -\code{EFAULT}.
  \end{itemize}
\end{frame}

\begin{frame}
 \frametitle{Exchanging data with user-space 3/3}
 \begin{center}
    \includegraphics[width=\textwidth]{slides/kernel-driver-development-character-drivers/copy-to-from-user.pdf}
 \end{center}
\end{frame}

\begin{frame}
  \frametitle{Zero copy access to user memory}
  \begin{itemize}
  \item Having to copy data to our from an intermediate kernel buffer
    is expensive.
  \item \emph{Zero copy} options are possible:
    \begin{itemize}
    \item \code{mmap()} system call to allow user space to directly
      access memory mapped I/O space (covered in the \code{mmap()}
      section).
    \item \code{get_user_pages()} to get a mapping to user pages
      without having to copy them. See \url{http://j.mp/oPW6Fb}
      (Kernel API doc). This API is more complex to use though.
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Read Operation Example}
\begin{minted}[fontsize=\tiny]{c}
static ssize_t
acme_read(struct file *file, char __user * buf, size_t count, loff_t * ppos)
{
        /* The acme_buf address corresponds to a device I/O memory area */
        /* of size acme_bufsize, obtained with ioremap() */
        int remaining_size, transfer_size;

        remaining_size = acme_bufsize - (int)(*ppos);
                                /* bytes left to transfer */
        if (remaining_size == 0) {
                                /* All read, returning 0 (End Of File) */
                return 0;
        }

        /* Size of this transfer */
        transfer_size = min_t(int, remaining_size, count);

        if (copy_to_user
            (buf /* to */ , acme_buf + *ppos /* from */ , transfer_size)) {
                return -EFAULT;
        } else {                /* Increase the position in the open file */
                *ppos += transfer_size;
                return transfer_size;
        }
}
\end{minted}
Piece of code available at \url{http://free-electrons.com/doc/c/acme.c}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Write Operation Example}
\begin{minted}[fontsize=\tiny]{c}
static ssize_t
acme_write(struct file *file, const char __user *buf, size_t count,
           loff_t *ppos)
{
        int remaining_bytes;

        /* Number of bytes not written yet in the device */
        remaining_bytes = acme_bufsize - (*ppos);

        if (count > remaining_bytes) {
                /* Can't write beyond the end of the device */
                return -EIO;
        }

        if (copy_from_user(acme_buf + *ppos /*to*/ , buf /*from*/ , count)) {
                return -EFAULT;
        } else {
                /* Increase the position in the open file */
                *ppos += count;
                return count;
        }
}
\end{minted}
Piece of code available at \url{http://free-electrons.com/doc/c/acme.c}
\end{frame}


\begin{frame}[fragile]
  \frametitle{unlocked\_ioctl()}
  \begin{itemize}
  \item \mint{c}+long unlocked_ioctl(struct file *f,+
    \mint{c}+unsigned int cmd, unsigned long arg)+
    \begin{itemize}
    \item Associated to the \code{ioctl()} system call.
    \item Called unlocked because it doesn't hold the Big Kernel Lock.
    \item Allows to extend the driver capabilities beyond the limited
      read/write API.
    \item For example: changing the speed of a serial port, setting
      video output format, querying a device serial number...
    \item \code{cmd} is a number identifying the operation to perform
    \item \code{arg} is the optional argument passed as third argument
      of the \code{ioctl()} system call. Can be an integer, an
      address, etc.
    \item The semantic of \code{cmd} and \code{arg} is
      driver-specific.
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{ioctl() example: kernel side}
\begin{minted}[fontsize=\tiny]{c}
static long phantom_ioctl(struct file *file, unsigned int cmd,
    unsigned long arg)
{
    struct phm_reg r;
    void __user *argp = (void __user *)arg;

    switch (cmd) {
    case PHN_SET_REG:
        if (copy_from_user(&r, argp, sizeof(r)))
            return -EFAULT;
        /* Do something */
        break;
    case PHN_GET_REG:
        if (copy_to_user(argp, &r, sizeof(r)))
            return -EFAULT;
        /* Do something */
        break;
    default:
        return -ENOTTY;
    }

    return 0; }
\end{minted}
Selected excerpt from \code{drivers/misc/phantom.c}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Ioctl() Example: Application Side}
\begin{minted}{c}
int main(void)
{
    int fd, ret;
    struct phm_reg reg;

    fd = open("/dev/phantom");
    assert(fd > 0);

    reg.field1 = 42;
    reg.field2 = 67;

    ret = ioctl(fd, PHN_SET_REG, & reg);
    assert(ret == 0);

    return 0;
}
\end{minted}
\end{frame}

\begin{frame}[fragile]
  \frametitle{File Operations Definition: Example 3/3}
  \begin{itemize}
  \item Defining a \code{file_operations} structure:
\begin{minted}{c}
#include <linux/fs.h>
static struct file_operations acme_fops =
{
    .owner = THIS_MODULE,
    .read = acme_read,
    .write = acme_write,
};
\end{minted}
  \item You just need to supply the functions you implemented!
    Defaults for other functions (such as open, release...) are fine
    if you do not implement anything special.
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{dev\_t data type}
  \begin{itemize}
  \item Kernel data type to represent a major / minor number pair
    \begin{itemize}
    \item Also called a \emph{device number}.
    \item Defined in \code{linux/kdev_t.h}
    \item Linux 2.6: 32 bit size (major: 12 bits, minor: 20 bits)
    \item Macro to compose the device number
      \begin{itemize}
      \item \code{MKDEV(int major, int minor);}
      \end{itemize}
    \item Macro to extract the minor and major numbers:
      \begin{itemize}
      \item \code{MAJOR(dev_t dev);}
      \item \code{MINOR(dev_t dev);}
      \end{itemize}
  \end{itemize}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Registering device numbers 1/2}
\begin{minted}[fontsize=\small]{c}
#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 */
\end{minted}
Returns 0 if the allocation was successful.\\
Example
\begin{minted}[fontsize=\small]{c}
static dev_t acme_dev = MKDEV(202, 128);

if (register_chrdev_region(acme_dev, acme_count, "acme")) {
        pr_err("Failed to allocate device number\n");
...
\end{minted}
\end{frame}

\begin{frame}
  \frametitle{Registering device numbers 2/2}
  \begin{itemize}
  \item If you don't have fixed device numbers assigned to your driver
    \begin{itemize}
    \item Better not to choose arbitrary ones. There could be
      conflicts with other drivers.
    \item The kernel API offers an \code{alloc_chrdev_region} function
      to have the kernel allocate free ones for you. You can find the
      allocated major number in \code{/proc/devices}.
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Information on registered devices: /proc/devices}
\begin{verbatim}
Character devices:
  1 mem
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
...

Block devices:
  1 ramdisk
  7 loop
  8 sd
  9 md
 11 sr
179 mmc
254 mdp
...
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Character device registration 1/2}
  \begin{itemize}
  \item The kernel represents character drivers with a cdev structure
  \item Declare this structure globally (within your module):
\begin{minted}{c}
#include <linux/cdev.h>

static struct cdev acme_cdev;
\end{minted}
  \item In the init function, initialize the structure:
\begin{minted}{c}
cdev_init(&acme_cdev, &acme_fops);
\end{minted}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Character device registration 2/2}
  \begin{itemize}
  \item Then, now that your structure is ready, add it to the system:
\begin{minted}[fontsize=\small]{c}
int cdev_add(
    struct cdev *p,  /* Character device structure */
    dev_t dev,       /* Starting device major/minor */
    unsigned count); /* Number of devices */
\end{minted}
  \item 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!
  \item Example (continued):
\end{itemize}
\begin{minted}[fontsize=\small]{c}
if (cdev_add(&acme_cdev, acme_dev, acme_count)) {
    printk (KERN_ERR "Char driver registration failed\n");
    ...
\end{minted}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Character device unregistration}
  \begin{itemize}
  \item First delete your character device
    \begin{itemize}
    \item \mint{c}+void cdev_del(struct cdev *p);+
    \end{itemize}
  \item Then, and only then, free the device number
    \begin{itemize}
    \item \mint{c}+void unregister_chrdev_region(dev_t from,+
      \mint{c}+unsigned count);+
    \end{itemize}
  \item Example (continued):
\begin{minted}{c}
cdev_del(&acme_cdev);
unregister_chrdev_region(acme_dev, acme_count);
\end{minted}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Linux error codes}
  \begin{itemize}
  \item The kernel convention for error management is
    \begin{itemize}
    \item Return 0 on success
    \item Return a negative error code on failure
    \end{itemize}
  \item Error codes
    \begin{itemize}
    \item \code{include/asm-generic/errno-base.h}
    \item \code{include/asm-generic/errno.h}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Char driver example summary 1/4}
\begin{minted}[fontsize=\small]{c}
static void *acme_buf;
static int acme_bufsize = 8192;

static int acme_count = 1;
static dev_t acme_dev = MKDEV(202, 128);

static struct cdev acme_cdev;

static ssize_t acme_read(...) {...}
static ssize_t acme_write(...) {...}

static const struct file_operations acme_fops = {
        .owner = THIS_MODULE,
        .read = acme_read,
        .write = acme_write,
};
\end{minted}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Char driver example summary 2/4}
\begin{minted}[fontsize=\tiny]{c}
static int __init acme_init(void)
{
        int err;
        acme_buf = ioremap(ACME_PHYS, acme_bufsize);

        if (!acme_buf) {
                err = -ENOMEM;
                goto err_exit;
        }

        if (register_chrdev_region(acme_dev, acme_count, "acme")) {
                err = -ENODEV;
                goto err_free_buf;
        }

        cdev_init(&acme_cdev, &acme_fops);

        if (cdev_add(&acme_cdev, acme_dev, acme_count)) {
                err = -ENODEV;
                goto err_dev_unregister;
        }

        return 0;

 err_dev_unregister:
        unregister_chrdev_region(acme_dev, acme_count);
 err_free_buf:
        iounmap(acme_buf);
 err_exit:
        return err;
}
\end{minted}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Character Driver Example Summary 3/4}
\begin{minted}[fontsize=\small]{c}
static void __exit acme_exit(void)
{
        cdev_del(&acme_cdev);
        unregister_chrdev_region(acme_dev, acme_count);
        iounmap(acme_buf);
}

module_init(acme_init);
module_exit(acme_exit);    
\end{minted}
\end{frame}

\begin{frame}
\frametitle{Character Driver Example Summary 4/4}
  \begin{itemize}
  \item Kernel: Character Device Writer
    \begin{itemize}
    \item Define the file operations callbacks for the device file:
      read, write, ioctl, ...
    \item In the module init function, reserve major and minor numbers
      with \code{register_chrdev_region()}, init a \code{cdev}
      structure with your file operations and add it to the system
      with \code{cdev_add()}.
    \end{itemize}
  \item User-space: system administration
    \begin{itemize}
    \item Load the character driver module
    \item Create device files with matching major and minor numbers if
      needed. The device file is ready to use!
    \end{itemize}
  \item User-space: system user
    \begin{itemize}
    \item Open the device file, read, write, or send ioctl's to it.
    \end{itemize}
  \item Kernel
    \begin{itemize}
    \item Executes the corresponding file operations
    \end{itemize}
  \end{itemize}
\end{frame}
