Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/accessibility/speakup/speakup_apollo.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
* originally written by: Kirk Reiser <[email protected]>
4
* this version considerably modified by David Borowski, [email protected]
5
*
6
* Copyright (C) 1998-99 Kirk Reiser.
7
* Copyright (C) 2003 David Borowski.
8
*
9
* this code is specifically written as a driver for the speakup screenreview
10
* package and is not a general device driver.
11
*/
12
#include <linux/jiffies.h>
13
#include <linux/sched.h>
14
#include <linux/timer.h>
15
#include <linux/kthread.h>
16
#include <linux/serial_reg.h> /* for UART_MCR* constants */
17
18
#include "spk_priv.h"
19
#include "speakup.h"
20
21
#define DRV_VERSION "2.21"
22
#define SYNTH_CLEAR 0x18
23
#define PROCSPEECH '\r'
24
25
static void do_catch_up(struct spk_synth *synth);
26
27
28
29
enum default_vars_id {
30
CAPS_START_ID = 0, CAPS_STOP_ID,
31
RATE_ID, PITCH_ID,
32
VOL_ID, VOICE_ID, LANG_ID,
33
DIRECT_ID, V_LAST_VAR_ID,
34
NB_ID
35
};
36
37
38
39
40
static struct var_t vars[NB_ID] = {
41
[CAPS_START_ID] = { CAPS_START, .u.s = {"cap, " } },
42
[CAPS_STOP_ID] = { CAPS_STOP, .u.s = {"" } },
43
[RATE_ID] = { RATE, .u.n = {"@W%d", 6, 1, 9, 0, 0, NULL } },
44
[PITCH_ID] = { PITCH, .u.n = {"@F%x", 10, 0, 15, 0, 0, NULL } },
45
[VOL_ID] = { VOL, .u.n = {"@A%x", 10, 0, 15, 0, 0, NULL } },
46
[VOICE_ID] = { VOICE, .u.n = {"@V%d", 1, 1, 6, 0, 0, NULL } },
47
[LANG_ID] = { LANG, .u.n = {"@=%d,", 1, 1, 4, 0, 0, NULL } },
48
[DIRECT_ID] = { DIRECT, .u.n = {NULL, 0, 0, 1, 0, 0, NULL } },
49
V_LAST_VAR
50
};
51
52
/*
53
* These attributes will appear in /sys/accessibility/speakup/apollo.
54
*/
55
static struct kobj_attribute caps_start_attribute =
56
__ATTR(caps_start, 0644, spk_var_show, spk_var_store);
57
static struct kobj_attribute caps_stop_attribute =
58
__ATTR(caps_stop, 0644, spk_var_show, spk_var_store);
59
static struct kobj_attribute lang_attribute =
60
__ATTR(lang, 0644, spk_var_show, spk_var_store);
61
static struct kobj_attribute pitch_attribute =
62
__ATTR(pitch, 0644, spk_var_show, spk_var_store);
63
static struct kobj_attribute rate_attribute =
64
__ATTR(rate, 0644, spk_var_show, spk_var_store);
65
static struct kobj_attribute voice_attribute =
66
__ATTR(voice, 0644, spk_var_show, spk_var_store);
67
static struct kobj_attribute vol_attribute =
68
__ATTR(vol, 0644, spk_var_show, spk_var_store);
69
70
static struct kobj_attribute delay_time_attribute =
71
__ATTR(delay_time, 0644, spk_var_show, spk_var_store);
72
static struct kobj_attribute direct_attribute =
73
__ATTR(direct, 0644, spk_var_show, spk_var_store);
74
static struct kobj_attribute full_time_attribute =
75
__ATTR(full_time, 0644, spk_var_show, spk_var_store);
76
static struct kobj_attribute jiffy_delta_attribute =
77
__ATTR(jiffy_delta, 0644, spk_var_show, spk_var_store);
78
static struct kobj_attribute trigger_time_attribute =
79
__ATTR(trigger_time, 0644, spk_var_show, spk_var_store);
80
81
/*
82
* Create a group of attributes so that we can create and destroy them all
83
* at once.
84
*/
85
static struct attribute *synth_attrs[] = {
86
&caps_start_attribute.attr,
87
&caps_stop_attribute.attr,
88
&lang_attribute.attr,
89
&pitch_attribute.attr,
90
&rate_attribute.attr,
91
&voice_attribute.attr,
92
&vol_attribute.attr,
93
&delay_time_attribute.attr,
94
&direct_attribute.attr,
95
&full_time_attribute.attr,
96
&jiffy_delta_attribute.attr,
97
&trigger_time_attribute.attr,
98
NULL, /* need to NULL terminate the list of attributes */
99
};
100
101
static struct spk_synth synth_apollo = {
102
.name = "apollo",
103
.version = DRV_VERSION,
104
.long_name = "Apollo",
105
.init = "@R3@D0@K1\r",
106
.procspeech = PROCSPEECH,
107
.clear = SYNTH_CLEAR,
108
.delay = 500,
109
.trigger = 50,
110
.jiffies = 50,
111
.full = 40000,
112
.dev_name = SYNTH_DEFAULT_DEV,
113
.startup = SYNTH_START,
114
.checkval = SYNTH_CHECK,
115
.vars = vars,
116
.io_ops = &spk_ttyio_ops,
117
.probe = spk_ttyio_synth_probe,
118
.release = spk_ttyio_release,
119
.synth_immediate = spk_ttyio_synth_immediate,
120
.catch_up = do_catch_up,
121
.flush = spk_synth_flush,
122
.is_alive = spk_synth_is_alive_restart,
123
.synth_adjust = NULL,
124
.read_buff_add = NULL,
125
.get_index = NULL,
126
.indexing = {
127
.command = NULL,
128
.lowindex = 0,
129
.highindex = 0,
130
.currindex = 0,
131
},
132
.attributes = {
133
.attrs = synth_attrs,
134
.name = "apollo",
135
},
136
};
137
138
static void do_catch_up(struct spk_synth *synth)
139
{
140
u_char ch;
141
unsigned long flags;
142
unsigned long jiff_max;
143
struct var_t *jiffy_delta;
144
struct var_t *delay_time;
145
struct var_t *full_time;
146
int full_time_val = 0;
147
int delay_time_val = 0;
148
int jiffy_delta_val = 0;
149
150
jiffy_delta = spk_get_var(JIFFY);
151
delay_time = spk_get_var(DELAY);
152
full_time = spk_get_var(FULL);
153
spin_lock_irqsave(&speakup_info.spinlock, flags);
154
jiffy_delta_val = jiffy_delta->u.n.value;
155
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
156
jiff_max = jiffies + jiffy_delta_val;
157
158
while (!kthread_should_stop()) {
159
spin_lock_irqsave(&speakup_info.spinlock, flags);
160
jiffy_delta_val = jiffy_delta->u.n.value;
161
full_time_val = full_time->u.n.value;
162
delay_time_val = delay_time->u.n.value;
163
if (speakup_info.flushing) {
164
speakup_info.flushing = 0;
165
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
166
synth->flush(synth);
167
continue;
168
}
169
synth_buffer_skip_nonlatin1();
170
if (synth_buffer_empty()) {
171
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
172
break;
173
}
174
ch = synth_buffer_peek();
175
set_current_state(TASK_INTERRUPTIBLE);
176
full_time_val = full_time->u.n.value;
177
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
178
if (!synth->io_ops->synth_out(synth, ch)) {
179
synth->io_ops->tiocmset(synth, 0, UART_MCR_RTS);
180
synth->io_ops->tiocmset(synth, UART_MCR_RTS, 0);
181
schedule_timeout(msecs_to_jiffies(full_time_val));
182
continue;
183
}
184
if (time_after_eq(jiffies, jiff_max) && (ch == SPACE)) {
185
spin_lock_irqsave(&speakup_info.spinlock, flags);
186
jiffy_delta_val = jiffy_delta->u.n.value;
187
full_time_val = full_time->u.n.value;
188
delay_time_val = delay_time->u.n.value;
189
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
190
if (synth->io_ops->synth_out(synth, synth->procspeech))
191
schedule_timeout(msecs_to_jiffies
192
(delay_time_val));
193
else
194
schedule_timeout(msecs_to_jiffies
195
(full_time_val));
196
jiff_max = jiffies + jiffy_delta_val;
197
}
198
set_current_state(TASK_RUNNING);
199
spin_lock_irqsave(&speakup_info.spinlock, flags);
200
synth_buffer_getc();
201
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
202
}
203
synth->io_ops->synth_out(synth, PROCSPEECH);
204
}
205
206
module_param_named(ser, synth_apollo.ser, int, 0444);
207
module_param_named(dev, synth_apollo.dev_name, charp, 0444);
208
module_param_named(start, synth_apollo.startup, short, 0444);
209
module_param_named(rate, vars[RATE_ID].u.n.default_val, int, 0444);
210
module_param_named(pitch, vars[PITCH_ID].u.n.default_val, int, 0444);
211
module_param_named(vol, vars[VOL_ID].u.n.default_val, int, 0444);
212
module_param_named(voice, vars[VOICE_ID].u.n.default_val, int, 0444);
213
module_param_named(lang, vars[LANG_ID].u.n.default_val, int, 0444);
214
module_param_named(direct, vars[DIRECT_ID].u.n.default_val, int, 0444);
215
216
217
MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
218
MODULE_PARM_DESC(dev, "Set the device e.g. ttyUSB0, for the synthesizer.");
219
MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
220
MODULE_PARM_DESC(rate, "Set the rate variable on load.");
221
MODULE_PARM_DESC(pitch, "Set the pitch variable on load.");
222
MODULE_PARM_DESC(vol, "Set the vol variable on load.");
223
MODULE_PARM_DESC(voice, "Set the voice variable on load.");
224
MODULE_PARM_DESC(lang, "Set the lang variable on load.");
225
MODULE_PARM_DESC(direct, "Set the direct variable on load.");
226
227
228
229
module_spk_synth(synth_apollo);
230
231
MODULE_AUTHOR("Kirk Reiser <[email protected]>");
232
MODULE_AUTHOR("David Borowski");
233
MODULE_DESCRIPTION("Speakup support for Apollo II synthesizer");
234
MODULE_LICENSE("GPL");
235
MODULE_VERSION(DRV_VERSION);
236
237
238