/*
* Speakup kobject implementation
*
* Copyright (C) 2009 William Hubbs
*
* This code is based on kobject-example.c, which came with linux 2.6.x.
*
* Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (C) 2007 Novell Inc.
*
* Released under the GPL version 2 only.
*
*/
#include <linux/slab.h> /* For kmalloc. */
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/string_helpers.h>
#include <linux/sysfs.h>
#include <linux/ctype.h>
#include "speakup.h"
#include "spk_priv.h"
/*
* This is called when a user reads the characters or chartab sys file.
*/
static ssize_t chars_chartab_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
int i;
int len = 0;
char *cp;
char *buf_pointer = buf;
size_t bufsize = PAGE_SIZE;
unsigned long flags;
spin_lock_irqsave(&speakup_info.spinlock, flags);
*buf_pointer = '\0';
for (i = 0; i < 256; i++) {
if (bufsize <= 1)
break;
if (strcmp("characters", attr->attr.name) == 0) {
len = scnprintf(buf_pointer, bufsize, "%d\t%s\n",
i, spk_characters[i]);
} else { /* show chartab entry */
if (IS_TYPE(i, B_CTL))
cp = "B_CTL";
else if (IS_TYPE(i, WDLM))
cp = "WDLM";
else if (IS_TYPE(i, A_PUNC))
cp = "A_PUNC";
else if (IS_TYPE(i, PUNC))
cp = "PUNC";
else if (IS_TYPE(i, NUM))
cp = "NUM";
else if (IS_TYPE(i, A_CAP))
cp = "A_CAP";
else if (IS_TYPE(i, ALPHA))
cp = "ALPHA";
else if (IS_TYPE(i, B_CAPSYM))
cp = "B_CAPSYM";
else if (IS_TYPE(i, B_SYM))
cp = "B_SYM";
else
cp = "0";
len =
scnprintf(buf_pointer, bufsize, "%d\t%s\n", i, cp);
}
bufsize -= len;
buf_pointer += len;
}
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
return buf_pointer - buf;
}
/*
* Print informational messages or warnings after updating
* character descriptions or chartab entries.
*/
static void report_char_chartab_status(int reset, int received, int used,
int rejected, int do_characters)
{
static char const *object_type[] = {
"character class entries",
"character descriptions",
};
int len;
char buf[80];
if (reset) {
pr_info("%s reset to defaults\n", object_type[do_characters]);
} else if (received) {
len = snprintf(buf, sizeof(buf),
" updated %d of %d %s\n",
used, received, object_type[do_characters]);
if (rejected)
snprintf(buf + (len - 1), sizeof(buf) - (len - 1),
" with %d reject%s\n",
rejected, rejected > 1 ? "s" : "");
printk(buf);
}
}
/*
* This is called when a user changes the characters or chartab parameters.
*/
static ssize_t chars_chartab_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t count)
{
char *cp = (char *) buf;
char *end = cp + count; /* the null at the end of the buffer */
char *linefeed = NULL;
char keyword[MAX_DESC_LEN + 1];
char *outptr = NULL;