Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (C) 2019 Axis Communications AB
4 : *
5 : * Based on ttyprintk.c:
6 : * Copyright (C) 2010 Samo Pogacnik
7 : */
8 :
9 : #include <kunit/visibility.h>
10 : #include <linux/console.h>
11 : #include <linux/module.h>
12 : #include <linux/tty.h>
13 :
14 : static const struct tty_port_operations ttynull_port_ops;
15 : static struct tty_driver *ttynull_driver;
16 : static struct tty_port ttynull_port;
17 :
18 2 : static int ttynull_open(struct tty_struct *tty, struct file *filp)
19 : {
20 2 : return tty_port_open(&ttynull_port, tty, filp);
21 : }
22 :
23 2 : static void ttynull_close(struct tty_struct *tty, struct file *filp)
24 : {
25 2 : tty_port_close(&ttynull_port, tty, filp);
26 2 : }
27 :
28 0 : static void ttynull_hangup(struct tty_struct *tty)
29 : {
30 0 : tty_port_hangup(&ttynull_port);
31 0 : }
32 :
33 3 : static ssize_t ttynull_write(struct tty_struct *tty, const u8 *buf,
34 : size_t count)
35 : {
36 3 : return count;
37 : }
38 :
39 5 : static unsigned int ttynull_write_room(struct tty_struct *tty)
40 : {
41 5 : return 65536;
42 : }
43 :
44 : static const struct tty_operations ttynull_ops = {
45 : .open = ttynull_open,
46 : .close = ttynull_close,
47 : .hangup = ttynull_hangup,
48 : .write = ttynull_write,
49 : .write_room = ttynull_write_room,
50 : };
51 :
52 0 : static struct tty_driver *ttynull_device(struct console *c, int *index)
53 : {
54 0 : *index = 0;
55 0 : return ttynull_driver;
56 : }
57 :
58 : static struct console ttynull_console = {
59 : .name = "ttynull",
60 : .device = ttynull_device,
61 : };
62 :
63 0 : static int __init ttynull_init(void)
64 : {
65 0 : struct tty_driver *driver;
66 0 : int ret;
67 :
68 0 : driver = tty_alloc_driver(1,
69 : TTY_DRIVER_RESET_TERMIOS |
70 : TTY_DRIVER_REAL_RAW |
71 : TTY_DRIVER_UNNUMBERED_NODE);
72 0 : if (IS_ERR(driver))
73 0 : return PTR_ERR(driver);
74 :
75 0 : tty_port_init(&ttynull_port);
76 0 : ttynull_port.ops = &ttynull_port_ops;
77 :
78 0 : driver->driver_name = "ttynull";
79 0 : driver->name = "ttynull";
80 0 : driver->type = TTY_DRIVER_TYPE_CONSOLE;
81 0 : driver->init_termios = tty_std_termios;
82 0 : driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
83 0 : tty_set_operations(driver, &ttynull_ops);
84 0 : tty_port_link_device(&ttynull_port, driver, 0);
85 :
86 0 : ret = tty_register_driver(driver);
87 0 : if (ret < 0) {
88 0 : tty_driver_kref_put(driver);
89 0 : tty_port_destroy(&ttynull_port);
90 0 : return ret;
91 : }
92 :
93 0 : ttynull_driver = driver;
94 0 : register_console(&ttynull_console);
95 :
96 0 : return 0;
97 0 : }
98 :
99 0 : static void __exit ttynull_exit(void)
100 : {
101 0 : unregister_console(&ttynull_console);
102 0 : tty_unregister_driver(ttynull_driver);
103 0 : tty_driver_kref_put(ttynull_driver);
104 0 : tty_port_destroy(&ttynull_port);
105 0 : }
106 :
107 : module_init(ttynull_init);
108 : module_exit(ttynull_exit);
109 :
110 : #ifdef CONFIG_TTY_KUNIT_NULL_TTY_TESTS
111 : #include "tests/test_ttynull.c"
112 : #endif /* CONFIG_TTY_KUNIT_TTYNULL_TESTS */
113 :
114 : MODULE_DESCRIPTION("NULL TTY driver");
115 : MODULE_LICENSE("GPL v2");
|