Skip to contentSkip to conversation

staging: speakup: support more than ttyS*

PATCH Superseded [email protected] 5 participants 17 messages Jun 13, 2017 – Jun 17, 2017

Subsystems (2)

v1 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

cover staging: speakup: support more than ttyS*

Hi,

These patches extend speakup support to ttyUSB* and lp*. They introduce a new module param dev whose function is similar to ser but instead of taking serial port number as argument, it takes strings like ttyS0 or ttyUSB0. First patch just adds functionality to convert such strings into dev_t. Second patch makes use of that functionlity.

Thanks,
Okash

#16 lore raw

PATCH 2/2 staging: speakup: make ttyio synths use device name

This patch introduces new module parameter, dev, which takes a string representing the device that the external synth is connected to, e.g. ttyS0, ttyUSB0 etc. This is then used to communicate with the synth. That way, speakup can support more than ttyS*. As of this patch, it only supports ttyS*, ttyUSB* and selected synths for lp*. dev parameter is only available for tty-migrated synths.

Users will either use dev or ser as both serve same purpose. This patch maintains backward compatility by allowing ser to be specified. When both are specified, whichever is non-default, i.e. not ttyS0, is used. If both are non-default then dev is used.

---
 drivers/staging/speakup/speakup_acntsa.c |    3 +++
 drivers/staging/speakup/speakup_apollo.c |    3 +++
 drivers/staging/speakup/speakup_audptr.c |    3 +++
 drivers/staging/speakup/speakup_bns.c    |    3 +++
 drivers/staging/speakup/speakup_decext.c |    3 +++
 drivers/staging/speakup/speakup_dectlk.c |    3 +++
 drivers/staging/speakup/speakup_dummy.c  |    3 +++
 drivers/staging/speakup/speakup_ltlk.c   |    3 +++
 drivers/staging/speakup/speakup_spkout.c |    3 +++
 drivers/staging/speakup/speakup_txprt.c  |    3 +++
 drivers/staging/speakup/spk_ttyio.c      |   15 +++++++--------
 11 files changed, 37 insertions(+), 8 deletions(-)
