broadcom-diag: make it work with kernel 3.10
In kernel 3.10 the proc interface changed, this patch adds the changes needed for the new interface. SVN-Revision: 37280
This commit is contained in:
parent
c7370edf98
commit
9a5a262324
1 changed files with 126 additions and 124 deletions
|
@ -45,9 +45,6 @@ static unsigned int gpiomask = 0;
|
|||
module_param(gpiomask, int, 0644);
|
||||
|
||||
extern char *nvram_get(char *str);
|
||||
|
||||
static void register_leds(struct led_t *l);
|
||||
static void unregister_leds(struct led_t *l);
|
||||
static void led_flash(unsigned long dummy);
|
||||
|
||||
static struct platform_t platform;
|
||||
|
@ -56,8 +53,20 @@ static struct timer_list led_timer = TIMER_INITIALIZER(&led_flash, 0, 0);
|
|||
|
||||
static struct proc_dir_entry *diag, *leds;
|
||||
|
||||
static struct prochandler_t proc_model = { .type = PROC_MODEL };
|
||||
static struct prochandler_t proc_gpiomask = { .type = PROC_GPIOMASK };
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)
|
||||
static inline struct inode *file_inode(struct file *f)
|
||||
{
|
||||
return f->f_path.dentry->d_inode;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
|
||||
static inline void *PDE_DATA(const struct inode *inode)
|
||||
{
|
||||
return PDE(inode)->data;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
enum {
|
||||
/* Linksys */
|
||||
|
@ -1586,122 +1595,65 @@ static void led_flash(unsigned long dummy) {
|
|||
}
|
||||
}
|
||||
|
||||
static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
|
||||
static int diag_led_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode);
|
||||
char *page;
|
||||
int len = 0;
|
||||
struct led_t * led = m->private;
|
||||
|
||||
if ((page = kmalloc(1024, GFP_KERNEL)) == NULL)
|
||||
return -ENOBUFS;
|
||||
|
||||
if (dent->data != NULL) {
|
||||
struct prochandler_t *handler = (struct prochandler_t *) dent->data;
|
||||
switch (handler->type) {
|
||||
case PROC_LED: {
|
||||
struct led_t * led = (struct led_t *) handler->ptr;
|
||||
u8 p = (led->polarity == NORMAL ? 0 : 1);
|
||||
if (led->flash) {
|
||||
len = sprintf(page, "f\n");
|
||||
return seq_printf(m, "f\n");
|
||||
} else if ((led->gpio & GPIO_TYPE_MASK) != GPIO_TYPE_NORMAL) {
|
||||
len = sprintf(page, "%d\n", ((led->state ^ p) ? 1 : 0));
|
||||
return seq_printf(m, "%d\n", ((led->state ^ p) ? 1 : 0));
|
||||
} else {
|
||||
u32 in = (bcm47xx_gpio_in(~0) & led->gpio ? 1 : 0);
|
||||
len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0));
|
||||
return seq_printf(m, "%d\n", ((in ^ p) ? 1 : 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROC_MODEL:
|
||||
len = sprintf(page, "%s\n", platform.name);
|
||||
break;
|
||||
case PROC_GPIOMASK:
|
||||
len = sprintf(page, "0x%04x\n", gpiomask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
len += 1;
|
||||
|
||||
if (*ppos < len) {
|
||||
len = min_t(int, len - *ppos, count);
|
||||
if (copy_to_user(buf, (page + *ppos), len)) {
|
||||
kfree(page);
|
||||
return -EFAULT;
|
||||
}
|
||||
*ppos += len;
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
kfree(page);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
|
||||
static int diag_led_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode);
|
||||
char *page;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if ((page = kmalloc(count + 1, GFP_KERNEL)) == NULL)
|
||||
return -ENOBUFS;
|
||||
|
||||
if (copy_from_user(page, buf, count)) {
|
||||
kfree(page);
|
||||
return -EINVAL;
|
||||
return single_open(file, diag_led_show, PDE_DATA(inode));
|
||||
}
|
||||
page[count] = 0;
|
||||
|
||||
if (dent->data != NULL) {
|
||||
struct prochandler_t *handler = (struct prochandler_t *) dent->data;
|
||||
switch (handler->type) {
|
||||
case PROC_LED: {
|
||||
struct led_t *led = (struct led_t *) handler->ptr;
|
||||
int p = (led->polarity == NORMAL ? 0 : 1);
|
||||
static ssize_t diag_led_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct led_t *led = PDE_DATA(file_inode(file));
|
||||
char cmd[5];
|
||||
size_t len;
|
||||
int p;
|
||||
|
||||
if (page[0] == 'f') {
|
||||
len = min(count, sizeof(cmd) - 1);
|
||||
if (copy_from_user(cmd, buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
cmd[len] = 0;
|
||||
|
||||
p = (led->polarity == NORMAL ? 0 : 1);
|
||||
if (cmd[0] == 'f') {
|
||||
led->flash = 1;
|
||||
led_flash(0);
|
||||
} else {
|
||||
led->flash = 0;
|
||||
if ((led->gpio & GPIO_TYPE_MASK) == GPIO_TYPE_EXTIF) {
|
||||
led->state = p ^ ((page[0] == '1') ? 1 : 0);
|
||||
led->state = p ^ ((cmd[0] == '1') ? 1 : 0);
|
||||
set_led_extif(led);
|
||||
} else if ((led->gpio & GPIO_TYPE_MASK) == GPIO_TYPE_SHIFT) {
|
||||
led->state = p ^ ((page[0] == '1') ? 1 : 0);
|
||||
led->state = p ^ ((cmd[0] == '1') ? 1 : 0);
|
||||
set_led_shift(led);
|
||||
} else {
|
||||
bcm47xx_gpio_outen(led->gpio, led->gpio);
|
||||
bcm47xx_gpio_control(led->gpio, 0);
|
||||
bcm47xx_gpio_out(led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0));
|
||||
bcm47xx_gpio_out(led->gpio, ((p ^ (cmd[0] == '1')) ? led->gpio : 0));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROC_GPIOMASK:
|
||||
gpiomask = simple_strtoul(page, NULL, 0);
|
||||
|
||||
if (platform.buttons) {
|
||||
unregister_buttons(platform.buttons);
|
||||
register_buttons(platform.buttons);
|
||||
return count;
|
||||
}
|
||||
|
||||
if (platform.leds) {
|
||||
unregister_leds(platform.leds);
|
||||
register_leds(platform.leds);
|
||||
}
|
||||
break;
|
||||
}
|
||||
ret = count;
|
||||
}
|
||||
|
||||
kfree(page);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct file_operations diag_proc_fops = {
|
||||
read: diag_proc_read,
|
||||
write: diag_proc_write
|
||||
static const struct file_operations diag_led_fops = {
|
||||
.open = diag_led_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.write = diag_led_write
|
||||
};
|
||||
|
||||
static void register_leds(struct led_t *l)
|
||||
|
@ -1740,12 +1692,7 @@ static void register_leds(struct led_t *l)
|
|||
|
||||
if (l->polarity == INPUT) continue;
|
||||
|
||||
if ((p = create_proc_entry(l->name, S_IRUSR, leds))) {
|
||||
l->proc.type = PROC_LED;
|
||||
l->proc.ptr = l;
|
||||
p->data = (void *) &l->proc;
|
||||
p->proc_fops = &diag_proc_fops;
|
||||
}
|
||||
p = proc_create_data(l->name, S_IRUSR, leds, &diag_led_fops, l);
|
||||
}
|
||||
|
||||
bcm47xx_gpio_outen(mask, oe_mask);
|
||||
|
@ -1762,6 +1709,58 @@ static void unregister_leds(struct led_t *l)
|
|||
remove_proc_entry("led", diag);
|
||||
}
|
||||
|
||||
static int diag_model_show(struct seq_file *m, void *v)
|
||||
{
|
||||
return seq_printf(m, "%s\n", platform.name);
|
||||
}
|
||||
|
||||
static int diag_model_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, diag_model_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static const struct file_operations diag_model_fops = {
|
||||
.open = diag_model_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek
|
||||
};
|
||||
|
||||
static int diag_gpiomask_show(struct seq_file *m, void *v)
|
||||
{
|
||||
return seq_printf(m, "0x%04x\n", gpiomask);
|
||||
}
|
||||
|
||||
static int diag_gpiomask_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, diag_gpiomask_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static ssize_t diag_gpiomask_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
int err = kstrtouint_from_user(buf, count, 0, &gpiomask);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (platform.buttons) {
|
||||
unregister_buttons(platform.buttons);
|
||||
register_buttons(platform.buttons);
|
||||
}
|
||||
|
||||
if (platform.leds) {
|
||||
unregister_leds(platform.leds);
|
||||
register_leds(platform.leds);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations diag_gpiomask_fops = {
|
||||
.open = diag_gpiomask_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.write = diag_gpiomask_write
|
||||
};
|
||||
|
||||
static int __init diag_init(void)
|
||||
{
|
||||
static struct proc_dir_entry *p;
|
||||
|
@ -1784,14 +1783,17 @@ static int __init diag_init(void)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((p = create_proc_entry("model", S_IRUSR, diag))) {
|
||||
p->data = (void *) &proc_model;
|
||||
p->proc_fops = &diag_proc_fops;
|
||||
p = proc_create("model", S_IRUSR, diag, &diag_model_fops);
|
||||
if (!p) {
|
||||
remove_proc_entry("diag", NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((p = create_proc_entry("gpiomask", S_IRUSR | S_IWUSR, diag))) {
|
||||
p->data = (void *) &proc_gpiomask;
|
||||
p->proc_fops = &diag_proc_fops;
|
||||
p = proc_create("gpiomask", S_IRUSR | S_IWUSR, diag, &diag_gpiomask_fops);
|
||||
if (!p) {
|
||||
remove_proc_entry("model", diag);
|
||||
remove_proc_entry("diag", NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (platform.buttons)
|
||||
|
|
Loading…
Reference in a new issue