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