aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/speakup/kobjects.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/speakup/kobjects.c')
-rw-r--r--drivers/staging/speakup/kobjects.c190
1 files changed, 101 insertions, 89 deletions
diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c
index 943b6c134a2..2ef7f6f201a 100644
--- a/drivers/staging/speakup/kobjects.c
+++ b/drivers/staging/speakup/kobjects.c
@@ -35,7 +35,7 @@ static ssize_t chars_chartab_show(struct kobject *kobj,
size_t bufsize = PAGE_SIZE;
unsigned long flags;
- spk_lock(flags);
+ spin_lock_irqsave(&speakup_info.spinlock, flags);
*buf_pointer = '\0';
for (i = 0; i < 256; i++) {
if (bufsize <= 1)
@@ -70,7 +70,7 @@ static ssize_t chars_chartab_show(struct kobject *kobj,
bufsize -= len;
buf_pointer += len;
}
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return buf_pointer - buf;
}
@@ -127,7 +127,7 @@ static ssize_t chars_chartab_store(struct kobject *kobj,
size_t desc_length = 0;
int i;
- spk_lock(flags);
+ spin_lock_irqsave(&speakup_info.spinlock, flags);
while (cp < end) {
while ((cp < end) && (*cp == ' ' || *cp == '\t'))
@@ -212,7 +212,7 @@ static ssize_t chars_chartab_store(struct kobject *kobj,
spk_reset_default_chartab();
}
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
report_char_chartab_status(reset, received, used, rejected,
do_characters);
return retval;
@@ -232,7 +232,7 @@ static ssize_t keymap_show(struct kobject *kobj, struct kobj_attribute *attr,
u_char *cp1;
u_char ch;
unsigned long flags;
- spk_lock(flags);
+ spin_lock_irqsave(&speakup_info.spinlock, flags);
cp1 = spk_key_buf + SHIFT_TBL_SIZE;
num_keys = (int)(*cp1);
nstates = (int)cp1[1];
@@ -248,7 +248,7 @@ static ssize_t keymap_show(struct kobject *kobj, struct kobj_attribute *attr,
}
}
cp += sprintf(cp, "0, %d\n", KEY_MAP_VER);
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return (int)(cp-buf);
}
@@ -265,17 +265,17 @@ static ssize_t keymap_store(struct kobject *kobj, struct kobj_attribute *attr,
u_char *cp1;
unsigned long flags;
- spk_lock(flags);
+ spin_lock_irqsave(&speakup_info.spinlock, flags);
in_buff = kmemdup(buf, count + 1, GFP_ATOMIC);
if (!in_buff) {
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return -ENOMEM;
}
if (strchr("dDrR", *in_buff)) {
spk_set_key_info(spk_key_defaults, spk_key_buf);
pr_info("keymap set to default values\n");
kfree(in_buff);
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return count;
}
if (in_buff[count - 1] == '\n')
@@ -294,7 +294,7 @@ static ssize_t keymap_store(struct kobject *kobj, struct kobj_attribute *attr,
pr_warn("i %d %d %d %d\n", i,
(int)cp1[-3], (int)cp1[-2], (int)cp1[-1]);
kfree(in_buff);
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return -EINVAL;
}
while (--i >= 0) {
@@ -315,7 +315,7 @@ static ssize_t keymap_store(struct kobject *kobj, struct kobj_attribute *attr,
}
}
kfree(in_buff);
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return ret;
}
@@ -341,7 +341,7 @@ static ssize_t silent_store(struct kobject *kobj, struct kobj_attribute *attr,
pr_warn("silent value '%c' not in range (0,7)\n", ch);
return -EINVAL;
}
- spk_lock(flags);
+ spin_lock_irqsave(&speakup_info.spinlock, flags);
if (ch&2) {
shut = 1;
spk_do_flush();
@@ -354,7 +354,7 @@ static ssize_t silent_store(struct kobject *kobj, struct kobj_attribute *attr,
spk_shut_up |= shut;
else
spk_shut_up &= ~shut;
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return count;
}
@@ -470,7 +470,7 @@ static ssize_t punc_show(struct kobject *kobj, struct kobj_attribute *attr,
return -EINVAL;
}
- spk_lock(flags);
+ spin_lock_irqsave(&speakup_info.spinlock, flags);
pb = (struct st_bits_data *) &spk_punc_info[var->value];
mask = pb->mask;
for (i = 33; i < 128; i++) {
@@ -478,7 +478,7 @@ static ssize_t punc_show(struct kobject *kobj, struct kobj_attribute *attr,
continue;
*cp++ = (char)i;
}
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return cp-buf;
}
@@ -518,14 +518,14 @@ static ssize_t punc_store(struct kobject *kobj, struct kobj_attribute *attr,
x--;
punc_buf[x] = '\0';
- spk_lock(flags);
+ spin_lock_irqsave(&speakup_info.spinlock, flags);
if (*punc_buf == 'd' || *punc_buf == 'r')
- x = spk_set_mask_bits(0, var->value, 3);
+ x = spk_set_mask_bits(NULL, var->value, 3);
else
x = spk_set_mask_bits(punc_buf, var->value, 3);
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return count;
}
@@ -547,7 +547,7 @@ ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr,
if (param == NULL)
return -EINVAL;
- spk_lock(flags);
+ spin_lock_irqsave(&speakup_info.spinlock, flags);
var = (struct var_t *) param->data;
switch (param->var_type) {
case VAR_NUM:
@@ -580,12 +580,31 @@ ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr,
param->name, param->var_type);
break;
}
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return rv;
}
EXPORT_SYMBOL_GPL(spk_var_show);
/*
+ * Used to reset either default_pitch or default_vol.
+ */
+static inline void spk_reset_default_value(char *header_name,
+ int *synth_default_value, int idx)
+{
+ struct st_var_header *param;
+
+ if (synth && synth_default_value) {
+ param = spk_var_header_by_name(header_name);
+ if (param) {
+ spk_set_num_var(synth_default_value[idx],
+ param, E_NEW_DEFAULT);
+ spk_set_num_var(0, param, E_DEFAULT);
+ pr_info("%s reset to default value\n", param->name);
+ }
+ }
+}
+
+/*
* This function is called when a user echos a value to one of the
* variable parameters.
*/
@@ -597,7 +616,7 @@ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
int len;
char *cp;
struct var_t *var_data;
- int value;
+ long value;
unsigned long flags;
param = spk_var_header_by_name(attr->attr.name);
@@ -609,7 +628,7 @@ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
cp = (char *)buf;
string_unescape_any_inplace(cp);
- spk_lock(flags);
+ spin_lock_irqsave(&speakup_info.spinlock, flags);
switch (param->var_type) {
case VAR_NUM:
case VAR_TIME:
@@ -619,61 +638,54 @@ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
len = E_INC;
else
len = E_SET;
- value = simple_strtol(cp, NULL, 10);
- ret = spk_set_num_var(value, param, len);
+ if (kstrtol(cp, 10, &value) == 0)
+ ret = spk_set_num_var(value, param, len);
+ else
+ pr_warn("overflow or parsing error has occurred");
if (ret == -ERANGE) {
var_data = param->data;
pr_warn("value for %s out of range, expect %d to %d\n",
- attr->attr.name,
+ param->name,
var_data->u.n.low, var_data->u.n.high);
}
+
+ /*
+ * If voice was just changed, we might need to reset our default
+ * pitch and volume.
+ */
+ if (param->var_id == VOICE && synth &&
+ (ret == 0 || ret == -ERESTART)) {
+ var_data = param->data;
+ value = var_data->u.n.value;
+ spk_reset_default_value("pitch", synth->default_pitch,
+ value);
+ spk_reset_default_value("vol", synth->default_vol,
+ value);
+ }
break;
case VAR_STRING:
- len = strlen(buf);
- if ((len >= 1) && (buf[len - 1] == '\n'))
+ len = strlen(cp);
+ if ((len >= 1) && (cp[len - 1] == '\n'))
--len;
- if ((len >= 2) && (buf[0] == '"') && (buf[len - 1] == '"')) {
- ++buf;
+ if ((len >= 2) && (cp[0] == '"') && (cp[len - 1] == '"')) {
+ ++cp;
len -= 2;
}
- cp = (char *) buf;
cp[len] = '\0';
- ret = spk_set_string_var(buf, param, len);
+ ret = spk_set_string_var(cp, param, len);
if (ret == -E2BIG)
pr_warn("value too long for %s\n",
- attr->attr.name);
+ param->name);
break;
default:
pr_warn("%s unknown type %d\n",
param->name, (int)param->var_type);
break;
}
- /*
- * If voice was just changed, we might need to reset our default
- * pitch and volume.
- */
- if (strcmp(attr->attr.name, "voice") == 0) {
- if (synth && synth->default_pitch) {
- param = spk_var_header_by_name("pitch");
- if (param) {
- spk_set_num_var(synth->default_pitch[value],
- param, E_NEW_DEFAULT);
- spk_set_num_var(0, param, E_DEFAULT);
- }
- }
- if (synth && synth->default_vol) {
- param = spk_var_header_by_name("vol");
- if (param) {
- spk_set_num_var(synth->default_vol[value],
- param, E_NEW_DEFAULT);
- spk_set_num_var(0, param, E_DEFAULT);
- }
- }
- }
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
if (ret == -ERESTART)
- pr_info("%s reset to default value\n", attr->attr.name);
+ pr_info("%s reset to default value\n", param->name);
return count;
}
EXPORT_SYMBOL_GPL(spk_var_store);
@@ -818,9 +830,9 @@ static ssize_t message_show(struct kobject *kobj,
unsigned long flags;
BUG_ON(!group);
- spk_lock(flags);
+ spin_lock_irqsave(&speakup_info.spinlock, flags);
retval = message_show_helper(buf, group->start, group->end);
- spk_unlock(flags);
+ spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return retval;
}
@@ -839,75 +851,75 @@ static ssize_t message_store(struct kobject *kobj, struct kobj_attribute *attr,
* Declare the attributes.
*/
static struct kobj_attribute keymap_attribute =
- __ATTR(keymap, ROOT_W, keymap_show, keymap_store);
+ __ATTR_RW(keymap);
static struct kobj_attribute silent_attribute =
- __ATTR(silent, USER_W, NULL, silent_store);
+ __ATTR_WO(silent);
static struct kobj_attribute synth_attribute =
- __ATTR(synth, USER_RW, synth_show, synth_store);
+ __ATTR_RW(synth);
static struct kobj_attribute synth_direct_attribute =
- __ATTR(synth_direct, USER_W, NULL, synth_direct_store);
+ __ATTR_WO(synth_direct);
static struct kobj_attribute version_attribute =
__ATTR_RO(version);
static struct kobj_attribute delimiters_attribute =
- __ATTR(delimiters, USER_RW, punc_show, punc_store);
+ __ATTR(delimiters, S_IWUSR|S_IRUGO, punc_show, punc_store);
static struct kobj_attribute ex_num_attribute =
- __ATTR(ex_num, USER_RW, punc_show, punc_store);
+ __ATTR(ex_num, S_IWUSR|S_IRUGO, punc_show, punc_store);
static struct kobj_attribute punc_all_attribute =
- __ATTR(punc_all, USER_RW, punc_show, punc_store);
+ __ATTR(punc_all, S_IWUSR|S_IRUGO, punc_show, punc_store);
static struct kobj_attribute punc_most_attribute =
- __ATTR(punc_most, USER_RW, punc_show, punc_store);
+ __ATTR(punc_most, S_IWUSR|S_IRUGO, punc_show, punc_store);
static struct kobj_attribute punc_some_attribute =
- __ATTR(punc_some, USER_RW, punc_show, punc_store);
+ __ATTR(punc_some, S_IWUSR|S_IRUGO, punc_show, punc_store);
static struct kobj_attribute repeats_attribute =
- __ATTR(repeats, USER_RW, punc_show, punc_store);
+ __ATTR(repeats, S_IWUSR|S_IRUGO, punc_show, punc_store);
static struct kobj_attribute attrib_bleep_attribute =
- __ATTR(attrib_bleep, USER_RW, spk_var_show, spk_var_store);
+ __ATTR(attrib_bleep, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute bell_pos_attribute =
- __ATTR(bell_pos, USER_RW, spk_var_show, spk_var_store);
+ __ATTR(bell_pos, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute bleep_time_attribute =
- __ATTR(bleep_time, USER_RW, spk_var_show, spk_var_store);
+ __ATTR(bleep_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute bleeps_attribute =
- __ATTR(bleeps, USER_RW, spk_var_show, spk_var_store);
+ __ATTR(bleeps, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute cursor_time_attribute =
- __ATTR(cursor_time, USER_RW, spk_var_show, spk_var_store);
+ __ATTR(cursor_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute key_echo_attribute =
- __ATTR(key_echo, USER_RW, spk_var_show, spk_var_store);
+ __ATTR(key_echo, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute no_interrupt_attribute =
- __ATTR(no_interrupt, USER_RW, spk_var_show, spk_var_store);
+ __ATTR(no_interrupt, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute punc_level_attribute =
- __ATTR(punc_level, USER_RW, spk_var_show, spk_var_store);
+ __ATTR(punc_level, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute reading_punc_attribute =
- __ATTR(reading_punc, USER_RW, spk_var_show, spk_var_store);
+ __ATTR(reading_punc, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute say_control_attribute =
- __ATTR(say_control, USER_RW, spk_var_show, spk_var_store);
+ __ATTR(say_control, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute say_word_ctl_attribute =
- __ATTR(say_word_ctl, USER_RW, spk_var_show, spk_var_store);
+ __ATTR(say_word_ctl, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute spell_delay_attribute =
- __ATTR(spell_delay, USER_RW, spk_var_show, spk_var_store);
+ __ATTR(spell_delay, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
/*
* These attributes are i18n related.
*/
static struct kobj_attribute announcements_attribute =
- __ATTR(announcements, USER_RW, message_show, message_store);
+ __ATTR(announcements, S_IWUSR|S_IRUGO, message_show, message_store);
static struct kobj_attribute characters_attribute =
- __ATTR(characters, USER_RW, chars_chartab_show, chars_chartab_store);
+ __ATTR(characters, S_IWUSR|S_IRUGO, chars_chartab_show, chars_chartab_store);
static struct kobj_attribute chartab_attribute =
- __ATTR(chartab, USER_RW, chars_chartab_show, chars_chartab_store);
+ __ATTR(chartab, S_IWUSR|S_IRUGO, chars_chartab_show, chars_chartab_store);
static struct kobj_attribute ctl_keys_attribute =
- __ATTR(ctl_keys, USER_RW, message_show, message_store);
+ __ATTR(ctl_keys, S_IWUSR|S_IRUGO, message_show, message_store);
static struct kobj_attribute colors_attribute =
- __ATTR(colors, USER_RW, message_show, message_store);
+ __ATTR(colors, S_IWUSR|S_IRUGO, message_show, message_store);
static struct kobj_attribute formatted_attribute =
- __ATTR(formatted, USER_RW, message_show, message_store);
+ __ATTR(formatted, S_IWUSR|S_IRUGO, message_show, message_store);
static struct kobj_attribute function_names_attribute =
- __ATTR(function_names, USER_RW, message_show, message_store);
+ __ATTR(function_names, S_IWUSR|S_IRUGO, message_show, message_store);
static struct kobj_attribute key_names_attribute =
- __ATTR(key_names, USER_RW, message_show, message_store);
+ __ATTR(key_names, S_IWUSR|S_IRUGO, message_show, message_store);
static struct kobj_attribute states_attribute =
- __ATTR(states, USER_RW, message_show, message_store);
+ __ATTR(states, S_IWUSR|S_IRUGO, message_show, message_store);
/*
* Create groups of attributes so that we can create and destroy them all