I. Write function to the underlying drive process in the application
As mentioned earlier, first register the serial port, using the Uart_register_driver function, respectively, Tty_register_driver,cdev_init function, to find the use of file_operations, The unified interface between the application and the TTY architecture. Step no longer repeat.
static const struct file_operations tty_fops = {. Llseek = No_llseek,. Read = Tty_read, .write = . Poll = Tty_poll,. Unlocked_ioctl = Tty_ioctl,. Compat_ioctl = Tty_compat_ioctl,. Open = Tty_open,. Release = Tty_release,. Fasync = Tty_fasync,};
tty_write function
static ssize_t tty_write (structconstchar __user *buf, *PPOs) { struct inode *inode = file->f_path.dentry->d_inode; struct tty_struct *tty = file_tty (file); struct tty_ldisc *ld; ssize_t ret; ... = do_tty_write (ld->ops->Write, TTY, file, buf, count); ...}
This is called by the Do_tty_write function to the function in the line discipline (LDISC), with the structure named Tty_ldisc_n_tty.
structTty_ldisc_ops Tty_ldisc_n_tty ={. Magic=tty_ldisc_magic,. Name="N_tty",. Open=N_tty_open,. Close=n_tty_close,. Flush_buffer=N_tty_flush_buffer,. Chars_in_buffer=N_tty_chars_in_buffer,. Read=N_tty_read, . Write = N_tty_write, . IOCTL=n_tty_ioctl,. Set_termios=N_tty_set_termios,. Poll=n_tty_poll,. Receive_buf=n_tty_receive_buf,. Write_wakeup=N_tty_write_wakeup};
N_tty_write function
static ssize_t n_tty_write (structstruct file *file, constChar *buf, size_t nr) { constchar *b = buf; Declare_waitqueue (wait, current); int C; 0;
...
c = Tty->ops->write (TTY, B, NR);
...
}
OPS is a struct tty_operations type, as described in the above structure named
Static Const struct tty_operations uart_ops = { ... . Write = uart_write, ... };
Uart_write function
Static intUart_write (structTty_struct *TTY,ConstUnsignedChar*buf,intcount) { structUart_state *state = tty->Driver_data; structUart_port *Port; structCIRC_BUF *circ; unsignedLongflags; intC, ret =0;
...
Uart_start (TTY);
...
}
The __uart_start function is also called in the Uart_start function
Static void __uart_start (struct tty_struct *tty) { struct uart_state *state = tty- >driver_data; struct uart_port *port = state->uart_port; if (!uart_circ_empty (&state->xmit) && state->xmit.buf && !tty->stopped &&! tty->hw_stopped) port->ops->start_tx (port);}
Here the port is the Uart_port type, and finally arrived at the bottom of the drive, good tired. Again this array, the same set of function operations
Static structS3c24xx_uart_port S3c24xx_serial_ports[config_serial_samsung_uarts] = { [0] ={. Port= { .Lock= __spin_lock_unlocked (s3c24xx_serial_ports[0].port.Lock),. Iotype=Upio_mem,. IRQ=irq_s3cuart_rx0,. UARTCLK=0,. Fifosize= -, . OPS = & s3c24xx_serial_ops, . Flags=upf_boot_autoconf,. Line=0, } },
...
}
static void S3c24xx_serial_start_ Tx (struct uart_port *port) { struct s3c24xx_uart_port *ourport = To_ourport (port); if (! if (port->flags & Upf_cons_flow) s3c24xx_serial_rx_disable (port); ENABLE_IRQ (ourport ->TX_IRQ); tx_enabled (port) = 1 }}
But let everyone crossing disappointed . This function is simple, functionally speaking, if you do not open the send enable to open. So what is the serial port driver doing to send data related operations?
Predict the funeral, and listen to the next analysis.
If you have questions or suggestions, please note.
Linux Serial driver Analysis--Send data