aboutsummaryrefslogtreecommitdiff
path: root/drivers/iio/industrialio-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/industrialio-core.c')
-rw-r--r--drivers/iio/industrialio-core.c125
1 files changed, 67 insertions, 58 deletions
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index acc911a836c..4b1f375c565 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -84,6 +84,9 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_LIGHT_RED] = "red",
[IIO_MOD_LIGHT_GREEN] = "green",
[IIO_MOD_LIGHT_BLUE] = "blue",
+ [IIO_MOD_QUATERNION] = "quaternion",
+ [IIO_MOD_TEMP_AMBIENT] = "ambient",
+ [IIO_MOD_TEMP_OBJECT] = "object",
};
/* relies on pairs of these shared then separate */
@@ -340,7 +343,7 @@ ssize_t iio_enum_read(struct iio_dev *indio_dev,
else if (i >= e->num_items)
return -EINVAL;
- return sprintf(buf, "%s\n", e->items[i]);
+ return snprintf(buf, PAGE_SIZE, "%s\n", e->items[i]);
}
EXPORT_SYMBOL_GPL(iio_enum_read);
@@ -373,41 +376,53 @@ EXPORT_SYMBOL_GPL(iio_enum_write);
* @buf: The buffer to which the formated value gets written
* @type: One of the IIO_VAL_... constants. This decides how the val and val2
* parameters are formatted.
- * @val: First part of the value, exact meaning depends on the type parameter.
- * @val2: Second part of the value, exact meaning depends on the type parameter.
+ * @vals: pointer to the values, exact meaning depends on the type parameter.
*/
-ssize_t iio_format_value(char *buf, unsigned int type, int val, int val2)
+ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
{
unsigned long long tmp;
bool scale_db = false;
switch (type) {
case IIO_VAL_INT:
- return sprintf(buf, "%d\n", val);
+ return sprintf(buf, "%d\n", vals[0]);
case IIO_VAL_INT_PLUS_MICRO_DB:
scale_db = true;
case IIO_VAL_INT_PLUS_MICRO:
- if (val2 < 0)
- return sprintf(buf, "-%ld.%06u%s\n", abs(val), -val2,
+ if (vals[1] < 0)
+ return sprintf(buf, "-%ld.%06u%s\n", abs(vals[0]),
+ -vals[1],
scale_db ? " dB" : "");
else
- return sprintf(buf, "%d.%06u%s\n", val, val2,
+ return sprintf(buf, "%d.%06u%s\n", vals[0], vals[1],
scale_db ? " dB" : "");
case IIO_VAL_INT_PLUS_NANO:
- if (val2 < 0)
- return sprintf(buf, "-%ld.%09u\n", abs(val), -val2);
+ if (vals[1] < 0)
+ return sprintf(buf, "-%ld.%09u\n", abs(vals[0]),
+ -vals[1]);
else
- return sprintf(buf, "%d.%09u\n", val, val2);
+ return sprintf(buf, "%d.%09u\n", vals[0], vals[1]);
case IIO_VAL_FRACTIONAL:
- tmp = div_s64((s64)val * 1000000000LL, val2);
- val2 = do_div(tmp, 1000000000LL);
- val = tmp;
- return sprintf(buf, "%d.%09u\n", val, val2);
+ tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]);
+ vals[1] = do_div(tmp, 1000000000LL);
+ vals[0] = tmp;
+ return sprintf(buf, "%d.%09u\n", vals[0], vals[1]);
case IIO_VAL_FRACTIONAL_LOG2:
- tmp = (s64)val * 1000000000LL >> val2;
- val2 = do_div(tmp, 1000000000LL);
- val = tmp;
- return sprintf(buf, "%d.%09u\n", val, val2);
+ tmp = (s64)vals[0] * 1000000000LL >> vals[1];
+ vals[1] = do_div(tmp, 1000000000LL);
+ vals[0] = tmp;
+ return sprintf(buf, "%d.%09u\n", vals[0], vals[1]);
+ case IIO_VAL_INT_MULTIPLE:
+ {
+ int i;
+ int len = 0;
+
+ for (i = 0; i < size; ++i)
+ len += snprintf(&buf[len], PAGE_SIZE - len, "%d ",
+ vals[i]);
+ len += snprintf(&buf[len], PAGE_SIZE - len, "\n");
+ return len;
+ }
default:
return 0;
}
@@ -419,14 +434,23 @@ static ssize_t iio_read_channel_info(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int val, val2;
- int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
- &val, &val2, this_attr->address);
+ int vals[INDIO_MAX_RAW_ELEMENTS];
+ int ret;
+ int val_len = 2;
+
+ if (indio_dev->info->read_raw_multi)
+ ret = indio_dev->info->read_raw_multi(indio_dev, this_attr->c,
+ INDIO_MAX_RAW_ELEMENTS,
+ vals, &val_len,
+ this_attr->address);
+ else
+ ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
+ &vals[0], &vals[1], this_attr->address);
if (ret < 0)
return ret;
- return iio_format_value(buf, ret, val, val2);
+ return iio_format_value(buf, ret, val_len, vals);
}
/**
@@ -540,7 +564,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
enum iio_shared_by shared_by)
{
int ret = 0;
- char *name_format = NULL;
+ char *name = NULL;
char *full_postfix;
sysfs_attr_init(&dev_attr->attr);
@@ -558,7 +582,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
->channel2],
postfix);
} else {
- if (chan->extend_name == NULL)
+ if (chan->extend_name == NULL || shared_by != IIO_SEPARATE)
full_postfix = kstrdup(postfix, GFP_KERNEL);
else
full_postfix = kasprintf(GFP_KERNEL,
@@ -572,16 +596,15 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
if (chan->differential) { /* Differential can not have modifier */
switch (shared_by) {
case IIO_SHARED_BY_ALL:
- name_format = kasprintf(GFP_KERNEL, "%s", full_postfix);
+ name = kasprintf(GFP_KERNEL, "%s", full_postfix);
break;
case IIO_SHARED_BY_DIR:
- name_format = kasprintf(GFP_KERNEL, "%s_%s",
+ name = kasprintf(GFP_KERNEL, "%s_%s",
iio_direction[chan->output],
full_postfix);
break;
case IIO_SHARED_BY_TYPE:
- name_format
- = kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
+ name = kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
iio_chan_type_name_spec[chan->type],
@@ -593,8 +616,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
ret = -EINVAL;
goto error_free_full_postfix;
}
- name_format
- = kasprintf(GFP_KERNEL,
+ name = kasprintf(GFP_KERNEL,
"%s_%s%d-%s%d_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
@@ -607,16 +629,15 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
} else { /* Single ended */
switch (shared_by) {
case IIO_SHARED_BY_ALL:
- name_format = kasprintf(GFP_KERNEL, "%s", full_postfix);
+ name = kasprintf(GFP_KERNEL, "%s", full_postfix);
break;
case IIO_SHARED_BY_DIR:
- name_format = kasprintf(GFP_KERNEL, "%s_%s",
+ name = kasprintf(GFP_KERNEL, "%s_%s",
iio_direction[chan->output],
full_postfix);
break;
case IIO_SHARED_BY_TYPE:
- name_format
- = kasprintf(GFP_KERNEL, "%s_%s_%s",
+ name = kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
full_postfix);
@@ -624,33 +645,24 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
case IIO_SEPARATE:
if (chan->indexed)
- name_format
- = kasprintf(GFP_KERNEL, "%s_%s%d_%s",
+ name = kasprintf(GFP_KERNEL, "%s_%s%d_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
chan->channel,
full_postfix);
else
- name_format
- = kasprintf(GFP_KERNEL, "%s_%s_%s",
+ name = kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
full_postfix);
break;
}
}
- if (name_format == NULL) {
+ if (name == NULL) {
ret = -ENOMEM;
goto error_free_full_postfix;
}
- dev_attr->attr.name = kasprintf(GFP_KERNEL,
- name_format,
- chan->channel,
- chan->channel2);
- if (dev_attr->attr.name == NULL) {
- ret = -ENOMEM;
- goto error_free_name_format;
- }
+ dev_attr->attr.name = name;
if (readfunc) {
dev_attr->attr.mode |= S_IRUGO;
@@ -661,8 +673,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
dev_attr->attr.mode |= S_IWUSR;
dev_attr->store = writefunc;
}
-error_free_name_format:
- kfree(name_format);
+
error_free_full_postfix:
kfree(full_postfix);
@@ -692,10 +703,8 @@ int __iio_add_chan_devattr(const char *postfix,
struct iio_dev_attr *iio_attr, *t;
iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL);
- if (iio_attr == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ if (iio_attr == NULL)
+ return -ENOMEM;
ret = __iio_device_attr_init(&iio_attr->dev_attr,
postfix, chan,
readfunc, writefunc, shared_by);
@@ -720,7 +729,6 @@ error_device_attr_deinit:
__iio_device_attr_deinit(&iio_attr->dev_attr);
error_iio_dev_attr_free:
kfree(iio_attr);
-error_ret:
return ret;
}
@@ -732,6 +740,8 @@ static int iio_device_add_info_mask_type(struct iio_dev *indio_dev,
int i, ret, attrcount = 0;
for_each_set_bit(i, infomask, sizeof(infomask)*8) {
+ if (i >= ARRAY_SIZE(iio_chan_info_postfix))
+ return -EINVAL;
ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
chan,
&iio_read_channel_info,
@@ -836,7 +846,7 @@ static ssize_t iio_show_dev_name(struct device *dev,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- return sprintf(buf, "%s\n", indio_dev->name);
+ return snprintf(buf, PAGE_SIZE, "%s\n", indio_dev->name);
}
static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
@@ -1134,7 +1144,7 @@ int iio_device_register(struct iio_dev *indio_dev)
if (ret) {
dev_err(indio_dev->dev.parent,
"Failed to register debugfs interfaces\n");
- goto error_ret;
+ return ret;
}
ret = iio_device_register_sysfs(indio_dev);
if (ret) {
@@ -1175,7 +1185,6 @@ error_free_sysfs:
iio_device_unregister_sysfs(indio_dev);
error_unreg_debugfs:
iio_device_unregister_debugfs(indio_dev);
-error_ret:
return ret;
}
EXPORT_SYMBOL(iio_device_register);