/* * tty line discipline example * * Copyright (C) 2016 Krzysztof Mazur * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #define pr_fmt(fmt) "ldisc-example: " fmt #include #include #include #include #include #include #ifndef N_EXAMPLE #define N_EXAMPLE 26 #endif static int ringdev_ldisc_open(struct tty_struct *tty) { if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (!tty->ops->write) return -EOPNOTSUPP; pr_info("ldisc open\n"); tty->receive_room = 65536; /* We don't flow control */ return 0; } static void ringdev_ldisc_close(struct tty_struct *tty) { pr_info("ldisc close\n"); } static int ringdev_ldisc_hangup(struct tty_struct *tty) { pr_info("ldisc hangup\n"); return 0; } static void ringdev_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { while (count--) { if (fp && *fp++) { pr_info("error %02x\n", *fp); cp++; continue; } pr_info("received %02x\n", *cp++); } } static void ringdev_write_wakeup(struct tty_struct *tty) { } static struct tty_ldisc_ops ringdev_ldisc = { .owner = THIS_MODULE, .magic = TTY_LDISC_MAGIC, .name = "ringdev", .open = ringdev_ldisc_open, .hangup = ringdev_ldisc_hangup, .close = ringdev_ldisc_close, .ioctl = tty_mode_ioctl, .receive_buf = ringdev_receive_buf, .write_wakeup = ringdev_write_wakeup, }; static int __init ringdev_init(void) { int ret; ret = tty_register_ldisc(N_EXAMPLE, &ringdev_ldisc); if (ret) { pr_err("can't register line discipline (err = %d)\n", ret); goto out; } return 0; out: return ret; } static void __exit ringdev_exit(void) { tty_unregister_ldisc(N_EXAMPLE); } module_init(ringdev_init); module_exit(ringdev_exit); MODULE_DESCRIPTION("tty line discripline example"); MODULE_AUTHOR("Krzysztof Mazur "); MODULE_LICENSE("GPL");