Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/types.h>
0003 #include <linux/ctype.h>    /* for isdigit() and friends */
0004 #include <linux/fs.h>
0005 #include <linux/mm.h>       /* for verify_area */
0006 #include <linux/errno.h>    /* for -EBUSY */
0007 #include <linux/ioport.h>   /* for check_region, request_region */
0008 #include <linux/interrupt.h>
0009 #include <linux/delay.h>    /* for loops_per_sec */
0010 #include <linux/kmod.h>
0011 #include <linux/jiffies.h>
0012 #include <linux/uaccess.h>  /* for copy_from_user */
0013 #include <linux/sched.h>
0014 #include <linux/timer.h>
0015 #include <linux/kthread.h>
0016 
0017 #include "spk_priv.h"
0018 #include "speakup.h"
0019 #include "serialio.h"
0020 
0021 static LIST_HEAD(synths);
0022 struct spk_synth *synth;
0023 char spk_pitch_buff[32] = "";
0024 static int module_status;
0025 bool spk_quiet_boot;
0026 
0027 struct speakup_info_t speakup_info = {
0028     /*
0029      * This spinlock is used to protect the entire speakup machinery, and
0030      * must be taken at each kernel->speakup transition and released at
0031      * each corresponding speakup->kernel transition.
0032      *
0033      * The progression thread only interferes with the speakup machinery
0034      * through the synth buffer, so only needs to take the lock
0035      * while tinkering with the buffer.
0036      *
0037      * We use spin_lock/trylock_irqsave and spin_unlock_irqrestore with this
0038      * spinlock because speakup needs to disable the keyboard IRQ.
0039      */
0040     .spinlock = __SPIN_LOCK_UNLOCKED(speakup_info.spinlock),
0041     .flushing = 0,
0042 };
0043 EXPORT_SYMBOL_GPL(speakup_info);
0044 
0045 static int do_synth_init(struct spk_synth *in_synth);
0046 
0047 /*
0048  * Main loop of the progression thread: keep eating from the buffer
0049  * and push to the serial port, waiting as needed
0050  *
0051  * For devices that have a "full" notification mechanism, the driver can
0052  * adapt the loop the way they prefer.
0053  */
0054 static void _spk_do_catch_up(struct spk_synth *synth, int unicode)
0055 {
0056     u16 ch;
0057     unsigned long flags;
0058     unsigned long jiff_max;
0059     struct var_t *delay_time;
0060     struct var_t *full_time;
0061     struct var_t *jiffy_delta;
0062     int jiffy_delta_val;
0063     int delay_time_val;
0064     int full_time_val;
0065     int ret;
0066 
0067     jiffy_delta = spk_get_var(JIFFY);
0068     full_time = spk_get_var(FULL);
0069     delay_time = spk_get_var(DELAY);
0070 
0071     spin_lock_irqsave(&speakup_info.spinlock, flags);
0072     jiffy_delta_val = jiffy_delta->u.n.value;
0073     spin_unlock_irqrestore(&speakup_info.spinlock, flags);
0074 
0075     jiff_max = jiffies + jiffy_delta_val;
0076     while (!kthread_should_stop()) {
0077         spin_lock_irqsave(&speakup_info.spinlock, flags);
0078         if (speakup_info.flushing) {
0079             speakup_info.flushing = 0;
0080             spin_unlock_irqrestore(&speakup_info.spinlock, flags);
0081             synth->flush(synth);
0082             continue;
0083         }
0084         if (!unicode)
0085             synth_buffer_skip_nonlatin1();
0086         if (synth_buffer_empty()) {
0087             spin_unlock_irqrestore(&speakup_info.spinlock, flags);
0088             break;
0089         }
0090         ch = synth_buffer_peek();
0091         set_current_state(TASK_INTERRUPTIBLE);
0092         full_time_val = full_time->u.n.value;
0093         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
0094         if (ch == '\n')
0095             ch = synth->procspeech;
0096         if (unicode)
0097             ret = synth->io_ops->synth_out_unicode(synth, ch);
0098         else
0099             ret = synth->io_ops->synth_out(synth, ch);
0100         if (!ret) {
0101             schedule_timeout(msecs_to_jiffies(full_time_val));
0102             continue;
0103         }
0104         if (time_after_eq(jiffies, jiff_max) && (ch == SPACE)) {
0105             spin_lock_irqsave(&speakup_info.spinlock, flags);
0106             jiffy_delta_val = jiffy_delta->u.n.value;
0107             delay_time_val = delay_time->u.n.value;
0108             full_time_val = full_time->u.n.value;
0109             spin_unlock_irqrestore(&speakup_info.spinlock, flags);
0110             if (synth->io_ops->synth_out(synth, synth->procspeech))
0111                 schedule_timeout(
0112                     msecs_to_jiffies(delay_time_val));
0113             else
0114                 schedule_timeout(
0115                     msecs_to_jiffies(full_time_val));
0116             jiff_max = jiffies + jiffy_delta_val;
0117         }
0118         set_current_state(TASK_RUNNING);
0119         spin_lock_irqsave(&speakup_info.spinlock, flags);
0120         synth_buffer_getc();
0121         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
0122     }
0123     synth->io_ops->synth_out(synth, synth->procspeech);
0124 }
0125 
0126 void spk_do_catch_up(struct spk_synth *synth)
0127 {
0128     _spk_do_catch_up(synth, 0);
0129 }
0130 EXPORT_SYMBOL_GPL(spk_do_catch_up);
0131 
0132 void spk_do_catch_up_unicode(struct spk_synth *synth)
0133 {
0134     _spk_do_catch_up(synth, 1);
0135 }
0136 EXPORT_SYMBOL_GPL(spk_do_catch_up_unicode);
0137 
0138 void spk_synth_flush(struct spk_synth *synth)
0139 {
0140     synth->io_ops->flush_buffer(synth);
0141     synth->io_ops->synth_out(synth, synth->clear);
0142 }
0143 EXPORT_SYMBOL_GPL(spk_synth_flush);
0144 
0145 unsigned char spk_synth_get_index(struct spk_synth *synth)
0146 {
0147     return synth->io_ops->synth_in_nowait(synth);
0148 }
0149 EXPORT_SYMBOL_GPL(spk_synth_get_index);
0150 
0151 int spk_synth_is_alive_nop(struct spk_synth *synth)
0152 {
0153     synth->alive = 1;
0154     return 1;
0155 }
0156 EXPORT_SYMBOL_GPL(spk_synth_is_alive_nop);
0157 
0158 int spk_synth_is_alive_restart(struct spk_synth *synth)
0159 {
0160     if (synth->alive)
0161         return 1;
0162     if (synth->io_ops->wait_for_xmitr(synth) > 0) {
0163         /* restart */
0164         synth->alive = 1;
0165         synth_printf("%s", synth->init);
0166         return 2; /* reenabled */
0167     }
0168     pr_warn("%s: can't restart synth\n", synth->long_name);
0169     return 0;
0170 }
0171 EXPORT_SYMBOL_GPL(spk_synth_is_alive_restart);
0172 
0173 static void thread_wake_up(struct timer_list *unused)
0174 {
0175     wake_up_interruptible_all(&speakup_event);
0176 }
0177 
0178 static DEFINE_TIMER(thread_timer, thread_wake_up);
0179 
0180 void synth_start(void)
0181 {
0182     struct var_t *trigger_time;
0183 
0184     if (!synth->alive) {
0185         synth_buffer_clear();
0186         return;
0187     }
0188     trigger_time = spk_get_var(TRIGGER);
0189     if (!timer_pending(&thread_timer))
0190         mod_timer(&thread_timer, jiffies +
0191             msecs_to_jiffies(trigger_time->u.n.value));
0192 }
0193 
0194 void spk_do_flush(void)
0195 {
0196     if (!synth)
0197         return;
0198 
0199     speakup_info.flushing = 1;
0200     synth_buffer_clear();
0201     if (synth->alive) {
0202         if (spk_pitch_shift) {
0203             synth_printf("%s", spk_pitch_buff);
0204             spk_pitch_shift = 0;
0205         }
0206     }
0207     wake_up_interruptible_all(&speakup_event);
0208     wake_up_process(speakup_task);
0209 }
0210 
0211 void synth_write(const char *buf, size_t count)
0212 {
0213     while (count--)
0214         synth_buffer_add(*buf++);
0215     synth_start();
0216 }
0217 
0218 void synth_printf(const char *fmt, ...)
0219 {
0220     va_list args;
0221     unsigned char buf[160], *p;
0222     int r;
0223 
0224     va_start(args, fmt);
0225     r = vsnprintf(buf, sizeof(buf), fmt, args);
0226     va_end(args);
0227     if (r > sizeof(buf) - 1)
0228         r = sizeof(buf) - 1;
0229 
0230     p = buf;
0231     while (r--)
0232         synth_buffer_add(*p++);
0233     synth_start();
0234 }
0235 EXPORT_SYMBOL_GPL(synth_printf);
0236 
0237 void synth_putwc(u16 wc)
0238 {
0239     synth_buffer_add(wc);
0240 }
0241 EXPORT_SYMBOL_GPL(synth_putwc);
0242 
0243 void synth_putwc_s(u16 wc)
0244 {
0245     synth_buffer_add(wc);
0246     synth_start();
0247 }
0248 EXPORT_SYMBOL_GPL(synth_putwc_s);
0249 
0250 void synth_putws(const u16 *buf)
0251 {
0252     const u16 *p;
0253 
0254     for (p = buf; *p; p++)
0255         synth_buffer_add(*p);
0256 }
0257 EXPORT_SYMBOL_GPL(synth_putws);
0258 
0259 void synth_putws_s(const u16 *buf)
0260 {
0261     synth_putws(buf);
0262     synth_start();
0263 }
0264 EXPORT_SYMBOL_GPL(synth_putws_s);
0265 
0266 static int index_count;
0267 static int sentence_count;
0268 
0269 void spk_reset_index_count(int sc)
0270 {
0271     static int first = 1;
0272 
0273     if (first)
0274         first = 0;
0275     else
0276         synth->get_index(synth);
0277     index_count = 0;
0278     sentence_count = sc;
0279 }
0280 
0281 int synth_supports_indexing(void)
0282 {
0283     if (synth->get_index)
0284         return 1;
0285     return 0;
0286 }
0287 
0288 void synth_insert_next_index(int sent_num)
0289 {
0290     int out;
0291 
0292     if (synth->alive) {
0293         if (sent_num == 0) {
0294             synth->indexing.currindex++;
0295             index_count++;
0296             if (synth->indexing.currindex >
0297                     synth->indexing.highindex)
0298                 synth->indexing.currindex =
0299                     synth->indexing.lowindex;
0300         }
0301 
0302         out = synth->indexing.currindex * 10 + sent_num;
0303         synth_printf(synth->indexing.command, out, out);
0304     }
0305 }
0306 
0307 void spk_get_index_count(int *linecount, int *sentcount)
0308 {
0309     int ind = synth->get_index(synth);
0310 
0311     if (ind) {
0312         sentence_count = ind % 10;
0313 
0314         if ((ind / 10) <= synth->indexing.currindex)
0315             index_count = synth->indexing.currindex - (ind / 10);
0316         else
0317             index_count = synth->indexing.currindex
0318                 - synth->indexing.lowindex
0319                 + synth->indexing.highindex - (ind / 10) + 1;
0320     }
0321     *sentcount = sentence_count;
0322     *linecount = index_count;
0323 }
0324 
0325 static struct resource synth_res;
0326 
0327 int synth_request_region(unsigned long start, unsigned long n)
0328 {
0329     struct resource *parent = &ioport_resource;
0330 
0331     memset(&synth_res, 0, sizeof(synth_res));
0332     synth_res.name = synth->name;
0333     synth_res.start = start;
0334     synth_res.end = start + n - 1;
0335     synth_res.flags = IORESOURCE_BUSY;
0336     return request_resource(parent, &synth_res);
0337 }
0338 EXPORT_SYMBOL_GPL(synth_request_region);
0339 
0340 int synth_release_region(unsigned long start, unsigned long n)
0341 {
0342     return release_resource(&synth_res);
0343 }
0344 EXPORT_SYMBOL_GPL(synth_release_region);
0345 
0346 struct var_t synth_time_vars[] = {
0347     { DELAY, .u.n = {NULL, 100, 100, 2000, 0, 0, NULL } },
0348     { TRIGGER, .u.n = {NULL, 20, 10, 2000, 0, 0, NULL } },
0349     { JIFFY, .u.n = {NULL, 50, 20, 200, 0, 0, NULL } },
0350     { FULL, .u.n = {NULL, 400, 200, 60000, 0, 0, NULL } },
0351     { FLUSH, .u.n = {NULL, 4000, 10, 4000, 0, 0, NULL } },
0352     V_LAST_VAR
0353 };
0354 
0355 /* called by: speakup_init() */
0356 int synth_init(char *synth_name)
0357 {
0358     int ret = 0;
0359     struct spk_synth *tmp, *synth = NULL;
0360 
0361     if (!synth_name)
0362         return 0;
0363 
0364     if (strcmp(synth_name, "none") == 0) {
0365         mutex_lock(&spk_mutex);
0366         synth_release();
0367         mutex_unlock(&spk_mutex);
0368         return 0;
0369     }
0370 
0371     mutex_lock(&spk_mutex);
0372     /* First, check if we already have it loaded. */
0373     list_for_each_entry(tmp, &synths, node) {
0374         if (strcmp(tmp->name, synth_name) == 0)
0375             synth = tmp;
0376     }
0377 
0378     /* If we got one, initialize it now. */
0379     if (synth)
0380         ret = do_synth_init(synth);
0381     else
0382         ret = -ENODEV;
0383     mutex_unlock(&spk_mutex);
0384 
0385     return ret;
0386 }
0387 
0388 /* called by: synth_add() */
0389 static int do_synth_init(struct spk_synth *in_synth)
0390 {
0391     struct var_t *var;
0392 
0393     synth_release();
0394     if (in_synth->checkval != SYNTH_CHECK)
0395         return -EINVAL;
0396     synth = in_synth;
0397     synth->alive = 0;
0398     pr_warn("synth probe\n");
0399     if (synth->probe(synth) < 0) {
0400         pr_warn("%s: device probe failed\n", in_synth->name);
0401         synth = NULL;
0402         return -ENODEV;
0403     }
0404     synth_time_vars[0].u.n.value =
0405         synth_time_vars[0].u.n.default_val = synth->delay;
0406     synth_time_vars[1].u.n.value =
0407         synth_time_vars[1].u.n.default_val = synth->trigger;
0408     synth_time_vars[2].u.n.value =
0409         synth_time_vars[2].u.n.default_val = synth->jiffies;
0410     synth_time_vars[3].u.n.value =
0411         synth_time_vars[3].u.n.default_val = synth->full;
0412     synth_time_vars[4].u.n.value =
0413         synth_time_vars[4].u.n.default_val = synth->flush_time;
0414     synth_printf("%s", synth->init);
0415     for (var = synth->vars;
0416         (var->var_id >= 0) && (var->var_id < MAXVARS); var++)
0417         speakup_register_var(var);
0418     if (!spk_quiet_boot)
0419         synth_printf("%s found\n", synth->long_name);
0420     if (synth->attributes.name &&
0421         sysfs_create_group(speakup_kobj, &synth->attributes) < 0)
0422         return -ENOMEM;
0423     synth_flags = synth->flags;
0424     wake_up_interruptible_all(&speakup_event);
0425     if (speakup_task)
0426         wake_up_process(speakup_task);
0427     return 0;
0428 }
0429 
0430 void synth_release(void)
0431 {
0432     struct var_t *var;
0433     unsigned long flags;
0434 
0435     if (!synth)
0436         return;
0437     spin_lock_irqsave(&speakup_info.spinlock, flags);
0438     pr_info("releasing synth %s\n", synth->name);
0439     synth->alive = 0;
0440     del_timer(&thread_timer);
0441     spin_unlock_irqrestore(&speakup_info.spinlock, flags);
0442     if (synth->attributes.name)
0443         sysfs_remove_group(speakup_kobj, &synth->attributes);
0444     for (var = synth->vars; var->var_id != MAXVARS; var++)
0445         speakup_unregister_var(var->var_id);
0446     synth->release(synth);
0447     synth = NULL;
0448 }
0449 
0450 /* called by: all_driver_init() */
0451 int synth_add(struct spk_synth *in_synth)
0452 {
0453     int status = 0;
0454     struct spk_synth *tmp;
0455 
0456     mutex_lock(&spk_mutex);
0457 
0458     list_for_each_entry(tmp, &synths, node) {
0459         if (tmp == in_synth) {
0460             mutex_unlock(&spk_mutex);
0461             return 0;
0462         }
0463     }
0464 
0465     if (in_synth->startup)
0466         status = do_synth_init(in_synth);
0467 
0468     if (!status)
0469         list_add_tail(&in_synth->node, &synths);
0470 
0471     mutex_unlock(&spk_mutex);
0472     return status;
0473 }
0474 EXPORT_SYMBOL_GPL(synth_add);
0475 
0476 void synth_remove(struct spk_synth *in_synth)
0477 {
0478     mutex_lock(&spk_mutex);
0479     if (synth == in_synth)
0480         synth_release();
0481     list_del(&in_synth->node);
0482     module_status = 0;
0483     mutex_unlock(&spk_mutex);
0484 }
0485 EXPORT_SYMBOL_GPL(synth_remove);
0486 
0487 struct spk_synth *synth_current(void)
0488 {
0489     return synth;
0490 }
0491 EXPORT_SYMBOL_GPL(synth_current);
0492 
0493 short spk_punc_masks[] = { 0, SOME, MOST, PUNC, PUNC | B_SYM };