TTY 驱动程序和 TTY 操作

分配

驱动程序需要做的第一件事是分配一个 struct tty_driver。这通过 tty_alloc_driver() (或 __tty_alloc_driver()) 完成。接下来,将新分配的结构填充信息。有关实际应填充的内容,请参阅本文档末尾的TTY 驱动程序参考

分配例程期望驱动程序最多可以处理的设备数量和标志。标志是 TTY 驱动程序标志中列出和描述的以 TTY_DRIVER_ 开头的标志。

当驱动程序即将被释放时,将对该驱动程序调用 tty_driver_kref_put()。它将递减引用计数,如果达到零,则释放驱动程序。

作为参考,此处详细解释了分配和释放函数

struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner, unsigned long flags)

分配 tty 驱动程序

参数

unsigned int lines

此驱动程序最多可以处理的行数

struct module *owner

负责此驱动程序的模块

unsigned long flags

一些 TTY_DRIVER_ 标志,将在 driver->flags 中设置

描述

不应直接调用此函数,应使用一些提供的宏。在 retval 上使用 IS_ERR() 和朋友。

void tty_driver_kref_put(struct tty_driver *driver)

减少对 tty 驱动程序的引用

参数

struct tty_driver *driver

要减少引用的驱动程序

描述

最终的 put 将销毁并释放驱动程序。

TTY 驱动程序标志

下面是 tty_alloc_driver() (或 __tty_alloc_driver()) 接受的标志的文档

TTY_DRIVER_RESET_TERMIOS

请求 tty 层在最后一个进程关闭设备时重置 termios 设置。特别是用于 PTY。

TTY_DRIVER_REAL_RAW

表示如果为 tty 设置此标志,驱动程序将保证不设置任何特殊字符处理标志

(IGNBRK || (!BRKINT && !PARMRK)) && (IGNPAR || !INPCK)

也就是说,如果没有理由让驱动程序将奇偶校验和中断字符的通知发送到线路驱动程序,则它不会这样做。如果设置了此标志,则允许线路驱动程序针对这种情况进行优化。(请注意,还有一个承诺,如果上述情况为真,也不会发出溢出信号。)

TTY_DRIVER_DYNAMIC_DEV

当在系统中找到设备时,需要通过调用 tty_register_device() 注册各个 tty 设备,并通过调用 tty_unregister_device() 取消注册,以便设备正确显示在 sysfs 中。如果未设置,则在调用 tty_register_driver() 时,tty 核心将在 sysfs 中创建所有 tty_driver.num 条目。这供驱动程序使用,这些驱动程序具有 tty 设备,这些设备可以在主 tty 驱动程序向 tty 核心注册时出现和消失。

TTY_DRIVER_DEVPTS_MEM

不要使用标准数组 (tty_driver.ttystty_driver.termios),而是使用通过 devpts 文件系统键控的动态内存。这仅适用于 PTY 驱动程序。

TTY_DRIVER_HARDWARE_BREAK

硬件处理中断信号。将请求的超时时间传递给 tty_operations.break_ctl,而不是使用简单的开/关接口。

TTY_DRIVER_DYNAMIC_ALLOC

不要为此驱动程序分配每个线路所需的结构 (tty_driver.ports),因为这会浪费内存。驱动程序会处理。这仅适用于 PTY 驱动程序。

TTY_DRIVER_UNNUMBERED_NODE

不要创建带编号的 /dev 节点。例如,创建 /dev/ttyprintk,而不是 /dev/ttyprintk0。仅当为单个 tty 设备分配驱动程序时适用。


注册

struct tty_driver 被分配并填充后,可以使用 tty_register_driver() 进行注册。建议在 tty_alloc_driver() 的标志中传递 TTY_DRIVER_DYNAMIC_DEV。如果没有传递,那么在 tty_register_driver() 期间也会注册所有设备,并且对于此类驱动程序,可以跳过以下注册设备段落。但是,struct tty_port 部分在 注册设备 中仍然相关。

int tty_register_driver(struct tty_driver *driver)

注册一个 tty 驱动程序

参数

struct tty_driver *driver

要注册的驱动程序

描述

由 tty 驱动程序调用以注册自身。

void tty_unregister_driver(struct tty_driver *driver)

注销一个 tty 驱动程序

参数

struct tty_driver *driver

要注销的驱动程序

描述

由 tty 驱动程序调用以注销自身。

注册设备

