diff options
-rw-r--r-- | drivers/iio/industrialio-core.c | 98 | ||||
-rw-r--r-- | include/linux/iio/iio.h | 3 |
2 files changed, 66 insertions, 35 deletions
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 3dccd6c3a889..8848f16c547b 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c | |||
@@ -408,6 +408,64 @@ static ssize_t iio_read_channel_info(struct device *dev, | |||
408 | } | 408 | } |
409 | } | 409 | } |
410 | 410 | ||
411 | /** | ||
412 | * iio_str_to_fixpoint() - Parse a fixed-point number from a string | ||
413 | * @str: The string to parse | ||
414 | * @fract_mult: Multiplier for the first decimal place, should be a power of 10 | ||
415 | * @integer: The integer part of the number | ||
416 | * @fract: The fractional part of the number | ||
417 | * | ||
418 | * Returns 0 on success, or a negative error code if the string could not be | ||
419 | * parsed. | ||
420 | */ | ||
421 | int iio_str_to_fixpoint(const char *str, int fract_mult, | ||
422 | int *integer, int *fract) | ||
423 | { | ||
424 | int i = 0, f = 0; | ||
425 | bool integer_part = true, negative = false; | ||
426 | |||
427 | if (str[0] == '-') { | ||
428 | negative = true; | ||
429 | str++; | ||
430 | } else if (str[0] == '+') { | ||
431 | str++; | ||
432 | } | ||
433 | |||
434 | while (*str) { | ||
435 | if ('0' <= *str && *str <= '9') { | ||
436 | if (integer_part) { | ||
437 | i = i * 10 + *str - '0'; | ||
438 | } else { | ||
439 | f += fract_mult * (*str - '0'); | ||
440 | fract_mult /= 10; | ||
441 | } | ||
442 | } else if (*str == '\n') { | ||
443 | if (*(str + 1) == '\0') | ||
444 | break; | ||
445 | else | ||
446 | return -EINVAL; | ||
447 | } else if (*str == '.' && integer_part) { | ||
448 | integer_part = false; | ||
449 | } else { | ||
450 | return -EINVAL; | ||
451 | } | ||
452 | str++; | ||
453 | } | ||
454 | |||
455 | if (negative) { | ||
456 | if (i) | ||
457 | i = -i; | ||
458 | else | ||
459 | f = -f; | ||
460 | } | ||
461 | |||
462 | *integer = i; | ||
463 | *fract = f; | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | EXPORT_SYMBOL_GPL(iio_str_to_fixpoint); | ||
468 | |||
411 | static ssize_t iio_write_channel_info(struct device *dev, | 469 | static ssize_t iio_write_channel_info(struct device *dev, |
412 | struct device_attribute *attr, | 470 | struct device_attribute *attr, |
413 | const char *buf, | 471 | const char *buf, |
@@ -415,8 +473,8 @@ static ssize_t iio_write_channel_info(struct device *dev, | |||
415 | { | 473 | { |
416 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 474 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
417 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | 475 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
418 | int ret, integer = 0, fract = 0, fract_mult = 100000; | 476 | int ret, fract_mult = 100000; |
419 | bool integer_part = true, negative = false; | 477 | int integer, fract; |
420 | 478 | ||
421 | /* Assumes decimal - precision based on number of digits */ | 479 | /* Assumes decimal - precision based on number of digits */ |
422 | if (!indio_dev->info->write_raw) | 480 | if (!indio_dev->info->write_raw) |
@@ -435,39 +493,9 @@ static ssize_t iio_write_channel_info(struct device *dev, | |||
435 | return -EINVAL; | 493 | return -EINVAL; |
436 | } | 494 | } |
437 | 495 | ||
438 | if (buf[0] == '-') { | 496 | ret = iio_str_to_fixpoint(buf, fract_mult, &integer, &fract); |
439 | negative = true; | 497 | if (ret) |
440 | buf++; | 498 | return ret; |
441 | } else if (buf[0] == '+') { | ||
442 | buf++; | ||
443 | } | ||
444 | |||
445 | while (*buf) { | ||
446 | if ('0' <= *buf && *buf <= '9') { | ||
447 | if (integer_part) | ||
448 | integer = integer*10 + *buf - '0'; | ||
449 | else { | ||
450 | fract += fract_mult*(*buf - '0'); | ||
451 | fract_mult /= 10; | ||
452 | } | ||
453 | } else if (*buf == '\n') { | ||
454 | if (*(buf + 1) == '\0') | ||
455 | break; | ||
456 | else | ||
457 | return -EINVAL; | ||
458 | } else if (*buf == '.' && integer_part) { | ||
459 | integer_part = false; | ||
460 | } else { | ||
461 | return -EINVAL; | ||
462 | } | ||
463 | buf++; | ||
464 | } | ||
465 | if (negative) { | ||
466 | if (integer) | ||
467 | integer = -integer; | ||
468 | else | ||
469 | fract = -fract; | ||
470 | } | ||
471 | 499 | ||
472 | ret = indio_dev->info->write_raw(indio_dev, this_attr->c, | 500 | ret = indio_dev->info->write_raw(indio_dev, this_attr->c, |
473 | integer, fract, this_attr->address); | 501 | integer, fract, this_attr->address); |
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index adca93a999a7..da8c776ba0bd 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h | |||
@@ -620,6 +620,9 @@ static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) | |||
620 | }; | 620 | }; |
621 | #endif | 621 | #endif |
622 | 622 | ||
623 | int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer, | ||
624 | int *fract); | ||
625 | |||
623 | /** | 626 | /** |
624 | * IIO_DEGREE_TO_RAD() - Convert degree to rad | 627 | * IIO_DEGREE_TO_RAD() - Convert degree to rad |
625 | * @deg: A value in degree | 628 | * @deg: A value in degree |