STRUCT TTY_OPERATIONS(9)
okay so bestie, welcome to struct tty_operations(9) from the Kernel API Manual โ this is literally the interface between your driver and tty, and it's giving main character energy for the whole subsystem ๐
โจ
โจ NAME โจ
struct tty_operations โ interface between driver and tty ๐
๐ธ SYNOPSIS ๐ธ
ok so here's the whole struct, no cap, every single member, don't skip a line:
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);
};
heads up ๐ซถ those last fewpoll_*ones are wrapped up inside#ifdef CONFIG_CONSOLE_POLL;โฆ#endif;โ so they only exist when that config is on, iykyk.
๐ Members ๐
okay so this page is very much a "here's the roster, that's the whole page" situation โ every member, one signature at a time, zero filler. Let's go down the list, nobody gets skipped ๐
lookupโstruct tty_struct *()(struct tty_driver *self, struct file *, int idx)installโint ()(struct tty_driver *self, struct tty_struct *tty)removeโvoid ()(struct tty_driver *self, struct tty_struct *tty)openโint ()(struct tty_struct *tty, struct file *)closeโvoid ()(struct tty_struct *tty, struct file *)shutdownโvoid ()(struct tty_struct *tty)cleanupโvoid ()(struct tty_struct *tty)writeโssize_t ()(struct tty_struct *tty, const u8 *buf, size_t count)put_charโint ()(struct tty_struct *tty, u8 ch)flush_charsโvoid ()(struct tty_struct *tty)write_roomโunsigned int ()(struct tty_struct *tty)chars_in_bufferโunsigned int ()(struct tty_struct *tty)ioctlโint ()(struct tty_struct *tty, unsigned int cmd, unsigned long arg)compat_ioctlโlong ()(struct tty_struct *tty, unsigned int cmd, unsigned long arg)set_termiosโvoid ()(struct tty_struct *tty, const struct ktermios *old)throttleโvoid ()(struct tty_struct *tty)unthrottleโvoid ()(struct tty_struct *tty)stopโvoid ()(struct tty_struct *tty)startโvoid ()(struct tty_struct *tty)hangupโvoid ()(struct tty_struct *tty)break_ctlโint ()(struct tty_struct *tty, int state)flush_bufferโvoid ()(struct tty_struct *tty)ldisc_okโint ()(struct tty_struct *tty, int ldisc)set_ldiscโvoid ()(struct tty_struct *tty)wait_until_sentโvoid ()(struct tty_struct *tty, int timeout)send_xcharโvoid ()(struct tty_struct *tty, u8 ch)tiocmgetโint ()(struct tty_struct *tty)tiocmsetโint ()(struct tty_struct *tty, unsigned int set, unsigned int clear)resizeโint ()(struct tty_struct *tty, struct winsize *ws)get_icountโint ()(struct tty_struct *tty, struct serial_icounter *icount)get_serialโint ()(struct tty_struct *tty, struct serial_struct *p)set_serialโint ()(struct tty_struct *tty, struct serial_struct *p)show_fdinfoโvoid ()(struct tty_struct *tty, struct seq_file *m)poll_initโint ()(struct tty_driver *driver, int line, char *options)poll_get_charโint ()(struct tty_driver *driver, int line)poll_put_charโvoid ()(struct tty_driver *driver, int line, char ch)proc_showโint ()(struct seq_file *m, void *driver)
that's the entire member roster, all 37 of them, ate and left no crumbs ๐ฅ๐
๐ DESCRIPTION ๐
okay so this is the part where we find out what all those members actually do, and bestie we're going in the exact same order as the Members list, so keep a finger on it ๐๐ซถ
one tiny heads-up before we dive: unless something says it's mandatory, assume it's optional and can literally just be NULL. I'll yell about the mandatory ones, don't worry ๐ฅ
- hand it a device or nothing โ returns the tty device corresponding to
idx,NULLif there isn't one currently in use, and anERR_PTRvalue on error ๐ญ. It's called undertty_mutex(for now! ๐). Optional method, and the default behaviour is to use theself->ttysarray. - the installer โ installs a new tty into the self's internal tables. Works as a trio with the lookup and remove methods ๐ค. Optional, default behaviour is the
self->ttysarray. - the evictor โ removes a closed tty from the self's internal tables. Used in conjunction with the lookup and remove methods. Optional, default behaviour is the
self->ttysarray. - open, the mandatory one โ this routine is called when a particular tty device is opened โจ. This routine is mandatory; if it's not filled in, the attempted open will fail with
ENODEV๐. Required method. Called with tty lock held. May sleep. - close, also mandatory โ called when a particular tty device is closed. At the point of return from this call the driver must make no further ldisc calls of any kind ๐ซ. Remark: it's called even if the corresponding open failed ๐. Required method. Called with tty lock held. May sleep.
- shutdown โ called under the tty lock when a particular tty device is closed for the last time. It executes before the tty resources are freed, so it may execute while another function holds a tty kref ๐ง
- cleanup โ called asynchronously when a particular tty device is closed for the last time, freeing up the resources. It's actually the second part of shutdown, for routines that might sleep ๐ด
- write โ the kernel calls this to write a series (
count) of characters (buf) to the tty device. The characters may come from user space or kernel space. It returns the number of characters actually accepted for writing ๐ฅ. May occur in parallel in special cases โ and because this includes panic paths, drivers generally shouldn't try and do clever locking here ๐. Optional: Required for writable devices. May not sleep. - put_char โ the kernel calls this to write a single character
chto the tty device. If the kernel uses this routine, it must call theflush_charsroutine (if defined) when it's done stuffing characters into the driver. If there's no room in the queue, the character is ignored ๐ซฅ. Optional: the kernel will use thewritemethod if this isn't provided. Do not call this function directly โ calltty_put_char. - flush_chars โ called by the kernel after it has written a series of characters to the tty device using
put_char๐. Optional. Do not call this function directly โ calltty_driver_flush_chars. - write_room โ returns the numbers of characters the tty driver will accept for queuing to be written ๐ฅ. This number is subject to change as output buffers get emptied, or if the output flow control is acted. The ldisc is responsible for being intelligent about multi-threading of
write_room/writecalls. Required if thewritemethod is provided, else not needed. Do not call this function directly โ calltty_write_room. - chars_in_buffer โ returns the number of characters in the device private output queue ๐. Used in
tty_wait_until_sentand for the poll implementation. Optional: if not provided, it's assumed there's no queue on the device. Do not call this function directly โ calltty_chars_in_buffer. - ioctl โ lets the tty driver implement device-specific ioctls ๐๏ธ. If the ioctl number passed in
cmdisn't recognized by the driver, it should returnENOIOCTLCMD. Optional. - compat_ioctl โ implement ioctl processing for a 32 bit process on a 64 bit system ๐ง . Optional.
- set_termios โ lets the tty driver be notified when the device's termios settings have changed. New settings are in
tty->termios. Previous settings are passed in theoldargument ๐ฐ๏ธ. The API is defined such that the driver should return the actual modes selected โ meaning the driver is responsible for modifying any bits intty->termiosit cannot fulfill, to indicate the actual modes being used. Optional. Called under thetty->termios_rwsem. May sleep. - the ldisc vibe check โ lets the tty driver decide if it can deal with a particular ldisc ๐ค. Optional. Called under the
tty->ldisc_semandtty->termios_rwsem. - ldisc switch notification โ lets the tty driver be notified when the device's line discipline is being changed. At the point this is done, the discipline is not yet usable โ ๏ธ. Optional. Called under the
tty->ldisc_semandtty->termios_rwsem. - throttle โ notifies the tty driver that input buffers for the line discipline are close to full, and it should somehow signal that no more characters should be sent to the tty ๐. Serialization including with unthrottle is the job of the ldisc layer. Optional: always invoke via
tty_throttle_safe. Called under thetty->termios_rwsem. - unthrottle โ notifies the tty driver that it should signal that characters can now be sent to the tty without fear of overrunning the input buffers of the line disciplines ๐โจ. Optional. Always invoke via
tty_unthrottle. Called under thetty->termios_rwsem. - stop โ notifies the tty driver that it should stop outputting characters to the tty device โ. Called with
tty->flow.lockheld. Serialized with thestartmethod. Optional. Always invoke viastop_tty. - start โ notifies the tty driver that it resumed sending characters to the tty device โถ๏ธ. Called with
tty->flow.lockheld. Serialized with thestopmethod. Optional. Always invoke viastart_tty. - hangup โ notifies the tty driver that it should hang up the tty device ๐ด. Optional. Called with tty lock held.
- break_ctl โ this optional routine requests the tty driver to turn on or off BREAK status on the RS-232 port ๐ฅ. If
stateis-1, then the BREAK status should be turned on; ifstateis0, then BREAK should be turned off. If this routine is implemented, the high-level tty driver will handle the following ioctls:TCSBRK,TCSBRKP,TIOCSBRK,TIOCCBRK. If the driver setsTTY_DRIVER_HARDWARE_BREAKintty_alloc_driver, then the interface will also be called with actual times and the hardware is expected to do the delay work itself โฑ๏ธ.0and-1are still used for on/off. Optional: Required forTCSBRK/BRKP/etc. handling. May sleep. - flush_buffer โ discards the device private output buffer ๐๏ธ. Invoked on close, hangup, to implement the
TCOFLUSHioctl and similar. Optional: if not provided, it's assumed there's no queue on the device. Do not call this function directly โ calltty_driver_flush_buffer. - wait_until_sent โ waits until the device has written out all of the characters in its transmitter FIFO, or until
timeout(in jiffies) is reached โณ. Optional: if not provided, the device is assumed to have no FIFO. Usually correct to invoke viatty_wait_until_sent. May sleep. - send_xchar โ used to send a high-priority XON/XOFF character (
ch) to the tty device โก. Optional: if not provided, then thewritemethod is called under thetty->atomic_write_lockto keep it serialized with the ldisc. - tiocmget โ used to obtain the modem status bits from the tty driver ๐ก. Optional: if not provided, then
ENOTTYis returned from theTIOCMGETioctl. Do not call this function directly โ calltty_tiocmget. - tiocmset โ used to set the modem status bits to the tty driver ๐ถ. First,
clearbits should be cleared, thensetbits set. Optional: if not provided, thenENOTTYis returned from theTIOCMSETioctl. Do not call this function directly โ calltty_tiocmset. - resize โ called when a termios request is issued which changes the requested terminal geometry to
ws๐. Optional: the default action is to update the termios structure without error. This is usually the correct behaviour. Drivers should not force errors here if they are not resizable objects (e.g. a serial line) ๐ . Seetty_do_resizeif you need to wrap the standard method in your own logic โ the usual case. - get_icount โ called when the tty device receives a
TIOCGICOUNTioctl. Passed a kernel structureicountto complete ๐งฎ. Optional: called only if provided, otherwiseENOTTYwill be returned. - get_serial โ called when the tty device receives a
TIOCGSERIALioctl. Passed a kernel structurep(struct serial_struct) to complete ๐. Optional: called only if provided, otherwiseENOTTYwill be returned. Do not call this function directly โ calltty_tiocgserial. - set_serial โ called when the tty device receives a
TIOCSSERIALioctl. Passed a kernel structurep(struct serial_struct) to set the values from ๐ง. Optional: called only if provided, otherwiseENOTTYwill be returned. Do not call this function directly โ calltty_tiocsserial. - show_fdinfo โ called when the tty device file descriptor receives a fdinfo request from VFS (to show in
/proc/<pid>/fdinfo/) ๐.mshould be filled with information. Optional: called only if provided, otherwise nothing is written tom. Do not call this function directly โ calltty_show_fdinfo. - poll_init โ kgdboc support (
Documentation/process/debugging/kgdb.rst) ๐. This routine is called to initialize the HW for later use by callingpoll_get_charorpoll_put_char. Optional: called only if provided, otherwise skipped as a non-polling driver. - poll_get_char โ kgdboc support (see
poll_init). The driver should read a character from a tty identified bylineand return it ๐. Optional: called only ifpoll_initprovided. - poll_put_char โ kgdboc support (see
poll_init). The driver should write characterchto a tty identified bylineโ๏ธ. Optional: called only ifpoll_initprovided. - proc_show โ Driver
driver(cast tostruct tty_driver) can show additional info in/proc/tty/driver/<driver_name>๐. It is enough to fill in the information intom. Optional: called only if provided, otherwise no/procentry created. - the closing statement ๐ซถ โ this structure defines the interface between the low-level tty driver and the tty routines. These routines can be defined. Unless noted otherwise, they are optional, and can be filled in with a
NULLpointer.
๐ SEE ALSO ๐
- Kernel file
./include/linux/tty_driver.hโenum tty_driver_flag(9),struct tty_driver(9),tty_alloc_driver(9)๐
and that's the whole thing, bestie, you made it ๐โจ go forth and fill in your function pointers responsibly ๐
sign-off szn: this gem lives in ./include/linux, it's dated October 2026, and it's the page for struct tty_operations(9) โ slay, go read the headers ๐
๐
๐ฆ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms