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