speakup_keypc.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * written by David Borowski
  4. *
  5. * Copyright (C) 2003 David Borowski.
  6. *
  7. * specifically written as a driver for the speakup screenreview
  8. * package it's not a general device driver.
  9. * This driver is for the Keynote Gold internal synthesizer.
  10. */
  11. #include <linux/jiffies.h>
  12. #include <linux/sched.h>
  13. #include <linux/timer.h>
  14. #include <linux/kthread.h>
  15. #include <linux/serial_reg.h>
  16. #include "spk_priv.h"
  17. #include "speakup.h"
  18. #define DRV_VERSION "2.10"
  19. #define SYNTH_IO_EXTENT 0x04
  20. #define SWAIT udelay(70)
  21. #define PROCSPEECH 0x1f
  22. #define SYNTH_CLEAR 0x03
  23. static int synth_probe(struct spk_synth *synth);
  24. static void keynote_release(struct spk_synth *synth);
  25. static const char *synth_immediate(struct spk_synth *synth, const char *buf);
  26. static void do_catch_up(struct spk_synth *synth);
  27. static void synth_flush(struct spk_synth *synth);
  28. static int synth_port;
  29. static int port_forced;
  30. static unsigned int synth_portlist[] = { 0x2a8, 0 };
  31. static struct var_t vars[] = {
  32. { CAPS_START, .u.s = {"[f130]" } },
  33. { CAPS_STOP, .u.s = {"[f90]" } },
  34. { RATE, .u.n = {"\04%c ", 8, 0, 10, 81, -8, NULL } },
  35. { PITCH, .u.n = {"[f%d]", 5, 0, 9, 40, 10, NULL } },
  36. { DIRECT, .u.n = {NULL, 0, 0, 1, 0, 0, NULL } },
  37. V_LAST_VAR
  38. };
  39. /*
  40. * These attributes will appear in /sys/accessibility/speakup/keypc.
  41. */
  42. static struct kobj_attribute caps_start_attribute =
  43. __ATTR(caps_start, 0644, spk_var_show, spk_var_store);
  44. static struct kobj_attribute caps_stop_attribute =
  45. __ATTR(caps_stop, 0644, spk_var_show, spk_var_store);
  46. static struct kobj_attribute pitch_attribute =
  47. __ATTR(pitch, 0644, spk_var_show, spk_var_store);
  48. static struct kobj_attribute rate_attribute =
  49. __ATTR(rate, 0644, spk_var_show, spk_var_store);
  50. static struct kobj_attribute delay_time_attribute =
  51. __ATTR(delay_time, 0644, spk_var_show, spk_var_store);
  52. static struct kobj_attribute direct_attribute =
  53. __ATTR(direct, 0644, spk_var_show, spk_var_store);
  54. static struct kobj_attribute full_time_attribute =
  55. __ATTR(full_time, 0644, spk_var_show, spk_var_store);
  56. static struct kobj_attribute jiffy_delta_attribute =
  57. __ATTR(jiffy_delta, 0644, spk_var_show, spk_var_store);
  58. static struct kobj_attribute trigger_time_attribute =
  59. __ATTR(trigger_time, 0644, spk_var_show, spk_var_store);
  60. /*
  61. * Create a group of attributes so that we can create and destroy them all
  62. * at once.
  63. */
  64. static struct attribute *synth_attrs[] = {
  65. &caps_start_attribute.attr,
  66. &caps_stop_attribute.attr,
  67. &pitch_attribute.attr,
  68. &rate_attribute.attr,
  69. &delay_time_attribute.attr,
  70. &direct_attribute.attr,
  71. &full_time_attribute.attr,
  72. &jiffy_delta_attribute.attr,
  73. &trigger_time_attribute.attr,
  74. NULL, /* need to NULL terminate the list of attributes */
  75. };
  76. static struct spk_synth synth_keypc = {
  77. .name = "keypc",
  78. .version = DRV_VERSION,
  79. .long_name = "Keynote PC",
  80. .init = "[t][n7,1][n8,0]",
  81. .procspeech = PROCSPEECH,
  82. .clear = SYNTH_CLEAR,
  83. .delay = 500,
  84. .trigger = 50,
  85. .jiffies = 50,
  86. .full = 1000,
  87. .startup = SYNTH_START,
  88. .checkval = SYNTH_CHECK,
  89. .vars = vars,
  90. .io_ops = &spk_serial_io_ops,
  91. .probe = synth_probe,
  92. .release = keynote_release,
  93. .synth_immediate = synth_immediate,
  94. .catch_up = do_catch_up,
  95. .flush = synth_flush,
  96. .is_alive = spk_synth_is_alive_nop,
  97. .synth_adjust = NULL,
  98. .read_buff_add = NULL,
  99. .get_index = NULL,
  100. .indexing = {
  101. .command = NULL,
  102. .lowindex = 0,
  103. .highindex = 0,
  104. .currindex = 0,
  105. },
  106. .attributes = {
  107. .attrs = synth_attrs,
  108. .name = "keypc",
  109. },
  110. };
  111. static inline bool synth_writable(void)
  112. {
  113. return (inb_p(synth_port + UART_RX) & 0x10) != 0;
  114. }
  115. static inline bool synth_full(void)
  116. {
  117. return (inb_p(synth_port + UART_RX) & 0x80) == 0;
  118. }
  119. static char *oops(void)
  120. {
  121. int s1, s2, s3, s4;
  122. s1 = inb_p(synth_port);
  123. s2 = inb_p(synth_port + 1);
  124. s3 = inb_p(synth_port + 2);
  125. s4 = inb_p(synth_port + 3);
  126. pr_warn("synth timeout %d %d %d %d\n", s1, s2, s3, s4);
  127. return NULL;
  128. }
  129. static const char *synth_immediate(struct spk_synth *synth, const char *buf)
  130. {
  131. u_char ch;
  132. int timeout;
  133. while ((ch = *buf)) {
  134. if (ch == '\n')
  135. ch = PROCSPEECH;
  136. if (synth_full())
  137. return buf;
  138. timeout = 1000;
  139. while (synth_writable())
  140. if (--timeout <= 0)
  141. return oops();
  142. outb_p(ch, synth_port);
  143. udelay(70);
  144. buf++;
  145. }
  146. return NULL;
  147. }
  148. static void do_catch_up(struct spk_synth *synth)
  149. {
  150. u_char ch;
  151. int timeout;
  152. unsigned long flags;
  153. unsigned long jiff_max;
  154. struct var_t *jiffy_delta;
  155. struct var_t *delay_time;
  156. struct var_t *full_time;
  157. int delay_time_val;
  158. int full_time_val;
  159. int jiffy_delta_val;
  160. jiffy_delta = spk_get_var(JIFFY);
  161. delay_time = spk_get_var(DELAY);
  162. full_time = spk_get_var(FULL);
  163. spin_lock_irqsave(&speakup_info.spinlock, flags);
  164. jiffy_delta_val = jiffy_delta->u.n.value;
  165. spin_unlock_irqrestore(&speakup_info.spinlock, flags);
  166. jiff_max = jiffies + jiffy_delta_val;
  167. while (!kthread_should_stop()) {
  168. spin_lock_irqsave(&speakup_info.spinlock, flags);
  169. if (speakup_info.flushing) {
  170. speakup_info.flushing = 0;
  171. spin_unlock_irqrestore(&speakup_info.spinlock, flags);
  172. synth->flush(synth);
  173. continue;
  174. }
  175. synth_buffer_skip_nonlatin1();
  176. if (synth_buffer_empty()) {
  177. spin_unlock_irqrestore(&speakup_info.spinlock, flags);
  178. break;
  179. }
  180. set_current_state(TASK_INTERRUPTIBLE);
  181. full_time_val = full_time->u.n.value;
  182. spin_unlock_irqrestore(&speakup_info.spinlock, flags);
  183. if (synth_full()) {
  184. schedule_timeout(msecs_to_jiffies(full_time_val));
  185. continue;
  186. }
  187. set_current_state(TASK_RUNNING);
  188. timeout = 1000;
  189. while (synth_writable())
  190. if (--timeout <= 0)
  191. break;
  192. if (timeout <= 0) {
  193. oops();
  194. break;
  195. }
  196. spin_lock_irqsave(&speakup_info.spinlock, flags);
  197. ch = synth_buffer_getc();
  198. spin_unlock_irqrestore(&speakup_info.spinlock, flags);
  199. if (ch == '\n')
  200. ch = PROCSPEECH;
  201. outb_p(ch, synth_port);
  202. SWAIT;
  203. if (time_after_eq(jiffies, jiff_max) && (ch == SPACE)) {
  204. timeout = 1000;
  205. while (synth_writable())
  206. if (--timeout <= 0)
  207. break;
  208. if (timeout <= 0) {
  209. oops();
  210. break;
  211. }
  212. outb_p(PROCSPEECH, synth_port);
  213. spin_lock_irqsave(&speakup_info.spinlock, flags);
  214. jiffy_delta_val = jiffy_delta->u.n.value;
  215. delay_time_val = delay_time->u.n.value;
  216. spin_unlock_irqrestore(&speakup_info.spinlock, flags);
  217. schedule_timeout(msecs_to_jiffies(delay_time_val));
  218. jiff_max = jiffies + jiffy_delta_val;
  219. }
  220. }
  221. timeout = 1000;
  222. while (synth_writable())
  223. if (--timeout <= 0)
  224. break;
  225. if (timeout <= 0)
  226. oops();
  227. else
  228. outb_p(PROCSPEECH, synth_port);
  229. }
  230. static void synth_flush(struct spk_synth *synth)
  231. {
  232. outb_p(SYNTH_CLEAR, synth_port);
  233. }
  234. static int synth_probe(struct spk_synth *synth)
  235. {
  236. unsigned int port_val = 0;
  237. int i;
  238. pr_info("Probing for %s.\n", synth->long_name);
  239. if (port_forced) {
  240. synth_port = port_forced;
  241. pr_info("probe forced to %x by kernel command line\n",
  242. synth_port);
  243. if (synth_request_region(synth_port - 1, SYNTH_IO_EXTENT)) {
  244. pr_warn("sorry, port already reserved\n");
  245. return -EBUSY;
  246. }
  247. port_val = inb(synth_port);
  248. } else {
  249. for (i = 0; synth_portlist[i]; i++) {
  250. if (synth_request_region(synth_portlist[i],
  251. SYNTH_IO_EXTENT)) {
  252. pr_warn
  253. ("request_region: failed with 0x%x, %d\n",
  254. synth_portlist[i], SYNTH_IO_EXTENT);
  255. continue;
  256. }
  257. port_val = inb(synth_portlist[i]);
  258. if (port_val == 0x80) {
  259. synth_port = synth_portlist[i];
  260. break;
  261. }
  262. }
  263. }
  264. if (port_val != 0x80) {
  265. pr_info("%s: not found\n", synth->long_name);
  266. synth_release_region(synth_port, SYNTH_IO_EXTENT);
  267. synth_port = 0;
  268. return -ENODEV;
  269. }
  270. pr_info("%s: %03x-%03x, driver version %s,\n", synth->long_name,
  271. synth_port, synth_port + SYNTH_IO_EXTENT - 1,
  272. synth->version);
  273. synth->alive = 1;
  274. return 0;
  275. }
  276. static void keynote_release(struct spk_synth *synth)
  277. {
  278. spk_stop_serial_interrupt();
  279. if (synth_port)
  280. synth_release_region(synth_port, SYNTH_IO_EXTENT);
  281. synth_port = 0;
  282. }
  283. module_param_hw_named(port, port_forced, int, ioport, 0444);
  284. module_param_named(start, synth_keypc.startup, short, 0444);
  285. MODULE_PARM_DESC(port, "Set the port for the synthesizer (override probing).");
  286. MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
  287. module_spk_synth(synth_keypc);
  288. MODULE_AUTHOR("David Borowski");
  289. MODULE_DESCRIPTION("Speakup support for Keynote Gold PC synthesizers");
  290. MODULE_LICENSE("GPL");
  291. MODULE_VERSION(DRV_VERSION);