Linux TTY驱动/串口驱动开发
一、TTY介绍
当前主要有三种类型tty设备及驱动程序:控制台、pty和串口。其中控制台和pty可看作为虚拟tty设备,物理tty设备包含串口、USB转串口、SPI转串口等。
二、TTY设备及驱动信息查看
确定tty设备及驱动程序类型可查阅/proc/tty/drivers文件。如下所示:
文件从左至右列举了:驱动程序名称,默认节点名称,驱动程序主设备号,次设备号范围,tty驱动程序类型。
以cdc-acm驱动为例,驱动为acm,节点名为/dev/ttyACMx,类型为serial串口。
当前注册并存在于内核的tty设备在/sys/class/tty下都有自己的子目录,如将USB CDC转双串口芯片CH342接入USB主机时,信息如下:
三、TTY驱动概览
Linux tty驱动包含硬件、tty驱动层、tty线路规程及tty核心层。
tty驱动层:将发送给它的数据格式化成硬件能理解的格式,并从硬件那里接收数据。
tty线路规程:使用特殊方法,把从用户或硬件接收的数据格式化,这类格式化通常使用一些协议完成转换,比如PPP或者蓝牙。
tty数据发送:tty核心从用户层得到发往tty设备的数据,然后把数据发送给tty线路规程驱动,该驱动负责把数据传递给tty驱动程序,tty驱动程序对数据进行格式化,然后才能发送给硬件。
tty数据接收:tty硬件接收的数据会传递给tty驱动程序,然后流入tty线路规程驱动程序,接着是tty核心,最后用户从tty核心获取数据。
四、TTY驱动实现
tty驱动的注册与注销
tty驱动程序的主要数据结构是结构tty_driver,被用来向tty核心注册和注销驱动程序。
注册tty驱动程序时,会同时注册字符设备驱动。
注册tty驱动
接口:tty_register_driver
- 指定驱动名
- 指定串口设备名
- 分配主从设备号
注销tty驱动
接口:tty_unregister_driver
实现TTY操作函数集
tty核心将和硬件有关的操作,抽象、封装出来,形成名称为struct tty_operations的数据结构,具体的tty driver不需要关心具体的业务逻辑,只需要根据实际的硬件情况,实现这些操作接口即可。
这些操作接口主要为上层tty应用程序操作硬件提供硬件实现,驱动和应用通过termios结构体关联,需要实现的通信接口主要包括:
- 设备的打开(open)和关闭(close)
- 设备的读(read)和写(write)
- 线路设置(set_termios):可看作串口参数配置
- 设置与获取控制线路参数(tiocmget/tiocmset):可看作MODEM信号读写
- 其他自定义ioctls方法:如设置和获得串口线路信息等
如:CDC驱动中相应实现
/*
* TTY driver structures.
*/
static const struct tty_operations acm_ops = {
.install = acm_tty_install,
.open = acm_tty_open,
.close = acm_tty_close,
.cleanup = acm_tty_cleanup,
.hangup = acm_tty_hangup,
.write = acm_tty_write,
.write_room = acm_tty_write_room,
.ioctl = acm_tty_ioctl,
.throttle = acm_tty_throttle,
.unthrottle = acm_tty_unthrottle,
.chars_in_buffer = acm_tty_chars_in_buffer,
.break_ctl = acm_tty_break_ctl,
.set_termios = acm_tty_set_termios,
.tiocmget = acm_tty_tiocmget,
.tiocmset = acm_tty_tiocmset,
.get_serial = get_serial_info,
.set_serial = set_serial_info,
.get_icount = acm_tty_get_icount,
};