0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/unistd.h>
0013 #include <linux/proc_fs.h>
0014 #include <linux/jiffies.h>
0015 #include <linux/spinlock.h>
0016 #include <linux/sched.h>
0017 #include <linux/timer.h>
0018 #include <linux/kthread.h>
0019 #include "speakup.h"
0020 #include "spk_priv.h"
0021
0022 #define DRV_VERSION "2.20"
0023 #define SYNTH_CLEAR 0x03
0024 #define PROCSPEECH 0x0b
0025 static int xoff;
0026
0027 static inline int synth_full(void)
0028 {
0029 return xoff;
0030 }
0031
0032 static void do_catch_up(struct spk_synth *synth);
0033 static void synth_flush(struct spk_synth *synth);
0034 static void read_buff_add(u_char c);
0035 static unsigned char get_index(struct spk_synth *synth);
0036
0037 static int in_escape;
0038 static int is_flushing;
0039
0040 static DEFINE_SPINLOCK(flush_lock);
0041 static DECLARE_WAIT_QUEUE_HEAD(flush);
0042
0043 static struct var_t vars[] = {
0044 { CAPS_START, .u.s = {"[:dv ap 160] " } },
0045 { CAPS_STOP, .u.s = {"[:dv ap 100 ] " } },
0046 { RATE, .u.n = {"[:ra %d] ", 180, 75, 650, 0, 0, NULL } },
0047 { PITCH, .u.n = {"[:dv ap %d] ", 122, 50, 350, 0, 0, NULL } },
0048 { INFLECTION, .u.n = {"[:dv pr %d] ", 100, 0, 10000, 0, 0, NULL } },
0049 { VOL, .u.n = {"[:dv g5 %d] ", 86, 60, 86, 0, 0, NULL } },
0050 { PUNCT, .u.n = {"[:pu %c] ", 0, 0, 2, 0, 0, "nsa" } },
0051 { VOICE, .u.n = {"[:n%c] ", 0, 0, 9, 0, 0, "phfdburwkv" } },
0052 { DIRECT, .u.n = {NULL, 0, 0, 1, 0, 0, NULL } },
0053 V_LAST_VAR
0054 };
0055
0056
0057
0058
0059 static struct kobj_attribute caps_start_attribute =
0060 __ATTR(caps_start, 0644, spk_var_show, spk_var_store);
0061 static struct kobj_attribute caps_stop_attribute =
0062 __ATTR(caps_stop, 0644, spk_var_show, spk_var_store);
0063 static struct kobj_attribute pitch_attribute =
0064 __ATTR(pitch, 0644, spk_var_show, spk_var_store);
0065 static struct kobj_attribute inflection_attribute =
0066 __ATTR(inflection, 0644, spk_var_show, spk_var_store);
0067 static struct kobj_attribute punct_attribute =
0068 __ATTR(punct, 0644, spk_var_show, spk_var_store);
0069 static struct kobj_attribute rate_attribute =
0070 __ATTR(rate, 0644, spk_var_show, spk_var_store);
0071 static struct kobj_attribute voice_attribute =
0072 __ATTR(voice, 0644, spk_var_show, spk_var_store);
0073 static struct kobj_attribute vol_attribute =
0074 __ATTR(vol, 0644, spk_var_show, spk_var_store);
0075
0076 static struct kobj_attribute delay_time_attribute =
0077 __ATTR(delay_time, 0644, spk_var_show, spk_var_store);
0078 static struct kobj_attribute direct_attribute =
0079 __ATTR(direct, 0644, spk_var_show, spk_var_store);
0080 static struct kobj_attribute full_time_attribute =
0081 __ATTR(full_time, 0644, spk_var_show, spk_var_store);
0082 static struct kobj_attribute flush_time_attribute =
0083 __ATTR(flush_time, 0644, spk_var_show, spk_var_store);
0084 static struct kobj_attribute jiffy_delta_attribute =
0085 __ATTR(jiffy_delta, 0644, spk_var_show, spk_var_store);
0086 static struct kobj_attribute trigger_time_attribute =
0087 __ATTR(trigger_time, 0644, spk_var_show, spk_var_store);
0088
0089
0090
0091
0092
0093 static struct attribute *synth_attrs[] = {
0094 &caps_start_attribute.attr,
0095 &caps_stop_attribute.attr,
0096 &pitch_attribute.attr,
0097 &inflection_attribute.attr,
0098 &punct_attribute.attr,
0099 &rate_attribute.attr,
0100 &voice_attribute.attr,
0101 &vol_attribute.attr,
0102 &delay_time_attribute.attr,
0103 &direct_attribute.attr,
0104 &full_time_attribute.attr,
0105 &flush_time_attribute.attr,
0106 &jiffy_delta_attribute.attr,
0107 &trigger_time_attribute.attr,
0108 NULL,
0109 };
0110
0111 static int ap_defaults[] = {122, 89, 155, 110, 208, 240, 200, 106, 306};
0112 static int g5_defaults[] = {86, 81, 86, 84, 81, 80, 83, 83, 73};
0113
0114 static struct spk_synth synth_dectlk = {
0115 .name = "dectlk",
0116 .version = DRV_VERSION,
0117 .long_name = "Dectalk Express",
0118 .init = "[:error sp :name paul :rate 180 :tsr off] ",
0119 .procspeech = PROCSPEECH,
0120 .clear = SYNTH_CLEAR,
0121 .delay = 500,
0122 .trigger = 50,
0123 .jiffies = 50,
0124 .full = 40000,
0125 .flush_time = 4000,
0126 .dev_name = SYNTH_DEFAULT_DEV,
0127 .startup = SYNTH_START,
0128 .checkval = SYNTH_CHECK,
0129 .vars = vars,
0130 .default_pitch = ap_defaults,
0131 .default_vol = g5_defaults,
0132 .io_ops = &spk_ttyio_ops,
0133 .probe = spk_ttyio_synth_probe,
0134 .release = spk_ttyio_release,
0135 .synth_immediate = spk_ttyio_synth_immediate,
0136 .catch_up = do_catch_up,
0137 .flush = synth_flush,
0138 .is_alive = spk_synth_is_alive_restart,
0139 .synth_adjust = NULL,
0140 .read_buff_add = read_buff_add,
0141 .get_index = get_index,
0142 .indexing = {
0143 .command = "[:in re %d ] ",
0144 .lowindex = 1,
0145 .highindex = 8,
0146 .currindex = 1,
0147 },
0148 .attributes = {
0149 .attrs = synth_attrs,
0150 .name = "dectlk",
0151 },
0152 };
0153
0154 static int is_indnum(u_char *ch)
0155 {
0156 if ((*ch >= '0') && (*ch <= '9')) {
0157 *ch = *ch - '0';
0158 return 1;
0159 }
0160 return 0;
0161 }
0162
0163 static u_char lastind;
0164
0165 static unsigned char get_index(struct spk_synth *synth)
0166 {
0167 u_char rv;
0168
0169 rv = lastind;
0170 lastind = 0;
0171 return rv;
0172 }
0173
0174 static void read_buff_add(u_char c)
0175 {
0176 static int ind = -1;
0177
0178 if (c == 0x01) {
0179 unsigned long flags;
0180
0181 spin_lock_irqsave(&flush_lock, flags);
0182 is_flushing = 0;
0183 wake_up_interruptible(&flush);
0184 spin_unlock_irqrestore(&flush_lock, flags);
0185 } else if (c == 0x13) {
0186 xoff = 1;
0187 } else if (c == 0x11) {
0188 xoff = 0;
0189 } else if (is_indnum(&c)) {
0190 if (ind == -1)
0191 ind = c;
0192 else
0193 ind = ind * 10 + c;
0194 } else if ((c > 31) && (c < 127)) {
0195 if (ind != -1)
0196 lastind = (u_char)ind;
0197 ind = -1;
0198 }
0199 }
0200
0201 static void do_catch_up(struct spk_synth *synth)
0202 {
0203 int synth_full_val = 0;
0204 static u_char ch;
0205 static u_char last = '\0';
0206 unsigned long flags;
0207 unsigned long jiff_max;
0208 unsigned long timeout;
0209 DEFINE_WAIT(wait);
0210 struct var_t *jiffy_delta;
0211 struct var_t *delay_time;
0212 struct var_t *flush_time;
0213 int jiffy_delta_val;
0214 int delay_time_val;
0215 int timeout_val;
0216
0217 jiffy_delta = spk_get_var(JIFFY);
0218 delay_time = spk_get_var(DELAY);
0219 flush_time = spk_get_var(FLUSH);
0220 spin_lock_irqsave(&speakup_info.spinlock, flags);
0221 jiffy_delta_val = jiffy_delta->u.n.value;
0222 timeout_val = flush_time->u.n.value;
0223 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
0224 timeout = msecs_to_jiffies(timeout_val);
0225 jiff_max = jiffies + jiffy_delta_val;
0226
0227 while (!kthread_should_stop()) {
0228
0229 spin_lock_irqsave(&flush_lock, flags);
0230 while (is_flushing && timeout) {
0231 prepare_to_wait(&flush, &wait, TASK_INTERRUPTIBLE);
0232 spin_unlock_irqrestore(&flush_lock, flags);
0233 timeout = schedule_timeout(timeout);
0234 spin_lock_irqsave(&flush_lock, flags);
0235 }
0236 finish_wait(&flush, &wait);
0237 is_flushing = 0;
0238 spin_unlock_irqrestore(&flush_lock, flags);
0239
0240 spin_lock_irqsave(&speakup_info.spinlock, flags);
0241 if (speakup_info.flushing) {
0242 speakup_info.flushing = 0;
0243 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
0244 synth->flush(synth);
0245 continue;
0246 }
0247 synth_buffer_skip_nonlatin1();
0248 if (synth_buffer_empty()) {
0249 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
0250 break;
0251 }
0252 ch = synth_buffer_peek();
0253 set_current_state(TASK_INTERRUPTIBLE);
0254 delay_time_val = delay_time->u.n.value;
0255 synth_full_val = synth_full();
0256 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
0257 if (ch == '\n')
0258 ch = 0x0D;
0259 if (synth_full_val || !synth->io_ops->synth_out(synth, ch)) {
0260 schedule_timeout(msecs_to_jiffies(delay_time_val));
0261 continue;
0262 }
0263 set_current_state(TASK_RUNNING);
0264 spin_lock_irqsave(&speakup_info.spinlock, flags);
0265 synth_buffer_getc();
0266 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
0267 if (ch == '[') {
0268 in_escape = 1;
0269 } else if (ch == ']') {
0270 in_escape = 0;
0271 } else if (ch <= SPACE) {
0272 if (!in_escape && strchr(",.!?;:", last))
0273 synth->io_ops->synth_out(synth, PROCSPEECH);
0274 if (time_after_eq(jiffies, jiff_max)) {
0275 if (!in_escape)
0276 synth->io_ops->synth_out(synth,
0277 PROCSPEECH);
0278 spin_lock_irqsave(&speakup_info.spinlock,
0279 flags);
0280 jiffy_delta_val = jiffy_delta->u.n.value;
0281 delay_time_val = delay_time->u.n.value;
0282 spin_unlock_irqrestore(&speakup_info.spinlock,
0283 flags);
0284 schedule_timeout(msecs_to_jiffies
0285 (delay_time_val));
0286 jiff_max = jiffies + jiffy_delta_val;
0287 }
0288 }
0289 last = ch;
0290 }
0291 if (!in_escape)
0292 synth->io_ops->synth_out(synth, PROCSPEECH);
0293 }
0294
0295 static void synth_flush(struct spk_synth *synth)
0296 {
0297 if (in_escape)
0298
0299 synth->io_ops->synth_out(synth, ']');
0300 in_escape = 0;
0301 is_flushing = 1;
0302 synth->io_ops->flush_buffer(synth);
0303 synth->io_ops->synth_out(synth, SYNTH_CLEAR);
0304 }
0305
0306 module_param_named(ser, synth_dectlk.ser, int, 0444);
0307 module_param_named(dev, synth_dectlk.dev_name, charp, 0444);
0308 module_param_named(start, synth_dectlk.startup, short, 0444);
0309
0310 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
0311 MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
0312 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
0313
0314 module_spk_synth(synth_dectlk);
0315
0316 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
0317 MODULE_AUTHOR("David Borowski");
0318 MODULE_DESCRIPTION("Speakup support for DECtalk Express synthesizers");
0319 MODULE_LICENSE("GPL");
0320 MODULE_VERSION(DRV_VERSION);
0321