* [patch 1/7] staging: speakup: add send_xchar and tiocmset methods
[patch 0/7] staging: speakup: migrate synths to use TTY-based comms Okash Khawaja
@ ` Okash Khawaja
` Okash Khawaja
` [patch 2/7] staging: speakup: make input functionality swappable Okash Khawaja
` (6 subsequent siblings)
7 siblings, 1 reply; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup, Okash Khawaja
[-- Attachment #1: 01_add_send_xchar_and_tiocmset_methods --]
[-- Type: text/plain, Size: 4442 bytes --]
This adds two methods to spk_synth struct: send_xchar and tiocmset, and
creates serial implementation for each of them. It takes existing code
in apollo, audptr and spkout which already fits the behaviour of
send_xchar and tiocmset. In follow-up patches there will be TTY-based
implementations of these methods. Then migrating the synths to TTY will
include repointing these methods to their TTY implementations
Rest of the changes simply make use of serial implementation of these two
functions.
Signed-off-by: Okash Khawaja <okash.khawaja@gmail.com>
Reviewed-by: Samuel Thibault <samuel.thibault at ens-lyon.org>
Index: linux-staging/drivers/staging/speakup/serialio.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/serialio.c
+++ linux-staging/drivers/staging/speakup/serialio.c
@@ -26,8 +26,13 @@ static const struct old_serial_port *ser
static int timeouts;
static int spk_serial_out(struct spk_synth *in_synth, const char ch);
+static void spk_serial_send_xchar(char ch);
+static void spk_serial_tiocmset(unsigned int set, unsigned int clear);
+
struct spk_io_ops spk_serial_io_ops = {
.synth_out = spk_serial_out,
+ .send_xchar = spk_serial_send_xchar,
+ .tiocmset = spk_serial_tiocmset,
};
EXPORT_SYMBOL_GPL(spk_serial_io_ops);
@@ -136,6 +141,24 @@ static void start_serial_interrupt(int i
outb(1, speakup_info.port_tts + UART_FCR); /* Turn FIFO On */
}
+static void spk_serial_send_xchar(char ch)
+{
+ int timeout = SPK_XMITR_TIMEOUT;
+
+ while (spk_serial_tx_busy()) {
+ if (!--timeout)
+ break;
+ udelay(1);
+ }
+ outb(ch, speakup_info.port_tts);
+}
+
+static void spk_serial_tiocmset(unsigned int set, unsigned int clear)
+{
+ int old = inb(speakup_info.port_tts + UART_MCR);
+ outb((old & ~clear) | set, speakup_info.port_tts + UART_MCR);
+}
+
int spk_serial_synth_probe(struct spk_synth *synth)
{
const struct old_serial_port *ser;
Index: linux-staging/drivers/staging/speakup/speakup_apollo.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_apollo.c
+++ linux-staging/drivers/staging/speakup/speakup_apollo.c
@@ -171,9 +171,8 @@ static void do_catch_up(struct spk_synth
full_time_val = full_time->u.n.value;
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
if (!synth->io_ops->synth_out(synth, ch)) {
- outb(UART_MCR_DTR, speakup_info.port_tts + UART_MCR);
- outb(UART_MCR_DTR | UART_MCR_RTS,
- speakup_info.port_tts + UART_MCR);
+ synth->io_ops->tiocmset(0, UART_MCR_RTS);
+ synth->io_ops->tiocmset(UART_MCR_RTS, 0);
schedule_timeout(msecs_to_jiffies(full_time_val));
continue;
}
Index: linux-staging/drivers/staging/speakup/speakup_audptr.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_audptr.c
+++ linux-staging/drivers/staging/speakup/speakup_audptr.c
@@ -128,14 +128,7 @@ static struct spk_synth synth_audptr = {
static void synth_flush(struct spk_synth *synth)
{
- int timeout = SPK_XMITR_TIMEOUT;
-
- while (spk_serial_tx_busy()) {
- if (!--timeout)
- break;
- udelay(1);
- }
- outb(SYNTH_CLEAR, speakup_info.port_tts);
+ synth->io_ops->send_xchar(SYNTH_CLEAR);
synth->io_ops->synth_out(synth, PROCSPEECH);
}
Index: linux-staging/drivers/staging/speakup/speakup_spkout.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_spkout.c
+++ linux-staging/drivers/staging/speakup/speakup_spkout.c
@@ -126,14 +126,7 @@ static struct spk_synth synth_spkout = {
static void synth_flush(struct spk_synth *synth)
{
- int timeout = SPK_XMITR_TIMEOUT;
-
- while (spk_serial_tx_busy()) {
- if (!--timeout)
- break;
- udelay(1);
- }
- outb(SYNTH_CLEAR, speakup_info.port_tts);
+ synth->io_ops->send_xchar(SYNTH_CLEAR);
}
module_param_named(ser, synth_spkout.ser, int, 0444);
Index: linux-staging/drivers/staging/speakup/spk_types.h
===================================================================
--- linux-staging.orig/drivers/staging/speakup/spk_types.h
+++ linux-staging/drivers/staging/speakup/spk_types.h
@@ -150,6 +150,8 @@ struct spk_synth;
struct spk_io_ops {
int (*synth_out)(struct spk_synth *synth, const char ch);
+ void (*send_xchar)(char ch);
+ void (*tiocmset)(unsigned int set, unsigned int clear);
};
struct spk_synth {
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [patch 1/7] staging: speakup: add send_xchar and tiocmset methods
` [patch 1/7] staging: speakup: add send_xchar and tiocmset methods Okash Khawaja
@ ` Okash Khawaja
0 siblings, 0 replies; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup
On Thu, Apr 13, 2017 at 06:41:29PM +0100, Okash Khawaja wrote:
> This adds two methods to spk_synth struct: send_xchar and tiocmset, and
> creates serial implementation for each of them. It takes existing code
> in apollo, audptr and spkout which already fits the behaviour of
> send_xchar and tiocmset. In follow-up patches there will be TTY-based
> implementations of these methods. Then migrating the synths to TTY will
> include repointing these methods to their TTY implementations
>
> Rest of the changes simply make use of serial implementation of these two
> functions.
>
> Signed-off-by: Okash Khawaja <okash.khawaja@gmail.com>
> Reviewed-by: Samuel Thibault <samuel.thibault at ens-lyon.org>
I'll fix the at symbol across the patchset - copy-paste mistake.
^ permalink raw reply [flat|nested] 32+ messages in thread
* [patch 2/7] staging: speakup: make input functionality swappable
[patch 0/7] staging: speakup: migrate synths to use TTY-based comms Okash Khawaja
` [patch 1/7] staging: speakup: add send_xchar and tiocmset methods Okash Khawaja
@ ` Okash Khawaja
` Samuel Thibault
` [patch 3/7] tty: export tty_open_by_driver Okash Khawaja
` (5 subsequent siblings)
7 siblings, 1 reply; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup, Okash Khawaja
[-- Attachment #1: 02_make_input_functionality_swappable --]
[-- Type: text/plain, Size: 10467 bytes --]
This moves functions which take input from external synth, into struct
spk_io_ops. The calling code then uses serial implementation of those methods
through spk_io_ops. That way we can add a parallel TTY-based implementation and
simply replace serial with TTY. That is what the next patch in this series does.
speakup_decext.c has get_last_char function which reads the most recent
available character from the synth. This patch changes that by defining
read_buff_add callback method of spk_syth and letting that update the last_char
global character read from the synth. read_buff_add is called from ISR, so
there is a possibility for last_char to be stale. Therefore it is marked as
volatile. It also pulls a repeated get_index implementation into synth.c, to
be used as a utility function.
Signed-off-by: Okash Khawaja <okash.khawaja@gmail.com>
Index: linux-staging/drivers/staging/speakup/serialio.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/serialio.c
+++ linux-staging/drivers/staging/speakup/serialio.c
@@ -28,11 +28,15 @@ static int timeouts;
static int spk_serial_out(struct spk_synth *in_synth, const char ch);
static void spk_serial_send_xchar(char ch);
static void spk_serial_tiocmset(unsigned int set, unsigned int clear);
+static unsigned char spk_serial_in(void);
+static unsigned char spk_serial_in_nowait(void);
struct spk_io_ops spk_serial_io_ops = {
.synth_out = spk_serial_out,
.send_xchar = spk_serial_send_xchar,
.tiocmset = spk_serial_tiocmset,
+ .synth_in = spk_serial_in,
+ .synth_in_nowait = spk_serial_in_nowait,
};
EXPORT_SYMBOL_GPL(spk_serial_io_ops);
@@ -240,7 +244,7 @@ int spk_wait_for_xmitr(struct spk_synth
return 1;
}
-unsigned char spk_serial_in(void)
+static unsigned char spk_serial_in(void)
{
int tmout = SPK_SERIAL_TIMEOUT;
@@ -253,9 +257,8 @@ unsigned char spk_serial_in(void)
}
return inb_p(speakup_info.port_tts + UART_RX);
}
-EXPORT_SYMBOL_GPL(spk_serial_in);
-unsigned char spk_serial_in_nowait(void)
+static unsigned char spk_serial_in_nowait(void)
{
unsigned char lsr;
@@ -264,7 +267,6 @@ unsigned char spk_serial_in_nowait(void)
return 0;
return inb_p(speakup_info.port_tts + UART_RX);
}
-EXPORT_SYMBOL_GPL(spk_serial_in_nowait);
static int spk_serial_out(struct spk_synth *in_synth, const char ch)
{
Index: linux-staging/drivers/staging/speakup/speakup_audptr.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_audptr.c
+++ linux-staging/drivers/staging/speakup/speakup_audptr.c
@@ -138,11 +138,11 @@ static void synth_version(struct spk_syn
char synth_id[40] = "";
synth->synth_immediate(synth, "\x05[Q]");
- synth_id[test] = spk_serial_in();
+ synth_id[test] = synth->io_ops->synth_in();
if (synth_id[test] == 'A') {
do {
/* read version string from synth */
- synth_id[++test] = spk_serial_in();
+ synth_id[++test] = synth->io_ops->synth_in();
} while (synth_id[test] != '\n' && test < 32);
synth_id[++test] = 0x00;
}
Index: linux-staging/drivers/staging/speakup/speakup_dectlk.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_dectlk.c
+++ linux-staging/drivers/staging/speakup/speakup_dectlk.c
@@ -42,7 +42,7 @@ static inline int synth_full(void)
static void do_catch_up(struct spk_synth *synth);
static void synth_flush(struct spk_synth *synth);
static void read_buff_add(u_char c);
-static unsigned char get_index(void);
+static unsigned char get_index(struct spk_synth *synth);
static int in_escape;
static int is_flushing;
@@ -163,7 +163,7 @@ static int is_indnum(u_char *ch)
static u_char lastind;
-static unsigned char get_index(void)
+static unsigned char get_index(struct spk_synth *synth)
{
u_char rv;
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
@@ -43,8 +43,6 @@
const struct old_serial_port *spk_serial_init(int index);
void spk_stop_serial_interrupt(void);
int spk_wait_for_xmitr(struct spk_synth *in_synth);
-unsigned char spk_serial_in(void);
-unsigned char spk_serial_in_nowait(void);
void spk_serial_release(void);
void synth_buffer_skip_nonlatin1(void);
@@ -61,6 +59,7 @@ int spk_serial_synth_probe(struct spk_sy
const char *spk_serial_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);
+unsigned char spk_synth_get_index(struct spk_synth *synth);
int spk_synth_is_alive_nop(struct spk_synth *synth);
int spk_synth_is_alive_restart(struct spk_synth *synth);
__printf(1, 2)
Index: linux-staging/drivers/staging/speakup/spk_types.h
===================================================================
--- linux-staging.orig/drivers/staging/speakup/spk_types.h
+++ linux-staging/drivers/staging/speakup/spk_types.h
@@ -152,6 +152,8 @@ struct spk_io_ops {
int (*synth_out)(struct spk_synth *synth, const char ch);
void (*send_xchar)(char ch);
void (*tiocmset)(unsigned int set, unsigned int clear);
+ unsigned char (*synth_in)(void);
+ unsigned char (*synth_in_nowait)(void);
};
struct spk_synth {
@@ -182,7 +184,7 @@ struct spk_synth {
int (*is_alive)(struct spk_synth *synth);
int (*synth_adjust)(struct st_var_header *var);
void (*read_buff_add)(u_char);
- unsigned char (*get_index)(void);
+ unsigned char (*get_index)(struct spk_synth *synth);
struct synth_indexing indexing;
int alive;
struct attribute_group attributes;
Index: linux-staging/drivers/staging/speakup/speakup_decext.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_decext.c
+++ linux-staging/drivers/staging/speakup/speakup_decext.c
@@ -30,20 +30,16 @@
#define DRV_VERSION "2.14"
#define SYNTH_CLEAR 0x03
#define PROCSPEECH 0x0b
-static unsigned char last_char;
+static volatile unsigned char last_char;
-static inline u_char get_last_char(void)
+static void read_buff_add(u_char ch)
{
- u_char avail = inb_p(speakup_info.port_tts + UART_LSR) & UART_LSR_DR;
-
- if (avail)
- last_char = inb_p(speakup_info.port_tts + UART_RX);
- return last_char;
+ last_char = ch;
}
static inline bool synth_full(void)
{
- return get_last_char() == 0x13;
+ return last_char == 0x13;
}
static void do_catch_up(struct spk_synth *synth);
@@ -135,7 +131,7 @@ static struct spk_synth synth_decext = {
.flush = synth_flush,
.is_alive = spk_synth_is_alive_restart,
.synth_adjust = NULL,
- .read_buff_add = NULL,
+ .read_buff_add = read_buff_add,
.get_index = NULL,
.indexing = {
.command = NULL,
Index: linux-staging/drivers/staging/speakup/speakup_dtlk.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_dtlk.c
+++ linux-staging/drivers/staging/speakup/speakup_dtlk.c
@@ -138,7 +138,7 @@ static struct spk_synth synth_dtlk = {
.is_alive = spk_synth_is_alive_nop,
.synth_adjust = NULL,
.read_buff_add = NULL,
- .get_index = spk_serial_in_nowait,
+ .get_index = spk_synth_get_index,
.indexing = {
.command = "\x01%di",
.lowindex = 1,
Index: linux-staging/drivers/staging/speakup/speakup_ltlk.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_ltlk.c
+++ linux-staging/drivers/staging/speakup/speakup_ltlk.c
@@ -120,7 +120,7 @@ static struct spk_synth synth_ltlk = {
.is_alive = spk_synth_is_alive_restart,
.synth_adjust = NULL,
.read_buff_add = NULL,
- .get_index = spk_serial_in_nowait,
+ .get_index = spk_synth_get_index,
.indexing = {
.command = "\x01%di",
.lowindex = 1,
@@ -141,7 +141,7 @@ static void synth_interrogate(struct spk
synth->synth_immediate(synth, "\x18\x01?");
for (i = 0; i < 50; i++) {
- buf[i] = spk_serial_in();
+ buf[i] = synth->io_ops->synth_in();
if (i > 2 && buf[i] == 0x7f)
break;
}
Index: linux-staging/drivers/staging/speakup/speakup_soft.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_soft.c
+++ linux-staging/drivers/staging/speakup/speakup_soft.c
@@ -36,7 +36,7 @@
static int softsynth_probe(struct spk_synth *synth);
static void softsynth_release(void);
static int softsynth_is_alive(struct spk_synth *synth);
-static unsigned char get_index(void);
+static unsigned char get_index(struct spk_synth *synth);
static struct miscdevice synth_device, synthu_device;
static int init_pos;
@@ -340,7 +340,7 @@ static unsigned int softsynth_poll(struc
return ret;
}
-static unsigned char get_index(void)
+static unsigned char get_index(struct spk_synth *synth)
{
int rv;
Index: linux-staging/drivers/staging/speakup/speakup_spkout.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_spkout.c
+++ linux-staging/drivers/staging/speakup/speakup_spkout.c
@@ -111,7 +111,7 @@ static struct spk_synth synth_spkout = {
.is_alive = spk_synth_is_alive_restart,
.synth_adjust = NULL,
.read_buff_add = NULL,
- .get_index = spk_serial_in_nowait,
+ .get_index = spk_synth_get_index,
.indexing = {
.command = "\x05[%c",
.lowindex = 1,
Index: linux-staging/drivers/staging/speakup/synth.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/synth.c
+++ linux-staging/drivers/staging/speakup/synth.c
@@ -124,6 +124,12 @@ void spk_synth_flush(struct spk_synth *s
}
EXPORT_SYMBOL_GPL(spk_synth_flush);
+unsigned char spk_synth_get_index(struct spk_synth *synth)
+{
+ return synth->io_ops->synth_in_nowait();
+}
+EXPORT_SYMBOL_GPL(spk_synth_get_index);
+
int spk_synth_is_alive_nop(struct spk_synth *synth)
{
synth->alive = 1;
@@ -249,7 +255,7 @@ void spk_reset_index_count(int sc)
if (first)
first = 0;
else
- synth->get_index();
+ synth->get_index(synth);
index_count = 0;
sentence_count = sc;
}
@@ -282,7 +288,7 @@ void synth_insert_next_index(int sent_nu
void spk_get_index_count(int *linecount, int *sentcount)
{
- int ind = synth->get_index();
+ int ind = synth->get_index(synth);
if (ind) {
sentence_count = ind % 10;
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [patch 2/7] staging: speakup: make input functionality swappable
` [patch 2/7] staging: speakup: make input functionality swappable Okash Khawaja
@ ` Samuel Thibault
0 siblings, 0 replies; 32+ messages in thread
From: Samuel Thibault @ UTC (permalink / raw)
To: Okash Khawaja; +Cc: speakup
Okash Khawaja, on jeu. 13 avril 2017 18:41:30 +0100, wrote:
> This moves functions which take input from external synth, into struct
> spk_io_ops. The calling code then uses serial implementation of those methods
> through spk_io_ops. That way we can add a parallel TTY-based implementation and
> simply replace serial with TTY. That is what the next patch in this series does.
>
> speakup_decext.c has get_last_char function which reads the most recent
> available character from the synth. This patch changes that by defining
> read_buff_add callback method of spk_syth and letting that update the last_char
> global character read from the synth. read_buff_add is called from ISR, so
> there is a possibility for last_char to be stale. Therefore it is marked as
> volatile. It also pulls a repeated get_index implementation into synth.c, to
> be used as a utility function.
>
> Signed-off-by: Okash Khawaja <okash.khawaja@gmail.com>
Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> Index: linux-staging/drivers/staging/speakup/serialio.c
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/serialio.c
> +++ linux-staging/drivers/staging/speakup/serialio.c
> @@ -28,11 +28,15 @@ static int timeouts;
> static int spk_serial_out(struct spk_synth *in_synth, const char ch);
> static void spk_serial_send_xchar(char ch);
> static void spk_serial_tiocmset(unsigned int set, unsigned int clear);
> +static unsigned char spk_serial_in(void);
> +static unsigned char spk_serial_in_nowait(void);
>
> struct spk_io_ops spk_serial_io_ops = {
> .synth_out = spk_serial_out,
> .send_xchar = spk_serial_send_xchar,
> .tiocmset = spk_serial_tiocmset,
> + .synth_in = spk_serial_in,
> + .synth_in_nowait = spk_serial_in_nowait,
> };
> EXPORT_SYMBOL_GPL(spk_serial_io_ops);
>
> @@ -240,7 +244,7 @@ int spk_wait_for_xmitr(struct spk_synth
> return 1;
> }
>
> -unsigned char spk_serial_in(void)
> +static unsigned char spk_serial_in(void)
> {
> int tmout = SPK_SERIAL_TIMEOUT;
>
> @@ -253,9 +257,8 @@ unsigned char spk_serial_in(void)
> }
> return inb_p(speakup_info.port_tts + UART_RX);
> }
> -EXPORT_SYMBOL_GPL(spk_serial_in);
>
> -unsigned char spk_serial_in_nowait(void)
> +static unsigned char spk_serial_in_nowait(void)
> {
> unsigned char lsr;
>
> @@ -264,7 +267,6 @@ unsigned char spk_serial_in_nowait(void)
> return 0;
> return inb_p(speakup_info.port_tts + UART_RX);
> }
> -EXPORT_SYMBOL_GPL(spk_serial_in_nowait);
>
> static int spk_serial_out(struct spk_synth *in_synth, const char ch)
> {
> Index: linux-staging/drivers/staging/speakup/speakup_audptr.c
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/speakup_audptr.c
> +++ linux-staging/drivers/staging/speakup/speakup_audptr.c
> @@ -138,11 +138,11 @@ static void synth_version(struct spk_syn
> char synth_id[40] = "";
>
> synth->synth_immediate(synth, "\x05[Q]");
> - synth_id[test] = spk_serial_in();
> + synth_id[test] = synth->io_ops->synth_in();
> if (synth_id[test] == 'A') {
> do {
> /* read version string from synth */
> - synth_id[++test] = spk_serial_in();
> + synth_id[++test] = synth->io_ops->synth_in();
> } while (synth_id[test] != '\n' && test < 32);
> synth_id[++test] = 0x00;
> }
> Index: linux-staging/drivers/staging/speakup/speakup_dectlk.c
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/speakup_dectlk.c
> +++ linux-staging/drivers/staging/speakup/speakup_dectlk.c
> @@ -42,7 +42,7 @@ static inline int synth_full(void)
> static void do_catch_up(struct spk_synth *synth);
> static void synth_flush(struct spk_synth *synth);
> static void read_buff_add(u_char c);
> -static unsigned char get_index(void);
> +static unsigned char get_index(struct spk_synth *synth);
>
> static int in_escape;
> static int is_flushing;
> @@ -163,7 +163,7 @@ static int is_indnum(u_char *ch)
>
> static u_char lastind;
>
> -static unsigned char get_index(void)
> +static unsigned char get_index(struct spk_synth *synth)
> {
> u_char rv;
>
> 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
> @@ -43,8 +43,6 @@
> const struct old_serial_port *spk_serial_init(int index);
> void spk_stop_serial_interrupt(void);
> int spk_wait_for_xmitr(struct spk_synth *in_synth);
> -unsigned char spk_serial_in(void);
> -unsigned char spk_serial_in_nowait(void);
> void spk_serial_release(void);
>
> void synth_buffer_skip_nonlatin1(void);
> @@ -61,6 +59,7 @@ int spk_serial_synth_probe(struct spk_sy
> const char *spk_serial_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);
> +unsigned char spk_synth_get_index(struct spk_synth *synth);
> int spk_synth_is_alive_nop(struct spk_synth *synth);
> int spk_synth_is_alive_restart(struct spk_synth *synth);
> __printf(1, 2)
> Index: linux-staging/drivers/staging/speakup/spk_types.h
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/spk_types.h
> +++ linux-staging/drivers/staging/speakup/spk_types.h
> @@ -152,6 +152,8 @@ struct spk_io_ops {
> int (*synth_out)(struct spk_synth *synth, const char ch);
> void (*send_xchar)(char ch);
> void (*tiocmset)(unsigned int set, unsigned int clear);
> + unsigned char (*synth_in)(void);
> + unsigned char (*synth_in_nowait)(void);
> };
>
> struct spk_synth {
> @@ -182,7 +184,7 @@ struct spk_synth {
> int (*is_alive)(struct spk_synth *synth);
> int (*synth_adjust)(struct st_var_header *var);
> void (*read_buff_add)(u_char);
> - unsigned char (*get_index)(void);
> + unsigned char (*get_index)(struct spk_synth *synth);
> struct synth_indexing indexing;
> int alive;
> struct attribute_group attributes;
> Index: linux-staging/drivers/staging/speakup/speakup_decext.c
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/speakup_decext.c
> +++ linux-staging/drivers/staging/speakup/speakup_decext.c
> @@ -30,20 +30,16 @@
> #define DRV_VERSION "2.14"
> #define SYNTH_CLEAR 0x03
> #define PROCSPEECH 0x0b
> -static unsigned char last_char;
> +static volatile unsigned char last_char;
>
> -static inline u_char get_last_char(void)
> +static void read_buff_add(u_char ch)
> {
> - u_char avail = inb_p(speakup_info.port_tts + UART_LSR) & UART_LSR_DR;
> -
> - if (avail)
> - last_char = inb_p(speakup_info.port_tts + UART_RX);
> - return last_char;
> + last_char = ch;
> }
>
> static inline bool synth_full(void)
> {
> - return get_last_char() == 0x13;
> + return last_char == 0x13;
> }
>
> static void do_catch_up(struct spk_synth *synth);
> @@ -135,7 +131,7 @@ static struct spk_synth synth_decext = {
> .flush = synth_flush,
> .is_alive = spk_synth_is_alive_restart,
> .synth_adjust = NULL,
> - .read_buff_add = NULL,
> + .read_buff_add = read_buff_add,
> .get_index = NULL,
> .indexing = {
> .command = NULL,
> Index: linux-staging/drivers/staging/speakup/speakup_dtlk.c
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/speakup_dtlk.c
> +++ linux-staging/drivers/staging/speakup/speakup_dtlk.c
> @@ -138,7 +138,7 @@ static struct spk_synth synth_dtlk = {
> .is_alive = spk_synth_is_alive_nop,
> .synth_adjust = NULL,
> .read_buff_add = NULL,
> - .get_index = spk_serial_in_nowait,
> + .get_index = spk_synth_get_index,
> .indexing = {
> .command = "\x01%di",
> .lowindex = 1,
> Index: linux-staging/drivers/staging/speakup/speakup_ltlk.c
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/speakup_ltlk.c
> +++ linux-staging/drivers/staging/speakup/speakup_ltlk.c
> @@ -120,7 +120,7 @@ static struct spk_synth synth_ltlk = {
> .is_alive = spk_synth_is_alive_restart,
> .synth_adjust = NULL,
> .read_buff_add = NULL,
> - .get_index = spk_serial_in_nowait,
> + .get_index = spk_synth_get_index,
> .indexing = {
> .command = "\x01%di",
> .lowindex = 1,
> @@ -141,7 +141,7 @@ static void synth_interrogate(struct spk
>
> synth->synth_immediate(synth, "\x18\x01?");
> for (i = 0; i < 50; i++) {
> - buf[i] = spk_serial_in();
> + buf[i] = synth->io_ops->synth_in();
> if (i > 2 && buf[i] == 0x7f)
> break;
> }
> Index: linux-staging/drivers/staging/speakup/speakup_soft.c
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/speakup_soft.c
> +++ linux-staging/drivers/staging/speakup/speakup_soft.c
> @@ -36,7 +36,7 @@
> static int softsynth_probe(struct spk_synth *synth);
> static void softsynth_release(void);
> static int softsynth_is_alive(struct spk_synth *synth);
> -static unsigned char get_index(void);
> +static unsigned char get_index(struct spk_synth *synth);
>
> static struct miscdevice synth_device, synthu_device;
> static int init_pos;
> @@ -340,7 +340,7 @@ static unsigned int softsynth_poll(struc
> return ret;
> }
>
> -static unsigned char get_index(void)
> +static unsigned char get_index(struct spk_synth *synth)
> {
> int rv;
>
> Index: linux-staging/drivers/staging/speakup/speakup_spkout.c
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/speakup_spkout.c
> +++ linux-staging/drivers/staging/speakup/speakup_spkout.c
> @@ -111,7 +111,7 @@ static struct spk_synth synth_spkout = {
> .is_alive = spk_synth_is_alive_restart,
> .synth_adjust = NULL,
> .read_buff_add = NULL,
> - .get_index = spk_serial_in_nowait,
> + .get_index = spk_synth_get_index,
> .indexing = {
> .command = "\x05[%c",
> .lowindex = 1,
> Index: linux-staging/drivers/staging/speakup/synth.c
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/synth.c
> +++ linux-staging/drivers/staging/speakup/synth.c
> @@ -124,6 +124,12 @@ void spk_synth_flush(struct spk_synth *s
> }
> EXPORT_SYMBOL_GPL(spk_synth_flush);
>
> +unsigned char spk_synth_get_index(struct spk_synth *synth)
> +{
> + return synth->io_ops->synth_in_nowait();
> +}
> +EXPORT_SYMBOL_GPL(spk_synth_get_index);
> +
> int spk_synth_is_alive_nop(struct spk_synth *synth)
> {
> synth->alive = 1;
> @@ -249,7 +255,7 @@ void spk_reset_index_count(int sc)
> if (first)
> first = 0;
> else
> - synth->get_index();
> + synth->get_index(synth);
> index_count = 0;
> sentence_count = sc;
> }
> @@ -282,7 +288,7 @@ void synth_insert_next_index(int sent_nu
>
> void spk_get_index_count(int *linecount, int *sentcount)
> {
> - int ind = synth->get_index();
> + int ind = synth->get_index(synth);
>
> if (ind) {
> sentence_count = ind % 10;
>
--
Samuel
<m> argh, pi est plus grand que 2. Ca casse tout
-+- #ens-mim -+-
^ permalink raw reply [flat|nested] 32+ messages in thread
* [patch 3/7] tty: export tty_open_by_driver
[patch 0/7] staging: speakup: migrate synths to use TTY-based comms Okash Khawaja
` [patch 1/7] staging: speakup: add send_xchar and tiocmset methods Okash Khawaja
` [patch 2/7] staging: speakup: make input functionality swappable Okash Khawaja
@ ` Okash Khawaja
` [patch 4/7] staging: speakup: add tty-based comms functions Okash Khawaja
` (4 subsequent siblings)
7 siblings, 0 replies; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup
[-- Attachment #1: 03_export_tty_open_by_driver --]
[-- Type: text/plain, Size: 2098 bytes --]
This applies on top of the changes already in staging-next branch which allow
kernel access to TTY dev.
Signe-doff-by: Okash Khawaja <okash.khawaja@gmail.com>
Reviewed-by: Samuel Thibault <samuel.thibault at ens-lyon.org>
Index: linux-staging/drivers/tty/tty_io.c
===================================================================
--- linux-staging.orig/drivers/tty/tty_io.c
+++ linux-staging/drivers/tty/tty_io.c
@@ -1369,7 +1369,10 @@ static struct tty_struct *tty_driver_loo
struct tty_struct *tty;
if (driver->ops->lookup)
- tty = driver->ops->lookup(driver, file, idx);
+ if (!file)
+ tty = ERR_PTR(-EIO);
+ else
+ tty = driver->ops->lookup(driver, file, idx);
else
tty = driver->ttys[idx];
@@ -2001,7 +2004,7 @@ static struct tty_driver *tty_lookup_dri
struct tty_driver *console_driver = console_device(index);
if (console_driver) {
driver = tty_driver_kref_get(console_driver);
- if (driver) {
+ if (driver && filp) {
/* Don't let /dev/console block */
filp->f_flags |= O_NONBLOCK;
break;
@@ -2034,7 +2037,7 @@ static struct tty_driver *tty_lookup_dri
* - concurrent tty driver removal w/ lookup
* - concurrent tty removal from driver table
*/
-static struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode,
+struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode,
struct file *filp)
{
struct tty_struct *tty;
@@ -2079,6 +2082,7 @@ out:
tty_driver_kref_put(driver);
return tty;
}
+EXPORT_SYMBOL(tty_open_by_driver);
/**
* tty_open - open a tty device
Index: linux-staging/include/linux/tty.h
===================================================================
--- linux-staging.orig/include/linux/tty.h
+++ linux-staging/include/linux/tty.h
@@ -401,6 +401,8 @@ extern struct tty_struct *get_current_tt
/* tty_io.c */
extern int __init tty_init(void);
extern const char *tty_name(const struct tty_struct *tty);
+extern struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode,
+ struct file *filp);
#else
static inline void console_init(void)
{ }
^ permalink raw reply [flat|nested] 32+ messages in thread* [patch 4/7] staging: speakup: add tty-based comms functions
[patch 0/7] staging: speakup: migrate synths to use TTY-based comms Okash Khawaja
` (2 preceding siblings ...)
` [patch 3/7] tty: export tty_open_by_driver Okash Khawaja
@ ` Okash Khawaja
` [patch 5/7] staging: speakup: migrate acntsa, bns, dummy and txprt to ttyio Okash Khawaja
` (3 subsequent siblings)
7 siblings, 0 replies; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup, Okash Khawaja
[-- Attachment #1: 04_add_spk_ttyio --]
[-- Type: text/plain, Size: 6783 bytes --]
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@gmail.com>
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
@@ -44,6 +44,7 @@ const struct old_serial_port *spk_serial
void spk_stop_serial_interrupt(void);
int spk_wait_for_xmitr(struct spk_synth *in_synth);
void spk_serial_release(void);
+void spk_ttyio_release(void);
void synth_buffer_skip_nonlatin1(void);
u16 synth_buffer_getc(void);
@@ -56,7 +57,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);
unsigned char spk_synth_get_index(struct spk_synth *synth);
@@ -78,5 +81,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 */
^ permalink raw reply [flat|nested] 32+ messages in thread* [patch 5/7] staging: speakup: migrate acntsa, bns, dummy and txprt to ttyio
[patch 0/7] staging: speakup: migrate synths to use TTY-based comms Okash Khawaja
` (3 preceding siblings ...)
` [patch 4/7] staging: speakup: add tty-based comms functions Okash Khawaja
@ ` Okash Khawaja
` [patch 6/7] staging: speakup: add send_xchar, tiocmset and input functionality for tty Okash Khawaja
` (2 subsequent siblings)
7 siblings, 0 replies; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup, Okash Khawaja
[-- Attachment #1: 05_migrate_dummy_acntsa_bns_txprt_to_ttyio --]
[-- Type: text/plain, Size: 2844 bytes --]
This changes the above five synths to TTY-based comms. They were chosen as a
first pass because their serial comms are straightforward, i.e. they don't use
serial input and don't do internal port knocking.
Signed-off-by: Okash Khawaja <okash.khawaja@gmail.com>
Reviewed-by: Samuel Thibault <samuel.thibault at ens-lyon.org>
Index: linux-staging/drivers/staging/speakup/speakup_dummy.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_dummy.c
+++ linux-staging/drivers/staging/speakup/speakup_dummy.c
@@ -98,10 +98,10 @@ static struct spk_synth synth_dummy = {
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
Index: linux-staging/drivers/staging/speakup/speakup_acntsa.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_acntsa.c
+++ linux-staging/drivers/staging/speakup/speakup_acntsa.c
@@ -99,10 +99,10 @@ static struct spk_synth synth_acntsa = {
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
+ .io_ops = &spk_ttyio_ops,
.probe = synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
@@ -125,7 +125,7 @@ static int synth_probe(struct spk_synth
{
int failed;
- failed = spk_serial_synth_probe(synth);
+ failed = spk_ttyio_synth_probe(synth);
if (failed == 0) {
synth->synth_immediate(synth, "\033=R\r");
mdelay(100);
Index: linux-staging/drivers/staging/speakup/speakup_txprt.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_txprt.c
+++ linux-staging/drivers/staging/speakup/speakup_txprt.c
@@ -95,10 +95,10 @@ static struct spk_synth synth_txprt = {
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
^ permalink raw reply [flat|nested] 32+ messages in thread* [patch 6/7] staging: speakup: add send_xchar, tiocmset and input functionality for tty
[patch 0/7] staging: speakup: migrate synths to use TTY-based comms Okash Khawaja
` (4 preceding siblings ...)
` [patch 5/7] staging: speakup: migrate acntsa, bns, dummy and txprt to ttyio Okash Khawaja
@ ` Okash Khawaja
` Samuel Thibault
` [patch 7/7] staging: speakup: migrate apollo, ltlk, audptr, decext, dectlk and spkout Okash Khawaja
` [patch 0/7] staging: speakup: migrate synths to use TTY-based comms Samuel Thibault
7 siblings, 1 reply; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup, Okash Khawaja
[-- Attachment #1: 06_add_tty_send_xchar_tiocmset_and_input_functionality --]
[-- Type: text/plain, Size: 6975 bytes --]
This patch adds further TTY-based functionality, specifically implementation
of send_xchar and tiocmset methods, and input. send_xchar and tiocmset
methods simply delegate to corresponding TTY operations.
For input, it implements the receive_buf2 callback in tty_ldisc_ops of
speakup's ldisc. If a synth defines read_buff_add method then receive_buf2
simply delegates to that and returns.
For spk_ttyio_in, the data is passed from receive_buf2 thread to
spk_ttyio_in thread through spk_ldisc_data structure. It has following
members:
- char buf: represents data received
- struct semaphore sem: used to signal to spk_ttyio_in thread that data
is available to be read without having to busy wait
- bool buf_free: this is used in comination with mb() calls to syncronise
the two threads over buf
receive_buf2 only writes to buf if buf_free is true. The check for buf_free
and writing to buf are separated by mb() to ensure that spk_ttyio_in has read
buf before receive_buf2 writes to it. After writing, it ups the semaphore to
signal to spk_ttyio_in that there is now data to read.
spk_ttyio_in waits for data to read by downing the semaphore. Thus when
signalled by receive_buf2 thread above, it reads from buf and sets buf_free
to true. These two operations are separated by mb() to ensure that
receive_buf2 thread finds buf_free to be true only after buf has been read.
After that spk_ttyio_in calls tty_schedule_flip for subsequent data to come
in through receive_buf2.
Signed-off-by: Okash Khawaja <okash.khawaja@gmail.com>
Index: linux-staging/drivers/staging/speakup/spk_ttyio.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/spk_ttyio.c
+++ linux-staging/drivers/staging/speakup/spk_ttyio.c
@@ -1,36 +1,98 @@
#include <linux/types.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/slab.h>
#include "speakup.h"
#include "spk_types.h"
+#include "spk_priv.h"
+struct spk_ldisc_data {
+ char buf;
+ struct semaphore sem;
+ bool buf_free;
+};
+
+static struct spk_synth *spk_ttyio_synth;
+/* TODO: make this part of synth and remove the global */
static struct tty_struct *speakup_tty;
static int spk_ttyio_ldisc_open(struct tty_struct *tty)
{
+ struct spk_ldisc_data *ldisc_data;
+
if (tty->ops->write == NULL)
return -EOPNOTSUPP;
speakup_tty = tty;
+ ldisc_data = kmalloc(sizeof(struct spk_ldisc_data), GFP_KERNEL);
+ if (!ldisc_data) {
+ pr_err("speakup: Failed to allocate ldisc_data.\n");
+ return -ENOMEM;
+ }
+
+ sema_init(&ldisc_data->sem, 0);
+ ldisc_data->buf_free = true;
+ speakup_tty->disc_data = ldisc_data;
+
return 0;
}
static void spk_ttyio_ldisc_close(struct tty_struct *tty)
{
+ kfree(speakup_tty->disc_data);
speakup_tty = NULL;
}
+static int spk_ttyio_receive_buf2(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count)
+{
+ struct spk_ldisc_data *ldisc_data = (struct spk_ldisc_data *)tty->disc_data;
+
+ if (spk_ttyio_synth->read_buff_add) {
+ int i;
+ for (i = 0; i < count; i++)
+ spk_ttyio_synth->read_buff_add(cp[i]);
+
+ return count;
+ }
+
+ if (!ldisc_data->buf_free)
+ /* ttyio_in will tty_schedule_flip */
+ return 0;
+
+ /* Make sure the consumer has read buf before we have seen
+ * buf_free == true and overwrite buf */
+ mb();
+
+ ldisc_data->buf = cp[0];
+ ldisc_data->buf_free = false;
+ up(&ldisc_data->sem);
+
+ return 1;
+}
+
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,
+ .receive_buf2 = spk_ttyio_receive_buf2,
};
static int spk_ttyio_out(struct spk_synth *in_synth, const char ch);
+static void spk_ttyio_send_xchar(char ch);
+static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear);
+static unsigned char spk_ttyio_in(void);
+static unsigned char spk_ttyio_in_nowait(void);
+
struct spk_io_ops spk_ttyio_ops = {
.synth_out = spk_ttyio_out,
+ .send_xchar = spk_ttyio_send_xchar,
+ .tiocmset = spk_ttyio_tiocmset,
+ .synth_in = spk_ttyio_in,
+ .synth_in_nowait = spk_ttyio_in_nowait,
};
EXPORT_SYMBOL_GPL(spk_ttyio_ops);
@@ -41,7 +103,7 @@ static int spk_ttyio_initialise_ldisc(in
ret = tty_register_ldisc(N_SPEAKUP, &spk_ttyio_ldisc_ops);
if (ret) {
- pr_err("Error registering line discipline.\n");
+ pr_err("speakup: Error registering line discipline.\n");
return ret;
}
@@ -95,6 +157,49 @@ static int spk_ttyio_out(struct spk_synt
return 0;
}
+static void spk_ttyio_send_xchar(char ch)
+{
+ speakup_tty->ops->send_xchar(speakup_tty, ch);
+}
+
+static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
+{
+ speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+}
+
+static unsigned char ttyio_in(int timeout)
+{
+ struct spk_ldisc_data *ldisc_data =
+ (struct spk_ldisc_data *)speakup_tty->disc_data;
+ char rv;
+
+ if (!down_timeout(&ldisc_data->sem, usecs_to_jiffies(timeout))) {
+ pr_warn("spk_ttyio: timeout (%d) while waiting for input\n",
+ timeout);
+ return 0xff;
+ }
+
+ rv = ldisc_data->buf;
+ /* Make sure we have read buf before we set buf_free to let
+ * the producer overwrite it */
+ mb();
+ ldisc_data->buf_free = true;
+ tty_schedule_flip(speakup_tty->port);
+ up(&ldisc_data->sem);
+
+ return rv;
+}
+
+static unsigned char spk_ttyio_in(void)
+{
+ return ttyio_in(SPK_SYNTH_TIMEOUT);
+}
+
+static unsigned char spk_ttyio_in_nowait(void)
+{
+ return ttyio_in(0);
+}
+
int spk_ttyio_synth_probe(struct spk_synth *synth)
{
int rv = spk_ttyio_initialise_ldisc(synth->ser);
@@ -103,6 +208,7 @@ int spk_ttyio_synth_probe(struct spk_syn
return rv;
synth->alive = 1;
+ spk_ttyio_synth = synth;
return 0;
}
Index: linux-staging/drivers/staging/speakup/serialio.h
===================================================================
--- linux-staging.orig/drivers/staging/speakup/serialio.h
+++ linux-staging/drivers/staging/speakup/serialio.h
@@ -8,6 +8,8 @@
#endif
#include <linux/serial_core.h>
+#include "spk_priv.h"
+
/*
* this is cut&paste from 8250.h. Get rid of the structure, the definitions
* and this whole broken driver.
@@ -21,7 +23,7 @@ struct old_serial_port {
};
/* countdown values for serial timeouts in us */
-#define SPK_SERIAL_TIMEOUT 100000
+#define SPK_SERIAL_TIMEOUT SPK_SYNTH_TIMEOUT
/* countdown values transmitter/dsr timeouts in us */
#define SPK_XMITR_TIMEOUT 100000
/* countdown values cts timeouts in us */
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
@@ -39,6 +39,7 @@
#endif
#define KT_SPKUP 15
+#define SPK_SYNTH_TIMEOUT 100000
const struct old_serial_port *spk_serial_init(int index);
void spk_stop_serial_interrupt(void);
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [patch 6/7] staging: speakup: add send_xchar, tiocmset and input functionality for tty
` [patch 6/7] staging: speakup: add send_xchar, tiocmset and input functionality for tty Okash Khawaja
@ ` Samuel Thibault
` Okash Khawaja
` Okash Khawaja
0 siblings, 2 replies; 32+ messages in thread
From: Samuel Thibault @ UTC (permalink / raw)
To: Okash Khawaja; +Cc: speakup
Hello,
Okash Khawaja, on jeu. 13 avril 2017 18:41:34 +0100, wrote:
> +static struct spk_synth *spk_ttyio_synth;
> +/* TODO: make this part of synth and remove the global */
Mmm, rather the other way round: add a synth pointer inside the
spk_ldisc_data structure, so you can get the synth from
> +static int spk_ttyio_receive_buf2(struct tty_struct *tty,
> - pr_err("Error registering line discipline.\n");
> + pr_err("speakup: Error registering line discipline.\n");
Do not mix with unrelated changes :)
> +static unsigned char ttyio_in(int timeout)
> +{
> + struct spk_ldisc_data *ldisc_data =
> + (struct spk_ldisc_data *)speakup_tty->disc_data;
> + char rv;
> +
> + if (!down_timeout(&ldisc_data->sem, usecs_to_jiffies(timeout))) {
Err, this should actually be if (down_timeout(...) != 0) (error case),
shouldn't it?
> + pr_warn("spk_ttyio: timeout (%d) while waiting for input\n",
> + timeout);
> + return 0xff;
> + }
> +
> + rv = ldisc_data->buf;
> + /* Make sure we have read buf before we set buf_free to let
> + * the producer overwrite it */
> + mb();
> + ldisc_data->buf_free = true;
> + tty_schedule_flip(speakup_tty->port);
Here, document that tty_schedule_flip lets the tty push more characters.
> + up(&ldisc_data->sem);
Err, no, it's spk_ttyio_receive_buf2 (the producer) which does the up(),
the consumer shouldn't do any up()! This is really a resource-counting
semaphore, not a mutex!
> 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
> @@ -39,6 +39,7 @@
> #endif
>
> #define KT_SPKUP 15
> +#define SPK_SYNTH_TIMEOUT 100000
Please document the unit (us)
Samuel
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [patch 6/7] staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Samuel Thibault
@ ` Okash Khawaja
` Okash Khawaja
1 sibling, 0 replies; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: Speakup is a screen review system for Linux.
Hi,
Two of the mistakes are frankly embarassing (down_timeout and up
inside spk_ttyio_in) . At some point during testing with apollo and
ltlk harwdare, I had to import and modify the patches to suit 4.10
kernel as 4.11 was still not stable and giving problems with USB on my
computer. I remember fixing them during tests, which is why those
synths worked. But didn't merge them back.
I will fix this patch today.
Thanks,
Okash
On Thu, Apr 27, 2017 at 3:06 PM, Samuel Thibault
<samuel.thibault@ens-lyon.org> wrote:
> Hello,
>
> Okash Khawaja, on jeu. 13 avril 2017 18:41:34 +0100, wrote:
>> +static struct spk_synth *spk_ttyio_synth;
>> +/* TODO: make this part of synth and remove the global */
>
> Mmm, rather the other way round: add a synth pointer inside the
> spk_ldisc_data structure, so you can get the synth from
>
>> +static int spk_ttyio_receive_buf2(struct tty_struct *tty,
>
>
>> - pr_err("Error registering line discipline.\n");
>> + pr_err("speakup: Error registering line discipline.\n");
>
> Do not mix with unrelated changes :)
>
>> +static unsigned char ttyio_in(int timeout)
>> +{
>> + struct spk_ldisc_data *ldisc_data =
>> + (struct spk_ldisc_data *)speakup_tty->disc_data;
>> + char rv;
>> +
>> + if (!down_timeout(&ldisc_data->sem, usecs_to_jiffies(timeout))) {
>
> Err, this should actually be if (down_timeout(...) != 0) (error case),
> shouldn't it?
>
>> + pr_warn("spk_ttyio: timeout (%d) while waiting for input\n",
>> + timeout);
>> + return 0xff;
>> + }
>> +
>> + rv = ldisc_data->buf;
>> + /* Make sure we have read buf before we set buf_free to let
>> + * the producer overwrite it */
>> + mb();
>> + ldisc_data->buf_free = true;
>> + tty_schedule_flip(speakup_tty->port);
>
> Here, document that tty_schedule_flip lets the tty push more characters.
>
>> + up(&ldisc_data->sem);
>
> Err, no, it's spk_ttyio_receive_buf2 (the producer) which does the up(),
> the consumer shouldn't do any up()! This is really a resource-counting
> semaphore, not a mutex!
>
>> 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
>> @@ -39,6 +39,7 @@
>> #endif
>>
>> #define KT_SPKUP 15
>> +#define SPK_SYNTH_TIMEOUT 100000
>
> Please document the unit (us)
>
> Samuel
^ permalink raw reply [flat|nested] 32+ messages in thread* staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Samuel Thibault
` Okash Khawaja
@ ` Okash Khawaja
` Samuel Thibault
1 sibling, 1 reply; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup
This patch adds further TTY-based functionality, specifically implementation
of send_xchar and tiocmset methods, and input. send_xchar and tiocmset
methods simply delegate to corresponding TTY operations.
For input, it implements the receive_buf2 callback in tty_ldisc_ops of
speakup's ldisc. If a synth defines read_buff_add method then receive_buf2
simply delegates to that and returns.
For spk_ttyio_in, the data is passed from receive_buf2 thread to
spk_ttyio_in thread through spk_ldisc_data structure. It has following
members:
- char buf: represents data received
- struct semaphore sem: used to signal to spk_ttyio_in thread that data
is available to be read without having to busy wait
- bool buf_free: this is used in comination with mb() calls to syncronise
the two threads over buf
receive_buf2 only writes to buf if buf_free is true. The check for buf_free
and writing to buf are separated by mb() to ensure that spk_ttyio_in has read
buf before receive_buf2 writes to it. After writing, it ups the semaphore to
signal to spk_ttyio_in that there is now data to read.
spk_ttyio_in waits for data to read by downing the semaphore. Thus when
signalled by receive_buf2 thread above, it reads from buf and sets buf_free
to true. These two operations are separated by mb() to ensure that
receive_buf2 thread finds buf_free to be true only after buf has been read.
After that spk_ttyio_in calls tty_schedule_flip for subsequent data to come
in through receive_buf2.
Signed-off-by: Okash Khawaja <okash.khawaja@gmail.com>
Index: linux-staging/drivers/staging/speakup/spk_ttyio.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/spk_ttyio.c
+++ linux-staging/drivers/staging/speakup/spk_ttyio.c
@@ -1,36 +1,97 @@
#include <linux/types.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/slab.h>
#include "speakup.h"
#include "spk_types.h"
+#include "spk_priv.h"
+struct spk_ldisc_data {
+ char buf;
+ struct semaphore sem;
+ bool buf_free;
+};
+
+static struct spk_synth *spk_ttyio_synth;
static struct tty_struct *speakup_tty;
static int spk_ttyio_ldisc_open(struct tty_struct *tty)
{
+ struct spk_ldisc_data *ldisc_data;
+
if (tty->ops->write == NULL)
return -EOPNOTSUPP;
speakup_tty = tty;
+ ldisc_data = kmalloc(sizeof(struct spk_ldisc_data), GFP_KERNEL);
+ if (!ldisc_data) {
+ pr_err("speakup: Failed to allocate ldisc_data.\n");
+ return -ENOMEM;
+ }
+
+ sema_init(&ldisc_data->sem, 0);
+ ldisc_data->buf_free = true;
+ speakup_tty->disc_data = ldisc_data;
+
return 0;
}
static void spk_ttyio_ldisc_close(struct tty_struct *tty)
{
+ kfree(speakup_tty->disc_data);
speakup_tty = NULL;
}
+static int spk_ttyio_receive_buf2(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count)
+{
+ struct spk_ldisc_data *ldisc_data = (struct spk_ldisc_data *)tty->disc_data;
+
+ if (spk_ttyio_synth->read_buff_add) {
+ int i;
+ for (i = 0; i < count; i++)
+ spk_ttyio_synth->read_buff_add(cp[i]);
+
+ return count;
+ }
+
+ if (!ldisc_data->buf_free)
+ /* ttyio_in will tty_schedule_flip */
+ return 0;
+
+ /* Make sure the consumer has read buf before we have seen
+ * buf_free == true and overwrite buf */
+ mb();
+
+ ldisc_data->buf = cp[0];
+ ldisc_data->buf_free = false;
+ up(&ldisc_data->sem);
+
+ return 1;
+}
+
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,
+ .receive_buf2 = spk_ttyio_receive_buf2,
};
static int spk_ttyio_out(struct spk_synth *in_synth, const char ch);
+static void spk_ttyio_send_xchar(char ch);
+static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear);
+static unsigned char spk_ttyio_in(void);
+static unsigned char spk_ttyio_in_nowait(void);
+
struct spk_io_ops spk_ttyio_ops = {
.synth_out = spk_ttyio_out,
+ .send_xchar = spk_ttyio_send_xchar,
+ .tiocmset = spk_ttyio_tiocmset,
+ .synth_in = spk_ttyio_in,
+ .synth_in_nowait = spk_ttyio_in_nowait,
};
EXPORT_SYMBOL_GPL(spk_ttyio_ops);
@@ -95,6 +156,49 @@
return 0;
}
+static void spk_ttyio_send_xchar(char ch)
+{
+ speakup_tty->ops->send_xchar(speakup_tty, ch);
+}
+
+static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
+{
+ speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+}
+
+static unsigned char ttyio_in(int timeout)
+{
+ struct spk_ldisc_data *ldisc_data =
+ (struct spk_ldisc_data *)speakup_tty->disc_data;
+ char rv;
+
+ if (down_timeout(&ldisc_data->sem, usecs_to_jiffies(timeout)) != 0) {
+ pr_warn("spk_ttyio: timeout (%d) while waiting for input\n",
+ timeout);
+ return 0xff;
+ }
+
+ rv = ldisc_data->buf;
+ /* Make sure we have read buf before we set buf_free to let
+ * the producer overwrite it */
+ mb();
+ ldisc_data->buf_free = true;
+ /* Let TTY push more characters */
+ tty_schedule_flip(speakup_tty->port);
+
+ return rv;
+}
+
+static unsigned char spk_ttyio_in(void)
+{
+ return ttyio_in(SPK_SYNTH_TIMEOUT);
+}
+
+static unsigned char spk_ttyio_in_nowait(void)
+{
+ return ttyio_in(0);
+}
+
int spk_ttyio_synth_probe(struct spk_synth *synth)
{
int rv = spk_ttyio_initialise_ldisc(synth->ser);
@@ -103,6 +207,7 @@
return rv;
synth->alive = 1;
+ spk_ttyio_synth = synth;
return 0;
}
Index: linux-staging/drivers/staging/speakup/serialio.h
===================================================================
--- linux-staging.orig/drivers/staging/speakup/serialio.h
+++ linux-staging/drivers/staging/speakup/serialio.h
@@ -8,6 +8,8 @@
#endif
#include <linux/serial_core.h>
+#include "spk_priv.h"
+
/*
* this is cut&paste from 8250.h. Get rid of the structure, the definitions
* and this whole broken driver.
@@ -21,7 +23,7 @@
};
/* countdown values for serial timeouts in us */
-#define SPK_SERIAL_TIMEOUT 100000
+#define SPK_SERIAL_TIMEOUT SPK_SYNTH_TIMEOUT
/* countdown values transmitter/dsr timeouts in us */
#define SPK_XMITR_TIMEOUT 100000
/* countdown values cts timeouts in us */
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
@@ -39,6 +39,7 @@
#endif
#define KT_SPKUP 15
+#define SPK_SYNTH_TIMEOUT 100000 /* in micro-seconds */
const struct old_serial_port *spk_serial_init(int index);
void spk_stop_serial_interrupt(void);
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Okash Khawaja
@ ` Samuel Thibault
` Okash Khawaja
` Okash Khawaja
0 siblings, 2 replies; 32+ messages in thread
From: Samuel Thibault @ UTC (permalink / raw)
To: Okash Khawaja; +Cc: speakup
Okash Khawaja, on ven. 28 avril 2017 21:54:48 +0100, wrote:
> +static int spk_ttyio_receive_buf2(struct tty_struct *tty,
> + const unsigned char *cp, char *fp, int count)
> +{
> + struct spk_ldisc_data *ldisc_data = (struct spk_ldisc_data *)tty->disc_data;
> +static unsigned char ttyio_in(int timeout)
> +{
> + struct spk_ldisc_data *ldisc_data =
> + (struct spk_ldisc_data *)speakup_tty->disc_data;
No need to make an explicit cast: disc_data is a void*, so the implicit
cast is fine and more readable ; only a C++ compiler would complain
about it.
Apart from that it looks good.
So I guess now we need to be more pushy with serdev.
Samuel
^ permalink raw reply [flat|nested] 32+ messages in thread* staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Samuel Thibault
@ ` Okash Khawaja
` Rob
` Samuel Thibault
` Okash Khawaja
1 sibling, 2 replies; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup
This patch adds further TTY-based functionality, specifically implementation
of send_xchar and tiocmset methods, and input. send_xchar and tiocmset
methods simply delegate to corresponding TTY operations.
For input, it implements the receive_buf2 callback in tty_ldisc_ops of
speakup's ldisc. If a synth defines read_buff_add method then receive_buf2
simply delegates to that and returns.
For spk_ttyio_in, the data is passed from receive_buf2 thread to
spk_ttyio_in thread through spk_ldisc_data structure. It has following
members:
- char buf: represents data received
- struct semaphore sem: used to signal to spk_ttyio_in thread that data
is available to be read without having to busy wait
- bool buf_free: this is used in comination with mb() calls to syncronise
the two threads over buf
receive_buf2 only writes to buf if buf_free is true. The check for buf_free
and writing to buf are separated by mb() to ensure that spk_ttyio_in has read
buf before receive_buf2 writes to it. After writing, it ups the semaphore to
signal to spk_ttyio_in that there is now data to read.
spk_ttyio_in waits for data to read by downing the semaphore. Thus when
signalled by receive_buf2 thread above, it reads from buf and sets buf_free
to true. These two operations are separated by mb() to ensure that
receive_buf2 thread finds buf_free to be true only after buf has been read.
After that spk_ttyio_in calls tty_schedule_flip for subsequent data to come
in through receive_buf2.
Signed-off-by: Okash Khawaja <okash.khawaja@gmail.com>
Index: linux-staging/drivers/staging/speakup/spk_ttyio.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/spk_ttyio.c
+++ linux-staging/drivers/staging/speakup/spk_ttyio.c
@@ -1,36 +1,97 @@
#include <linux/types.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/slab.h>
#include "speakup.h"
#include "spk_types.h"
+#include "spk_priv.h"
+struct spk_ldisc_data {
+ char buf;
+ struct semaphore sem;
+ bool buf_free;
+};
+
+static struct spk_synth *spk_ttyio_synth;
static struct tty_struct *speakup_tty;
static int spk_ttyio_ldisc_open(struct tty_struct *tty)
{
+ struct spk_ldisc_data *ldisc_data;
+
if (tty->ops->write == NULL)
return -EOPNOTSUPP;
speakup_tty = tty;
+ ldisc_data = kmalloc(sizeof(struct spk_ldisc_data), GFP_KERNEL);
+ if (!ldisc_data) {
+ pr_err("speakup: Failed to allocate ldisc_data.\n");
+ return -ENOMEM;
+ }
+
+ sema_init(&ldisc_data->sem, 0);
+ ldisc_data->buf_free = true;
+ speakup_tty->disc_data = ldisc_data;
+
return 0;
}
static void spk_ttyio_ldisc_close(struct tty_struct *tty)
{
+ kfree(speakup_tty->disc_data);
speakup_tty = NULL;
}
+static int spk_ttyio_receive_buf2(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count)
+{
+ struct spk_ldisc_data *ldisc_data = (struct spk_ldisc_data *)tty->disc_data;
+
+ if (spk_ttyio_synth->read_buff_add) {
+ int i;
+ for (i = 0; i < count; i++)
+ spk_ttyio_synth->read_buff_add(cp[i]);
+
+ return count;
+ }
+
+ if (!ldisc_data->buf_free)
+ /* ttyio_in will tty_schedule_flip */
+ return 0;
+
+ /* Make sure the consumer has read buf before we have seen
+ * buf_free == true and overwrite buf */
+ mb();
+
+ ldisc_data->buf = cp[0];
+ ldisc_data->buf_free = false;
+ up(&ldisc_data->sem);
+
+ return 1;
+}
+
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,
+ .receive_buf2 = spk_ttyio_receive_buf2,
};
static int spk_ttyio_out(struct spk_synth *in_synth, const char ch);
+static void spk_ttyio_send_xchar(char ch);
+static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear);
+static unsigned char spk_ttyio_in(void);
+static unsigned char spk_ttyio_in_nowait(void);
+
struct spk_io_ops spk_ttyio_ops = {
.synth_out = spk_ttyio_out,
+ .send_xchar = spk_ttyio_send_xchar,
+ .tiocmset = spk_ttyio_tiocmset,
+ .synth_in = spk_ttyio_in,
+ .synth_in_nowait = spk_ttyio_in_nowait,
};
EXPORT_SYMBOL_GPL(spk_ttyio_ops);
@@ -95,6 +156,48 @@
return 0;
}
+static void spk_ttyio_send_xchar(char ch)
+{
+ speakup_tty->ops->send_xchar(speakup_tty, ch);
+}
+
+static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
+{
+ speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+}
+
+static unsigned char ttyio_in(int timeout)
+{
+ struct spk_ldisc_data *ldisc_data = speakup_tty->disc_data;
+ char rv;
+
+ if (down_timeout(&ldisc_data->sem, usecs_to_jiffies(timeout)) != 0) {
+ pr_warn("spk_ttyio: timeout (%d) while waiting for input\n",
+ timeout);
+ return 0xff;
+ }
+
+ rv = ldisc_data->buf;
+ /* Make sure we have read buf before we set buf_free to let
+ * the producer overwrite it */
+ mb();
+ ldisc_data->buf_free = true;
+ /* Let TTY push more characters */
+ tty_schedule_flip(speakup_tty->port);
+
+ return rv;
+}
+
+static unsigned char spk_ttyio_in(void)
+{
+ return ttyio_in(SPK_SYNTH_TIMEOUT);
+}
+
+static unsigned char spk_ttyio_in_nowait(void)
+{
+ return ttyio_in(0);
+}
+
int spk_ttyio_synth_probe(struct spk_synth *synth)
{
int rv = spk_ttyio_initialise_ldisc(synth->ser);
@@ -103,6 +206,7 @@
return rv;
synth->alive = 1;
+ spk_ttyio_synth = synth;
return 0;
}
Index: linux-staging/drivers/staging/speakup/serialio.h
===================================================================
--- linux-staging.orig/drivers/staging/speakup/serialio.h
+++ linux-staging/drivers/staging/speakup/serialio.h
@@ -8,6 +8,8 @@
#endif
#include <linux/serial_core.h>
+#include "spk_priv.h"
+
/*
* this is cut&paste from 8250.h. Get rid of the structure, the definitions
* and this whole broken driver.
@@ -21,7 +23,7 @@
};
/* countdown values for serial timeouts in us */
-#define SPK_SERIAL_TIMEOUT 100000
+#define SPK_SERIAL_TIMEOUT SPK_SYNTH_TIMEOUT
/* countdown values transmitter/dsr timeouts in us */
#define SPK_XMITR_TIMEOUT 100000
/* countdown values cts timeouts in us */
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
@@ -39,6 +39,7 @@
#endif
#define KT_SPKUP 15
+#define SPK_SYNTH_TIMEOUT 100000 /* in micro-seconds */
const struct old_serial_port *spk_serial_init(int index);
void spk_stop_serial_interrupt(void);
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Okash Khawaja
@ ` Rob
` Okash Khawaja
` Samuel Thibault
1 sibling, 1 reply; 32+ messages in thread
From: Rob @ UTC (permalink / raw)
To: Speakup is a screen review system for Linux.
Okash Khawaja <okash.khawaja@gmail.com> wrote:
> This patch adds further TTY-based functionality, specifically implementation
of send_xchar and tiocmset methods, and input.
Just out of curiosity, do you have all these patches archived somewhere so they can be applied all at once? I've not been following closely all the recent developments, so forgive me if this has already been answered.
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Rob
@ ` Okash Khawaja
0 siblings, 0 replies; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Speakup is a screen review system for Linux.
Hi Rob,
On Sat, Apr 29, 2017 at 02:37:26AM -0500, Rob wrote:
> Okash Khawaja <okash.khawaja@gmail.com> wrote:
> > This patch adds further TTY-based functionality, specifically implementation
> of send_xchar and tiocmset methods, and input.
>
> Just out of curiosity, do you have all these patches archived somewhere so they can be applied all at once? I've not been following closely all the recent developments, so forgive me if this has already been answered.
Yes, I created a set of instructions here
https://github.com/bytefire/speakup-decext. The patches target kernel's
staging-next branch which has some problems with USB (although that
might have been fixed now). So the instructions target the latest stable
release - 4.10.x. Although it says decext, the changes can be tested
with any of the external synths. Please ask if you have questions.
Related discussion is in this thread:
http://linux-speakup.org/pipermail/speakup/2017-April/060629.html.
Thanks,
Okash
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Okash Khawaja
` Rob
@ ` Samuel Thibault
` Okash Khawaja
1 sibling, 1 reply; 32+ messages in thread
From: Samuel Thibault @ UTC (permalink / raw)
To: Okash Khawaja; +Cc: speakup
Okash Khawaja, on sam. 29 avril 2017 09:41:23 +0100, wrote:
> +static int spk_ttyio_receive_buf2(struct tty_struct *tty,
> + const unsigned char *cp, char *fp, int count)
> +{
> + struct spk_ldisc_data *ldisc_data = (struct spk_ldisc_data *)tty->disc_data;
You can drop the cast here too :)
Samuel
^ permalink raw reply [flat|nested] 32+ messages in thread* staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Samuel Thibault
@ ` Okash Khawaja
` Samuel Thibault
0 siblings, 1 reply; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup
This patch adds further TTY-based functionality, specifically implementation
of send_xchar and tiocmset methods, and input. send_xchar and tiocmset
methods simply delegate to corresponding TTY operations.
For input, it implements the receive_buf2 callback in tty_ldisc_ops of
speakup's ldisc. If a synth defines read_buff_add method then receive_buf2
simply delegates to that and returns.
For spk_ttyio_in, the data is passed from receive_buf2 thread to
spk_ttyio_in thread through spk_ldisc_data structure. It has following
members:
- char buf: represents data received
- struct semaphore sem: used to signal to spk_ttyio_in thread that data
is available to be read without having to busy wait
- bool buf_free: this is used in comination with mb() calls to syncronise
the two threads over buf
receive_buf2 only writes to buf if buf_free is true. The check for buf_free
and writing to buf are separated by mb() to ensure that spk_ttyio_in has read
buf before receive_buf2 writes to it. After writing, it ups the semaphore to
signal to spk_ttyio_in that there is now data to read.
spk_ttyio_in waits for data to read by downing the semaphore. Thus when
signalled by receive_buf2 thread above, it reads from buf and sets buf_free
to true. These two operations are separated by mb() to ensure that
receive_buf2 thread finds buf_free to be true only after buf has been read.
After that spk_ttyio_in calls tty_schedule_flip for subsequent data to come
in through receive_buf2.
Signed-off-by: Okash Khawaja <okash.khawaja@gmail.com>
Index: linux-staging/drivers/staging/speakup/spk_ttyio.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/spk_ttyio.c
+++ linux-staging/drivers/staging/speakup/spk_ttyio.c
@@ -1,36 +1,97 @@
#include <linux/types.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/slab.h>
#include "speakup.h"
#include "spk_types.h"
+#include "spk_priv.h"
+struct spk_ldisc_data {
+ char buf;
+ struct semaphore sem;
+ bool buf_free;
+};
+
+static struct spk_synth *spk_ttyio_synth;
static struct tty_struct *speakup_tty;
static int spk_ttyio_ldisc_open(struct tty_struct *tty)
{
+ struct spk_ldisc_data *ldisc_data;
+
if (tty->ops->write == NULL)
return -EOPNOTSUPP;
speakup_tty = tty;
+ ldisc_data = kmalloc(sizeof(struct spk_ldisc_data), GFP_KERNEL);
+ if (!ldisc_data) {
+ pr_err("speakup: Failed to allocate ldisc_data.\n");
+ return -ENOMEM;
+ }
+
+ sema_init(&ldisc_data->sem, 0);
+ ldisc_data->buf_free = true;
+ speakup_tty->disc_data = ldisc_data;
+
return 0;
}
static void spk_ttyio_ldisc_close(struct tty_struct *tty)
{
+ kfree(speakup_tty->disc_data);
speakup_tty = NULL;
}
+static int spk_ttyio_receive_buf2(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count)
+{
+ struct spk_ldisc_data *ldisc_data = tty->disc_data;
+
+ if (spk_ttyio_synth->read_buff_add) {
+ int i;
+ for (i = 0; i < count; i++)
+ spk_ttyio_synth->read_buff_add(cp[i]);
+
+ return count;
+ }
+
+ if (!ldisc_data->buf_free)
+ /* ttyio_in will tty_schedule_flip */
+ return 0;
+
+ /* Make sure the consumer has read buf before we have seen
+ * buf_free == true and overwrite buf */
+ mb();
+
+ ldisc_data->buf = cp[0];
+ ldisc_data->buf_free = false;
+ up(&ldisc_data->sem);
+
+ return 1;
+}
+
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,
+ .receive_buf2 = spk_ttyio_receive_buf2,
};
static int spk_ttyio_out(struct spk_synth *in_synth, const char ch);
+static void spk_ttyio_send_xchar(char ch);
+static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear);
+static unsigned char spk_ttyio_in(void);
+static unsigned char spk_ttyio_in_nowait(void);
+
struct spk_io_ops spk_ttyio_ops = {
.synth_out = spk_ttyio_out,
+ .send_xchar = spk_ttyio_send_xchar,
+ .tiocmset = spk_ttyio_tiocmset,
+ .synth_in = spk_ttyio_in,
+ .synth_in_nowait = spk_ttyio_in_nowait,
};
EXPORT_SYMBOL_GPL(spk_ttyio_ops);
@@ -95,6 +156,48 @@
return 0;
}
+static void spk_ttyio_send_xchar(char ch)
+{
+ speakup_tty->ops->send_xchar(speakup_tty, ch);
+}
+
+static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
+{
+ speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+}
+
+static unsigned char ttyio_in(int timeout)
+{
+ struct spk_ldisc_data *ldisc_data = speakup_tty->disc_data;
+ char rv;
+
+ if (down_timeout(&ldisc_data->sem, usecs_to_jiffies(timeout)) != 0) {
+ pr_warn("spk_ttyio: timeout (%d) while waiting for input\n",
+ timeout);
+ return 0xff;
+ }
+
+ rv = ldisc_data->buf;
+ /* Make sure we have read buf before we set buf_free to let
+ * the producer overwrite it */
+ mb();
+ ldisc_data->buf_free = true;
+ /* Let TTY push more characters */
+ tty_schedule_flip(speakup_tty->port);
+
+ return rv;
+}
+
+static unsigned char spk_ttyio_in(void)
+{
+ return ttyio_in(SPK_SYNTH_TIMEOUT);
+}
+
+static unsigned char spk_ttyio_in_nowait(void)
+{
+ return ttyio_in(0);
+}
+
int spk_ttyio_synth_probe(struct spk_synth *synth)
{
int rv = spk_ttyio_initialise_ldisc(synth->ser);
@@ -103,6 +206,7 @@
return rv;
synth->alive = 1;
+ spk_ttyio_synth = synth;
return 0;
}
Index: linux-staging/drivers/staging/speakup/serialio.h
===================================================================
--- linux-staging.orig/drivers/staging/speakup/serialio.h
+++ linux-staging/drivers/staging/speakup/serialio.h
@@ -8,6 +8,8 @@
#endif
#include <linux/serial_core.h>
+#include "spk_priv.h"
+
/*
* this is cut&paste from 8250.h. Get rid of the structure, the definitions
* and this whole broken driver.
@@ -21,7 +23,7 @@
};
/* countdown values for serial timeouts in us */
-#define SPK_SERIAL_TIMEOUT 100000
+#define SPK_SERIAL_TIMEOUT SPK_SYNTH_TIMEOUT
/* countdown values transmitter/dsr timeouts in us */
#define SPK_XMITR_TIMEOUT 100000
/* countdown values cts timeouts in us */
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
@@ -39,6 +39,7 @@
#endif
#define KT_SPKUP 15
+#define SPK_SYNTH_TIMEOUT 100000 /* in micro-seconds */
const struct old_serial_port *spk_serial_init(int index);
void spk_stop_serial_interrupt(void);
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Okash Khawaja
@ ` Samuel Thibault
` Okash Khawaja
` Okash Khawaja
0 siblings, 2 replies; 32+ messages in thread
From: Samuel Thibault @ UTC (permalink / raw)
To: Okash Khawaja; +Cc: speakup
Okash Khawaja, on sam. 29 avril 2017 13:48:09 +0100, wrote:
> +static unsigned char ttyio_in(int timeout)
> +{
> + struct spk_ldisc_data *ldisc_data = speakup_tty->disc_data;
> + char rv;
> +
> + if (down_timeout(&ldisc_data->sem, usecs_to_jiffies(timeout)) != 0) {
> + pr_warn("spk_ttyio: timeout (%d) while waiting for input\n",
> + timeout);
> + return 0xff;
> + }
> +static unsigned char spk_ttyio_in_nowait(void)
> +{
> + return ttyio_in(0);
> +}
Thinking of it: for spk_ttyio_in_nowait(), we shouldn't print a warning
when down_timeout returns ETIMEDOUT. So pr_warn should be guarded by
"if (timeout)".
Also, spk_ttyio_in_nowait() should return 0 instead of 0xff on timeout,
since that's used for synth_insert_next_index() which takes 0 as "no new
value", not 0xff.
I know, it's converging slowly, but we need to make sure we don't change
things, otherwise it'll bring regressions.
Samuel
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Samuel Thibault
@ ` Okash Khawaja
` Okash Khawaja
1 sibling, 0 replies; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup
On Sat, Apr 29, 2017 at 03:06:04PM +0200, Samuel Thibault wrote:
> Thinking of it: for spk_ttyio_in_nowait(), we shouldn't print a warning
> when down_timeout returns ETIMEDOUT. So pr_warn should be guarded by
> "if (timeout)".
>
> Also, spk_ttyio_in_nowait() should return 0 instead of 0xff on timeout,
> since that's used for synth_insert_next_index() which takes 0 as "no new
> value", not 0xff.
>
> I know, it's converging slowly, but we need to make sure we don't change
> things, otherwise it'll bring regressions.
Sure, I understand. These are also things I should have considered
before submitting.
Thanks,
Okash
^ permalink raw reply [flat|nested] 32+ messages in thread* staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Samuel Thibault
` Okash Khawaja
@ ` Okash Khawaja
` Samuel Thibault
1 sibling, 1 reply; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup
This patch adds further TTY-based functionality, specifically implementation
of send_xchar and tiocmset methods, and input. send_xchar and tiocmset
methods simply delegate to corresponding TTY operations.
For input, it implements the receive_buf2 callback in tty_ldisc_ops of
speakup's ldisc. If a synth defines read_buff_add method then receive_buf2
simply delegates to that and returns.
For spk_ttyio_in, the data is passed from receive_buf2 thread to
spk_ttyio_in thread through spk_ldisc_data structure. It has following
members:
- char buf: represents data received
- struct semaphore sem: used to signal to spk_ttyio_in thread that data
is available to be read without having to busy wait
- bool buf_free: this is used in comination with mb() calls to syncronise
the two threads over buf
receive_buf2 only writes to buf if buf_free is true. The check for buf_free
and writing to buf are separated by mb() to ensure that spk_ttyio_in has read
buf before receive_buf2 writes to it. After writing, it ups the semaphore to
signal to spk_ttyio_in that there is now data to read.
spk_ttyio_in waits for data to read by downing the semaphore. Thus when
signalled by receive_buf2 thread above, it reads from buf and sets buf_free
to true. These two operations are separated by mb() to ensure that
receive_buf2 thread finds buf_free to be true only after buf has been read.
After that spk_ttyio_in calls tty_schedule_flip for subsequent data to come
in through receive_buf2.
Signed-off-by: Okash Khawaja <okash.khawaja@gmail.com>
Index: linux-staging/drivers/staging/speakup/spk_ttyio.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/spk_ttyio.c
+++ linux-staging/drivers/staging/speakup/spk_ttyio.c
@@ -1,36 +1,97 @@
#include <linux/types.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/slab.h>
#include "speakup.h"
#include "spk_types.h"
+#include "spk_priv.h"
+struct spk_ldisc_data {
+ char buf;
+ struct semaphore sem;
+ bool buf_free;
+};
+
+static struct spk_synth *spk_ttyio_synth;
static struct tty_struct *speakup_tty;
static int spk_ttyio_ldisc_open(struct tty_struct *tty)
{
+ struct spk_ldisc_data *ldisc_data;
+
if (tty->ops->write == NULL)
return -EOPNOTSUPP;
speakup_tty = tty;
+ ldisc_data = kmalloc(sizeof(struct spk_ldisc_data), GFP_KERNEL);
+ if (!ldisc_data) {
+ pr_err("speakup: Failed to allocate ldisc_data.\n");
+ return -ENOMEM;
+ }
+
+ sema_init(&ldisc_data->sem, 0);
+ ldisc_data->buf_free = true;
+ speakup_tty->disc_data = ldisc_data;
+
return 0;
}
static void spk_ttyio_ldisc_close(struct tty_struct *tty)
{
+ kfree(speakup_tty->disc_data);
speakup_tty = NULL;
}
+static int spk_ttyio_receive_buf2(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count)
+{
+ struct spk_ldisc_data *ldisc_data = tty->disc_data;
+
+ if (spk_ttyio_synth->read_buff_add) {
+ int i;
+ for (i = 0; i < count; i++)
+ spk_ttyio_synth->read_buff_add(cp[i]);
+
+ return count;
+ }
+
+ if (!ldisc_data->buf_free)
+ /* ttyio_in will tty_schedule_flip */
+ return 0;
+
+ /* Make sure the consumer has read buf before we have seen
+ * buf_free == true and overwrite buf */
+ mb();
+
+ ldisc_data->buf = cp[0];
+ ldisc_data->buf_free = false;
+ up(&ldisc_data->sem);
+
+ return 1;
+}
+
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,
+ .receive_buf2 = spk_ttyio_receive_buf2,
};
static int spk_ttyio_out(struct spk_synth *in_synth, const char ch);
+static void spk_ttyio_send_xchar(char ch);
+static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear);
+static unsigned char spk_ttyio_in(void);
+static unsigned char spk_ttyio_in_nowait(void);
+
struct spk_io_ops spk_ttyio_ops = {
.synth_out = spk_ttyio_out,
+ .send_xchar = spk_ttyio_send_xchar,
+ .tiocmset = spk_ttyio_tiocmset,
+ .synth_in = spk_ttyio_in,
+ .synth_in_nowait = spk_ttyio_in_nowait,
};
EXPORT_SYMBOL_GPL(spk_ttyio_ops);
@@ -95,6 +156,51 @@
return 0;
}
+static void spk_ttyio_send_xchar(char ch)
+{
+ speakup_tty->ops->send_xchar(speakup_tty, ch);
+}
+
+static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
+{
+ speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+}
+
+static unsigned char ttyio_in(int timeout)
+{
+ struct spk_ldisc_data *ldisc_data = speakup_tty->disc_data;
+ char rv;
+
+ if (down_timeout(&ldisc_data->sem, usecs_to_jiffies(timeout)) == -ETIME) {
+ if (timeout)
+ pr_warn("spk_ttyio: timeout (%d) while waiting for input\n",
+ timeout);
+ return 0xff;
+ }
+
+ rv = ldisc_data->buf;
+ /* Make sure we have read buf before we set buf_free to let
+ * the producer overwrite it */
+ mb();
+ ldisc_data->buf_free = true;
+ /* Let TTY push more characters */
+ tty_schedule_flip(speakup_tty->port);
+
+ return rv;
+}
+
+static unsigned char spk_ttyio_in(void)
+{
+ return ttyio_in(SPK_SYNTH_TIMEOUT);
+}
+
+static unsigned char spk_ttyio_in_nowait(void)
+{
+ char rv = ttyio_in(0);
+
+ return (rv == 0xff) ? 0 : rv;
+}
+
int spk_ttyio_synth_probe(struct spk_synth *synth)
{
int rv = spk_ttyio_initialise_ldisc(synth->ser);
@@ -103,6 +209,7 @@
return rv;
synth->alive = 1;
+ spk_ttyio_synth = synth;
return 0;
}
Index: linux-staging/drivers/staging/speakup/serialio.h
===================================================================
--- linux-staging.orig/drivers/staging/speakup/serialio.h
+++ linux-staging/drivers/staging/speakup/serialio.h
@@ -8,6 +8,8 @@
#endif
#include <linux/serial_core.h>
+#include "spk_priv.h"
+
/*
* this is cut&paste from 8250.h. Get rid of the structure, the definitions
* and this whole broken driver.
@@ -21,7 +23,7 @@
};
/* countdown values for serial timeouts in us */
-#define SPK_SERIAL_TIMEOUT 100000
+#define SPK_SERIAL_TIMEOUT SPK_SYNTH_TIMEOUT
/* countdown values transmitter/dsr timeouts in us */
#define SPK_XMITR_TIMEOUT 100000
/* countdown values cts timeouts in us */
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
@@ -39,6 +39,7 @@
#endif
#define KT_SPKUP 15
+#define SPK_SYNTH_TIMEOUT 100000 /* in micro-seconds */
const struct old_serial_port *spk_serial_init(int index);
void spk_stop_serial_interrupt(void);
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Okash Khawaja
@ ` Samuel Thibault
0 siblings, 0 replies; 32+ messages in thread
From: Samuel Thibault @ UTC (permalink / raw)
To: Okash Khawaja; +Cc: speakup
Okash Khawaja, on sam. 29 avril 2017 14:53:18 +0100, wrote:
> This patch adds further TTY-based functionality, specifically implementation
> of send_xchar and tiocmset methods, and input. send_xchar and tiocmset
> methods simply delegate to corresponding TTY operations.
>
> For input, it implements the receive_buf2 callback in tty_ldisc_ops of
> speakup's ldisc. If a synth defines read_buff_add method then receive_buf2
> simply delegates to that and returns.
>
> For spk_ttyio_in, the data is passed from receive_buf2 thread to
> spk_ttyio_in thread through spk_ldisc_data structure. It has following
> members:
>
> - char buf: represents data received
> - struct semaphore sem: used to signal to spk_ttyio_in thread that data
> is available to be read without having to busy wait
> - bool buf_free: this is used in comination with mb() calls to syncronise
> the two threads over buf
>
> receive_buf2 only writes to buf if buf_free is true. The check for buf_free
> and writing to buf are separated by mb() to ensure that spk_ttyio_in has read
> buf before receive_buf2 writes to it. After writing, it ups the semaphore to
> signal to spk_ttyio_in that there is now data to read.
>
> spk_ttyio_in waits for data to read by downing the semaphore. Thus when
> signalled by receive_buf2 thread above, it reads from buf and sets buf_free
> to true. These two operations are separated by mb() to ensure that
> receive_buf2 thread finds buf_free to be true only after buf has been read.
> After that spk_ttyio_in calls tty_schedule_flip for subsequent data to come
> in through receive_buf2.
>
> Signed-off-by: Okash Khawaja <okash.khawaja@gmail.com>
Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> Index: linux-staging/drivers/staging/speakup/spk_ttyio.c
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/spk_ttyio.c
> +++ linux-staging/drivers/staging/speakup/spk_ttyio.c
> @@ -1,36 +1,97 @@
> #include <linux/types.h>
> #include <linux/tty.h>
> +#include <linux/tty_flip.h>
> +#include <linux/slab.h>
>
> #include "speakup.h"
> #include "spk_types.h"
> +#include "spk_priv.h"
>
> +struct spk_ldisc_data {
> + char buf;
> + struct semaphore sem;
> + bool buf_free;
> +};
> +
> +static struct spk_synth *spk_ttyio_synth;
> static struct tty_struct *speakup_tty;
>
> static int spk_ttyio_ldisc_open(struct tty_struct *tty)
> {
> + struct spk_ldisc_data *ldisc_data;
> +
> if (tty->ops->write == NULL)
> return -EOPNOTSUPP;
> speakup_tty = tty;
>
> + ldisc_data = kmalloc(sizeof(struct spk_ldisc_data), GFP_KERNEL);
> + if (!ldisc_data) {
> + pr_err("speakup: Failed to allocate ldisc_data.\n");
> + return -ENOMEM;
> + }
> +
> + sema_init(&ldisc_data->sem, 0);
> + ldisc_data->buf_free = true;
> + speakup_tty->disc_data = ldisc_data;
> +
> return 0;
> }
>
> static void spk_ttyio_ldisc_close(struct tty_struct *tty)
> {
> + kfree(speakup_tty->disc_data);
> speakup_tty = NULL;
> }
>
> +static int spk_ttyio_receive_buf2(struct tty_struct *tty,
> + const unsigned char *cp, char *fp, int count)
> +{
> + struct spk_ldisc_data *ldisc_data = tty->disc_data;
> +
> + if (spk_ttyio_synth->read_buff_add) {
> + int i;
> + for (i = 0; i < count; i++)
> + spk_ttyio_synth->read_buff_add(cp[i]);
> +
> + return count;
> + }
> +
> + if (!ldisc_data->buf_free)
> + /* ttyio_in will tty_schedule_flip */
> + return 0;
> +
> + /* Make sure the consumer has read buf before we have seen
> + * buf_free == true and overwrite buf */
> + mb();
> +
> + ldisc_data->buf = cp[0];
> + ldisc_data->buf_free = false;
> + up(&ldisc_data->sem);
> +
> + return 1;
> +}
> +
> 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,
> + .receive_buf2 = spk_ttyio_receive_buf2,
> };
>
> static int spk_ttyio_out(struct spk_synth *in_synth, const char ch);
> +static void spk_ttyio_send_xchar(char ch);
> +static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear);
> +static unsigned char spk_ttyio_in(void);
> +static unsigned char spk_ttyio_in_nowait(void);
> +
> struct spk_io_ops spk_ttyio_ops = {
> .synth_out = spk_ttyio_out,
> + .send_xchar = spk_ttyio_send_xchar,
> + .tiocmset = spk_ttyio_tiocmset,
> + .synth_in = spk_ttyio_in,
> + .synth_in_nowait = spk_ttyio_in_nowait,
> };
> EXPORT_SYMBOL_GPL(spk_ttyio_ops);
>
> @@ -95,6 +156,51 @@
> return 0;
> }
>
> +static void spk_ttyio_send_xchar(char ch)
> +{
> + speakup_tty->ops->send_xchar(speakup_tty, ch);
> +}
> +
> +static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
> +{
> + speakup_tty->ops->tiocmset(speakup_tty, set, clear);
> +}
> +
> +static unsigned char ttyio_in(int timeout)
> +{
> + struct spk_ldisc_data *ldisc_data = speakup_tty->disc_data;
> + char rv;
> +
> + if (down_timeout(&ldisc_data->sem, usecs_to_jiffies(timeout)) == -ETIME) {
> + if (timeout)
> + pr_warn("spk_ttyio: timeout (%d) while waiting for input\n",
> + timeout);
> + return 0xff;
> + }
> +
> + rv = ldisc_data->buf;
> + /* Make sure we have read buf before we set buf_free to let
> + * the producer overwrite it */
> + mb();
> + ldisc_data->buf_free = true;
> + /* Let TTY push more characters */
> + tty_schedule_flip(speakup_tty->port);
> +
> + return rv;
> +}
> +
> +static unsigned char spk_ttyio_in(void)
> +{
> + return ttyio_in(SPK_SYNTH_TIMEOUT);
> +}
> +
> +static unsigned char spk_ttyio_in_nowait(void)
> +{
> + char rv = ttyio_in(0);
> +
> + return (rv == 0xff) ? 0 : rv;
> +}
> +
> int spk_ttyio_synth_probe(struct spk_synth *synth)
> {
> int rv = spk_ttyio_initialise_ldisc(synth->ser);
> @@ -103,6 +209,7 @@
> return rv;
>
> synth->alive = 1;
> + spk_ttyio_synth = synth;
>
> return 0;
> }
> Index: linux-staging/drivers/staging/speakup/serialio.h
> ===================================================================
> --- linux-staging.orig/drivers/staging/speakup/serialio.h
> +++ linux-staging/drivers/staging/speakup/serialio.h
> @@ -8,6 +8,8 @@
> #endif
> #include <linux/serial_core.h>
>
> +#include "spk_priv.h"
> +
> /*
> * this is cut&paste from 8250.h. Get rid of the structure, the definitions
> * and this whole broken driver.
> @@ -21,7 +23,7 @@
> };
>
> /* countdown values for serial timeouts in us */
> -#define SPK_SERIAL_TIMEOUT 100000
> +#define SPK_SERIAL_TIMEOUT SPK_SYNTH_TIMEOUT
> /* countdown values transmitter/dsr timeouts in us */
> #define SPK_XMITR_TIMEOUT 100000
> /* countdown values cts timeouts in us */
> 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
> @@ -39,6 +39,7 @@
> #endif
>
> #define KT_SPKUP 15
> +#define SPK_SYNTH_TIMEOUT 100000 /* in micro-seconds */
>
> const struct old_serial_port *spk_serial_init(int index);
> void spk_stop_serial_interrupt(void);
>
--
Samuel
<y> t1 faich
<y> les programmes ils segfaultent jamais quand on veut
-+- #ens-mim en plein débogage -+-
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Samuel Thibault
` Okash Khawaja
@ ` Okash Khawaja
` Samuel Thibault
1 sibling, 1 reply; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup
Hi,
On Fri, Apr 28, 2017 at 11:23:58PM +0200, Samuel Thibault wrote:
> So I guess now we need to be more pushy with serdev.
Haven't heard from Rob Herring yet. What do you suggest?
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Okash Khawaja
@ ` Samuel Thibault
` Okash Khawaja
0 siblings, 1 reply; 32+ messages in thread
From: Samuel Thibault @ UTC (permalink / raw)
To: Okash Khawaja; +Cc: speakup
Okash Khawaja, on sam. 29 avril 2017 09:47:23 +0100, wrote:
> On Fri, Apr 28, 2017 at 11:23:58PM +0200, Samuel Thibault wrote:
>
> > So I guess now we need to be more pushy with serdev.
> Haven't heard from Rob Herring yet. What do you suggest?
I'd say assume that it's fine, and work on writing a patch that works,
for more concrete discussion, and possibly mere integration by gkh
without going through Rob.
Samuel
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Samuel Thibault
@ ` Okash Khawaja
` Samuel Thibault
0 siblings, 1 reply; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup
Hi,
On Sat, Apr 29, 2017 at 02:07:45PM +0200, Samuel Thibault wrote:
> Okash Khawaja, on sam. 29 avril 2017 09:47:23 +0100, wrote:
> > On Fri, Apr 28, 2017 at 11:23:58PM +0200, Samuel Thibault wrote:
> >
> > > So I guess now we need to be more pushy with serdev.
> > Haven't heard from Rob Herring yet. What do you suggest?
>
> I'd say assume that it's fine, and work on writing a patch that works,
> for more concrete discussion, and possibly mere integration by gkh
> without going through Rob.
Sounds good! We have all the patches. Apart from the patch you are
reviewing in this thread there is
http://linux-speakup.org/pipermail/speakup/2017-April/060645.html
which is not yet signed off (we haven't had feedback on decext).
I will now get latest staging-next from kernel source, just to be sure
that patches all apply cleanly.
Do you want me to post all of them here as one patch set? Because since
I last posted, one of them has been upstreamed.
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: staging: speakup: add send_xchar, tiocmset and input functionality for tty
` Okash Khawaja
@ ` Samuel Thibault
0 siblings, 0 replies; 32+ messages in thread
From: Samuel Thibault @ UTC (permalink / raw)
To: Okash Khawaja; +Cc: speakup
Hello,
Okash Khawaja, on sam. 29 avril 2017 14:28:01 +0100, wrote:
> Sounds good! We have all the patches. Apart from the patch you are
> reviewing in this thread there is
> http://linux-speakup.org/pipermail/speakup/2017-April/060645.html
> which is not yet signed off (we haven't had feedback on decext).
Ah, sorry, I missed adding my Reviewed-by tag, now done so.
> Do you want me to post all of them here as one patch set? Because since
> I last posted, one of them has been upstreamed.
I'd say no need for a new post for review, they are fine. Posting them
for people to be able to test them could be useful, though.
Samuel
^ permalink raw reply [flat|nested] 32+ messages in thread
* [patch 7/7] staging: speakup: migrate apollo, ltlk, audptr, decext, dectlk and spkout
[patch 0/7] staging: speakup: migrate synths to use TTY-based comms Okash Khawaja
` (5 preceding siblings ...)
` [patch 6/7] staging: speakup: add send_xchar, tiocmset and input functionality for tty Okash Khawaja
@ ` Okash Khawaja
` [patch 0/7] staging: speakup: migrate synths to use TTY-based comms Samuel Thibault
7 siblings, 0 replies; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup
[-- Attachment #1: 07_migrate_apollo_ltlk_audptr_decext_dectlk_spkout --]
[-- Type: text/plain, Size: 6546 bytes --]
This patch simply uses the changes introduced in previous patches and migrates
apollo, ltlk, audptr, decext, spkout and dectlk. Migrations are straightforward
function pointer updates.
Signed-off by: Okash Khawaja <okash.khawaja@gmail.com>
Reviewed-by: Samuel Thibault <samuel.thibault at ens-lyon.org>
Index: linux-staging/drivers/staging/speakup/speakup_apollo.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_apollo.c
+++ linux-staging/drivers/staging/speakup/speakup_apollo.c
@@ -22,9 +22,9 @@
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/kthread.h>
+#include <linux/serial_reg.h> /* for UART_MCR* constants */
#include "spk_priv.h"
-#include "serialio.h"
#include "speakup.h"
#define DRV_VERSION "2.21"
@@ -108,10 +108,10 @@ static struct spk_synth synth_apollo = {
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = do_catch_up,
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
Index: linux-staging/drivers/staging/speakup/speakup_ltlk.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_ltlk.c
+++ linux-staging/drivers/staging/speakup/speakup_ltlk.c
@@ -20,7 +20,6 @@
*/
#include "speakup.h"
#include "spk_priv.h"
-#include "serialio.h"
#include "speakup_dtlk.h" /* local header file for LiteTalk values */
#define DRV_VERSION "2.11"
@@ -111,10 +110,10 @@ static struct spk_synth synth_ltlk = {
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
+ .io_ops = &spk_ttyio_ops,
.probe = synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = spk_synth_flush,
.is_alive = spk_synth_is_alive_restart,
@@ -159,7 +158,7 @@ static int synth_probe(struct spk_synth
{
int failed = 0;
- failed = spk_serial_synth_probe(synth);
+ failed = spk_ttyio_synth_probe(synth);
if (failed == 0)
synth_interrogate(synth);
synth->alive = !failed;
Index: linux-staging/drivers/staging/speakup/speakup_audptr.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_audptr.c
+++ linux-staging/drivers/staging/speakup/speakup_audptr.c
@@ -20,7 +20,6 @@
*/
#include "spk_priv.h"
#include "speakup.h"
-#include "serialio.h"
#define DRV_VERSION "2.11"
#define SYNTH_CLEAR 0x18 /* flush synth buffer */
@@ -104,10 +103,10 @@ static struct spk_synth synth_audptr = {
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
+ .io_ops = &spk_ttyio_ops,
.probe = synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = synth_flush,
.is_alive = spk_synth_is_alive_restart,
@@ -154,7 +153,7 @@ static int synth_probe(struct spk_synth
{
int failed;
- failed = spk_serial_synth_probe(synth);
+ failed = spk_ttyio_synth_probe(synth);
if (failed == 0)
synth_version(synth);
synth->alive = !failed;
Index: linux-staging/drivers/staging/speakup/speakup_decext.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_decext.c
+++ linux-staging/drivers/staging/speakup/speakup_decext.c
@@ -24,12 +24,12 @@
#include <linux/kthread.h>
#include "spk_priv.h"
-#include "serialio.h"
#include "speakup.h"
#define DRV_VERSION "2.14"
#define SYNTH_CLEAR 0x03
#define PROCSPEECH 0x0b
+
static volatile unsigned char last_char;
static void read_buff_add(u_char ch)
@@ -123,10 +123,10 @@ static struct spk_synth synth_decext = {
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = do_catch_up,
.flush = synth_flush,
.is_alive = spk_synth_is_alive_restart,
Index: linux-staging/drivers/staging/speakup/speakup_spkout.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_spkout.c
+++ linux-staging/drivers/staging/speakup/speakup_spkout.c
@@ -20,7 +20,6 @@
*/
#include "spk_priv.h"
#include "speakup.h"
-#include "serialio.h"
#define DRV_VERSION "2.11"
#define SYNTH_CLEAR 0x18
@@ -102,10 +101,10 @@ static struct spk_synth synth_spkout = {
.startup = SYNTH_START,
.checkval = SYNTH_CHECK,
.vars = vars,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = spk_do_catch_up,
.flush = synth_flush,
.is_alive = spk_synth_is_alive_restart,
Index: linux-staging/drivers/staging/speakup/speakup_dectlk.c
===================================================================
--- linux-staging.orig/drivers/staging/speakup/speakup_dectlk.c
+++ linux-staging/drivers/staging/speakup/speakup_dectlk.c
@@ -27,7 +27,6 @@
#include <linux/kthread.h>
#include "speakup.h"
#include "spk_priv.h"
-#include "serialio.h"
#define DRV_VERSION "2.20"
#define SYNTH_CLEAR 0x03
@@ -130,10 +129,10 @@ static struct spk_synth synth_dectlk = {
.vars = vars,
.default_pitch = ap_defaults,
.default_vol = g5_defaults,
- .io_ops = &spk_serial_io_ops,
- .probe = spk_serial_synth_probe,
- .release = spk_serial_release,
- .synth_immediate = spk_serial_synth_immediate,
+ .io_ops = &spk_ttyio_ops,
+ .probe = spk_ttyio_synth_probe,
+ .release = spk_ttyio_release,
+ .synth_immediate = spk_ttyio_synth_immediate,
.catch_up = do_catch_up,
.flush = synth_flush,
.is_alive = spk_synth_is_alive_restart,
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [patch 0/7] staging: speakup: migrate synths to use TTY-based comms
[patch 0/7] staging: speakup: migrate synths to use TTY-based comms Okash Khawaja
` (6 preceding siblings ...)
` [patch 7/7] staging: speakup: migrate apollo, ltlk, audptr, decext, dectlk and spkout Okash Khawaja
@ ` Samuel Thibault
` Okash Khawaja
7 siblings, 1 reply; 32+ messages in thread
From: Samuel Thibault @ UTC (permalink / raw)
To: Okash Khawaja; +Cc: speakup
Okash Khawaja, on jeu. 13 avril 2017 18:41:28 +0100, wrote:
> so that top two patches can be send upstream but I guess
> we need feedback from decext testers before we actually do that?
For the second, yes. The first one, however, looks completely
submittable to me: it just shuffles code without any actualy behavior
change.
Samuel
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [patch 0/7] staging: speakup: migrate synths to use TTY-based comms
` [patch 0/7] staging: speakup: migrate synths to use TTY-based comms Samuel Thibault
@ ` Okash Khawaja
0 siblings, 0 replies; 32+ messages in thread
From: Okash Khawaja @ UTC (permalink / raw)
To: Samuel Thibault; +Cc: speakup
Hi,
On Thu, Apr 13, 2017 at 07:53:41PM +0200, Samuel Thibault wrote:
> Okash Khawaja, on jeu. 13 avril 2017 18:41:28 +0100, wrote:
> > so that top two patches can be send upstream but I guess
> > we need feedback from decext testers before we actually do that?
>
> For the second, yes. The first one, however, looks completely
> submittable to me: it just shuffles code without any actualy behavior
> change.
Cool, I can send the first one and wait for feedback from decext testers
for the second one.
What would you suggest for serdev? Rob Herring hasn't replied yet. Shall
we wait?
Thanks,
Okash
^ permalink raw reply [flat|nested] 32+ messages in thread