at v5.11-rc2 2.8 kB view raw
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");