Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/types.h>
0003 #include <linux/tty.h>
0004 #include <linux/tty_flip.h>
0005 #include <linux/slab.h>
0006 
0007 #include "speakup.h"
0008 #include "spk_types.h"
0009 #include "spk_priv.h"
0010 
0011 struct spk_ldisc_data {
0012     char buf;
0013     struct completion completion;
0014     bool buf_free;
0015     struct spk_synth *synth;
0016 };
0017 
0018 /*
0019  * This allows to catch within spk_ttyio_ldisc_open whether it is getting set
0020  * on for a speakup-driven device.
0021  */
0022 static struct tty_struct *speakup_tty;
0023 /* This mutex serializes the use of such global speakup_tty variable */
0024 static DEFINE_MUTEX(speakup_tty_mutex);
0025 
0026 static int ser_to_dev(int ser, dev_t *dev_no)
0027 {
0028     if (ser < 0 || ser > (255 - 64)) {
0029         pr_err("speakup: Invalid ser param. Must be between 0 and 191 inclusive.\n");
0030         return -EINVAL;
0031     }
0032 
0033     *dev_no = MKDEV(4, (64 + ser));
0034     return 0;
0035 }
0036 
0037 static int get_dev_to_use(struct spk_synth *synth, dev_t *dev_no)
0038 {
0039     /* use ser only when dev is not specified */
0040     if (strcmp(synth->dev_name, SYNTH_DEFAULT_DEV) ||
0041         synth->ser == SYNTH_DEFAULT_SER)
0042         return tty_dev_name_to_number(synth->dev_name, dev_no);
0043 
0044     return ser_to_dev(synth->ser, dev_no);
0045 }
0046 
0047 static int spk_ttyio_ldisc_open(struct tty_struct *tty)
0048 {
0049     struct spk_ldisc_data *ldisc_data;
0050 
0051     if (tty != speakup_tty)
0052         /* Somebody tried to use this line discipline outside speakup */
0053         return -ENODEV;
0054 
0055     if (!tty->ops->write)
0056         return -EOPNOTSUPP;
0057 
0058     ldisc_data = kmalloc(sizeof(*ldisc_data), GFP_KERNEL);
0059     if (!ldisc_data)
0060         return -ENOMEM;
0061 
0062     init_completion(&ldisc_data->completion);
0063     ldisc_data->buf_free = true;
0064     tty->disc_data = ldisc_data;
0065 
0066     return 0;
0067 }
0068 
0069 static void spk_ttyio_ldisc_close(struct tty_struct *tty)
0070 {
0071     kfree(tty->disc_data);
0072 }
0073 
0074 static int spk_ttyio_receive_buf2(struct tty_struct *tty,
0075                   const unsigned char *cp,
0076                   const char *fp, int count)
0077 {
0078     struct spk_ldisc_data *ldisc_data = tty->disc_data;
0079     struct spk_synth *synth = ldisc_data->synth;
0080 
0081     if (synth->read_buff_add) {
0082         int i;
0083 
0084         for (i = 0; i < count; i++)
0085             synth->read_buff_add(cp[i]);
0086 
0087         return count;
0088     }
0089 
0090     if (!ldisc_data->buf_free)
0091         /* ttyio_in will tty_flip_buffer_push */
0092         return 0;
0093 
0094     /* Make sure the consumer has read buf before we have seen
0095      * buf_free == true and overwrite buf
0096      */
0097     mb();
0098 
0099     ldisc_data->buf = cp[0];
0100     ldisc_data->buf_free = false;
0101     complete(&ldisc_data->completion);
0102 
0103     return 1;
0104 }
0105 
0106 static struct tty_ldisc_ops spk_ttyio_ldisc_ops = {
0107     .owner          = THIS_MODULE,
0108     .num        = N_SPEAKUP,
0109     .name           = "speakup_ldisc",
0110     .open           = spk_ttyio_ldisc_open,
0111     .close          = spk_ttyio_ldisc_close,
0112     .receive_buf2   = spk_ttyio_receive_buf2,
0113 };
0114 
0115 static int spk_ttyio_out(struct spk_synth *in_synth, const char ch);
0116 static int spk_ttyio_out_unicode(struct spk_synth *in_synth, u16 ch);
0117 static void spk_ttyio_send_xchar(struct spk_synth *in_synth, char ch);
0118 static void spk_ttyio_tiocmset(struct spk_synth *in_synth, unsigned int set, unsigned int clear);
0119 static unsigned char spk_ttyio_in(struct spk_synth *in_synth);
0120 static unsigned char spk_ttyio_in_nowait(struct spk_synth *in_synth);
0121 static void spk_ttyio_flush_buffer(struct spk_synth *in_synth);
0122 static int spk_ttyio_wait_for_xmitr(struct spk_synth *in_synth);
0123 
0124 struct spk_io_ops spk_ttyio_ops = {
0125     .synth_out = spk_ttyio_out,
0126     .synth_out_unicode = spk_ttyio_out_unicode,
0127     .send_xchar = spk_ttyio_send_xchar,
0128     .tiocmset = spk_ttyio_tiocmset,
0129     .synth_in = spk_ttyio_in,
0130     .synth_in_nowait = spk_ttyio_in_nowait,
0131     .flush_buffer = spk_ttyio_flush_buffer,
0132     .wait_for_xmitr = spk_ttyio_wait_for_xmitr,
0133 };
0134 EXPORT_SYMBOL_GPL(spk_ttyio_ops);
0135 
0136 static inline void get_termios(struct tty_struct *tty,
0137                    struct ktermios *out_termios)
0138 {
0139     down_read(&tty->termios_rwsem);
0140     *out_termios = tty->termios;
0141     up_read(&tty->termios_rwsem);
0142 }
0143 
0144 static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
0145 {
0146     int ret = 0;
0147     struct tty_struct *tty;
0148     struct ktermios tmp_termios;
0149     dev_t dev;
0150 
0151     ret = get_dev_to_use(synth, &dev);
0152     if (ret)
0153         return ret;
0154 
0155     tty = tty_kopen_exclusive(dev);
0156     if (IS_ERR(tty))
0157         return PTR_ERR(tty);
0158 
0159     if (tty->ops->open)
0160         ret = tty->ops->open(tty, NULL);
0161     else
0162         ret = -ENODEV;
0163 
0164     if (ret) {
0165         tty_unlock(tty);
0166         return ret;
0167     }
0168 
0169     clear_bit(TTY_HUPPED, &tty->flags);
0170     /* ensure hardware flow control is enabled */
0171     get_termios(tty, &tmp_termios);
0172     if (!(tmp_termios.c_cflag & CRTSCTS)) {
0173         tmp_termios.c_cflag |= CRTSCTS;
0174         tty_set_termios(tty, &tmp_termios);
0175         /*
0176          * check c_cflag to see if it's updated as tty_set_termios
0177          * may not return error even when no tty bits are
0178          * changed by the request.
0179          */
0180         get_termios(tty, &tmp_termios);
0181         if (!(tmp_termios.c_cflag & CRTSCTS))
0182             pr_warn("speakup: Failed to set hardware flow control\n");
0183     }
0184 
0185     tty_unlock(tty);
0186 
0187     mutex_lock(&speakup_tty_mutex);
0188     speakup_tty = tty;
0189     ret = tty_set_ldisc(tty, N_SPEAKUP);
0190     speakup_tty = NULL;
0191     mutex_unlock(&speakup_tty_mutex);
0192 
0193     if (!ret) {
0194         /* Success */
0195         struct spk_ldisc_data *ldisc_data = tty->disc_data;
0196 
0197         ldisc_data->synth = synth;
0198         synth->dev = tty;
0199         return 0;
0200     }
0201 
0202     pr_err("speakup: Failed to set N_SPEAKUP on tty\n");
0203 
0204     tty_lock(tty);
0205     if (tty->ops->close)
0206         tty->ops->close(tty, NULL);
0207     tty_unlock(tty);
0208 
0209     tty_kclose(tty);
0210 
0211     return ret;
0212 }
0213 
0214 void spk_ttyio_register_ldisc(void)
0215 {
0216     if (tty_register_ldisc(&spk_ttyio_ldisc_ops))
0217         pr_warn("speakup: Error registering line discipline. Most synths won't work.\n");
0218 }
0219 
0220 void spk_ttyio_unregister_ldisc(void)
0221 {
0222     tty_unregister_ldisc(&spk_ttyio_ldisc_ops);
0223 }
0224 
0225 static int spk_ttyio_out(struct spk_synth *in_synth, const char ch)
0226 {
0227     struct tty_struct *tty = in_synth->dev;
0228     int ret;
0229 
0230     if (!in_synth->alive || !tty->ops->write)
0231         return 0;
0232 
0233     ret = tty->ops->write(tty, &ch, 1);
0234 
0235     if (ret == 0)
0236         /* No room */
0237         return 0;
0238 
0239     if (ret > 0)
0240         /* Success */
0241         return 1;
0242 
0243     pr_warn("%s: I/O error, deactivating speakup\n",
0244         in_synth->long_name);
0245     /* No synth any more, so nobody will restart TTYs,
0246      * and we thus need to do it ourselves.  Now that there
0247      * is no synth we can let application flood anyway
0248      */
0249     in_synth->alive = 0;
0250     speakup_start_ttys();
0251     return 0;
0252 }
0253 
0254 static int spk_ttyio_out_unicode(struct spk_synth *in_synth, u16 ch)
0255 {
0256     int ret;
0257 
0258     if (ch < 0x80) {
0259         ret = spk_ttyio_out(in_synth, ch);
0260     } else if (ch < 0x800) {
0261         ret  = spk_ttyio_out(in_synth, 0xc0 | (ch >> 6));
0262         ret &= spk_ttyio_out(in_synth, 0x80 | (ch & 0x3f));
0263     } else {
0264         ret  = spk_ttyio_out(in_synth, 0xe0 | (ch >> 12));
0265         ret &= spk_ttyio_out(in_synth, 0x80 | ((ch >> 6) & 0x3f));
0266         ret &= spk_ttyio_out(in_synth, 0x80 | (ch & 0x3f));
0267     }
0268     return ret;
0269 }
0270 
0271 static void spk_ttyio_send_xchar(struct spk_synth *in_synth, char ch)
0272 {
0273     struct tty_struct *tty = in_synth->dev;
0274 
0275     if (tty->ops->send_xchar)
0276         tty->ops->send_xchar(tty, ch);
0277 }
0278 
0279 static void spk_ttyio_tiocmset(struct spk_synth *in_synth, unsigned int set, unsigned int clear)
0280 {
0281     struct tty_struct *tty = in_synth->dev;
0282 
0283     if (tty->ops->tiocmset)
0284         tty->ops->tiocmset(tty, set, clear);
0285 }
0286 
0287 static int spk_ttyio_wait_for_xmitr(struct spk_synth *in_synth)
0288 {
0289     return 1;
0290 }
0291 
0292 static unsigned char ttyio_in(struct spk_synth *in_synth, int timeout)
0293 {
0294     struct tty_struct *tty = in_synth->dev;
0295     struct spk_ldisc_data *ldisc_data = tty->disc_data;
0296     char rv;
0297 
0298     if (!timeout) {
0299         if (!try_wait_for_completion(&ldisc_data->completion))
0300             return 0xff;
0301     } else if (wait_for_completion_timeout(&ldisc_data->completion,
0302                     usecs_to_jiffies(timeout)) == 0) {
0303         pr_warn("spk_ttyio: timeout (%d)  while waiting for input\n",
0304             timeout);
0305         return 0xff;
0306     }
0307 
0308     rv = ldisc_data->buf;
0309     /* Make sure we have read buf before we set buf_free to let
0310      * the producer overwrite it
0311      */
0312     mb();
0313     ldisc_data->buf_free = true;
0314     /* Let TTY push more characters */
0315     tty_flip_buffer_push(tty->port);
0316 
0317     return rv;
0318 }
0319 
0320 static unsigned char spk_ttyio_in(struct spk_synth *in_synth)
0321 {
0322     return ttyio_in(in_synth, SPK_SYNTH_TIMEOUT);
0323 }
0324 
0325 static unsigned char spk_ttyio_in_nowait(struct spk_synth *in_synth)
0326 {
0327     u8 rv = ttyio_in(in_synth, 0);
0328 
0329     return (rv == 0xff) ? 0 : rv;
0330 }
0331 
0332 static void spk_ttyio_flush_buffer(struct spk_synth *in_synth)
0333 {
0334     struct tty_struct *tty = in_synth->dev;
0335 
0336     if (tty->ops->flush_buffer)
0337         tty->ops->flush_buffer(tty);
0338 }
0339 
0340 int spk_ttyio_synth_probe(struct spk_synth *synth)
0341 {
0342     int rv = spk_ttyio_initialise_ldisc(synth);
0343 
0344     if (rv)
0345         return rv;
0346 
0347     synth->alive = 1;
0348 
0349     return 0;
0350 }
0351 EXPORT_SYMBOL_GPL(spk_ttyio_synth_probe);
0352 
0353 void spk_ttyio_release(struct spk_synth *in_synth)
0354 {
0355     struct tty_struct *tty = in_synth->dev;
0356 
0357     tty_lock(tty);
0358 
0359     if (tty->ops->close)
0360         tty->ops->close(tty, NULL);
0361 
0362     tty_ldisc_flush(tty);
0363     tty_unlock(tty);
0364     tty_kclose(tty);
0365 
0366     in_synth->dev = NULL;
0367 }
0368 EXPORT_SYMBOL_GPL(spk_ttyio_release);
0369 
0370 const char *spk_ttyio_synth_immediate(struct spk_synth *in_synth, const char *buff)
0371 {
0372     struct tty_struct *tty = in_synth->dev;
0373     u_char ch;
0374 
0375     while ((ch = *buff)) {
0376         if (ch == '\n')
0377             ch = in_synth->procspeech;
0378         if (tty_write_room(tty) < 1 ||
0379             !in_synth->io_ops->synth_out(in_synth, ch))
0380             return buff;
0381         buff++;
0382     }
0383     return NULL;
0384 }
0385 EXPORT_SYMBOL_GPL(spk_ttyio_synth_immediate);