linux终端设备驱动分析

一、字符设备驱动概述

1、两个结构体

struct cdev{

...

struct  file operations  *ops;

}

struct file_opreations{  ...  }

2、分配/注销设备号函数register_chrdev_region()/  unregister_chrdev_region (  )

          注册/注销设备   cdev_add ()  /     cdev_del   (   )


3、简单的驱动架构

     a、头文件、宏定义等

     b、字符设备结构体的定义

           操作结构体的定义及成员的填写

     c、初始化并添加cdev结构体

     d、加载与卸载函数      



二、终端设备

属于字符设备

1、终端设备驱动结构
    Linux内核中 tty的层次结构包含tty核心、tty线路规程和tty驱动

2、结构分析

通用层(drivers/char/...)

    在tty_dirver.h

struct tty_driver{ ... struct cdev *cdev ...}  实现对cdev的封装

struct tty_opreations{ ... }  特有的操作,相对于file_operations结构体

    在tty_io.c

1、定义 struct  cdev tty_cdev{ ... }  以及console结构体

源码:static struct cdev tty_cdev, console_cdev;

     

2、定义 struct  file_operations tty_ops{ ... } 以及 console_ops 结构体 

源码:

static const struct file_operations tty_fops = {
.llseek = no_llseek,
.read = tty_read,
.write = tty_write,
.poll = tty_poll,
.unlocked_ioctl = tty_ioctl,
.compat_ioctl = tty_compat_ioctl,
.open = tty_open,
.release = tty_release,
.fasync = tty_fasync,
};

static const struct file_operations console_fops = {
.llseek = no_llseek,
.read = tty_read,
.write = redirected_tty_write,
.poll = tty_poll,
.unlocked_ioctl = tty_ioctl,
.compat_ioctl = tty_compat_ioctl,
.open = tty_open,
.release = tty_release,
.fasync = tty_fasync,
};

3、注册tty设备,console

源码:

static int __init tty_init(void)
{
cdev_init(&tty_cdev, &tty_fops);
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
   register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n");
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL,
     "tty");
cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
   register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n");
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
     "console");
#ifdef CONFIG_VT
vty_init(&console_fops);
#endif
return 0;
}
module_init(tty_init);


4.定义接口函数

tty驱动,tty设备的注册和注销等接口函数



特有层(drivers/setial/...)

1、serial_core.h

(1)定义了struct uart_driver { ...struct tty_driver...  }   实现了对  tty_driver  的封装

        定义 了 struct  uart_ops  {  ....   }   特有的操作

(2)定义了uart_port结构体,用于描述UART端口


2、在serial_core.c中 

(1)定义了struct tty_operations  uart_ops{  } 结构体,及其成员

 实现了tty_operations  与 uart_ops 的连接,用  uart_ops 的 成员填充了 tty_operations 的成员

(2)定义关于uart的 接口函数   uart接口函数包含  tty驱动的接口函数 


 

3、开发板串口驱动位于samsung,c(定义了一系列接口函数) 

(1)定义了static struct uart_ops s3c24xx_serial_ops 并填充了uart_ops

static struct uart_ops s3c24xx_serial_ops = {
.pm = s3c24xx_serial_pm,
.tx_empty = s3c24xx_serial_tx_empty,
.get_mctrl = s3c24xx_serial_get_mctrl,
.set_mctrl = s3c24xx_serial_set_mctrl,
.stop_tx = s3c24xx_serial_stop_tx,
.start_tx = s3c24xx_serial_start_tx,
.stop_rx = s3c24xx_serial_stop_rx,
.enable_ms = s3c24xx_serial_enable_ms,
.break_ctl = s3c24xx_serial_break_ctl,
.startup = s3c24xx_serial_startup,
.shutdown = s3c24xx_serial_shutdown,
.set_termios = s3c24xx_serial_set_termios,
.type = s3c24xx_serial_type,
.release_port = s3c24xx_serial_release_port,
.request_port = s3c24xx_serial_request_port,
.config_port = s3c24xx_serial_config_port,
.verify_port = s3c24xx_serial_verify_port,
};


(2)定义static struct uart_driver s3c24xx_uart_drv 

static struct uart_driver s3c24xx_uart_drv = {
.owner = THIS_MODULE,
.dev_name = "s3c2410_serial",
.nr = CONFIG_SERIAL_SAMSUNG_UARTS,
.cons = S3C24XX_SERIAL_CONSOLE,
.driver_name = S3C24XX_SERIAL_NAME,
.major = S3C24XX_SERIAL_MAJOR,
.minor = S3C24XX_SERIAL_MINOR,
};


(3)定义static struct s3c24xx_uart_port s3c24xx_serial_ports结构体


(4)

int s3c24xx_serial_init(struct platform_driver *drv,
struct s3c24xx_uart_info *info)
{
dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);


#ifdef CONFIG_PM
drv->suspend = s3c24xx_serial_suspend;
drv->resume = s3c24xx_serial_resume;
#endif


return platform_driver_register(drv);
}
EXPORT_SYMBOL_GPL(s3c24xx_serial_init);

(5)注册s3c24xx_uart_drv
static int __init s3c24xx_serial_modinit(void)
{
int ret;
ret = uart_register_driver(&s3c24xx_uart_drv);
if (ret < 0) {
printk(KERN_ERR "failed to register UART driver\n");
return -1;
}
return 0;
}


static void __exit s3c24xx_serial_modexit(void)
{
uart_unregister_driver(&s3c24xx_uart_drv);
}


module_init(s3c24xx_serial_modinit);
module_exit(s3c24xx_serial_modexit);


4、 s3c2440. c  文件主要完成   获取资源,定义,注册

(1)定义platform设备

static struct platform_driver s3c2440_serial_driver = {
.probe = s3c2440_serial_probe,
.remove = __devexit_p(s3c24xx_serial_remove),
.driver = {
.name = "s3c2440-uart",
.owner = THIS_MODULE,
},
};

(2)注册设备模块

static int __init s3c2440_serial_init(void)
{
return s3c24xx_serial_init(&s3c2440_serial_driver, &s3c2440_uart_inf);
}

static void __exit s3c2440_serial_exit(void)
{
platform_driver_unregister(&s3c2440_serial_driver);
}


module_init(s3c2440_serial_init);
module_exit(s3c2440_serial_exit);

你可能感兴趣的:(linux终端设备驱动分析)