Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2019 Axis Communications AB
4 *
5 * The console is useful for userspace applications which expect a console
6 * device to work without modifications even when no console is available
7 * or desired.
8 *
9 * In order to use this driver, you should redirect the console to this
10 * TTY, or boot the kernel with console=ttynull.
11 *
12 * Based on ttyprintk.c:
13 * Copyright (C) 2010 Samo Pogacnik
14 */
15
16#include <linux/console.h>
17#include <linux/module.h>
18#include <linux/tty.h>
19
20static const struct tty_port_operations ttynull_port_ops;
21static struct tty_driver *ttynull_driver;
22static struct tty_port ttynull_port;
23
24static int ttynull_open(struct tty_struct *tty, struct file *filp)
25{
26 return tty_port_open(&ttynull_port, tty, filp);
27}
28
29static void ttynull_close(struct tty_struct *tty, struct file *filp)
30{
31 tty_port_close(&ttynull_port, tty, filp);
32}
33
34static void ttynull_hangup(struct tty_struct *tty)
35{
36 tty_port_hangup(&ttynull_port);
37}
38
39static int ttynull_write(struct tty_struct *tty, const unsigned char *buf,
40 int count)
41{
42 return count;
43}
44
45static int ttynull_write_room(struct tty_struct *tty)
46{
47 return 65536;
48}
49
50static const struct tty_operations ttynull_ops = {
51 .open = ttynull_open,
52 .close = ttynull_close,
53 .hangup = ttynull_hangup,
54 .write = ttynull_write,
55 .write_room = ttynull_write_room,
56};
57
58static struct tty_driver *ttynull_device(struct console *c, int *index)
59{
60 *index = 0;
61 return ttynull_driver;
62}
63
64static struct console ttynull_console = {
65 .name = "ttynull",
66 .device = ttynull_device,
67};
68
69void __init register_ttynull_console(void)
70{
71 if (!ttynull_driver)
72 return;
73
74 if (add_preferred_console(ttynull_console.name, 0, NULL))
75 return;
76
77 register_console(&ttynull_console);
78}
79
80static int __init ttynull_init(void)
81{
82 struct tty_driver *driver;
83 int ret;
84
85 driver = tty_alloc_driver(1,
86 TTY_DRIVER_RESET_TERMIOS |
87 TTY_DRIVER_REAL_RAW |
88 TTY_DRIVER_UNNUMBERED_NODE);
89 if (IS_ERR(driver))
90 return PTR_ERR(driver);
91
92 tty_port_init(&ttynull_port);
93 ttynull_port.ops = &ttynull_port_ops;
94
95 driver->driver_name = "ttynull";
96 driver->name = "ttynull";
97 driver->type = TTY_DRIVER_TYPE_CONSOLE;
98 driver->init_termios = tty_std_termios;
99 driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
100 tty_set_operations(driver, &ttynull_ops);
101 tty_port_link_device(&ttynull_port, driver, 0);
102
103 ret = tty_register_driver(driver);
104 if (ret < 0) {
105 put_tty_driver(driver);
106 tty_port_destroy(&ttynull_port);
107 return ret;
108 }
109
110 ttynull_driver = driver;
111 register_console(&ttynull_console);
112
113 return 0;
114}
115
116static void __exit ttynull_exit(void)
117{
118 unregister_console(&ttynull_console);
119 tty_unregister_driver(ttynull_driver);
120 put_tty_driver(ttynull_driver);
121 tty_port_destroy(&ttynull_port);
122}
123
124module_init(ttynull_init);
125module_exit(ttynull_exit);
126
127MODULE_LICENSE("GPL v2");