drivers/staging/speakup/speakup_acntsa.c +3 -0
@@ -96,6 +96,7 @@ static struct spk_synth synth_acntsa = {
 	.trigger = 50,
 	.jiffies = 30,
 	.full = 40000,
+	.dev = SYNTH_DEFAULT_DEV,
 	.startup = SYNTH_START,
 	.checkval = SYNTH_CHECK,
 	.vars = vars,
@@ -135,9 +136,11 @@ static int synth_probe(struct spk_synth
 }
 
 module_param_named(ser, synth_acntsa.ser, int, 0444);
+module_param_named(dev, synth_acntsa.dev, charp, S_IRUGO);
 module_param_named(start, synth_acntsa.startup, short, 0444);
 
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
 module_spk_synth(synth_acntsa);
drivers/staging/speakup/speakup_apollo.c +3 -0
@@ -105,6 +105,7 @@ static struct spk_synth synth_apollo = {
 	.trigger = 50,
 	.jiffies = 50,
 	.full = 40000,
+	.dev = SYNTH_DEFAULT_DEV,
 	.startup = SYNTH_START,
 	.checkval = SYNTH_CHECK,
 	.vars = vars,
@@ -199,9 +200,11 @@ static void do_catch_up(struct spk_synth
 }
 
 module_param_named(ser, synth_apollo.ser, int, 0444);
+module_param_named(dev, synth_apollo.dev, charp, S_IRUGO);
 module_param_named(start, synth_apollo.startup, short, 0444);
 
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
 module_spk_synth(synth_apollo);
drivers/staging/speakup/speakup_audptr.c +3 -0
@@ -100,6 +100,7 @@ static struct spk_synth synth_audptr = {
 	.trigger = 50,
 	.jiffies = 30,
 	.full = 18000,
+	.dev = SYNTH_DEFAULT_DEV,
 	.startup = SYNTH_START,
 	.checkval = SYNTH_CHECK,
 	.vars = vars,
@@ -162,9 +163,11 @@ static int synth_probe(struct spk_synth
 }
 
 module_param_named(ser, synth_audptr.ser, int, 0444);
+module_param_named(dev, synth_audptr.dev, charp, S_IRUGO);
 module_param_named(start, synth_audptr.startup, short, 0444);
 
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
 module_spk_synth(synth_audptr);
drivers/staging/speakup/speakup_bns.c +3 -0
@@ -93,6 +93,7 @@ static struct spk_synth synth_bns = {
 	.trigger = 50,
 	.jiffies = 50,
 	.full = 40000,
+	.dev = SYNTH_DEFAULT_DEV,
 	.startup = SYNTH_START,
 	.checkval = SYNTH_CHECK,
 	.vars = vars,
@@ -119,9 +120,11 @@ static struct spk_synth synth_bns = {
 };
 
 module_param_named(ser, synth_bns.ser, int, 0444);
+module_param_named(dev, synth_bns.dev, charp, S_IRUGO);
 module_param_named(start, synth_bns.startup, short, 0444);
 
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
 module_spk_synth(synth_bns);
drivers/staging/speakup/speakup_decext.c +3 -0
@@ -120,6 +120,7 @@ static struct spk_synth synth_decext = {
 	.jiffies = 50,
 	.full = 40000,
 	.flags = SF_DEC,
+	.dev = SYNTH_DEFAULT_DEV,
 	.startup = SYNTH_START,
 	.checkval = SYNTH_CHECK,
 	.vars = vars,
@@ -226,9 +227,11 @@ static void synth_flush(struct spk_synth
 }
 
 module_param_named(ser, synth_decext.ser, int, 0444);
+module_param_named(dev, synth_decext.dev, charp, S_IRUGO);
 module_param_named(start, synth_decext.startup, short, 0444);
 
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
 module_spk_synth(synth_decext);
drivers/staging/speakup/speakup_dectlk.c +3 -0
@@ -124,6 +124,7 @@ static struct spk_synth synth_dectlk = {
 	.trigger = 50,
 	.jiffies = 50,
 	.full = 40000,
+	.dev = SYNTH_DEFAULT_DEV,
 	.startup = SYNTH_START,
 	.checkval = SYNTH_CHECK,
 	.vars = vars,
@@ -298,9 +299,11 @@ static void synth_flush(struct spk_synth
 }
 
 module_param_named(ser, synth_dectlk.ser, int, 0444);
+module_param_named(dev, synth_dectlk.dev, charp, S_IRUGO);
 module_param_named(start, synth_dectlk.startup, short, 0444);
 
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
 module_spk_synth(synth_dectlk);
drivers/staging/speakup/speakup_dummy.c +3 -0
@@ -95,6 +95,7 @@ static struct spk_synth synth_dummy = {
 	.trigger = 50,
 	.jiffies = 50,
 	.full = 40000,
+	.dev = SYNTH_DEFAULT_DEV,
 	.startup = SYNTH_START,
 	.checkval = SYNTH_CHECK,
 	.vars = vars,
@@ -121,9 +122,11 @@ static struct spk_synth synth_dummy = {
 };
 
 module_param_named(ser, synth_dummy.ser, int, 0444);
+module_param_named(dev, synth_dummy.dev, charp, S_IRUGO);
 module_param_named(start, synth_dummy.startup, short, 0444);
 
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
 module_spk_synth(synth_dummy);
drivers/staging/speakup/speakup_ltlk.c +3 -0
@@ -107,6 +107,7 @@ static struct spk_synth synth_ltlk = {
 	.trigger = 50,
 	.jiffies = 50,
 	.full = 40000,
+	.dev = SYNTH_DEFAULT_DEV,
 	.startup = SYNTH_START,
 	.checkval = SYNTH_CHECK,
 	.vars = vars,
@@ -166,9 +167,11 @@ static int synth_probe(struct spk_synth
 }
 
 module_param_named(ser, synth_ltlk.ser, int, 0444);
+module_param_named(dev, synth_ltlk.dev, charp, S_IRUGO);
 module_param_named(start, synth_ltlk.startup, short, 0444);
 
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
 module_spk_synth(synth_ltlk);
drivers/staging/speakup/speakup_spkout.c +3 -0
@@ -98,6 +98,7 @@ static struct spk_synth synth_spkout = {
 	.trigger = 50,
 	.jiffies = 50,
 	.full = 40000,
+	.dev = SYNTH_DEFAULT_DEV,
 	.startup = SYNTH_START,
 	.checkval = SYNTH_CHECK,
 	.vars = vars,
@@ -130,9 +131,11 @@ static void synth_flush(struct spk_synth
 }
 
 module_param_named(ser, synth_spkout.ser, int, 0444);
+module_param_named(dev, synth_spkout.dev, charp, S_IRUGO);
 module_param_named(start, synth_spkout.startup, short, 0444);
 
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
 module_spk_synth(synth_spkout);
drivers/staging/speakup/speakup_txprt.c +3 -0
@@ -92,6 +92,7 @@ static struct spk_synth synth_txprt = {
 	.trigger = 50,
 	.jiffies = 50,
 	.full = 40000,
+	.dev = SYNTH_DEFAULT_DEV,
 	.startup = SYNTH_START,
 	.checkval = SYNTH_CHECK,
 	.vars = vars,
@@ -118,9 +119,11 @@ static struct spk_synth synth_txprt = {
 };
 
 module_param_named(ser, synth_txprt.ser, int, 0444);
+module_param_named(dev, synth_txprt.dev, charp, S_IRUGO);
 module_param_named(start, synth_txprt.startup, short, 0444);
 
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
+MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
 module_spk_synth(synth_txprt);
drivers/staging/speakup/spk_ttyio.c +7 -8
@@ -209,11 +209,12 @@ static inline void get_termios(struct tt
 	up_read(&tty->termios_rwsem);
 }
 
-static int spk_ttyio_initialise_ldisc(int ser)
+static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
 {
 	int ret = 0;
 	struct tty_struct *tty;
 	struct ktermios tmp_termios;
+	dev_t dev;
 
 	ret = tty_register_ldisc(N_SPEAKUP, &spk_ttyio_ldisc_ops);
 	if (ret) {
@@ -221,13 +222,11 @@ static int spk_ttyio_initialise_ldisc(in
 		return ret;
 	}
 
-	if (ser < 0 || ser > (255 - 64)) {
-		pr_err("speakup: Invalid ser param. Must be between 0 and 191 inclusive.\n");
-		return -EINVAL;
-	}
+	ret = get_dev_to_use(synth, &dev);
+	if (ret)
+		return ret;
 
-	/* TODO: support more than ttyS* */
-	tty = tty_open_by_driver(MKDEV(4, (ser +  64)), NULL, NULL);
+	tty = tty_open_by_driver(dev, NULL, NULL);
 	if (IS_ERR(tty))
 		return PTR_ERR(tty);
 
@@ -338,7 +337,7 @@ static void spk_ttyio_flush_buffer(void)
 
 int spk_ttyio_synth_probe(struct spk_synth *synth)
 {
-	int rv = spk_ttyio_initialise_ldisc(synth->ser);
+	int rv = spk_ttyio_initialise_ldisc(synth);
 
 	if (rv)
 		return rv;
#1 lore raw

PATCH 1/2 staging: speakup: add function to convert dev name to number

In reply to [email protected]

The function converts strings like ttyS0 and ttyUSB0 to dev_t like (4, 64) and (188, 0). Subsequent patch in this set will call it to convert user-supplied device into device number. The function does some basic sanity checks on the string passed in. It currently supports ttyS*, ttyUSB* and, for selected synths, lp*.

In order to do this, the patch also introduces a string member variable named 'dev' to struct spk_synth. 'dev' represents the device name - ttyUSB0 etc - which needs conversion to dev_t.

---
 drivers/staging/speakup/spk_priv.h  |    2 
 drivers/staging/speakup/spk_ttyio.c |  105 ++++++++++++++++++++++++++++++++++++
 drivers/staging/speakup/spk_types.h |    1 
 3 files changed, 108 insertions(+)
drivers/staging/speakup/spk_priv.h +2 -0
@@ -40,6 +40,8 @@
 
 #define KT_SPKUP 15
 #define SPK_SYNTH_TIMEOUT 100000 /* in micro-seconds */
+#define SYNTH_DEFAULT_DEV "ttyS0"
+#define SYNTH_DEFAULT_SER 0
 
 const struct old_serial_port *spk_serial_init(int index);
 void spk_stop_serial_interrupt(void);
drivers/staging/speakup/spk_ttyio.c +105 -0

117 lines not on this page · raw message

drivers/staging/speakup/spk_types.h +1 -0
@@ -169,6 +169,7 @@ struct spk_synth {
 	int jiffies;
 	int full;
 	int ser;
+	char *dev;
 	short flags;
 	short startup;
 	const int checkval; /* for validating a proper synth module */
#2 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

Quoted 48 lines · On Tue, Jun 13, 2017 at 11:37:03PM +0100, [email protected] wrote:

The function converts strings like ttyS0 and ttyUSB0 to dev_t like (4, 64) and (188, 0). Subsequent patch in this set will call it to convert user-supplied device into device number. The function does some basic sanity checks on the string passed in. It currently supports ttyS*, ttyUSB* and, for selected synths, lp*.

In order to do this, the patch also introduces a string member variable named 'dev' to struct spk_synth. 'dev' represents the device name - ttyUSB0 etc - which needs conversion to dev_t.

---
 drivers/staging/speakup/spk_priv.h  |    2 
 drivers/staging/speakup/spk_ttyio.c |  105 ++++++++++++++++++++++++++++++++++++
 drivers/staging/speakup/spk_types.h |    1 
 3 files changed, 108 insertions(+)
drivers/staging/speakup/spk_priv.h +2 -0
@@ -40,6 +40,8 @@
 
 #define KT_SPKUP 15
 #define SPK_SYNTH_TIMEOUT 100000 /* in micro-seconds */
+#define SYNTH_DEFAULT_DEV "ttyS0"
+#define SYNTH_DEFAULT_SER 0
 
 const struct old_serial_port *spk_serial_init(int index);
 void spk_stop_serial_interrupt(void);
drivers/staging/speakup/spk_ttyio.c +7 -0
@@ -7,6 +7,13 @@
 #include "spk_types.h"
 #include "spk_priv.h"
 
+/* Supported device types */
+#define DEV_PREFIX_TTYS "ttyS"
+#define DEV_PREFIX_TTYUSB "ttyUSB"
+#define DEV_PREFIX_LP "lp"
+
+const char *lp_supported[] = { "acntsa", "bns", "dummy", "txprt" };
+
 struct spk_ldisc_data {
 	char buf;
 	struct semaphore sem;
@@ -16,6 +23,104 @@ struct spk_ldisc_data {
 static struct spk_synth *spk_ttyio_synth;

drivers/staging/speakup/spk_ttyio.c struct spk_ldisc_data { · line 33

Quoted 10 lines
drivers/staging/speakup/spk_ttyio.c +8 -0
 static struct tty_struct *speakup_tty;
 
+static int name_to_dev(const char *name, dev_t *dev_no)
+{
+        int maj = -1, min = -1;
+
+        if (strncmp(name, DEV_PREFIX_TTYS, strlen(DEV_PREFIX_TTYS)) == 0) {
+                if (kstrtoint(name + strlen(DEV_PREFIX_TTYS), 10, &min)) {
+			pr_err("speakup: Invalid ser param. Must be \
+					between 0 and 191 inclusive.\n");

String needs fixed.

drivers/staging/speakup/spk_ttyio.c struct spk_ldisc_data { · line 34

Quoted 1 line
drivers/staging/speakup/spk_ttyio.c +1 -0
+                        return -EINVAL;

Preserve the error code from kstrtoint().

drivers/staging/speakup/spk_ttyio.c struct spk_ldisc_data { · line 40

Quoted 6 lines
drivers/staging/speakup/spk_ttyio.c +6 -0
+                }
+                maj = 4;
+
+                if (min < 0 || min > 191) {
+			pr_err("speakup: Invalid ser param. Must be \
+					between 0 and 191 inclusive.\n");

This too.

drivers/staging/speakup/spk_ttyio.c struct spk_ldisc_data { · line 49

Quoted 9 lines
drivers/staging/speakup/spk_ttyio.c +9 -0
+                        return -EINVAL;
+                }
+                min = min + 64;
+        } else if (strncmp(name, DEV_PREFIX_TTYUSB, strlen(DEV_PREFIX_TTYUSB))
+			== 0) {
+                if (kstrtoint(name + strlen(DEV_PREFIX_TTYUSB), 10, &min)) {
+                        pr_err("speakup: Invalid ttyUSB number. \
+					Must be a number from 0 onwards\n");
+                        return -EINVAL;

Same.

drivers/staging/speakup/spk_ttyio.c struct spk_ldisc_data { · line 55

Quoted 6 lines
drivers/staging/speakup/spk_ttyio.c +6 -0
+                }
+                maj = 188;
+
+                if (min < 0) {
+                        pr_err("speakup: Invalid ttyUSB number. \
+					Must be a number from 0 onwards\n");

Same.

drivers/staging/speakup/spk_ttyio.c struct spk_ldisc_data { · line 62

Quoted 7 lines
drivers/staging/speakup/spk_ttyio.c +7 -0
+                        return -EINVAL;
+                }
+        } else if (strncmp(name, DEV_PREFIX_LP, strlen(DEV_PREFIX_LP)) == 0) {
+                if (kstrtoint(name + strlen(DEV_PREFIX_LP), 10, &min)) {
+                        pr_warn("speakup: Invalid lp number. \
+					Must be a number from 0 onwards\n");
+                        return -EINVAL;

Same. Preserve.

drivers/staging/speakup/spk_ttyio.c struct spk_ldisc_data { · line 68

Quoted 6 lines
drivers/staging/speakup/spk_ttyio.c +6 -0
+                }
+                maj = 6;
+
+                if (min < 0) {
+                        pr_warn("speakup: Invalid lp number. \
+					Must be a number from 0 onwards\n");

Again.

Quoted 8 lines
drivers/staging/speakup/spk_ttyio.c +8 -0
+                        return -EINVAL;
+                }
+        }
+
+        if (maj == -1 || min == -1)
+                return -EINVAL;
+
+        /* if here, maj and min must be valid */

drivers/staging/speakup/spk_ttyio.c struct spk_ldisc_data { · line 86

Quoted 10 lines
drivers/staging/speakup/spk_ttyio.c +10 -0
+        *dev_no = MKDEV(maj, min);
+
+        return 0;
+}
+
+int ser_to_dev(int ser, dev_t *dev_no)
+{
+	if (ser < 0 || ser > (255 - 64)) {
+                pr_err("speakup: Invalid ser param. \
+				Must be between 0 and 191 inclusive.\n");

String. I feel like 191 and 255 - 64 are the same. Let's just use 191 everywhere.

Quoted 43 lines
drivers/staging/speakup/spk_ttyio.c +37 -0
+
+		return -EINVAL;
+        }
+
+	*dev_no = MKDEV(4, (64 + ser));
+	return 0;
+}
+
+static int get_dev_to_use(struct spk_synth *synth, dev_t *dev_no)
+{
+	/* use ser only when dev is not specified */
+	if (strcmp(synth->dev, SYNTH_DEFAULT_DEV) || synth->ser == SYNTH_DEFAULT_SER) {
+		/* for /dev/lp* check if synth is supported */
+		if (strncmp(synth->dev, DEV_PREFIX_LP, strlen(DEV_PREFIX_LP)) == 0) {
+			int i;
+
+			for (i = 0; i < ARRAY_SIZE(lp_supported); i++) {
+				if (strcmp(synth->name, lp_supported[i]) == 0)
+					break;
+			}
+
+			if (i >= ARRAY_SIZE(lp_supported)) {
+				pr_err("speakup: lp* is only supported on:");
+				for (i = 0; i < ARRAY_SIZE(lp_supported); i++)
+					pr_cont(" %s", lp_supported[i]);
+				pr_cont("\n");
+
+				return -ENOTSUPP;
+			}
+		}
+
+		return name_to_dev(synth->dev, dev_no);
+	}
+
+	return ser_to_dev(synth->ser, dev_no);
+}
+
 static int spk_ttyio_ldisc_open(struct tty_struct *tty)
 {
 	struct spk_ldisc_data *ldisc_data;

drivers/staging/speakup/spk_types.h struct spk_synth { · line 172

Quoted 4 lines
drivers/staging/speakup/spk_types.h +1 -0
@@ -169,6 +169,7 @@ struct spk_synth {
 	int jiffies;
 	int full;
 	int ser;
+	char *dev;

Could you call it "dev_name" instead? I normally expect "dev" to be a device struct.

regards,
dan carpenter

#4 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

In reply to [email protected]
Quoted 95 lines · On Tue, Jun 13, 2017 at 11:37:03PM +0100, [email protected] wrote:

The function converts strings like ttyS0 and ttyUSB0 to dev_t like (4, 64) and (188, 0). Subsequent patch in this set will call it to convert user-supplied device into device number. The function does some basic sanity checks on the string passed in. It currently supports ttyS*, ttyUSB* and, for selected synths, lp*.

In order to do this, the patch also introduces a string member variable named 'dev' to struct spk_synth. 'dev' represents the device name - ttyUSB0 etc - which needs conversion to dev_t.

---
 drivers/staging/speakup/spk_priv.h  |    2 
 drivers/staging/speakup/spk_ttyio.c |  105 ++++++++++++++++++++++++++++++++++++
 drivers/staging/speakup/spk_types.h |    1 
 3 files changed, 108 insertions(+)
drivers/staging/speakup/spk_priv.h +2 -0
@@ -40,6 +40,8 @@
 
 #define KT_SPKUP 15
 #define SPK_SYNTH_TIMEOUT 100000 /* in micro-seconds */
+#define SYNTH_DEFAULT_DEV "ttyS0"
+#define SYNTH_DEFAULT_SER 0
 
 const struct old_serial_port *spk_serial_init(int index);
 void spk_stop_serial_interrupt(void);
drivers/staging/speakup/spk_ttyio.c +52 -0
@@ -7,6 +7,13 @@
 #include "spk_types.h"
 #include "spk_priv.h"
 
+/* Supported device types */
+#define DEV_PREFIX_TTYS "ttyS"
+#define DEV_PREFIX_TTYUSB "ttyUSB"
+#define DEV_PREFIX_LP "lp"
+
+const char *lp_supported[] = { "acntsa", "bns", "dummy", "txprt" };
+
 struct spk_ldisc_data {
 	char buf;
 	struct semaphore sem;
@@ -16,6 +23,104 @@ struct spk_ldisc_data {
 static struct spk_synth *spk_ttyio_synth;
 static struct tty_struct *speakup_tty;
 
+static int name_to_dev(const char *name, dev_t *dev_no)
+{
+        int maj = -1, min = -1;
+
+        if (strncmp(name, DEV_PREFIX_TTYS, strlen(DEV_PREFIX_TTYS)) == 0) {
+                if (kstrtoint(name + strlen(DEV_PREFIX_TTYS), 10, &min)) {
+			pr_err("speakup: Invalid ser param. Must be \
+					between 0 and 191 inclusive.\n");
+                        return -EINVAL;
+                }
+                maj = 4;
+
+                if (min < 0 || min > 191) {
+			pr_err("speakup: Invalid ser param. Must be \
+					between 0 and 191 inclusive.\n");
+                        return -EINVAL;
+                }
+                min = min + 64;
+        } else if (strncmp(name, DEV_PREFIX_TTYUSB, strlen(DEV_PREFIX_TTYUSB))
+			== 0) {
+                if (kstrtoint(name + strlen(DEV_PREFIX_TTYUSB), 10, &min)) {
+                        pr_err("speakup: Invalid ttyUSB number. \
+					Must be a number from 0 onwards\n");
+                        return -EINVAL;
+                }
+                maj = 188;
+
+                if (min < 0) {
+                        pr_err("speakup: Invalid ttyUSB number. \
+					Must be a number from 0 onwards\n");
+                        return -EINVAL;
+                }
+        } else if (strncmp(name, DEV_PREFIX_LP, strlen(DEV_PREFIX_LP)) == 0) {
+                if (kstrtoint(name + strlen(DEV_PREFIX_LP), 10, &min)) {
+                        pr_warn("speakup: Invalid lp number. \
+					Must be a number from 0 onwards\n");
+                        return -EINVAL;
+                }
+                maj = 6;
+
+                if (min < 0) {
+                        pr_warn("speakup: Invalid lp number. \
+					Must be a number from 0 onwards\n");
+                        return -EINVAL;
+                }

drivers/staging/speakup/spk_ttyio.c struct spk_ldisc_data { · line 80

Quoted 10 lines
drivers/staging/speakup/spk_ttyio.c +10 -0
+        }
+
+        if (maj == -1 || min == -1)
+                return -EINVAL;
+
+        /* if here, maj and min must be valid */
+        *dev_no = MKDEV(maj, min);
+
+        return 0;
+}

Eeek, no, let's never try to parse strings like this and "figure out" what major/minor number it is. That's madness and will break if we ever make all char majors dynamic (there's a thread on lkml about that.)

Why would the kernel need to know major/minor? Is it going to open a device node? If so, again, crazy stuff, that's not good...

thanks,

greg k-h

#5 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

Quoted 111 lines · Greg Kroah-Hartman
Quoted 95 lines · On Tue, Jun 13, 2017 at 11:37:03PM +0100, [email protected] wrote:

The function converts strings like ttyS0 and ttyUSB0 to dev_t like (4, 64) and (188, 0). Subsequent patch in this set will call it to convert user-supplied device into device number. The function does some basic sanity checks on the string passed in. It currently supports ttyS*, ttyUSB* and, for selected synths, lp*.

In order to do this, the patch also introduces a string member variable named 'dev' to struct spk_synth. 'dev' represents the device name - ttyUSB0 etc - which needs conversion to dev_t.

---
 drivers/staging/speakup/spk_priv.h  |    2 
 drivers/staging/speakup/spk_ttyio.c |  105 ++++++++++++++++++++++++++++++++++++
 drivers/staging/speakup/spk_types.h |    1 
 3 files changed, 108 insertions(+)
drivers/staging/speakup/spk_priv.h +2 -0
@@ -40,6 +40,8 @@
 
 #define KT_SPKUP 15
 #define SPK_SYNTH_TIMEOUT 100000 /* in micro-seconds */
+#define SYNTH_DEFAULT_DEV "ttyS0"
+#define SYNTH_DEFAULT_SER 0
 
 const struct old_serial_port *spk_serial_init(int index);
 void spk_stop_serial_interrupt(void);
drivers/staging/speakup/spk_ttyio.c +52 -0
@@ -7,6 +7,13 @@
 #include "spk_types.h"
 #include "spk_priv.h"
 
+/* Supported device types */
+#define DEV_PREFIX_TTYS "ttyS"
+#define DEV_PREFIX_TTYUSB "ttyUSB"
+#define DEV_PREFIX_LP "lp"
+
+const char *lp_supported[] = { "acntsa", "bns", "dummy", "txprt" };
+
 struct spk_ldisc_data {
 	char buf;
 	struct semaphore sem;
@@ -16,6 +23,104 @@ struct spk_ldisc_data {
 static struct spk_synth *spk_ttyio_synth;
 static struct tty_struct *speakup_tty;
 
+static int name_to_dev(const char *name, dev_t *dev_no)
+{
+        int maj = -1, min = -1;
+
+        if (strncmp(name, DEV_PREFIX_TTYS, strlen(DEV_PREFIX_TTYS)) == 0) {
+                if (kstrtoint(name + strlen(DEV_PREFIX_TTYS), 10, &min)) {
+			pr_err("speakup: Invalid ser param. Must be \
+					between 0 and 191 inclusive.\n");
+                        return -EINVAL;
+                }
+                maj = 4;
+
+                if (min < 0 || min > 191) {
+			pr_err("speakup: Invalid ser param. Must be \
+					between 0 and 191 inclusive.\n");
+                        return -EINVAL;
+                }
+                min = min + 64;
+        } else if (strncmp(name, DEV_PREFIX_TTYUSB, strlen(DEV_PREFIX_TTYUSB))
+			== 0) {
+                if (kstrtoint(name + strlen(DEV_PREFIX_TTYUSB), 10, &min)) {
+                        pr_err("speakup: Invalid ttyUSB number. \
+					Must be a number from 0 onwards\n");
+                        return -EINVAL;
+                }
+                maj = 188;
+
+                if (min < 0) {
+                        pr_err("speakup: Invalid ttyUSB number. \
+					Must be a number from 0 onwards\n");
+                        return -EINVAL;
+                }
+        } else if (strncmp(name, DEV_PREFIX_LP, strlen(DEV_PREFIX_LP)) == 0) {
+                if (kstrtoint(name + strlen(DEV_PREFIX_LP), 10, &min)) {
+                        pr_warn("speakup: Invalid lp number. \
+					Must be a number from 0 onwards\n");
+                        return -EINVAL;
+                }
+                maj = 6;
+
+                if (min < 0) {
+                        pr_warn("speakup: Invalid lp number. \
+					Must be a number from 0 onwards\n");
+                        return -EINVAL;
+                }

drivers/staging/speakup/spk_ttyio.c struct spk_ldisc_data { · line 80

Quoted 10 lines
drivers/staging/speakup/spk_ttyio.c +10 -0
+        }
+
+        if (maj == -1 || min == -1)
+                return -EINVAL;
+
+        /* if here, maj and min must be valid */
+        *dev_no = MKDEV(maj, min);
+
+        return 0;
+}

Eeek, no, let's never try to parse strings like this and "figure out" what major/minor number it is. That's madness and will break if we ever make all char majors dynamic (there's a thread on lkml about that.)

Quoted 2 lines

Why would the kernel need to know major/minor? Is it going to open a device node? If so, again, crazy stuff, that's not good...

Ah, no, nevermind, you just need the major/minor. So why not just take that as the input here, and not a string?

thanks,

greg k-h

#6 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

Quoted 2 lines · Greg KH, on mer. 14 juin 2017 12:15:41 +0200, wrote:

Ah, no, nevermind, you just need the major/minor. So why not just take that as the input here, and not a string?

Because real users don't know about major/minor numbers.

Samuel

#7 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

Quoted 5 lines · Samuel Thibault
Quoted 2 lines · Greg KH, on mer. 14 juin 2017 12:15:41 +0200, wrote:

Ah, no, nevermind, you just need the major/minor. So why not just take that as the input here, and not a string?

Because real users don't know about major/minor numbers.

I'm not disagreeing, it's just that the kernel doesn't know about "device names" either :)

And trying to have the kernel do the mapping based on strings like this is not ok, sorry.

greg k-h

#8 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

Quoted 9 lines · Greg KH, on mer. 14 juin 2017 13:48:02 +0200, wrote:
Quoted 5 lines · Samuel Thibault
Quoted 2 lines · Greg KH, on mer. 14 juin 2017 12:15:41 +0200, wrote:

Ah, no, nevermind, you just need the major/minor. So why not just take that as the input here, and not a string?

Because real users don't know about major/minor numbers.

I'm not disagreeing, it's just that the kernel doesn't know about "device names" either :)

Well, it does for the console= parameter, for instance. I know it's not actually related with major/minor numbering, but it's still meant to designate the same thing.

Quoted 2 lines

And trying to have the kernel do the mapping based on strings like this is not ok, sorry.

So what is the solution? Users would find it completely crazy to have to provide major/minor numbers.

Samuel

#9 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

Quoted 9 lines · Samuel Thibault
Quoted 5 lines · Greg KH, on mer. 14 juin 2017 13:48:02 +0200, wrote:
Quoted 1 line · Samuel Thibault

Greg KH, on mer. 14 juin 2017 12:15:41 +0200, wrote:

And trying to have the kernel do the mapping based on strings like this is not ok, sorry.

So what is the solution? Users would find it completely crazy to have to provide major/minor numbers.

Shouldn't udev take care of major/minor and alike stuff in user space?

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#10 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

Quoted 6 lines · Andy Shevchenko, on mer. 14 juin 2017 15:36:30 +0300, wrote:
Quoted 3 lines · Samuel Thibault
Quoted 2 lines · Greg KH, on mer. 14 juin 2017 13:48:02 +0200, wrote:
Quoted 1 line · Samuel Thibault

Greg KH, on mer. 14 juin 2017 12:15:41 +0200, wrote:

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

And trying to have the kernel do the mapping based on strings like this is not ok, sorry.

So what is the solution? Users would find it completely crazy to have to provide major/minor numbers.

Shouldn't udev take care of major/minor and alike stuff in user space?

We want speakup to get initialized before udev etc., just like the early console.

Samuel

#11 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

In reply to Andy Shevchenko
Quoted 6 lines · Andy Shevchenko
Quoted 3 lines · Samuel Thibault
Quoted 2 lines · Greg KH, on mer. 14 juin 2017 13:48:02 +0200, wrote:
Quoted 1 line · Samuel Thibault

Greg KH, on mer. 14 juin 2017 12:15:41 +0200, wrote:

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

And trying to have the kernel do the mapping based on strings like this is not ok, sorry.

So what is the solution? Users would find it completely crazy to have to provide major/minor numbers.

Shouldn't udev take care of major/minor and alike stuff in user space?

No, that's all handled by the kernel now, in devtmpfs.

The console stuff is odd though, but that is each driver defining the name for itself, major/minor does not apply. Also, a separate driver is not having to figure this all out. I wonder if we could just add a tty core function for this as it does know the name of everything that has been registered with it, right?

thanks,

greg k-h

#12 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

Hi,

Quoted 5 lines · Greg Kroah-Hartman

The console stuff is odd though, but that is each driver defining the name for itself, major/minor does not apply. Also, a separate driver is not having to figure this all out. I wonder if we could just add a tty core function for this as it does know the name of everything that has been registered with it, right?

I can start working on a patch for this. I'm still new to the tty code so will follow up with any questions I might have.

Thanks,
Okash

#3 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

In reply to Dan Carpenter

Hi,

On Wed, Jun 14, 2017 at 9:23 AM, Dan Carpenter <[email protected]> wrote:
[...]

Quoted 3 lines

Could you call it "dev_name" instead? I normally expect "dev" to be a device struct.

Thanks for the feedback. Will keep these in mind for next version of the patch.

Okash

#13 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

In reply to Okash Khawaja

Hi,

Quoted 9 lines · Okash Khawaja
Quoted 5 lines · Greg Kroah-Hartman

The console stuff is odd though, but that is each driver defining the name for itself, major/minor does not apply. Also, a separate driver is not having to figure this all out. I wonder if we could just add a tty core function for this as it does know the name of everything that has been registered with it, right?

I can start working on a patch for this. I'm still new to the tty code so will follow up with any questions I might have.

I've put together this function for converting device name to number. It traverses tty_drivers list looking for corresponding dev name and index. Is this the right approach?

Thanks,
Okash

---
 drivers/tty/tty_io.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/tty.h  |    4 ++++
 2 files changed, 49 insertions(+)
drivers/tty/tty_io.c +45 -0
@@ -325,6 +325,51 @@ static struct tty_driver *get_tty_driver
 	return NULL;
 }
 
+/**
+ *	tty_dev_name_to_number	-	return dev_t for device name
+ *	@device_name: user space name of device under /dev
+ *	@dev_no: pointer to dev_t that this function will populate
+ *
+ *	This function converts device names like ttyS0 or ttyUSB1 into dev_t
+ *	like (4, 64) or (188, 1). If no corresponding driver is registered then
+ *	the function returns -ENODEV.
+ *
+ *	Locking: this acquires tty_mutex
+ */
+int tty_dev_name_to_number(char *dev_name, dev_t *dev_no)
+{
+	struct tty_driver *p;
+	int rv, index, prefix_length = 0;
+
+	while (!isdigit(*(dev_name + prefix_length)) && prefix_length <
+			strlen(dev_name) )
+		prefix_length++;
+
+	if (prefix_length == strlen(dev_name))
+		return -EINVAL;
+
+	mutex_lock(&tty_mutex);
+
+	list_for_each_entry(p, &tty_drivers, tty_drivers)
+		if (prefix_length == strlen(p->name) && strncmp(dev_name,
+					p->name, prefix_length) == 0) {
+			rv = kstrtoint(dev_name + prefix_length, 10, &index);
+			if (rv) {
+				mutex_unlock(&tty_mutex);
+				return rv;
+			}
+			if (index < p->num) {
+				*dev_no = MKDEV(p->major, p->minor_start + index);
+				mutex_unlock(&tty_mutex);
+				return 0;
+			}
+		}
+
+	mutex_unlock(&tty_mutex);
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(tty_dev_name_to_number);
+
 #ifdef CONFIG_CONSOLE_POLL
 
 /**
include/linux/tty.h +4 -0
@@ -402,6 +402,7 @@ 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);
+extern int tty_dev_name_to_number(char *dev_name, dev_t *dev_no);
 #else
 static inline void tty_kref_put(struct tty_struct *tty)
 { }
@@ -422,6 +423,9 @@ static inline int __init tty_init(void)
 { return 0; }
 static inline const char *tty_name(const struct tty_struct *tty)
 { return "(none)"; }
+extern int tty_dev_name_to_number(char *dev_name, dev_t *dev_no)
+{ return -ENOTSUPP; }
+
 #endif
 
 extern struct ktermios tty_std_termios;
#14 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

Quoted 10 lines · Okash Khawaja

Hi,

Quoted 7 lines · Okash Khawaja
Quoted 5 lines · Greg Kroah-Hartman

The console stuff is odd though, but that is each driver defining the name for itself, major/minor does not apply. Also, a separate driver is not having to figure this all out. I wonder if we could just add a tty core function for this as it does know the name of everything that has been registered with it, right?

Quoted 6 lines
Quoted 2 lines

I can start working on a patch for this. I'm still new to the tty code so will follow up with any questions I might have.

I've put together this function for converting device name to number. It traverses tty_drivers list looking for corresponding dev name and index. Is this the right approach?

Yes, this looks great, nice job! It is a lot simpler than your previous function, and now you are not limited to just a subset off the different serial ports in the system.

Keep up the good work, it's really appreciated.

greg k-h

#15 lore raw

Re: [patch 1/2] staging: speakup: add function to convert dev name to number

Quoted 18 lines · Greg Kroah-Hartman
Quoted 10 lines · Okash Khawaja

Hi,

Quoted 7 lines · Okash Khawaja
Quoted 5 lines · Greg Kroah-Hartman

The console stuff is odd though, but that is each driver defining the name for itself, major/minor does not apply. Also, a separate driver is not having to figure this all out. I wonder if we could just add a tty core function for this as it does know the name of everything that has been registered with it, right?

Quoted 6 lines
Quoted 2 lines

I can start working on a patch for this. I'm still new to the tty code so will follow up with any questions I might have.

I've put together this function for converting device name to number. It traverses tty_drivers list looking for corresponding dev name and index. Is this the right approach?

Quoted 5 lines

Yes, this looks great, nice job! It is a lot simpler than your previous function, and now you are not limited to just a subset off the different serial ports in the system.

Keep up the good work, it's really appreciated.

Great, thanks. I'll re-send the full patch set as v2.

Okash