Hi, On Tue, Jan 24, 2017 at 8:30 AM, Samuel Thibault <samuel.thibault@xxxxxxxxxxxx> 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.
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; }
_______________________________________________ Speakup mailing list Speakup@xxxxxxxxxxxxxxxxx http://linux-speakup.org/cgi-bin/mailman/listinfo/speakup