[patch 2/7] staging: speakup: add tty-based comms functions
Samuel Thibault
samuel.thibault at ens-lyon.org
Sun Apr 9 17:30:31 EDT 2017
Okash Khawaja, on lun. 03 avril 2017 21:21:25 +0100, wrote:
> This adds spk_ttyio.c file. It contains a set of functions which implement
> those methods in spk_synth struct which relate to sending bytes out using
> serial comms. Implementations in this file perform the same function but
> using TTY subsystem instead. Currently synths access serial ports, directly
> poking standard ISA ports by trying to steal them from serial driver. Some ISA
> cards actually need this way of doing it, but most other synthesizers don't,
> and can actually work by using the proper TTY subsystem through a new N_SPEAKUP
> line discipline. So this adds the methods for drivers to switch to accessing
> serial ports through the TTY subsystem, whenever appropriate.
>
> Signed-off-by: Okash Khawaja <okash.khawaja at gmail.com>
Ditto.
Reviewed-by: Samuel Thibault <samuel.thibault at ens-lyon.org>
>
> Index: linux-staging/drivers/staging/speakup/Makefile
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/Makefile
> +++ linux-staging/drivers/staging/speakup/Makefile
> @@ -25,6 +25,7 @@ speakup-y := \
> kobjects.o \
> selection.o \
> serialio.o \
> + spk_ttyio.o \
> synth.o \
> thread.o \
> varhandlers.o
> Index: linux-staging/drivers/staging/speakup/spk_priv.h
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/spk_priv.h
> +++ linux-staging/drivers/staging/speakup/spk_priv.h
> @@ -46,6 +46,7 @@ int spk_wait_for_xmitr(struct spk_synth
> unsigned char spk_serial_in(void);
> unsigned char spk_serial_in_nowait(void);
> void spk_serial_release(void);
> +void spk_ttyio_release(void);
>
> void synth_buffer_skip_nonlatin1(void);
> u16 synth_buffer_getc(void);
> @@ -58,7 +59,9 @@ ssize_t spk_var_store(struct kobject *ko
> const char *buf, size_t count);
>
> int spk_serial_synth_probe(struct spk_synth *synth);
> +int spk_ttyio_synth_probe(struct spk_synth *synth);
> const char *spk_serial_synth_immediate(struct spk_synth *synth, const char *buff);
> +const char *spk_ttyio_synth_immediate(struct spk_synth *synth, const char *buff);
> void spk_do_catch_up(struct spk_synth *synth);
> void spk_synth_flush(struct spk_synth *synth);
> int spk_synth_is_alive_nop(struct spk_synth *synth);
> @@ -79,5 +82,6 @@ extern struct speakup_info_t speakup_inf
> extern struct var_t synth_time_vars[];
>
> extern struct spk_io_ops spk_serial_io_ops;
> +extern struct spk_io_ops spk_ttyio_ops;
>
> #endif
> Index: linux-staging/drivers/staging/speakup/spk_ttyio.c
> ===================================================================
> --- /dev/null
> +++ linux-staging/drivers/staging/speakup/spk_ttyio.c
> @@ -0,0 +1,143 @@
> +#include <linux/types.h>
> +#include <linux/tty.h>
> +
> +#include "speakup.h"
> +#include "spk_types.h"
> +
> +static struct tty_struct *speakup_tty;
> +
> +static int spk_ttyio_ldisc_open(struct tty_struct *tty)
> +{
> + if (tty->ops->write == NULL)
> + return -EOPNOTSUPP;
> + speakup_tty = tty;
> +
> + return 0;
> +}
> +
> +static void spk_ttyio_ldisc_close(struct tty_struct *tty)
> +{
> + speakup_tty = NULL;
> +}
> +
> +static struct tty_ldisc_ops spk_ttyio_ldisc_ops = {
> + .owner = THIS_MODULE,
> + .magic = TTY_LDISC_MAGIC,
> + .name = "speakup_ldisc",
> + .open = spk_ttyio_ldisc_open,
> + .close = spk_ttyio_ldisc_close,
> +};
> +
> +static int spk_ttyio_out(struct spk_synth *in_synth, const char ch);
> +struct spk_io_ops spk_ttyio_ops = {
> + .synth_out = spk_ttyio_out,
> +};
> +EXPORT_SYMBOL_GPL(spk_ttyio_ops);
> +
> +static int spk_ttyio_initialise_ldisc(int ser)
> +{
> + int ret = 0;
> + struct tty_struct *tty;
> +
> + ret = tty_register_ldisc(N_SPEAKUP, &spk_ttyio_ldisc_ops);
> + if (ret) {
> + pr_err("Error registering line discipline.\n");
> + return ret;
> + }
> +
> + if (ser < 0 || ser > (255 - 64)) {
> + pr_err("speakup: Invalid ser param. Must be between 0 and 191 inclusive.\n");
> + return -EINVAL;
> + }
> +
> + /* TODO: support more than ttyS* */
> + tty = tty_open_by_driver(MKDEV(4, (ser + 64)), NULL, NULL);
> + if (IS_ERR(tty))
> + return PTR_ERR(tty);
> +
> + if (tty->ops->open)
> + ret = tty->ops->open(tty, NULL);
> + else
> + ret = -ENODEV;
> +
> + if (ret) {
> + tty_unlock(tty);
> + return ret;
> + }
> +
> + clear_bit(TTY_HUPPED, &tty->flags);
> + tty_unlock(tty);
> +
> + ret = tty_set_ldisc(tty, N_SPEAKUP);
> +
> + return ret;
> +}
> +
> +static int spk_ttyio_out(struct spk_synth *in_synth, const char ch)
> +{
> + if (in_synth->alive && speakup_tty && speakup_tty->ops->write) {
> + int ret = speakup_tty->ops->write(speakup_tty, &ch, 1);
> + if (ret == 0)
> + /* No room */
> + return 0;
> + if (ret < 0) {
> + pr_warn("%s: I/O error, deactivating speakup\n", in_synth->long_name);
> + /* No synth any more, so nobody will restart TTYs, and we thus
> + * need to do it ourselves. Now that there is no synth we can
> + * let application flood anyway
> + */
> + in_synth->alive = 0;
> + speakup_start_ttys();
> + return 0;
> + }
> + return 1;
> + }
> + return 0;
> +}
> +
> +int spk_ttyio_synth_probe(struct spk_synth *synth)
> +{
> + int rv = spk_ttyio_initialise_ldisc(synth->ser);
> +
> + if (rv)
> + return rv;
> +
> + synth->alive = 1;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(spk_ttyio_synth_probe);
> +
> +void spk_ttyio_release(void)
> +{
> + int idx;
> +
> + if (!speakup_tty)
> + return;
> +
> + tty_lock(speakup_tty);
> + idx = speakup_tty->index;
> +
> + if (speakup_tty->ops->close)
> + speakup_tty->ops->close(speakup_tty, NULL);
> +
> + tty_ldisc_flush(speakup_tty);
> + tty_unlock(speakup_tty);
> + tty_ldisc_release(speakup_tty);
> +}
> +EXPORT_SYMBOL_GPL(spk_ttyio_release);
> +
> +const char *spk_ttyio_synth_immediate(struct spk_synth *synth, const char *buff)
> +{
> + u_char ch;
> +
> + while ((ch = *buff)) {
> + if (ch == '\n')
> + ch = synth->procspeech;
> + if (tty_write_room(speakup_tty) < 1 || !synth->io_ops->synth_out(synth, ch))
> + return buff;
> + buff++;
> + }
> + return NULL;
> +}
> +EXPORT_SYMBOL_GPL(spk_ttyio_synth_immediate);
> Index: linux-staging/drivers/tty/tty_ldisc.c
> ===================================================================
> --- linux-staging.orig/drivers/tty/tty_ldisc.c
> +++ linux-staging/drivers/tty/tty_ldisc.c
> @@ -556,6 +556,7 @@ err:
> tty_unlock(tty);
> return retval;
> }
> +EXPORT_SYMBOL(tty_set_ldisc);
>
> /**
> * tty_ldisc_kill - teardown ldisc
> @@ -744,6 +745,7 @@ void tty_ldisc_release(struct tty_struct
>
> tty_ldisc_debug(tty, "released\n");
> }
> +EXPORT_SYMBOL(tty_ldisc_release);
>
> /**
> * tty_ldisc_init - ldisc setup for new tty
> Index: linux-staging/include/uapi/linux/tty.h
> ===================================================================
> --- linux-staging.orig/include/uapi/linux/tty.h
> +++ linux-staging/include/uapi/linux/tty.h
> @@ -35,5 +35,6 @@
> #define N_TRACESINK 23 /* Trace data routing for MIPI P1149.7 */
> #define N_TRACEROUTER 24 /* Trace data routing for MIPI P1149.7 */
> #define N_NCI 25 /* NFC NCI UART */
> +#define N_SPEAKUP 26 /* Speakup communication with synths*/
>
> #endif /* _UAPI_LINUX_TTY_H */
>
--
Samuel
>bah moi j'aime bien le flash et je cherche plus a comprendre
>crosoft. Ca plante : je reinstalle
Ca à le mérite de créer des emplois jeunes : "réinstalleur de crosoft"
-+- BD in NPC : Bill Gates au secours de l'emploi -+-
More information about the Speakup
mailing list