Skip to content

Commit

Permalink
Input: atmel_mxt_ts - add memory access interface via sysfs
Browse files Browse the repository at this point in the history
Atmel maXTouch chips can be addressed via an "Object Based Protocol" which
defines how i2c registers are mapped to different functions within the
chips. This interface exposes the register map and allows user-space
utilities to inspect and alter object configuration, and to view diagnostic
data, while the device is running.

Signed-off-by: Nick Dyer <[email protected]>
Acked-by: Benson Leung <[email protected]>
  • Loading branch information
ndyer committed Apr 26, 2016
1 parent 3c3fcfd commit 80731e9
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions drivers/input/touchscreen/atmel_mxt_ts.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ struct mxt_data {
u8 t100_aux_ampl;
u8 t100_aux_area;
u8 t100_aux_vect;
struct bin_attribute mem_access_attr;
bool debug_enabled;
u8 max_reportid;
u32 config_crc;
Expand Down Expand Up @@ -3024,6 +3025,56 @@ static ssize_t mxt_debug_enable_store(struct device *dev,
return ret;
}

static int mxt_check_mem_access_params(struct mxt_data *data, loff_t off,
size_t *count)
{
if (off >= data->mem_size)
return -EIO;

if (off + *count > data->mem_size)
*count = data->mem_size - off;

if (*count > MXT_MAX_BLOCK_WRITE)
*count = MXT_MAX_BLOCK_WRITE;

return 0;
}

static ssize_t mxt_mem_access_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct mxt_data *data = dev_get_drvdata(dev);
int ret = 0;

ret = mxt_check_mem_access_params(data, off, &count);
if (ret < 0)
return ret;

if (count > 0)
ret = __mxt_read_reg(data->client, off, count, buf);

return ret == 0 ? count : ret;
}

static ssize_t mxt_mem_access_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, char *buf, loff_t off,
size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct mxt_data *data = dev_get_drvdata(dev);
int ret = 0;

ret = mxt_check_mem_access_params(data, off, &count);
if (ret < 0)
return ret;

if (count > 0)
ret = __mxt_write_reg(data->client, off, count, buf);

return ret == 0 ? count : ret;
}

static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);

static struct attribute *mxt_fw_attrs[] = {
Expand Down Expand Up @@ -3069,13 +3120,36 @@ static int mxt_sysfs_init(struct mxt_data *data)
return error;
}

sysfs_bin_attr_init(&data->mem_access_attr);
data->mem_access_attr.attr.name = "mem_access";
data->mem_access_attr.attr.mode = S_IRUGO | S_IWUSR;
data->mem_access_attr.read = mxt_mem_access_read;
data->mem_access_attr.write = mxt_mem_access_write;
data->mem_access_attr.size = data->mem_size;

error = sysfs_create_bin_file(&client->dev.kobj,
&data->mem_access_attr);
if (error) {
dev_err(&client->dev, "Failed to create %s\n",
data->mem_access_attr.attr.name);
goto err_remove_sysfs_group;
}

return 0;

err_remove_sysfs_group:
sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
return error;
}

static void mxt_sysfs_remove(struct mxt_data *data)
{
struct i2c_client *client = data->client;

if (data->mem_access_attr.attr.name)
sysfs_remove_bin_file(&client->dev.kobj,
&data->mem_access_attr);

sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
}

Expand Down

0 comments on commit 80731e9

Please sign in to comment.