1. tty_io.c层的操作描述符
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,
};
2. nuc972_serial.c驱动注册
//对应驱动层操作,它的上一层是系统调用 tty_io.c的tty_fops
static const struct tty_operations uart_ops = {
.open = uart_open,
.close = uart_close,
.write = uart_write,
.put_char = uart_put_char,
.flush_chars = uart_flush_chars,
.write_room = uart_write_room,
.chars_in_buffer= uart_chars_in_buffer,
.flush_buffer = uart_flush_buffer,
.ioctl = uart_ioctl,
.throttle = uart_throttle,
.unthrottle = uart_unthrottle,
.send_xchar = uart_send_xchar,
.set_termios = uart_set_termios,
.set_ldisc = uart_set_ldisc,
.stop = uart_stop,
.start = uart_start,
.hangup = uart_hangup,
.break_ctl = uart_break_ctl,
.wait_until_sent= uart_wait_until_sent,
#ifdef CONFIG_PROC_FS
.proc_fops = &uart_proc_fops,
#endif
.tiocmget = uart_tiocmget,
.tiocmset = uart_tiocmset,
.get_icount = uart_get_icount,
#ifdef CONFIG_CONSOLE_POLL
.poll_init = uart_poll_init,
.poll_get_char = uart_poll_get_char,
.poll_put_char = uart_poll_put_char,
#endif
};
nuc970_serial.c驱动注册流程:
nuc970serial_init
uart_register_driver(&nuc970serial_reg)
uart_register_driver(struct uart_driver *drv)
struct tty_driver *normal;
normal = alloc_tty_driver(drv->nr);
normal->driver_name = drv->driver_name;
normal->name = drv->dev_name;
normal->major = drv->major;
normal->minor_start = drv->minor;
normal->type = TTY_DRIVER_TYPE_SERIAL;
normal->subtype = SERIAL_TYPE_NORMAL;
normal->init_termios = tty_std_termios;
normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
normal->driver_state = drv;
tty_set_operations(normal, &uart_ops); //注意驱动绑定的是 uart_ops
tty_register_driver(normal);
tty_register_driver(struct tty_driver *driver)
tty_cdev_add(driver, dev, 0, driver->num);
cdev_init(&driver->cdevs[index], &tty_fops); //tty_fops这个操作接口对应的是系统调用时的接口
list_add(&driver->tty_drivers, &tty_drivers);
3. n_gsm.c驱动注册
//n_gsm.c的驱动层操作,它的上一层对应tty_io.c tty_fops
static const struct tty_operations gsmtty_ops = {
.install = gsmtty_install,
.open = gsmtty_open,
.close = gsmtty_close,
.write = gsmtty_write,
.write_room = gsmtty_write_room,
.chars_in_buffer = gsmtty_chars_in_buffer,
.flush_buffer = gsmtty_flush_buffer,
.ioctl = gsmtty_ioctl,
.throttle = gsmtty_throttle,
.unthrottle = gsmtty_unthrottle,
.set_termios = gsmtty_set_termios,
.hangup = gsmtty_hangup,
.wait_until_sent = gsmtty_wait_until_sent,
.tiocmget = gsmtty_tiocmget,
.tiocmset = gsmtty_tiocmset,
.break_ctl = gsmtty_break_ctl,
};
//n_gsm.c的注册流程
gsm_init
static struct tty_driver *gsm_tty_driver;
gsm_tty_driver = alloc_tty_driver(256);
gsm_tty_driver->driver_name = "gsmtty";
gsm_tty_driver->name = "gsmtty";
gsm_tty_driver->major = 0; /* Dynamic */
gsm_tty_driver->minor_start = 0;
gsm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
gsm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
gsm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV
| TTY_DRIVER_HARDWARE_BREAK;
gsm_tty_driver->init_termios = tty_std_termios;
/* Fixme */
gsm_tty_driver->init_termios.c_lflag &= ~ECHO;
tty_set_operations(gsm_tty_driver, &gsmtty_ops); //注意驱动绑定的是 gsmtty_ops
tty_register_driver(gsm_tty_driver)
tty_cdev_add(driver, dev, 0, driver->num);
cdev_init(&driver->cdevs[index], &tty_fops); //tty_fops这个操作接口对应的是系统调用时的接口
list_add(&driver->tty_drivers, &tty_drivers); //
4. 总结
所以应用层在打开一个串口的时候先调用tty_io.c,即ops描述符为 tty_fops,再到下一层即为驱动注册时绑定的ops描述符,
如果为nuc970_serial.c驱动,则是 uart_ops,所以调用的顺序为 tty_fops-->uart_ops;
如果为n_gsm.c驱动,则是 gsmtty_ops,所以调用的顺序为 tty_fops-->gsmtty_ops;
比如你在打开一个串口,调用的顺序是tty_open[tty_io.c ]-->通过主、次设备号匹配到对应的驱动driver = tty_lookup_driver(device, filp, &noctty, &index)-->然后在是调用驱动的接口操作。tty->ops->open(tty, filp)[gsmtty_ops或者uart_ops]