diff options
Diffstat (limited to 'drivers/iio/industrialio-core.c')
| -rw-r--r-- | drivers/iio/industrialio-core.c | 125 |
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); |