每个 TTY 设备都应由 struct tty_port 支持。通常,TTY 驱动程序将 tty_port 嵌入到设备的私有结构中。有关处理 tty_port 的更多详细信息,请参见 TTY 端口。还建议驱动程序使用 tty_port 的引用计数,通过 tty_port_get() 和 tty_port_put()。最后的 put 操作应该释放 tty_port,包括设备的私有结构。

除非 TTY_DRIVER_DYNAMIC_DEV 作为标志传递给 tty_alloc_driver(),否则 TTY 驱动程序应该注册系统中发现的每个设备(后者是首选)。这是通过 tty_register_device() 执行的。或者,如果驱动程序希望通过 struct attribute_group 公开一些信息,则通过 tty_register_device_attr() 执行。它们都会注册第 index 个设备,并在返回后,可以打开该设备。还有一些首选的 tty_port 变体在稍后的 将设备链接到端口 中描述。由驱动程序管理空闲索引并选择正确的索引。TTY 层只拒绝注册比传递给 tty_alloc_driver() 的更多的设备。

当设备被打开时,TTY 层会分配 struct tty_struct,并开始调用 tty_driver.ops 中的操作,请参阅 TTY 操作参考

注册例程记录如下

struct device *tty_register_device(struct tty_driver *driver, unsigned index, struct device *device)

注册一个 tty 设备

参数

struct tty_driver *driver

描述 tty 设备的 tty 驱动程序

unsigned index

此 tty 设备在 tty 驱动程序中的索引

struct device *device

与此 tty 设备关联的 struct device。此字段是可选的,如果没有此 tty 设备的已知 struct device,可以安全地将其设置为 NULL。

描述

如果 tty 驱动程序的标志设置了 TTY_DRIVER_DYNAMIC_DEV 位,则必须进行此调用以注册单个 tty 设备。如果未设置该位,则 tty 驱动程序不应调用此函数。

锁定:??

返回

指向此 tty 设备的 struct device 的指针(或错误时为 ERR_PTR(-EFOO))。

struct device *tty_register_device_attr(struct tty_driver *driver, unsigned index, struct device *device, void *drvdata, const struct attribute_group **attr_grp)

注册一个 tty 设备

参数

struct tty_driver *driver

描述 tty 设备的 tty 驱动程序

unsigned index

此 tty 设备在 tty 驱动程序中的索引

struct device *device

与此 tty 设备关联的 struct device。此字段是可选的,如果没有此 tty 设备的已知 struct device,可以安全地将其设置为 NULL

void *drvdata

要设置到设备的驱动程序数据。

const struct attribute_group **attr_grp

要设置到设备的属性组。

描述

如果 tty 驱动程序的标志设置了 TTY_DRIVER_DYNAMIC_DEV 位,则必须进行此调用以注册单个 tty 设备。如果未设置该位,则 tty 驱动程序不应调用此函数。

锁定:??

返回

指向此 tty 设备的 struct device 的指针(或错误时为 ERR_PTR(-EFOO))。

void tty_unregister_device(struct tty_driver *driver, unsigned index)

注销一个 tty 设备

参数

struct tty_driver *driver

描述 tty 设备的 tty 驱动程序

unsigned index

此 tty 设备在 tty 驱动程序中的索引

描述

如果 tty 设备通过调用 tty_register_device() 进行注册,则当 tty 设备消失时必须调用此函数。

锁定:??


将设备链接到端口

如前所述,每个 TTY 设备都应分配一个 struct tty_port。它必须最迟在 tty_driver.ops.install() 时被 TTY 层知道。有一些助手可以链接这两个。理想情况下,驱动程序使用 tty_port_register_device()tty_port_register_device_attr(),而不是注册时的 tty_register_device()tty_register_device_attr()。这样,驱动程序无需在以后关心链接。

如果不可能这样做,驱动程序仍然可以通过 tty_port_link_device() 在实际注册之前将 tty_port 链接到特定的索引。如果仍然不适合,则可以从 tty_driver.ops.install 钩子中使用 tty_port_install() 作为最后的手段。最后一个主要用于按需分配 tty_port 的内存设备(如 PTY)。

链接例程在此处记录

链接 tty 和 tty_port

参数

struct tty_port *port

设备的 tty_port

struct tty_driver *driver

此设备的 tty_driver

unsigned index

tty 的索引

描述

为 tty 层提供一个从 tty(由 index 指定)到 tty_port(port)的链接。仅当驱动程序中未使用 tty_port_register_device()tty_port_install() 时才使用此函数。如果使用,则必须在 tty_register_driver() 之前调用此函数。

