0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/console.h>
0015 #include <linux/device.h>
0016 #include <linux/serial.h>
0017 #include <linux/tty.h>
0018 #include <linux/module.h>
0019 #include <linux/spinlock.h>
0020
0021 struct ttyprintk_port {
0022 struct tty_port port;
0023 spinlock_t spinlock;
0024 };
0025
0026 static struct ttyprintk_port tpk_port;
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #define TPK_STR_SIZE 508
0038 #define TPK_MAX_ROOM 4096
0039 #define TPK_PREFIX KERN_SOH __stringify(CONFIG_TTY_PRINTK_LEVEL)
0040
0041 static int tpk_curr;
0042
0043 static char tpk_buffer[TPK_STR_SIZE + 4];
0044
0045 static void tpk_flush(void)
0046 {
0047 if (tpk_curr > 0) {
0048 tpk_buffer[tpk_curr] = '\0';
0049 printk(TPK_PREFIX "[U] %s\n", tpk_buffer);
0050 tpk_curr = 0;
0051 }
0052 }
0053
0054 static int tpk_printk(const unsigned char *buf, int count)
0055 {
0056 int i;
0057
0058 for (i = 0; i < count; i++) {
0059 if (tpk_curr >= TPK_STR_SIZE) {
0060
0061 tpk_buffer[tpk_curr++] = '\\';
0062 tpk_flush();
0063 }
0064
0065 switch (buf[i]) {
0066 case '\r':
0067 tpk_flush();
0068 if ((i + 1) < count && buf[i + 1] == '\n')
0069 i++;
0070 break;
0071 case '\n':
0072 tpk_flush();
0073 break;
0074 default:
0075 tpk_buffer[tpk_curr++] = buf[i];
0076 break;
0077 }
0078 }
0079
0080 return count;
0081 }
0082
0083
0084
0085
0086 static int tpk_open(struct tty_struct *tty, struct file *filp)
0087 {
0088 tty->driver_data = &tpk_port;
0089
0090 return tty_port_open(&tpk_port.port, tty, filp);
0091 }
0092
0093
0094
0095
0096 static void tpk_close(struct tty_struct *tty, struct file *filp)
0097 {
0098 struct ttyprintk_port *tpkp = tty->driver_data;
0099
0100 tty_port_close(&tpkp->port, tty, filp);
0101 }
0102
0103
0104
0105
0106 static int tpk_write(struct tty_struct *tty,
0107 const unsigned char *buf, int count)
0108 {
0109 struct ttyprintk_port *tpkp = tty->driver_data;
0110 unsigned long flags;
0111 int ret;
0112
0113
0114 spin_lock_irqsave(&tpkp->spinlock, flags);
0115 ret = tpk_printk(buf, count);
0116 spin_unlock_irqrestore(&tpkp->spinlock, flags);
0117
0118 return ret;
0119 }
0120
0121
0122
0123
0124 static unsigned int tpk_write_room(struct tty_struct *tty)
0125 {
0126 return TPK_MAX_ROOM;
0127 }
0128
0129
0130
0131
0132 static void tpk_hangup(struct tty_struct *tty)
0133 {
0134 struct ttyprintk_port *tpkp = tty->driver_data;
0135
0136 tty_port_hangup(&tpkp->port);
0137 }
0138
0139
0140
0141
0142 static void tpk_port_shutdown(struct tty_port *tport)
0143 {
0144 struct ttyprintk_port *tpkp =
0145 container_of(tport, struct ttyprintk_port, port);
0146 unsigned long flags;
0147
0148 spin_lock_irqsave(&tpkp->spinlock, flags);
0149 tpk_flush();
0150 spin_unlock_irqrestore(&tpkp->spinlock, flags);
0151 }
0152
0153 static const struct tty_operations ttyprintk_ops = {
0154 .open = tpk_open,
0155 .close = tpk_close,
0156 .write = tpk_write,
0157 .write_room = tpk_write_room,
0158 .hangup = tpk_hangup,
0159 };
0160
0161 static const struct tty_port_operations tpk_port_ops = {
0162 .shutdown = tpk_port_shutdown,
0163 };
0164
0165 static struct tty_driver *ttyprintk_driver;
0166
0167 static struct tty_driver *ttyprintk_console_device(struct console *c,
0168 int *index)
0169 {
0170 *index = 0;
0171 return ttyprintk_driver;
0172 }
0173
0174 static struct console ttyprintk_console = {
0175 .name = "ttyprintk",
0176 .device = ttyprintk_console_device,
0177 };
0178
0179 static int __init ttyprintk_init(void)
0180 {
0181 int ret;
0182
0183 spin_lock_init(&tpk_port.spinlock);
0184
0185 ttyprintk_driver = tty_alloc_driver(1,
0186 TTY_DRIVER_RESET_TERMIOS |
0187 TTY_DRIVER_REAL_RAW |
0188 TTY_DRIVER_UNNUMBERED_NODE);
0189 if (IS_ERR(ttyprintk_driver))
0190 return PTR_ERR(ttyprintk_driver);
0191
0192 tty_port_init(&tpk_port.port);
0193 tpk_port.port.ops = &tpk_port_ops;
0194
0195 ttyprintk_driver->driver_name = "ttyprintk";
0196 ttyprintk_driver->name = "ttyprintk";
0197 ttyprintk_driver->major = TTYAUX_MAJOR;
0198 ttyprintk_driver->minor_start = 3;
0199 ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE;
0200 ttyprintk_driver->init_termios = tty_std_termios;
0201 ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
0202 tty_set_operations(ttyprintk_driver, &ttyprintk_ops);
0203 tty_port_link_device(&tpk_port.port, ttyprintk_driver, 0);
0204
0205 ret = tty_register_driver(ttyprintk_driver);
0206 if (ret < 0) {
0207 printk(KERN_ERR "Couldn't register ttyprintk driver\n");
0208 goto error;
0209 }
0210
0211 register_console(&ttyprintk_console);
0212
0213 return 0;
0214
0215 error:
0216 tty_driver_kref_put(ttyprintk_driver);
0217 tty_port_destroy(&tpk_port.port);
0218 return ret;
0219 }
0220
0221 static void __exit ttyprintk_exit(void)
0222 {
0223 unregister_console(&ttyprintk_console);
0224 tty_unregister_driver(ttyprintk_driver);
0225 tty_driver_kref_put(ttyprintk_driver);
0226 tty_port_destroy(&tpk_port.port);
0227 }
0228
0229 device_initcall(ttyprintk_init);
0230 module_exit(ttyprintk_exit);
0231
0232 MODULE_LICENSE("GPL");