static int get_register_interruptible(struct device *dev, u8 bank, u8 reg, u8 *value) { struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); return ab3100_get_register_interruptible(ab3100, reg, value); }
/* * Some debugfs entries only exposed if we're using debug */ static int ab3100_registers_print(struct seq_file *s, void *p) { struct ab3100 *ab3100 = s->private; u8 value; u8 reg; seq_printf(s, "AB3100 registers:\n"); for (reg = 0; reg < 0xff; reg++) { ab3100_get_register_interruptible(ab3100, reg, &value); seq_printf(s, "[0x%x]: 0x%x\n", reg, value); } return 0; }
static ssize_t ab3100_get_set_reg(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct ab3100_get_set_reg_priv *priv = file->private_data; struct ab3100 *ab3100 = priv->ab3100; char buf[32]; ssize_t buf_size; int regp; unsigned long user_reg; int err; int i = 0; /* Get userspace string and assure termination */ buf_size = min(count, (sizeof(buf)-1)); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; buf[buf_size] = 0; /* * The idea is here to parse a string which is either * "0xnn" for reading a register, or "0xaa 0xbb" for * writing 0xbb to the register 0xaa. First move past * whitespace and then begin to parse the register. */ while ((i < buf_size) && (buf[i] == ' ')) i++; regp = i; /* * Advance pointer to end of string then terminate * the register string. This is needed to satisfy * the strict_strtoul() function. */ while ((i < buf_size) && (buf[i] != ' ')) i++; buf[i] = '\0'; err = strict_strtoul(&buf[regp], 16, &user_reg); if (err) return err; if (user_reg > 0xff) return -EINVAL; /* Either we read or we write a register here */ if (!priv->mode) { /* Reading */ u8 reg = (u8) user_reg; u8 regvalue; ab3100_get_register_interruptible(ab3100, reg, ®value); dev_info(ab3100->dev, "debug read AB3100 reg[0x%02x]: 0x%02x\n", reg, regvalue); } else { int valp; unsigned long user_value; u8 reg = (u8) user_reg; u8 value; u8 regvalue; /* * Writing, we need some value to write to * the register so keep parsing the string * from userspace. */ i++; while ((i < buf_size) && (buf[i] == ' ')) i++; valp = i; while ((i < buf_size) && (buf[i] != ' ')) i++; buf[i] = '\0'; err = strict_strtoul(&buf[valp], 16, &user_value); if (err) return err; if (user_reg > 0xff) return -EINVAL; value = (u8) user_value; ab3100_set_register_interruptible(ab3100, reg, value); ab3100_get_register_interruptible(ab3100, reg, ®value); dev_info(ab3100->dev, "debug write reg[0x%02x] with 0x%02x, " "after readback: 0x%02x\n", reg, value, regvalue); } return buf_size; }
static ssize_t ab3100_get_set_reg(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct ab3100_get_set_reg_priv *priv = file->private_data; struct ab3100 *ab3100 = priv->ab3100; char buf[32]; ssize_t buf_size; int regp; unsigned long user_reg; int err; int i = 0; /* */ buf_size = min(count, (sizeof(buf)-1)); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; buf[buf_size] = 0; /* */ while ((i < buf_size) && (buf[i] == ' ')) i++; regp = i; /* */ while ((i < buf_size) && (buf[i] != ' ')) i++; buf[i] = '\0'; err = strict_strtoul(&buf[regp], 16, &user_reg); if (err) return err; if (user_reg > 0xff) return -EINVAL; /* */ if (!priv->mode) { /* */ u8 reg = (u8) user_reg; u8 regvalue; ab3100_get_register_interruptible(ab3100, reg, ®value); dev_info(ab3100->dev, "debug read AB3100 reg[0x%02x]: 0x%02x\n", reg, regvalue); } else { int valp; unsigned long user_value; u8 reg = (u8) user_reg; u8 value; u8 regvalue; /* */ i++; while ((i < buf_size) && (buf[i] == ' ')) i++; valp = i; while ((i < buf_size) && (buf[i] != ' ')) i++; buf[i] = '\0'; err = strict_strtoul(&buf[valp], 16, &user_value); if (err) return err; if (user_reg > 0xff) return -EINVAL; value = (u8) user_value; ab3100_set_register_interruptible(ab3100, reg, value); ab3100_get_register_interruptible(ab3100, reg, ®value); dev_info(ab3100->dev, "debug write reg[0x%02x] with 0x%02x, " "after readback: 0x%02x\n", reg, value, regvalue); } return buf_size; }