struct device *tty_port_register_device(struct tty_port *port, struct tty_driver *driver, unsigned index, struct device *device)

注册 tty 设备

参数

struct tty_port *port

设备的 tty_port

struct tty_driver *driver

此设备的 tty_driver

unsigned index

tty 的索引

struct device *device

父设备(如果存在),否则为 NULL

描述

它与 tty_register_device() 相同,只不过提供的 port 链接到一个由 index 指定的具体 tty。 使用此函数或 tty_port_install()(或两者都使用)。 将 tty_port_link_device() 作为最后的手段调用。

struct device *tty_port_register_device_attr(struct tty_port *port, struct tty_driver *driver, unsigned index, struct device *device, void *drvdata, const struct attribute_group **attr_grp)

注册 tty 设备

参数

struct tty_port *port

设备的 tty_port

struct tty_driver *driver

此设备的 tty_driver

unsigned index

tty 的索引

struct device *device

父设备(如果存在),否则为 NULL

void *drvdata

要设置到设备的驱动程序数据。

const struct attribute_group **attr_grp

要设置到设备的属性组。

描述

它与 tty_register_device_attr() 相同,只不过提供的 port 链接到一个由 index 指定的具体 tty。 使用此函数或 tty_port_install()(或两者都使用)。 将 tty_port_link_device() 作为最后的手段调用。


TTY 驱动程序参考

此处记录了 struct tty_driver 的所有成员。必需的成员在末尾注明。接下来记录 struct tty_operations

struct tty_driver
  • TTY 设备的驱动程序

定义:

struct tty_driver {
    struct kref kref;
    struct cdev **cdevs;
    struct module   *owner;
    const char      *driver_name;
    const char      *name;
    int name_base;
    int major;
    int minor_start;
    unsigned int    num;
    short type;
    short subtype;
    struct ktermios init_termios;
    unsigned long   flags;
    struct proc_dir_entry *proc_entry;
    struct tty_driver *other;
    struct tty_struct **ttys;
    struct tty_port **ports;
    struct ktermios **termios;
    void *driver_state;
    const struct tty_operations *ops;
    struct list_head tty_drivers;
};

成员

kref

引用计数。达到零时会释放所有内部结构和驱动程序。

cdevs

已分配/注册的字符 /dev 设备

owner

拥有此驱动程序的模块。正在使用的驱动程序无法使用 rmmod 卸载。由 tty_alloc_driver() 自动设置。

driver_name

在 /proc/tty 中使用的驱动程序名称

name

用于构造 /dev 节点名称

name_base

用作构造 /dev 节点名称的数字基数

major

主 /dev 设备号(零表示自动分配)

minor_start

第一个次 /dev 设备号

num

已分配的设备数量

type

