/* Should be in include/linux/tty.h */
#define N_SLLIN 25
+#define N_SLLIN_SLAVE 26
/* -------------------------------- */
#ifdef SLLIN_LED_TRIGGER
* 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;
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");
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
.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;
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
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