一、字符设备驱动概述
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);