在Linux中,UART串口驱动完全遵循tty驱动的框架结构,但是进行了底层操作的再次封装,所以先介绍tty终端设备驱动。
一、终端设备
1.串行端口终端(/dev/ttySACn)
2.伪终端(/dev/pty/)
3.控制台终端(/dev/ttyn,/dev/console)
二、驱动结构
1.tty分层结构如下图所示:
包含tty核心、tty线路规程、tty驱动,其中tty规程的工作是以特殊的方式格式化从一个用户或者硬件接收到的数据,常采用一个协议转换的形式,如PPP、Bluetooth。
2.tty主要源文件关系及数据流向如下图:
特定的tty设备驱动的主体工作是填充tty_driver结构体中的成员,实现tty_operations结构体中的一系列成员函数
struct tty_driver { int magic; /* magic number for this structure */ struct kref kref; /* Reference management */ struct cdev cdev; struct module *owner; const char *driver_name;//驱动名字 const char *name;//驱动设备结点名字 int name_base; /* offset of printed name */ int major; /* major device number */ int minor_start; /* start of minor device number */ int minor_num; /* number of *possible* devices */ int num; /* number of devices allocated */ short type; /* type of tty driver */ short subtype; /* subtype of tty driver */ struct ktermios init_termios; /* Initial termios */ int flags; /* tty driver flags */ struct proc_dir_entry *proc_entry; /* /proc fs entry */ struct tty_driver *other; /* only used for the PTY driver */ /* * Pointer to the tty data structures */ struct tty_struct **ttys; struct ktermios **termios; struct ktermios **termios_locked; void *driver_state; /* * Driver methods */ const struct tty_operations *ops; struct list_head tty_drivers; };
tty_operations中的成员函数需在特定设备tty驱动模块初始化函数中被赋值;
tty_struct结构体被tty核心用来保存当前tty端口的状态。
struct tty_operations { struct tty_struct * (*lookup)(struct tty_driver *driver, struct inode *inode, int idx); int (*install)(struct tty_driver *driver, struct tty_struct *tty); void (*remove)(struct tty_driver *driver, struct tty_struct *tty); int (*open)(struct tty_struct * tty, struct file * filp); void (*close)(struct tty_struct * tty, struct file * filp); void (*shutdown)(struct tty_struct *tty); void (*cleanup)(struct tty_struct *tty); int (*write)(struct tty_struct * tty, const unsigned char *buf, int count); int (*put_char)(struct tty_struct *tty, unsigned char ch); void (*flush_chars)(struct tty_struct *tty); int (*write_room)(struct tty_struct *tty); int (*chars_in_buffer)(struct tty_struct *tty); int (*ioctl)(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); long (*compat_ioctl)(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); void (*set_termios)(struct tty_struct *tty, struct ktermios * old); void (*throttle)(struct tty_struct * tty); void (*unthrottle)(struct tty_struct * tty); void (*stop)(struct tty_struct *tty); void (*start)(struct tty_struct *tty); void (*hangup)(struct tty_struct *tty); int (*break_ctl)(struct tty_struct *tty, int state); void (*flush_buffer)(struct tty_struct *tty); void (*set_ldisc)(struct tty_struct *tty); void (*wait_until_sent)(struct tty_struct *tty, int timeout); void (*send_xchar)(struct tty_struct *tty, char ch); int (*tiocmget)(struct tty_struct *tty, struct file *file); int (*tiocmset)(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); int (*resize)(struct tty_struct *tty, struct winsize *ws); int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); #ifdef CONFIG_CONSOLE_POLL int (*poll_init)(struct tty_driver *driver, int line, char *options); int (*poll_get_char)(struct tty_driver *driver, int line); void (*poll_put_char)(struct tty_driver *driver, int line, char ch); #endif const struct file_operations *proc_fops; };