I have handled several serial port problems, so I have a little time to sort out these items in the past few days.
The directory is roughly divided into the following parts:
0, Background
1. Serial Drive Structure
2. Implementation of serial port driver
3. About tty Core
Bytes ---------------------------------------------------------------------------------------------------
0, Background
When you review this piece of code, the Linux code tree is often confused by the code of UART, TTY and serial device in the Middle East. According to the Linux driver model, the serial driver is actually perfectly assembled in layers.
For direct access to serial interfaces, this is a device interface that is widely used on computers or embedded devices. UART, which we often refer to, is actually a hardware implementation method for serial communication, but it is the earliest and most widely used method, so we hear a lot. Now there are more and more hardware implementation methods behind the serial port: infrared devices, USB devices, and so on. There are more and more types of chips connected to those wires, each type of film requires a different driver to work. Based on these situations and development trends, the Linux experts abstracted some common interfaces to form a subsystem supporting multiple serial communications-tty core, of course, a common interface supporting Linux device models is also provided to facilitate the compilation of driver code that complies with the Linux device model specifications ,:).
Note: tty does not fully refer to the underlying abstraction of the serial port.
1. Serial Drive Structure
For a general UART serial port, its implementation is divided into three layers, the bottom layer is tty core, the middle is UART core, and the top layer is a specific chip driver.
The driver at the upper layer uses the UART core API to register devices and drivers. The UART core uses the TTY core API to register device drivers.
2. Implementation of serial port driver
When the system starts, tty will register as a char device early to the kernel (Driver/Char/tty_io.c), because it is the purest abstraction ,:).
UART core is not registered as a module to the kernel. It implements some common APIs for the serial port device that uses UART to call.
The upper-Layer Chip driver relies on Some APIs of UART core to implement relevant functions for user layer configuration and use based on the specific characteristics of the chip and the basic mode of serial communication. It mainly implements some callback functions declared in some tty_operations. If you use UART devices, some implementations will also be implemented in UART core.
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,
Void * rx_callback );
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;
};
3. About tty Core
Tty refers to a terminal in the Linux field. It can refer to any terminal device, including serial port Devices and console devices.
In the/dev directory, if you see TTYs *, it indicates that it refers to the serial port device (s 'serial' TTY ), pty refers to the virtual/Pseudo Terminal Device (pseudo TTY)
The tty sub-system uses tty_driver to represent a device driver abstracted at this level. tty implements the following API to register a terminal device driver:
1) alloc_tty_driver ()
2) tty_set_operations (): Create a tty entry point
3) tty_register_driver ()
4) tty_register_device ()
This makes the registration of a terminal driver very clear.