tty 驱动程序的类型(TTY_DRIVER_TYPE_

subtype

tty 驱动程序的子类型(SYSTEM_TYPE_PTY_TYPE_SERIAL_TYPE_

init_termios

最初设置为每个 tty 的 termios(例如 tty_std_termios

flags

tty 驱动程序标志(TTY_DRIVER_

proc_entry

proc fs 条目,内部使用

other

链接的 tty 的驱动程序;仅用于 PTY 驱动程序

ttys

活动的 struct tty_struct 数组,由 tty_standard_install() 设置

ports

struct tty_port 数组;可以在初始化期间由 tty_port_link_device() 和类似函数设置

termios

用于在每次 TTY 关闭时存储 termios,以便下次打开时使用

driver_state

指向驱动程序任意数据的指针

ops

TTY 的驱动程序钩子。使用 tty_set_operations() 设置它们。尽可能在其中使用 struct tty_port 助手。

tty_drivers

内部用于将 tty_drivers 链接在一起

描述

处理 struct tty_driver 的通常方式是使用 tty_alloc_driver() 分配它,设置所有必要的成员,并通过 tty_register_driver() 注册它。最后,通过调用 tty_unregister_driver(),然后调用 tty_driver_kref_put() 来拆卸驱动程序。

在调用 tty_register_driver() 之前需要设置的字段包括 driver_namenametypesubtypeinit_termiosops


TTY 操作参考

注册 TTY 时,TTY 层可以调用这些驱动程序钩子

struct tty_operations
  • 驱动程序和 tty 之间的接口

定义:

struct tty_operations {
    struct tty_struct * (*lookup)(struct tty_driver *driver, struct file *filp, 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);
    ssize_t (*write)(struct tty_struct *tty, const u8 *buf, size_t count);
    int (*put_char)(struct tty_struct *tty, u8 ch);
    void (*flush_chars)(struct tty_struct *tty);
    unsigned int (*write_room)(struct tty_struct *tty);
    unsigned int (*chars_in_buffer)(struct tty_struct *tty);
    int (*ioctl)(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
    long (*compat_ioctl)(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
    void (*set_termios)(struct tty_struct *tty, const 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);
    int (*ldisc_ok)(struct tty_struct *tty, int ldisc);
    void (*set_ldisc)(struct tty_struct *tty);
    void (*wait_until_sent)(struct tty_struct *tty, int timeout);
    void (*send_xchar)(struct tty_struct *tty, u8 ch);
    int (*tiocmget)(struct tty_struct *tty);
    int (*tiocmset)(struct tty_struct *tty, unsigned int set, unsigned int clear);
    int (*resize)(struct tty_struct *tty, struct winsize *ws);
    int (*get_icount)(struct tty_struct *tty, struct serial_icounter_struct *icount);
    int (*get_serial)(struct tty_struct *tty, struct serial_struct *p);
    int (*set_serial)(struct tty_struct *tty, struct serial_struct *p);
    void (*show_fdinfo)(struct tty_struct *tty, struct seq_file *m);
#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;
    int (*proc_show)(struct seq_file *m, void *driver);
};

成员

lookup

struct tty_struct *()(struct tty_driver *self, struct file *, int idx)

返回与 idx 对应的 tty 设备,如果没有当前正在使用的设备,则返回 NULL,如果出现错误,则返回 ERR_PTR 值。在 tty_mutex 下调用(目前!)

可选方法。默认行为是使用 self->ttys 数组。

install

int ()(struct tty_driver *self, struct tty_struct *tty)

将新的 tty 安装到 self 的内部表中。与 lookupremove 方法结合使用。

可选方法。默认行为是使用 self->ttys 数组。

remove

void ()(struct tty_driver *self, struct tty_struct *tty)

self 的内部表中删除已关闭的 tty。与 lookupremove 方法结合使用。

可选方法。默认行为是使用 self->ttys 数组。

open

int ()(struct tty_struct *tty, struct file *)

当打开特定的 tty 设备时,将调用此例程。此例程是强制性的;如果未填写此例程,则尝试打开将会失败并返回 ENODEV

必需的方法。在持有 tty 锁的情况下调用。可能会睡眠。

close

void ()(struct tty_struct *tty, struct file *)

当特定的 tty 设备被关闭时,会调用此例程。在此调用返回时,驱动程序不得再进行任何类型的 ldisc 调用。

备注:即使相应的 open() 失败也会调用。

必需的方法。在持有 tty 锁的情况下调用。可能会睡眠。

shutdown

void ()(struct tty_struct *tty)

当特定的 tty 设备最后一次关闭时,会在 tty 锁下调用此例程。它会在 tty 资源被释放之前执行,因此可能会在另一个函数持有 tty kref 时执行。

cleanup

void ()(struct tty_struct *tty)

当特定的 tty 设备最后一次关闭并释放资源时,会异步调用此例程。这实际上是可能睡眠的例程的 shutdown 的第二部分。

write

ssize_t ()(struct tty_struct *tty, const u8 *buf, size_t count)

内核调用此例程,将一系列 (count) 字符 (buf) 写入 tty 设备。这些字符可能来自用户空间或内核空间。此例程将返回实际接受写入的字符数。

在特殊情况下可能会并行发生。因为这包括 panic 路径,驱动程序通常不应该在此处尝试进行巧妙的锁定。

可选:可写设备必需。可能不会睡眠。

put_char

int ()(struct tty_struct *tty, u8 ch)

内核调用此例程,将单个字符 ch 写入 tty 设备。如果内核使用此例程,则在将字符填充到驱动程序中完成后,必须调用 flush_chars() 例程(如果已定义)。如果队列中没有空间,则会忽略该字符。

可选:如果未提供,内核将使用 write 方法。不要直接调用此函数,请调用 tty_put_char()

flush_chars

void ()(struct tty_struct *tty)

内核在使用 put_char() 将一系列字符写入 tty 设备后会调用此例程。

可选。不要直接调用此函数,请调用 tty_driver_flush_chars()。

write_room

unsigned int ()(struct tty_struct *tty)

此例程返回 tty 驱动程序将接受排队等待写入的字符数。此数字会随着输出缓冲区被清空或输出流控制生效而发生变化。

ldisc 负责智能地处理 write_room/write 调用的多线程

如果提供了 write 方法,则必需,否则不需要。不要直接调用此函数,请调用 tty_write_room()

chars_in_buffer

unsigned int ()(struct tty_struct *tty)

此例程返回设备私有输出队列中的字符数。在 tty_wait_until_sent() 和 poll() 实现中使用。

可选:如果未提供,则假定设备上没有队列。不要直接调用此函数,请调用 tty_chars_in_buffer()

ioctl

int ()(struct tty_struct *tty, unsigned int cmd, unsigned long arg)

此例程允许 tty 驱动程序实现特定于设备的 ioctl。如果驱动程序无法识别传入的 ioctl 号 cmd,则应返回 ENOIOCTLCMD

可选。

compat_ioctl

long ()(struct tty_struct *tty, unsigned int cmd, unsigned long arg)

在 64 位系统上为 32 位进程实现 ioctl 处理。

可选。

set_termios

void ()(struct tty_struct *tty, const struct ktermios *old)

此例程允许在设备的 termios 设置更改时通知 tty 驱动程序。新设置位于 tty->termios 中。之前的设置在 old 参数中传递。

API 的定义方式是驱动程序应返回实际选择的模式。这意味着驱动程序负责修改 tty->termios 中的任何无法满足的位,以指示正在使用的实际模式。

可选。在 tty->termios_rwsem 下调用。可能会睡眠。

throttle

void ()(struct tty_struct *tty)

此例程通知 tty 驱动程序线路规程的输入缓冲区即将满,它应该以某种方式发出信号,表示不应再向 tty 发送字符。

包括与 unthrottle() 的序列化是 ldisc 层的工作。

可选:始终通过 tty_throttle_safe() 调用。在 tty->termios_rwsem 下调用。

unthrottle

void ()(struct tty_struct *tty)

此例程通知 tty 驱动程序,它应该发出信号,表示现在可以向 tty 发送字符,而不用担心超出线路规程的输入缓冲区。

可选。始终通过 tty_unthrottle() 调用。在 tty->termios_rwsem 下调用。

stop

void ()(struct tty_struct *tty)

此例程通知 tty 驱动程序,它应该停止向 tty 设备输出字符。

在持有 tty->flow.lock 的情况下调用。与 start() 方法序列化。

可选。始终通过 stop_tty() 调用。

start

void ()(struct tty_struct *tty)

此例程通知 tty 驱动程序,它已恢复向 tty 设备发送字符。

在持有 tty->flow.lock 的情况下调用。与 stop() 方法序列化。

可选。始终通过 start_tty() 调用。

hangup

void ()(struct tty_struct *tty)

此例程通知 tty 驱动程序,它应该挂断 tty 设备。

可选。在持有 tty 锁的情况下调用。

break_ctl

int ()(struct tty_struct *tty, int state)

此可选例程请求 tty 驱动程序打开或关闭 RS-232 端口上的 BREAK 状态。如果 state 为 -1,则应打开 BREAK 状态;如果 state 为 0,则应关闭 BREAK 状态。

如果实现了此例程,则高级 tty 驱动程序将处理以下 ioctl:TCSBRKTCSBRKPTIOCSBRKTIOCCBRK

如果驱动程序在 tty_alloc_driver() 中设置了 TTY_DRIVER_HARDWARE_BREAK,则该接口也会使用实际时间调用,并且硬件应自行完成延迟工作。0 和 -1 仍用于开/关。

可选:对于 TCSBRK/BRKP/等处理是必需的。可能会睡眠。

flush_buffer

void ()(struct tty_struct *tty)

此例程丢弃设备私有输出缓冲区。在关闭、挂断时调用,以实现 TCOFLUSH ioctl 和类似操作。

可选:如果未提供,则假定设备上没有队列。不要直接调用此函数,请调用 tty_driver_flush_buffer()

ldisc_ok

int ()(struct tty_struct *tty, int ldisc)

此例程允许 tty 驱动程序决定它是否可以处理特定的 ldisc

可选。在 tty->ldisc_semtty->termios_rwsem 下调用。

set_ldisc

void ()(struct tty_struct *tty)

此例程允许在设备的线路规程正在更改时通知 tty 驱动程序。在完成此操作时,该规程尚不可用。

可选。在 tty->ldisc_semtty->termios_rwsem 下调用。

wait_until_sent

void ()(struct tty_struct *tty, int timeout)

此例程等待直到设备将其发送器 FIFO 中的所有字符都写出。或者直到达到 timeout(以 jiffies 为单位)。

可选:如果未提供,则假定该设备没有 FIFO。通常通过 tty_wait_until_sent() 调用是正确的。可能会休眠。

send_xchar

void ()(struct tty_struct *tty, u8 ch)

此例程用于向 tty 设备发送高优先级的 XON/XOFF 字符(ch)。

可选:如果未提供,则在 tty->atomic_write_lock 下调用 write 方法,以使其与 ldisc 保持串行化。

tiocmget

int ()(struct tty_struct *tty)

此例程用于从 tty 驱动程序获取调制解调器状态位。

可选:如果未提供,则从 TIOCMGET ioctl 返回 ENOTTY。不要直接调用此函数,请调用 tty_tiocmget()

tiocmset

int ()(struct tty_struct *tty, unsigned int set, unsigned int clear)

此例程用于将调制解调器状态位设置到 tty 驱动程序。首先,应该清除 clear 位,然后设置 set 位。

可选:如果未提供,则从 TIOCMSET ioctl 返回 ENOTTY。不要直接调用此函数,请调用 tty_tiocmset()

resize

int ()(struct tty_struct *tty, struct winsize *ws)

当发出 termios 请求将请求的终端几何形状更改为 ws 时调用。

可选:默认操作是在没有错误的情况下更新 termios 结构。这通常是正确的行为。如果驱动程序不是可调整大小的对象(例如,串行线),则不应在此处强制错误。如果需要将标准方法包装在您自己的逻辑中(通常情况),请参阅 tty_do_resize()

get_icount

int ()(struct tty_struct *tty, struct serial_icounter *icount)

tty 设备收到 TIOCGICOUNT ioctl 时调用。传递一个内核结构 icount 来完成。

可选:仅在提供时调用,否则将返回 ENOTTY

get_serial

int ()(struct tty_struct *tty, struct serial_struct *p)

tty 设备收到 TIOCGSERIAL ioctl 时调用。传递一个内核结构 p (struct serial_struct) 来完成。

可选:仅在提供时调用,否则将返回 ENOTTY。不要直接调用此函数,请调用 tty_tiocgserial()。

set_serial

int ()(struct tty_struct *tty, struct serial_struct *p)

tty 设备收到 TIOCSSERIAL ioctl 时调用。传递一个内核结构 p (struct serial_struct) 以设置值。

可选:仅在提供时调用,否则将返回 ENOTTY。不要直接调用此函数,请调用 tty_tiocsserial()。

show_fdinfo

void ()(struct tty_struct *tty, struct seq_file *m)

tty 设备文件描述符收到来自 VFS 的 fdinfo 请求(在 /proc/<pid>/fdinfo/ 中显示)时调用。m 应该填充信息。

可选:仅在提供时调用,否则不会将任何内容写入 m。不要直接调用此函数,请调用 tty_show_fdinfo()。

poll_init

int ()(struct tty_driver *driver, int line, char *options)

kgdboc 支持(使用 kgdb,kdb 和内核调试器内部原理)。此例程被调用以初始化硬件,以便稍后通过调用 poll_get_charpoll_put_char 来使用。

可选:仅在提供时调用,否则跳过作为非轮询驱动程序。

poll_get_char

int ()(struct tty_driver *driver, int line)

kgdboc 支持(请参阅 poll_init)。driver 应该从由 line 标识的 tty 读取一个字符并返回它。

可选:仅在提供 poll_init 时调用。

poll_put_char

void ()(struct tty_driver *driver, int line, char ch)

kgdboc 支持(请参阅 poll_init)。driver 应该将字符 ch 写入由 line 标识的 tty。

可选:仅在提供 poll_init 时调用。

proc_show

int ()(struct seq_file *m, void *driver)

驱动程序 driver(强制转换为 struct tty_driver)可以在 /proc/tty/driver/<driver_name> 中显示其他信息。只需将信息填充到 m 中即可。

可选:仅在提供时调用,否则不创建 /proc 条目。

描述

此结构定义了底层 tty 驱动程序和 tty 例程之间的接口。可以定义这些例程。除非另有说明,否则它们是可选的,并且可以用 NULL 指针填充。