Line discipline
Okash Khawaja
okash.khawaja at gmail.com
Tue Jan 24 16:52:26 EST 2017
Hi,
On Tue, Jan 24, 2017 at 8:30 AM, Samuel Thibault
<samuel.thibault at ens-lyon.org> wrote:
> Okash Khawaja, on Tue 24 Jan 2017 06:16:46 +0000, wrote:
>> Combined the refactor changes with your tty code to test speakup_dummy. It
>> seems okay
>
> Good :)
>
>> except for problem when unloading speakup.ko - it is in use so can't
>> be unloaded. I have just got this so investigating it.
>
> I guess it's a release issue on the tty or such. Could you share your
> code so we can investigate too?
>
>> One question. Using your code, we can obtain tty, cache it and use it directly
>> for all subsequent writes. Why then use ldisc?
>
> To be able to read characters. There is no "read" operation in the tty.
> We'll receive characters through the receive_buf callback.
Thanks for clarification.
>
> Samuel
I have attached the relevant diff. This is applied after the refactor
changes which allow us to use tty version of spk_serial_out(). Also
I've just hacked it together to test speakup_dummy - other synths
won't work after this change. Please not that since I haven't been
able to look into it yet, it might be a trivial error on my part.
-------------- next part --------------
diff --git a/drivers/staging/speakup/serialio.c b/drivers/staging/speakup/serialio.c
index d8b891f..61c82ba 100644
--- a/drivers/staging/speakup/serialio.c
+++ b/drivers/staging/speakup/serialio.c
@@ -217,9 +217,19 @@ int spk_serial_out(const char ch)
}
EXPORT_SYMBOL_GPL(spk_serial_out);
+extern struct tty_struct *speakup_tty;
+
int spk_serial_out_tty(const char ch)
{
- return spk_serial_out(ch);
+ // return spk_serial_out(ch);
+
+ pr_warn("spk_serial_out_tty(): ch=%c, speakup_tty=0x%x\n", ch, speakup_tty);
+
+ if (speakup_tty && speakup_tty->ops->write) {
+ speakup_tty->ops->write(speakup_tty, &ch, 1);
+ return 1;
+ }
+ return 0;
}
EXPORT_SYMBOL_GPL(spk_serial_out_tty);
diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c
index 425438b..dd192a6 100644
--- a/drivers/staging/speakup/synth.c
+++ b/drivers/staging/speakup/synth.c
@@ -12,6 +12,7 @@
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/kthread.h>
+#include <linux/tty.h>
#include "spk_priv.h"
#include "speakup.h"
@@ -44,8 +45,116 @@ EXPORT_SYMBOL_GPL(speakup_info);
static int do_synth_init(struct spk_synth *in_synth);
+struct tty_struct *speakup_tty;
+EXPORT_SYMBOL_GPL(speakup_tty);
+
+static int speakup_ldisc_open(struct tty_struct *tty)
+{
+ int rv;
+
+ // okashTODO: check for errors
+
+ pr_warn("speakup_test_open(): tty->name: %s; tty->ldisc->ops->name: %s\n",
+ tty->name, tty->ldisc->ops->name);
+ rv = tty->ops->write(tty, "hi ldisc\n", 9);
+ pr_warn("speakup_test_open(): done writing. rv=%d\n", rv);
+ speakup_tty = tty;
+
+ return 0;
+}
+
+static void speakup_ldisc_close(struct tty_struct *tty)
+{
+ pr_warn("speakup_test_close()\n");
+ speakup_tty = NULL;
+}
+
+static struct tty_ldisc_ops speakup_ldisc_ops = {
+ .owner = THIS_MODULE,
+ .magic = TTY_LDISC_MAGIC,
+ .name = "speakup_ldisc",
+ .open = speakup_ldisc_open,
+ .close = speakup_ldisc_close,
+};
+
+
+static int initialise_ldisc(void)
+{
+ int ret = 0;
+ struct tty_struct *tty;
+
+ ret = tty_register_ldisc(N_SPEAKUP, &speakup_ldisc_ops);
+ if (ret) {
+ pr_err("speakup_test_init(): Error registering line discipline.\n");
+ return ret;
+ }
+
+
+ tty = tty_open_by_driver(MKDEV(4, 64), NULL, NULL);
+ if (IS_ERR(tty))
+ return PTR_ERR(tty);
+
+ printk("got tty %p\n", tty);
+
+ if (tty->ops->open)
+ ret = tty->ops->open(tty, NULL);
+ else
+ ret = -ENODEV;
+
+/* to be put in ldisc open */
+ if (tty->ops->write == NULL)
+ ret = -EOPNOTSUPP;
+/* */
+
+ if (ret) {
+ tty_unlock(tty);
+ return ret;
+ }
+
+ clear_bit(TTY_HUPPED, &tty->flags);
+ tty_unlock(tty);
+
+ tty_set_ldisc(tty, N_SPEAKUP);
+ pr_warn(">>> finished calling tty_set_ldisc\n");
+
+ tty->ops->write(tty, "test\n", 5);
+
+ return ret;
+}
+
+static void release_ldisc(void)
+{
+ int idx;
+
+ if (!speakup_tty)
+ return;
+
+ tty_lock(speakup_tty);
+ idx = speakup_tty->index;
+
+#if 0
+ if (tty_release_checks(tty, idx)) {
+ tty_unlock(tty);
+ return 0;
+ }
+#endif
+
+ if (speakup_tty->ops->close)
+ speakup_tty->ops->close(speakup_tty, NULL);
+ tty_unlock(speakup_tty);
+#if 0
+ tty_flush_works(tty);
+#endif
+#if 0
+ mutex_lock(&tty_mutex);
+ release_tty(tty, idx);
+ mutex_unlock(&tty_mutex);
+#endif
+}
+
int spk_serial_synth_probe(struct spk_synth *synth)
{
+/*
const struct old_serial_port *ser;
int failed = 0;
@@ -68,7 +177,10 @@ int spk_serial_synth_probe(struct spk_synth *synth)
}
pr_info("%s: ttyS%i, Driver Version %s\n",
synth->long_name, synth->ser, synth->version);
+*/
+ initialise_ldisc();
synth->alive = 1;
+
return 0;
}
EXPORT_SYMBOL_GPL(spk_serial_synth_probe);
@@ -421,6 +533,10 @@ void synth_release(void)
struct var_t *var;
unsigned long flags;
+ // okashTODO: maybe speakup_tty should be part of synth.
+
+ release_ldisc();
+
if (synth == NULL)
return;
spin_lock_irqsave(&speakup_info.spinlock, flags);
@@ -432,7 +548,7 @@ void synth_release(void)
sysfs_remove_group(speakup_kobj, &synth->attributes);
for (var = synth->vars; var->var_id != MAXVARS; var++)
speakup_unregister_var(var->var_id);
- spk_stop_serial_interrupt();
+// spk_stop_serial_interrupt();
synth->release();
synth = NULL;
}
More information about the Speakup
mailing list