speakup_dectlk.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. * originally written by: Kirk Reiser <kirk@braille.uwo.ca>
  3. * this version considerably modified by David Borowski, david575@rogers.com
  4. *
  5. * Copyright (C) 1998-99 Kirk Reiser.
  6. * Copyright (C) 2003 David Borowski.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. *
  22. * specificly written as a driver for the speakup screenreview
  23. * s not a general device driver.
  24. */
  25. #include <linux/unistd.h>
  26. #include <linux/proc_fs.h>
  27. #include <linux/jiffies.h>
  28. #include <linux/spinlock.h>
  29. #include <linux/sched.h>
  30. #include <linux/timer.h>
  31. #include <linux/kthread.h>
  32. #include "speakup.h"
  33. #include "spk_priv.h"
  34. #include "serialio.h"
  35. #define DRV_VERSION "2.20"
  36. #define SYNTH_CLEAR 0x03
  37. #define PROCSPEECH 0x0b
  38. static int xoff;
  39. static inline int synth_full(void)
  40. {
  41. return xoff;
  42. }
  43. static void do_catch_up(struct spk_synth *synth);
  44. static void synth_flush(struct spk_synth *synth);
  45. static void read_buff_add(u_char c);
  46. static unsigned char get_index(void);
  47. static int in_escape;
  48. static int is_flushing;
  49. static spinlock_t flush_lock;
  50. static DECLARE_WAIT_QUEUE_HEAD(flush);
  51. static struct var_t vars[] = {
  52. { CAPS_START, .u.s = {"[:dv ap 160] " } },
  53. { CAPS_STOP, .u.s = {"[:dv ap 100 ] " } },
  54. { RATE, .u.n = {"[:ra %d] ", 180, 75, 650, 0, 0, NULL } },
  55. { PITCH, .u.n = {"[:dv ap %d] ", 122, 50, 350, 0, 0, NULL } },
  56. { VOL, .u.n = {"[:dv g5 %d] ", 86, 60, 86, 0, 0, NULL } },
  57. { PUNCT, .u.n = {"[:pu %c] ", 0, 0, 2, 0, 0, "nsa" } },
  58. { VOICE, .u.n = {"[:n%c] ", 0, 0, 9, 0, 0, "phfdburwkv" } },
  59. { DIRECT, .u.n = {NULL, 0, 0, 1, 0, 0, NULL } },
  60. V_LAST_VAR
  61. };
  62. /*
  63. * These attributes will appear in /sys/accessibility/speakup/dectlk.
  64. */
  65. static struct kobj_attribute caps_start_attribute =
  66. __ATTR(caps_start, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
  67. static struct kobj_attribute caps_stop_attribute =
  68. __ATTR(caps_stop, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
  69. static struct kobj_attribute pitch_attribute =
  70. __ATTR(pitch, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
  71. static struct kobj_attribute punct_attribute =
  72. __ATTR(punct, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
  73. static struct kobj_attribute rate_attribute =
  74. __ATTR(rate, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
  75. static struct kobj_attribute voice_attribute =
  76. __ATTR(voice, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
  77. static struct kobj_attribute vol_attribute =
  78. __ATTR(vol, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
  79. static struct kobj_attribute delay_time_attribute =
  80. __ATTR(delay_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
  81. static struct kobj_attribute direct_attribute =
  82. __ATTR(direct, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
  83. static struct kobj_attribute full_time_attribute =
  84. __ATTR(full_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
  85. static struct kobj_attribute jiffy_delta_attribute =
  86. __ATTR(jiffy_delta, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
  87. static struct kobj_attribute trigger_time_attribute =
  88. __ATTR(trigger_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
  89. /*
  90. * Create a group of attributes so that we can create and destroy them all
  91. * at once.
  92. */
  93. static struct attribute *synth_attrs[] = {
  94. &caps_start_attribute.attr,
  95. &caps_stop_attribute.attr,
  96. &pitch_attribute.attr,
  97. &punct_attribute.attr,
  98. &rate_attribute.attr,
  99. &voice_attribute.attr,
  100. &vol_attribute.attr,
  101. &delay_time_attribute.attr,
  102. &direct_attribute.attr,
  103. &full_time_attribute.attr,
  104. &jiffy_delta_attribute.attr,
  105. &trigger_time_attribute.attr,
  106. NULL, /* need to NULL terminate the list of attributes */
  107. };
  108. static int ap_defaults[] = {122, 89, 155, 110, 208, 240, 200, 106, 306};
  109. static int g5_defaults[] = {86, 81, 86, 84, 81, 80, 83, 83, 73};
  110. static struct spk_synth synth_dectlk = {
  111. .name = "dectlk",
  112. .version = DRV_VERSION,
  113. .long_name = "Dectalk Express",
  114. .init = "[:error sp :name paul :rate 180 :tsr off] ",
  115. .procspeech = PROCSPEECH,
  116. .clear = SYNTH_CLEAR,
  117. .delay = 500,
  118. .trigger = 50,
  119. .jiffies = 50,
  120. .full = 40000,
  121. .startup = SYNTH_START,
  122. .checkval = SYNTH_CHECK,
  123. .vars = vars,
  124. .default_pitch = ap_defaults,
  125. .default_vol = g5_defaults,
  126. .probe = spk_serial_synth_probe,
  127. .release = spk_serial_release,
  128. .synth_immediate = spk_synth_immediate,
  129. .catch_up = do_catch_up,
  130. .flush = synth_flush,
  131. .is_alive = spk_synth_is_alive_restart,
  132. .synth_adjust = NULL,
  133. .read_buff_add = read_buff_add,
  134. .get_index = get_index,
  135. .indexing = {
  136. .command = "[:in re %d ] ",
  137. .lowindex = 1,
  138. .highindex = 8,
  139. .currindex = 1,
  140. },
  141. .attributes = {
  142. .attrs = synth_attrs,
  143. .name = "dectlk",
  144. },
  145. };
  146. static int is_indnum(u_char *ch)
  147. {
  148. if ((*ch >= '0') && (*ch <= '9')) {
  149. *ch = *ch - '0';
  150. return 1;
  151. }
  152. return 0;
  153. }
  154. static u_char lastind;
  155. static unsigned char get_index(void)
  156. {
  157. u_char rv;
  158. rv = lastind;
  159. lastind = 0;
  160. return rv;
  161. }
  162. static void read_buff_add(u_char c)
  163. {
  164. static int ind = -1;
  165. if (c == 0x01) {
  166. unsigned long flags;
  167. spin_lock_irqsave(&flush_lock, flags);
  168. is_flushing = 0;
  169. wake_up_interruptible(&flush);
  170. spin_unlock_irqrestore(&flush_lock, flags);
  171. } else if (c == 0x13) {
  172. xoff = 1;
  173. } else if (c == 0x11) {
  174. xoff = 0;
  175. } else if (is_indnum(&c)) {
  176. if (ind == -1)
  177. ind = c;
  178. else
  179. ind = ind * 10 + c;
  180. } else if ((c > 31) && (c < 127)) {
  181. if (ind != -1)
  182. lastind = (u_char)ind;
  183. ind = -1;
  184. }
  185. }
  186. static void do_catch_up(struct spk_synth *synth)
  187. {
  188. int synth_full_val = 0;
  189. static u_char ch;
  190. static u_char last = '\0';
  191. unsigned long flags;
  192. unsigned long jiff_max;
  193. unsigned long timeout = msecs_to_jiffies(4000);
  194. DEFINE_WAIT(wait);
  195. struct var_t *jiffy_delta;
  196. struct var_t *delay_time;
  197. int jiffy_delta_val;
  198. int delay_time_val;
  199. jiffy_delta = spk_get_var(JIFFY);
  200. delay_time = spk_get_var(DELAY);
  201. spin_lock_irqsave(&speakup_info.spinlock, flags);
  202. jiffy_delta_val = jiffy_delta->u.n.value;
  203. spin_unlock_irqrestore(&speakup_info.spinlock, flags);
  204. jiff_max = jiffies + jiffy_delta_val;
  205. while (!kthread_should_stop()) {
  206. /* if no ctl-a in 4, send data anyway */
  207. spin_lock_irqsave(&flush_lock, flags);
  208. while (is_flushing && timeout) {
  209. prepare_to_wait(&flush, &wait, TASK_INTERRUPTIBLE);
  210. spin_unlock_irqrestore(&flush_lock, flags);
  211. timeout = schedule_timeout(timeout);
  212. spin_lock_irqsave(&flush_lock, flags);
  213. }
  214. finish_wait(&flush, &wait);
  215. is_flushing = 0;
  216. spin_unlock_irqrestore(&flush_lock, flags);
  217. spin_lock_irqsave(&speakup_info.spinlock, flags);
  218. if (speakup_info.flushing) {
  219. speakup_info.flushing = 0;
  220. spin_unlock_irqrestore(&speakup_info.spinlock, flags);
  221. synth->flush(synth);
  222. continue;
  223. }
  224. if (synth_buffer_empty()) {
  225. spin_unlock_irqrestore(&speakup_info.spinlock, flags);
  226. break;
  227. }
  228. ch = synth_buffer_peek();
  229. set_current_state(TASK_INTERRUPTIBLE);
  230. delay_time_val = delay_time->u.n.value;
  231. synth_full_val = synth_full();
  232. spin_unlock_irqrestore(&speakup_info.spinlock, flags);
  233. if (ch == '\n')
  234. ch = 0x0D;
  235. if (synth_full_val || !spk_serial_out(ch)) {
  236. schedule_timeout(msecs_to_jiffies(delay_time_val));
  237. continue;
  238. }
  239. set_current_state(TASK_RUNNING);
  240. spin_lock_irqsave(&speakup_info.spinlock, flags);
  241. synth_buffer_getc();
  242. spin_unlock_irqrestore(&speakup_info.spinlock, flags);
  243. if (ch == '[')
  244. in_escape = 1;
  245. else if (ch == ']')
  246. in_escape = 0;
  247. else if (ch <= SPACE) {
  248. if (!in_escape && strchr(",.!?;:", last))
  249. spk_serial_out(PROCSPEECH);
  250. if (time_after_eq(jiffies, jiff_max)) {
  251. if (!in_escape)
  252. spk_serial_out(PROCSPEECH);
  253. spin_lock_irqsave(&speakup_info.spinlock,
  254. flags);
  255. jiffy_delta_val = jiffy_delta->u.n.value;
  256. delay_time_val = delay_time->u.n.value;
  257. spin_unlock_irqrestore(&speakup_info.spinlock,
  258. flags);
  259. schedule_timeout(msecs_to_jiffies
  260. (delay_time_val));
  261. jiff_max = jiffies + jiffy_delta_val;
  262. }
  263. }
  264. last = ch;
  265. }
  266. if (!in_escape)
  267. spk_serial_out(PROCSPEECH);
  268. }
  269. static void synth_flush(struct spk_synth *synth)
  270. {
  271. if (in_escape)
  272. /* if in command output ']' so we don't get an error */
  273. spk_serial_out(']');
  274. in_escape = 0;
  275. is_flushing = 1;
  276. spk_serial_out(SYNTH_CLEAR);
  277. }
  278. module_param_named(ser, synth_dectlk.ser, int, S_IRUGO);
  279. module_param_named(start, synth_dectlk.startup, short, S_IRUGO);
  280. MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
  281. MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
  282. module_spk_synth(synth_dectlk);
  283. MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
  284. MODULE_AUTHOR("David Borowski");
  285. MODULE_DESCRIPTION("Speakup support for DECtalk Express synthesizers");
  286. MODULE_LICENSE("GPL");
  287. MODULE_VERSION(DRV_VERSION);