]> rtime.felk.cvut.cz Git - linux-lin.git/commitdiff
sllin: register the second line discipline to distinguish request for slave configura... master
authorPavel Pisa <pisa@cmp.felk.cvut.cz>
Mon, 29 Jul 2019 17:21:50 +0000 (19:21 +0200)
committerPavel Pisa <pisa@cmp.felk.cvut.cz>
Mon, 29 Jul 2019 17:21:55 +0000 (19:21 +0200)
This allows to combining master and slave devices on single
computer/system.

Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
sllin/sllin.c

index ff9b0fe8d22f83f0bb1714ef3581824d01a875f1..cdc4327912d7779c431a14a0924fcc7eb8bcea07 100644 (file)
@@ -72,6 +72,7 @@
 
 /* Should be in include/linux/tty.h */
 #define N_SLLIN                        25
+#define N_SLLIN_SLAVE          26
 /* -------------------------------- */
 
 #ifdef SLLIN_LED_TRIGGER
@@ -1597,7 +1598,7 @@ static struct sllin *sll_alloc(dev_t line)
  * Called in process context serialized from other ldisc calls.
  */
 
-static int sllin_open(struct tty_struct *tty)
+static int sllin_open_common(struct tty_struct *tty, bool setup_master)
 {
        struct sllin *sl;
        int err;
@@ -1638,8 +1639,8 @@ static int sllin_open(struct tty_struct *tty)
 
        if (!test_bit(SLF_INUSE, &sl->flags)) {
                /* Perform the low-level SLLIN initialization. */
-               sl->lin_master = master;
-               if (master)
+               sl->lin_master = setup_master;
+               if (sl->lin_master)
                        pr_debug("sllin: Configured as MASTER\n");
                else
                        pr_debug("sllin: Configured as SLAVE\n");
@@ -1704,6 +1705,43 @@ err_exit:
        return err;
 }
 
+/*
+ * Open the high-level part of the SLLIN channel.
+ * This function is called by the TTY module when the
+ * SLLIN line discipline is called for.  Because we are
+ * sure the tty line exists, we only have to link it to
+ * a free SLLIN channel...
+ *
+ * Called in process context serialized from other ldisc calls.
+ *
+ * This call variant preserves original functionality where
+ * slave/master can be selected by module parameter.
+ * Default is the master.
+ */
+
+static int sllin_open(struct tty_struct *tty)
+{
+       return sllin_open_common(tty, master);
+}
+
+/*
+ * Open the high-level part of the SLLIN channel.
+ * This function is called by the TTY module when the
+ * SLLIN line discipline is called for.  Because we are
+ * sure the tty line exists, we only have to link it to
+ * a free SLLIN channel...
+ *
+ * Called in process context serialized from other ldisc calls.
+ *
+ * This call variant enforces slave/LIN device functionality.
+ */
+
+static int sllin_open_slave(struct tty_struct *tty)
+{
+       return sllin_open_common(tty, false);
+}
+
+
 /*
  * Close down a SLLIN channel.
  * This means flushing out any pending queues, and then returning. This
@@ -1775,6 +1813,18 @@ static struct tty_ldisc_ops sll_ldisc = {
        .write_wakeup   = sllin_write_wakeup,
 };
 
+static struct tty_ldisc_ops sll_slave_ldisc = {
+       .owner          = THIS_MODULE,
+       .magic          = TTY_LDISC_MAGIC,
+       .name           = "sllin-slave",
+       .open           = sllin_open_slave,
+       .close          = sllin_close,
+       .hangup         = sllin_hangup,
+       .ioctl          = sllin_ioctl,
+       .receive_buf    = sllin_receive_buf,
+       .write_wakeup   = sllin_write_wakeup,
+};
+
 static int __init sllin_init(void)
 {
        int status;
@@ -1802,8 +1852,16 @@ static int __init sllin_init(void)
        if (status)  {
                pr_err("sllin: can't register line discipline\n");
                kfree(sllin_devs);
+       } else {
+               status = tty_register_ldisc(N_SLLIN_SLAVE, &sll_slave_ldisc);
+               if (status)  {
+                       tty_unregister_ldisc(N_SLLIN);
+                       pr_err("sllin: can't register slave line discipline\n");
+                       kfree(sllin_devs);
+               }
        }
 
+
        if (break_by_baud)
                pr_debug("sllin: Break is generated by baud-rate change.");
        else
@@ -1874,6 +1932,11 @@ static void __exit sllin_exit(void)
        if (i)
                pr_err("sllin: can't unregister ldisc (err %d)\n", i);
 
+       i = tty_unregister_ldisc(N_SLLIN_SLAVE);
+       if (i)
+               pr_err("sllin: can't unregister slave ldisc (err %d)\n", i);
+
+
 #ifdef SLLIN_LED_TRIGGER
        unregister_netdevice_notifier(&sllin_netdev_notifier);
 #endif