| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* The industrial I/O core |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (c) 2008 Jonathan Cameron |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 6 | | - * under the terms of the GNU General Public License version 2 as published by |
|---|
| 7 | | - * the Free Software Foundation. |
|---|
| 8 | 5 | * |
|---|
| 9 | 6 | * Based on elements of hwmon and input subsystems. |
|---|
| 10 | 7 | */ |
|---|
| .. | .. |
|---|
| 19 | 16 | #include <linux/device.h> |
|---|
| 20 | 17 | #include <linux/fs.h> |
|---|
| 21 | 18 | #include <linux/poll.h> |
|---|
| 19 | +#include <linux/property.h> |
|---|
| 22 | 20 | #include <linux/sched.h> |
|---|
| 23 | 21 | #include <linux/wait.h> |
|---|
| 24 | 22 | #include <linux/cdev.h> |
|---|
| .. | .. |
|---|
| 27 | 25 | #include <linux/debugfs.h> |
|---|
| 28 | 26 | #include <linux/mutex.h> |
|---|
| 29 | 27 | #include <linux/iio/iio.h> |
|---|
| 28 | +#include <linux/iio/iio-opaque.h> |
|---|
| 30 | 29 | #include "iio_core.h" |
|---|
| 31 | 30 | #include "iio_core_trigger.h" |
|---|
| 32 | 31 | #include <linux/iio/sysfs.h> |
|---|
| .. | .. |
|---|
| 87 | 86 | [IIO_GRAVITY] = "gravity", |
|---|
| 88 | 87 | [IIO_POSITIONRELATIVE] = "positionrelative", |
|---|
| 89 | 88 | [IIO_PHASE] = "phase", |
|---|
| 89 | + [IIO_MASSCONCENTRATION] = "massconcentration", |
|---|
| 90 | +#ifdef CONFIG_NO_GKI |
|---|
| 91 | + [IIO_SIGN_MOTION] = "signmotion", |
|---|
| 92 | + [IIO_STEP_DETECTOR] = "stepdetector", |
|---|
| 93 | + [IIO_STEP_COUNTER] = "stepcounter", |
|---|
| 94 | + [IIO_TILT] = "tilt", |
|---|
| 95 | + [IIO_TAP] = "tap", |
|---|
| 96 | + [IIO_TAP_TAP] = "taptap", |
|---|
| 97 | + [IIO_WRIST_TILT_GESTURE] = "wristtiltgesture", |
|---|
| 98 | + [IIO_GESTURE] = "gesture", |
|---|
| 99 | +#endif |
|---|
| 90 | 100 | }; |
|---|
| 91 | 101 | |
|---|
| 92 | 102 | static const char * const iio_modifier_names[] = { |
|---|
| .. | .. |
|---|
| 127 | 137 | [IIO_MOD_Q] = "q", |
|---|
| 128 | 138 | [IIO_MOD_CO2] = "co2", |
|---|
| 129 | 139 | [IIO_MOD_VOC] = "voc", |
|---|
| 140 | + [IIO_MOD_PM1] = "pm1", |
|---|
| 141 | + [IIO_MOD_PM2P5] = "pm2p5", |
|---|
| 142 | + [IIO_MOD_PM4] = "pm4", |
|---|
| 143 | + [IIO_MOD_PM10] = "pm10", |
|---|
| 144 | + [IIO_MOD_ETHANOL] = "ethanol", |
|---|
| 145 | + [IIO_MOD_H2] = "h2", |
|---|
| 146 | + [IIO_MOD_O2] = "o2", |
|---|
| 130 | 147 | }; |
|---|
| 131 | 148 | |
|---|
| 132 | 149 | /* relies on pairs of these shared then separate */ |
|---|
| .. | .. |
|---|
| 158 | 175 | [IIO_CHAN_INFO_DEBOUNCE_TIME] = "debounce_time", |
|---|
| 159 | 176 | [IIO_CHAN_INFO_CALIBEMISSIVITY] = "calibemissivity", |
|---|
| 160 | 177 | [IIO_CHAN_INFO_OVERSAMPLING_RATIO] = "oversampling_ratio", |
|---|
| 178 | + [IIO_CHAN_INFO_THERMOCOUPLE_TYPE] = "thermocouple_type", |
|---|
| 179 | + [IIO_CHAN_INFO_CALIBAMBIENT] = "calibambient", |
|---|
| 161 | 180 | }; |
|---|
| 181 | + |
|---|
| 182 | +#if defined(CONFIG_DEBUG_FS) |
|---|
| 183 | +/* |
|---|
| 184 | + * There's also a CONFIG_DEBUG_FS guard in include/linux/iio/iio.h for |
|---|
| 185 | + * iio_get_debugfs_dentry() to make it inline if CONFIG_DEBUG_FS is undefined |
|---|
| 186 | + */ |
|---|
| 187 | +struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) |
|---|
| 188 | +{ |
|---|
| 189 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
|---|
| 190 | + return iio_dev_opaque->debugfs_dentry; |
|---|
| 191 | +} |
|---|
| 192 | +EXPORT_SYMBOL_GPL(iio_get_debugfs_dentry); |
|---|
| 193 | +#endif |
|---|
| 162 | 194 | |
|---|
| 163 | 195 | /** |
|---|
| 164 | 196 | * iio_find_channel_from_si() - get channel from its scan index |
|---|
| .. | .. |
|---|
| 185 | 217 | } |
|---|
| 186 | 218 | EXPORT_SYMBOL(iio_read_const_attr); |
|---|
| 187 | 219 | |
|---|
| 188 | | -static int iio_device_set_clock(struct iio_dev *indio_dev, clockid_t clock_id) |
|---|
| 220 | +/** |
|---|
| 221 | + * iio_device_set_clock() - Set current timestamping clock for the device |
|---|
| 222 | + * @indio_dev: IIO device structure containing the device |
|---|
| 223 | + * @clock_id: timestamping clock posix identifier to set. |
|---|
| 224 | + */ |
|---|
| 225 | +int iio_device_set_clock(struct iio_dev *indio_dev, clockid_t clock_id) |
|---|
| 189 | 226 | { |
|---|
| 190 | 227 | int ret; |
|---|
| 191 | | - const struct iio_event_interface *ev_int = indio_dev->event_interface; |
|---|
| 228 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
|---|
| 229 | + const struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; |
|---|
| 192 | 230 | |
|---|
| 193 | 231 | ret = mutex_lock_interruptible(&indio_dev->mlock); |
|---|
| 194 | 232 | if (ret) |
|---|
| .. | .. |
|---|
| 203 | 241 | |
|---|
| 204 | 242 | return 0; |
|---|
| 205 | 243 | } |
|---|
| 244 | +EXPORT_SYMBOL(iio_device_set_clock); |
|---|
| 206 | 245 | |
|---|
| 207 | 246 | /** |
|---|
| 208 | 247 | * iio_get_time_ns() - utility function to get a time stamp for events etc |
|---|
| .. | .. |
|---|
| 225 | 264 | ktime_get_coarse_ts64(&tp); |
|---|
| 226 | 265 | return timespec64_to_ns(&tp); |
|---|
| 227 | 266 | case CLOCK_BOOTTIME: |
|---|
| 228 | | - return ktime_get_boot_ns(); |
|---|
| 267 | + return ktime_get_boottime_ns(); |
|---|
| 229 | 268 | case CLOCK_TAI: |
|---|
| 230 | | - return ktime_get_tai_ns(); |
|---|
| 269 | + return ktime_get_clocktai_ns(); |
|---|
| 231 | 270 | default: |
|---|
| 232 | 271 | BUG(); |
|---|
| 233 | 272 | } |
|---|
| .. | .. |
|---|
| 297 | 336 | size_t count, loff_t *ppos) |
|---|
| 298 | 337 | { |
|---|
| 299 | 338 | struct iio_dev *indio_dev = file->private_data; |
|---|
| 300 | | - char buf[20]; |
|---|
| 339 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
|---|
| 301 | 340 | unsigned val = 0; |
|---|
| 302 | | - ssize_t len; |
|---|
| 303 | 341 | int ret; |
|---|
| 304 | 342 | |
|---|
| 343 | + if (*ppos > 0) |
|---|
| 344 | + return simple_read_from_buffer(userbuf, count, ppos, |
|---|
| 345 | + iio_dev_opaque->read_buf, |
|---|
| 346 | + iio_dev_opaque->read_buf_len); |
|---|
| 347 | + |
|---|
| 305 | 348 | ret = indio_dev->info->debugfs_reg_access(indio_dev, |
|---|
| 306 | | - indio_dev->cached_reg_addr, |
|---|
| 349 | + iio_dev_opaque->cached_reg_addr, |
|---|
| 307 | 350 | 0, &val); |
|---|
| 308 | 351 | if (ret) { |
|---|
| 309 | 352 | dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__); |
|---|
| 310 | 353 | return ret; |
|---|
| 311 | 354 | } |
|---|
| 312 | 355 | |
|---|
| 313 | | - len = snprintf(buf, sizeof(buf), "0x%X\n", val); |
|---|
| 356 | + iio_dev_opaque->read_buf_len = snprintf(iio_dev_opaque->read_buf, |
|---|
| 357 | + sizeof(iio_dev_opaque->read_buf), |
|---|
| 358 | + "0x%X\n", val); |
|---|
| 314 | 359 | |
|---|
| 315 | | - return simple_read_from_buffer(userbuf, count, ppos, buf, len); |
|---|
| 360 | + return simple_read_from_buffer(userbuf, count, ppos, |
|---|
| 361 | + iio_dev_opaque->read_buf, |
|---|
| 362 | + iio_dev_opaque->read_buf_len); |
|---|
| 316 | 363 | } |
|---|
| 317 | 364 | |
|---|
| 318 | 365 | static ssize_t iio_debugfs_write_reg(struct file *file, |
|---|
| 319 | 366 | const char __user *userbuf, size_t count, loff_t *ppos) |
|---|
| 320 | 367 | { |
|---|
| 321 | 368 | struct iio_dev *indio_dev = file->private_data; |
|---|
| 369 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
|---|
| 322 | 370 | unsigned reg, val; |
|---|
| 323 | 371 | char buf[80]; |
|---|
| 324 | 372 | int ret; |
|---|
| .. | .. |
|---|
| 333 | 381 | |
|---|
| 334 | 382 | switch (ret) { |
|---|
| 335 | 383 | case 1: |
|---|
| 336 | | - indio_dev->cached_reg_addr = reg; |
|---|
| 384 | + iio_dev_opaque->cached_reg_addr = reg; |
|---|
| 337 | 385 | break; |
|---|
| 338 | 386 | case 2: |
|---|
| 339 | | - indio_dev->cached_reg_addr = reg; |
|---|
| 387 | + iio_dev_opaque->cached_reg_addr = reg; |
|---|
| 340 | 388 | ret = indio_dev->info->debugfs_reg_access(indio_dev, reg, |
|---|
| 341 | 389 | val, NULL); |
|---|
| 342 | 390 | if (ret) { |
|---|
| .. | .. |
|---|
| 360 | 408 | |
|---|
| 361 | 409 | static void iio_device_unregister_debugfs(struct iio_dev *indio_dev) |
|---|
| 362 | 410 | { |
|---|
| 363 | | - debugfs_remove_recursive(indio_dev->debugfs_dentry); |
|---|
| 411 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
|---|
| 412 | + debugfs_remove_recursive(iio_dev_opaque->debugfs_dentry); |
|---|
| 364 | 413 | } |
|---|
| 365 | 414 | |
|---|
| 366 | | -static int iio_device_register_debugfs(struct iio_dev *indio_dev) |
|---|
| 415 | +static void iio_device_register_debugfs(struct iio_dev *indio_dev) |
|---|
| 367 | 416 | { |
|---|
| 368 | | - struct dentry *d; |
|---|
| 417 | + struct iio_dev_opaque *iio_dev_opaque; |
|---|
| 369 | 418 | |
|---|
| 370 | 419 | if (indio_dev->info->debugfs_reg_access == NULL) |
|---|
| 371 | | - return 0; |
|---|
| 420 | + return; |
|---|
| 372 | 421 | |
|---|
| 373 | 422 | if (!iio_debugfs_dentry) |
|---|
| 374 | | - return 0; |
|---|
| 423 | + return; |
|---|
| 375 | 424 | |
|---|
| 376 | | - indio_dev->debugfs_dentry = |
|---|
| 425 | + iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
|---|
| 426 | + |
|---|
| 427 | + iio_dev_opaque->debugfs_dentry = |
|---|
| 377 | 428 | debugfs_create_dir(dev_name(&indio_dev->dev), |
|---|
| 378 | 429 | iio_debugfs_dentry); |
|---|
| 379 | | - if (indio_dev->debugfs_dentry == NULL) { |
|---|
| 380 | | - dev_warn(indio_dev->dev.parent, |
|---|
| 381 | | - "Failed to create debugfs directory\n"); |
|---|
| 382 | | - return -EFAULT; |
|---|
| 383 | | - } |
|---|
| 384 | 430 | |
|---|
| 385 | | - d = debugfs_create_file("direct_reg_access", 0644, |
|---|
| 386 | | - indio_dev->debugfs_dentry, |
|---|
| 387 | | - indio_dev, &iio_debugfs_reg_fops); |
|---|
| 388 | | - if (!d) { |
|---|
| 389 | | - iio_device_unregister_debugfs(indio_dev); |
|---|
| 390 | | - return -ENOMEM; |
|---|
| 391 | | - } |
|---|
| 392 | | - |
|---|
| 393 | | - return 0; |
|---|
| 431 | + debugfs_create_file("direct_reg_access", 0644, |
|---|
| 432 | + iio_dev_opaque->debugfs_dentry, indio_dev, |
|---|
| 433 | + &iio_debugfs_reg_fops); |
|---|
| 394 | 434 | } |
|---|
| 395 | 435 | #else |
|---|
| 396 | | -static int iio_device_register_debugfs(struct iio_dev *indio_dev) |
|---|
| 436 | +static void iio_device_register_debugfs(struct iio_dev *indio_dev) |
|---|
| 397 | 437 | { |
|---|
| 398 | | - return 0; |
|---|
| 399 | 438 | } |
|---|
| 400 | 439 | |
|---|
| 401 | 440 | static void iio_device_unregister_debugfs(struct iio_dev *indio_dev) |
|---|
| .. | .. |
|---|
| 525 | 564 | EXPORT_SYMBOL_GPL(iio_show_mount_matrix); |
|---|
| 526 | 565 | |
|---|
| 527 | 566 | /** |
|---|
| 528 | | - * of_iio_read_mount_matrix() - retrieve iio device mounting matrix from |
|---|
| 529 | | - * device-tree "mount-matrix" property |
|---|
| 567 | + * iio_read_mount_matrix() - retrieve iio device mounting matrix from |
|---|
| 568 | + * device "mount-matrix" property |
|---|
| 530 | 569 | * @dev: device the mounting matrix property is assigned to |
|---|
| 531 | 570 | * @propname: device specific mounting matrix property name |
|---|
| 532 | 571 | * @matrix: where to store retrieved matrix |
|---|
| .. | .. |
|---|
| 536 | 575 | * |
|---|
| 537 | 576 | * Return: 0 if success, or a negative error code on failure. |
|---|
| 538 | 577 | */ |
|---|
| 539 | | -#ifdef CONFIG_OF |
|---|
| 540 | | -int of_iio_read_mount_matrix(const struct device *dev, |
|---|
| 541 | | - const char *propname, |
|---|
| 542 | | - struct iio_mount_matrix *matrix) |
|---|
| 578 | +int iio_read_mount_matrix(struct device *dev, const char *propname, |
|---|
| 579 | + struct iio_mount_matrix *matrix) |
|---|
| 543 | 580 | { |
|---|
| 544 | | - if (dev->of_node) { |
|---|
| 545 | | - int err = of_property_read_string_array(dev->of_node, |
|---|
| 546 | | - propname, matrix->rotation, |
|---|
| 547 | | - ARRAY_SIZE(iio_mount_idmatrix.rotation)); |
|---|
| 581 | + size_t len = ARRAY_SIZE(iio_mount_idmatrix.rotation); |
|---|
| 582 | + int err; |
|---|
| 548 | 583 | |
|---|
| 549 | | - if (err == ARRAY_SIZE(iio_mount_idmatrix.rotation)) |
|---|
| 550 | | - return 0; |
|---|
| 584 | + err = device_property_read_string_array(dev, propname, |
|---|
| 585 | + matrix->rotation, len); |
|---|
| 586 | + if (err == len) |
|---|
| 587 | + return 0; |
|---|
| 551 | 588 | |
|---|
| 552 | | - if (err >= 0) |
|---|
| 553 | | - /* Invalid number of matrix entries. */ |
|---|
| 554 | | - return -EINVAL; |
|---|
| 589 | + if (err >= 0) |
|---|
| 590 | + /* Invalid number of matrix entries. */ |
|---|
| 591 | + return -EINVAL; |
|---|
| 555 | 592 | |
|---|
| 556 | | - if (err != -EINVAL) |
|---|
| 557 | | - /* Invalid matrix declaration format. */ |
|---|
| 558 | | - return err; |
|---|
| 559 | | - } |
|---|
| 593 | + if (err != -EINVAL) |
|---|
| 594 | + /* Invalid matrix declaration format. */ |
|---|
| 595 | + return err; |
|---|
| 560 | 596 | |
|---|
| 561 | 597 | /* Matrix was not declared at all: fallback to identity. */ |
|---|
| 562 | 598 | return iio_setup_mount_idmatrix(dev, matrix); |
|---|
| 563 | 599 | } |
|---|
| 564 | | -#else |
|---|
| 565 | | -int of_iio_read_mount_matrix(const struct device *dev, |
|---|
| 566 | | - const char *propname, |
|---|
| 567 | | - struct iio_mount_matrix *matrix) |
|---|
| 568 | | -{ |
|---|
| 569 | | - return iio_setup_mount_idmatrix(dev, matrix); |
|---|
| 570 | | -} |
|---|
| 571 | | -#endif |
|---|
| 572 | | -EXPORT_SYMBOL(of_iio_read_mount_matrix); |
|---|
| 600 | +EXPORT_SYMBOL(iio_read_mount_matrix); |
|---|
| 573 | 601 | |
|---|
| 574 | 602 | static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type, |
|---|
| 575 | 603 | int size, const int *vals) |
|---|
| .. | .. |
|---|
| 580 | 608 | |
|---|
| 581 | 609 | switch (type) { |
|---|
| 582 | 610 | case IIO_VAL_INT: |
|---|
| 583 | | - return snprintf(buf, len, "%d", vals[0]); |
|---|
| 611 | + return scnprintf(buf, len, "%d", vals[0]); |
|---|
| 584 | 612 | case IIO_VAL_INT_PLUS_MICRO_DB: |
|---|
| 585 | 613 | scale_db = true; |
|---|
| 586 | | - /* fall through */ |
|---|
| 614 | + fallthrough; |
|---|
| 587 | 615 | case IIO_VAL_INT_PLUS_MICRO: |
|---|
| 588 | 616 | if (vals[1] < 0) |
|---|
| 589 | | - return snprintf(buf, len, "-%d.%06u%s", abs(vals[0]), |
|---|
| 617 | + return scnprintf(buf, len, "-%d.%06u%s", abs(vals[0]), |
|---|
| 590 | 618 | -vals[1], scale_db ? " dB" : ""); |
|---|
| 591 | 619 | else |
|---|
| 592 | | - return snprintf(buf, len, "%d.%06u%s", vals[0], vals[1], |
|---|
| 620 | + return scnprintf(buf, len, "%d.%06u%s", vals[0], vals[1], |
|---|
| 593 | 621 | scale_db ? " dB" : ""); |
|---|
| 594 | 622 | case IIO_VAL_INT_PLUS_NANO: |
|---|
| 595 | 623 | if (vals[1] < 0) |
|---|
| 596 | | - return snprintf(buf, len, "-%d.%09u", abs(vals[0]), |
|---|
| 624 | + return scnprintf(buf, len, "-%d.%09u", abs(vals[0]), |
|---|
| 597 | 625 | -vals[1]); |
|---|
| 598 | 626 | else |
|---|
| 599 | | - return snprintf(buf, len, "%d.%09u", vals[0], vals[1]); |
|---|
| 627 | + return scnprintf(buf, len, "%d.%09u", vals[0], vals[1]); |
|---|
| 600 | 628 | case IIO_VAL_FRACTIONAL: |
|---|
| 601 | 629 | tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]); |
|---|
| 602 | 630 | tmp1 = vals[1]; |
|---|
| 603 | 631 | tmp0 = (int)div_s64_rem(tmp, 1000000000, &tmp1); |
|---|
| 604 | | - return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1)); |
|---|
| 632 | + return scnprintf(buf, len, "%d.%09u", tmp0, abs(tmp1)); |
|---|
| 605 | 633 | case IIO_VAL_FRACTIONAL_LOG2: |
|---|
| 606 | 634 | tmp = shift_right((s64)vals[0] * 1000000000LL, vals[1]); |
|---|
| 607 | 635 | tmp0 = (int)div_s64_rem(tmp, 1000000000LL, &tmp1); |
|---|
| 608 | | - return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1)); |
|---|
| 636 | + return scnprintf(buf, len, "%d.%09u", tmp0, abs(tmp1)); |
|---|
| 609 | 637 | case IIO_VAL_INT_MULTIPLE: |
|---|
| 610 | 638 | { |
|---|
| 611 | 639 | int i; |
|---|
| 612 | 640 | int l = 0; |
|---|
| 613 | 641 | |
|---|
| 614 | 642 | for (i = 0; i < size; ++i) { |
|---|
| 615 | | - l += snprintf(&buf[l], len - l, "%d ", vals[i]); |
|---|
| 643 | + l += scnprintf(&buf[l], len - l, "%d ", vals[i]); |
|---|
| 616 | 644 | if (l >= len) |
|---|
| 617 | 645 | break; |
|---|
| 618 | 646 | } |
|---|
| 619 | 647 | return l; |
|---|
| 620 | 648 | } |
|---|
| 649 | + case IIO_VAL_CHAR: |
|---|
| 650 | + return scnprintf(buf, len, "%c", (char)vals[0]); |
|---|
| 621 | 651 | default: |
|---|
| 622 | 652 | return 0; |
|---|
| 623 | 653 | } |
|---|
| .. | .. |
|---|
| 688 | 718 | if (len >= PAGE_SIZE) |
|---|
| 689 | 719 | return -EFBIG; |
|---|
| 690 | 720 | if (i < length - 1) |
|---|
| 691 | | - len += snprintf(buf + len, PAGE_SIZE - len, |
|---|
| 721 | + len += scnprintf(buf + len, PAGE_SIZE - len, |
|---|
| 692 | 722 | " "); |
|---|
| 693 | 723 | else |
|---|
| 694 | | - len += snprintf(buf + len, PAGE_SIZE - len, |
|---|
| 724 | + len += scnprintf(buf + len, PAGE_SIZE - len, |
|---|
| 695 | 725 | "\n"); |
|---|
| 696 | 726 | if (len >= PAGE_SIZE) |
|---|
| 697 | 727 | return -EFBIG; |
|---|
| .. | .. |
|---|
| 704 | 734 | if (len >= PAGE_SIZE) |
|---|
| 705 | 735 | return -EFBIG; |
|---|
| 706 | 736 | if (i < length / 2 - 1) |
|---|
| 707 | | - len += snprintf(buf + len, PAGE_SIZE - len, |
|---|
| 737 | + len += scnprintf(buf + len, PAGE_SIZE - len, |
|---|
| 708 | 738 | " "); |
|---|
| 709 | 739 | else |
|---|
| 710 | | - len += snprintf(buf + len, PAGE_SIZE - len, |
|---|
| 740 | + len += scnprintf(buf + len, PAGE_SIZE - len, |
|---|
| 711 | 741 | "\n"); |
|---|
| 712 | 742 | if (len >= PAGE_SIZE) |
|---|
| 713 | 743 | return -EFBIG; |
|---|
| .. | .. |
|---|
| 731 | 761 | if (len >= PAGE_SIZE) |
|---|
| 732 | 762 | return -EFBIG; |
|---|
| 733 | 763 | if (i < 2) |
|---|
| 734 | | - len += snprintf(buf + len, PAGE_SIZE - len, |
|---|
| 764 | + len += scnprintf(buf + len, PAGE_SIZE - len, |
|---|
| 735 | 765 | " "); |
|---|
| 736 | 766 | else |
|---|
| 737 | | - len += snprintf(buf + len, PAGE_SIZE - len, |
|---|
| 767 | + len += scnprintf(buf + len, PAGE_SIZE - len, |
|---|
| 738 | 768 | "]\n"); |
|---|
| 739 | 769 | if (len >= PAGE_SIZE) |
|---|
| 740 | 770 | return -EFBIG; |
|---|
| .. | .. |
|---|
| 747 | 777 | if (len >= PAGE_SIZE) |
|---|
| 748 | 778 | return -EFBIG; |
|---|
| 749 | 779 | if (i < 2) |
|---|
| 750 | | - len += snprintf(buf + len, PAGE_SIZE - len, |
|---|
| 780 | + len += scnprintf(buf + len, PAGE_SIZE - len, |
|---|
| 751 | 781 | " "); |
|---|
| 752 | 782 | else |
|---|
| 753 | | - len += snprintf(buf + len, PAGE_SIZE - len, |
|---|
| 783 | + len += scnprintf(buf + len, PAGE_SIZE - len, |
|---|
| 754 | 784 | "]\n"); |
|---|
| 755 | 785 | if (len >= PAGE_SIZE) |
|---|
| 756 | 786 | return -EFBIG; |
|---|
| .. | .. |
|---|
| 788 | 818 | } |
|---|
| 789 | 819 | |
|---|
| 790 | 820 | /** |
|---|
| 791 | | - * iio_str_to_fixpoint() - Parse a fixed-point number from a string |
|---|
| 821 | + * __iio_str_to_fixpoint() - Parse a fixed-point number from a string |
|---|
| 792 | 822 | * @str: The string to parse |
|---|
| 793 | 823 | * @fract_mult: Multiplier for the first decimal place, should be a power of 10 |
|---|
| 794 | 824 | * @integer: The integer part of the number |
|---|
| 795 | 825 | * @fract: The fractional part of the number |
|---|
| 826 | + * @scale_db: True if this should parse as dB |
|---|
| 796 | 827 | * |
|---|
| 797 | 828 | * Returns 0 on success, or a negative error code if the string could not be |
|---|
| 798 | 829 | * parsed. |
|---|
| 799 | 830 | */ |
|---|
| 800 | | -int iio_str_to_fixpoint(const char *str, int fract_mult, |
|---|
| 801 | | - int *integer, int *fract) |
|---|
| 831 | +static int __iio_str_to_fixpoint(const char *str, int fract_mult, |
|---|
| 832 | + int *integer, int *fract, bool scale_db) |
|---|
| 802 | 833 | { |
|---|
| 803 | 834 | int i = 0, f = 0; |
|---|
| 804 | 835 | bool integer_part = true, negative = false; |
|---|
| .. | .. |
|---|
| 829 | 860 | break; |
|---|
| 830 | 861 | else |
|---|
| 831 | 862 | return -EINVAL; |
|---|
| 863 | + } else if (!strncmp(str, " dB", sizeof(" dB") - 1) && scale_db) { |
|---|
| 864 | + /* Ignore the dB suffix */ |
|---|
| 865 | + str += sizeof(" dB") - 1; |
|---|
| 866 | + continue; |
|---|
| 867 | + } else if (!strncmp(str, "dB", sizeof("dB") - 1) && scale_db) { |
|---|
| 868 | + /* Ignore the dB suffix */ |
|---|
| 869 | + str += sizeof("dB") - 1; |
|---|
| 870 | + continue; |
|---|
| 832 | 871 | } else if (*str == '.' && integer_part) { |
|---|
| 833 | 872 | integer_part = false; |
|---|
| 834 | 873 | } else { |
|---|
| .. | .. |
|---|
| 849 | 888 | |
|---|
| 850 | 889 | return 0; |
|---|
| 851 | 890 | } |
|---|
| 891 | + |
|---|
| 892 | +/** |
|---|
| 893 | + * iio_str_to_fixpoint() - Parse a fixed-point number from a string |
|---|
| 894 | + * @str: The string to parse |
|---|
| 895 | + * @fract_mult: Multiplier for the first decimal place, should be a power of 10 |
|---|
| 896 | + * @integer: The integer part of the number |
|---|
| 897 | + * @fract: The fractional part of the number |
|---|
| 898 | + * |
|---|
| 899 | + * Returns 0 on success, or a negative error code if the string could not be |
|---|
| 900 | + * parsed. |
|---|
| 901 | + */ |
|---|
| 902 | +int iio_str_to_fixpoint(const char *str, int fract_mult, |
|---|
| 903 | + int *integer, int *fract) |
|---|
| 904 | +{ |
|---|
| 905 | + return __iio_str_to_fixpoint(str, fract_mult, integer, fract, false); |
|---|
| 906 | +} |
|---|
| 852 | 907 | EXPORT_SYMBOL_GPL(iio_str_to_fixpoint); |
|---|
| 853 | 908 | |
|---|
| 854 | 909 | static ssize_t iio_write_channel_info(struct device *dev, |
|---|
| .. | .. |
|---|
| 859 | 914 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
|---|
| 860 | 915 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
|---|
| 861 | 916 | int ret, fract_mult = 100000; |
|---|
| 862 | | - int integer, fract; |
|---|
| 917 | + int integer, fract = 0; |
|---|
| 918 | + bool is_char = false; |
|---|
| 919 | + bool scale_db = false; |
|---|
| 863 | 920 | |
|---|
| 864 | 921 | /* Assumes decimal - precision based on number of digits */ |
|---|
| 865 | 922 | if (!indio_dev->info->write_raw) |
|---|
| .. | .. |
|---|
| 871 | 928 | case IIO_VAL_INT: |
|---|
| 872 | 929 | fract_mult = 0; |
|---|
| 873 | 930 | break; |
|---|
| 931 | + case IIO_VAL_INT_PLUS_MICRO_DB: |
|---|
| 932 | + scale_db = true; |
|---|
| 933 | + fallthrough; |
|---|
| 874 | 934 | case IIO_VAL_INT_PLUS_MICRO: |
|---|
| 875 | 935 | fract_mult = 100000; |
|---|
| 876 | 936 | break; |
|---|
| 877 | 937 | case IIO_VAL_INT_PLUS_NANO: |
|---|
| 878 | 938 | fract_mult = 100000000; |
|---|
| 879 | 939 | break; |
|---|
| 940 | + case IIO_VAL_CHAR: |
|---|
| 941 | + is_char = true; |
|---|
| 942 | + break; |
|---|
| 880 | 943 | default: |
|---|
| 881 | 944 | return -EINVAL; |
|---|
| 882 | 945 | } |
|---|
| 883 | 946 | |
|---|
| 884 | | - ret = iio_str_to_fixpoint(buf, fract_mult, &integer, &fract); |
|---|
| 885 | | - if (ret) |
|---|
| 886 | | - return ret; |
|---|
| 947 | + if (is_char) { |
|---|
| 948 | + char ch; |
|---|
| 949 | + |
|---|
| 950 | + if (sscanf(buf, "%c", &ch) != 1) |
|---|
| 951 | + return -EINVAL; |
|---|
| 952 | + integer = ch; |
|---|
| 953 | + } else { |
|---|
| 954 | + ret = __iio_str_to_fixpoint(buf, fract_mult, &integer, &fract, |
|---|
| 955 | + scale_db); |
|---|
| 956 | + if (ret) |
|---|
| 957 | + return ret; |
|---|
| 958 | + } |
|---|
| 887 | 959 | |
|---|
| 888 | 960 | ret = indio_dev->info->write_raw(indio_dev, this_attr->c, |
|---|
| 889 | 961 | integer, fract, this_attr->address); |
|---|
| .. | .. |
|---|
| 1080 | 1152 | enum iio_shared_by shared_by, |
|---|
| 1081 | 1153 | const long *infomask) |
|---|
| 1082 | 1154 | { |
|---|
| 1155 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
|---|
| 1083 | 1156 | int i, ret, attrcount = 0; |
|---|
| 1084 | 1157 | |
|---|
| 1085 | 1158 | for_each_set_bit(i, infomask, sizeof(*infomask)*8) { |
|---|
| .. | .. |
|---|
| 1092 | 1165 | i, |
|---|
| 1093 | 1166 | shared_by, |
|---|
| 1094 | 1167 | &indio_dev->dev, |
|---|
| 1095 | | - &indio_dev->channel_attr_list); |
|---|
| 1168 | + &iio_dev_opaque->channel_attr_list); |
|---|
| 1096 | 1169 | if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE)) |
|---|
| 1097 | 1170 | continue; |
|---|
| 1098 | 1171 | else if (ret < 0) |
|---|
| .. | .. |
|---|
| 1108 | 1181 | enum iio_shared_by shared_by, |
|---|
| 1109 | 1182 | const long *infomask) |
|---|
| 1110 | 1183 | { |
|---|
| 1184 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
|---|
| 1111 | 1185 | int i, ret, attrcount = 0; |
|---|
| 1112 | 1186 | char *avail_postfix; |
|---|
| 1113 | 1187 | |
|---|
| 1114 | 1188 | for_each_set_bit(i, infomask, sizeof(*infomask) * 8) { |
|---|
| 1189 | + if (i >= ARRAY_SIZE(iio_chan_info_postfix)) |
|---|
| 1190 | + return -EINVAL; |
|---|
| 1115 | 1191 | avail_postfix = kasprintf(GFP_KERNEL, |
|---|
| 1116 | 1192 | "%s_available", |
|---|
| 1117 | 1193 | iio_chan_info_postfix[i]); |
|---|
| .. | .. |
|---|
| 1125 | 1201 | i, |
|---|
| 1126 | 1202 | shared_by, |
|---|
| 1127 | 1203 | &indio_dev->dev, |
|---|
| 1128 | | - &indio_dev->channel_attr_list); |
|---|
| 1204 | + &iio_dev_opaque->channel_attr_list); |
|---|
| 1129 | 1205 | kfree(avail_postfix); |
|---|
| 1130 | 1206 | if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE)) |
|---|
| 1131 | 1207 | continue; |
|---|
| .. | .. |
|---|
| 1140 | 1216 | static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, |
|---|
| 1141 | 1217 | struct iio_chan_spec const *chan) |
|---|
| 1142 | 1218 | { |
|---|
| 1219 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
|---|
| 1143 | 1220 | int ret, attrcount = 0; |
|---|
| 1144 | 1221 | const struct iio_chan_spec_ext_info *ext_info; |
|---|
| 1145 | 1222 | |
|---|
| .. | .. |
|---|
| 1215 | 1292 | i, |
|---|
| 1216 | 1293 | ext_info->shared, |
|---|
| 1217 | 1294 | &indio_dev->dev, |
|---|
| 1218 | | - &indio_dev->channel_attr_list); |
|---|
| 1295 | + &iio_dev_opaque->channel_attr_list); |
|---|
| 1219 | 1296 | i++; |
|---|
| 1220 | 1297 | if (ret == -EBUSY && ext_info->shared) |
|---|
| 1221 | 1298 | continue; |
|---|
| .. | .. |
|---|
| 1257 | 1334 | } |
|---|
| 1258 | 1335 | |
|---|
| 1259 | 1336 | static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); |
|---|
| 1337 | + |
|---|
| 1338 | +static ssize_t iio_show_dev_label(struct device *dev, |
|---|
| 1339 | + struct device_attribute *attr, |
|---|
| 1340 | + char *buf) |
|---|
| 1341 | +{ |
|---|
| 1342 | + struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
|---|
| 1343 | + return snprintf(buf, PAGE_SIZE, "%s\n", indio_dev->label); |
|---|
| 1344 | +} |
|---|
| 1345 | + |
|---|
| 1346 | +static DEVICE_ATTR(label, S_IRUGO, iio_show_dev_label, NULL); |
|---|
| 1260 | 1347 | |
|---|
| 1261 | 1348 | static ssize_t iio_show_timestamp_clock(struct device *dev, |
|---|
| 1262 | 1349 | struct device_attribute *attr, |
|---|
| .. | .. |
|---|
| 1340 | 1427 | |
|---|
| 1341 | 1428 | static int iio_device_register_sysfs(struct iio_dev *indio_dev) |
|---|
| 1342 | 1429 | { |
|---|
| 1430 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
|---|
| 1343 | 1431 | int i, ret = 0, attrcount, attrn, attrcount_orig = 0; |
|---|
| 1344 | 1432 | struct iio_dev_attr *p; |
|---|
| 1345 | 1433 | struct attribute **attr, *clk = NULL; |
|---|
| .. | .. |
|---|
| 1369 | 1457 | attrcount += ret; |
|---|
| 1370 | 1458 | } |
|---|
| 1371 | 1459 | |
|---|
| 1372 | | - if (indio_dev->event_interface) |
|---|
| 1460 | + if (iio_dev_opaque->event_interface) |
|---|
| 1373 | 1461 | clk = &dev_attr_current_timestamp_clock.attr; |
|---|
| 1374 | 1462 | |
|---|
| 1375 | 1463 | if (indio_dev->name) |
|---|
| 1376 | 1464 | attrcount++; |
|---|
| 1465 | + if (indio_dev->label) |
|---|
| 1466 | + attrcount++; |
|---|
| 1377 | 1467 | if (clk) |
|---|
| 1378 | 1468 | attrcount++; |
|---|
| 1379 | 1469 | |
|---|
| 1380 | | - indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1, |
|---|
| 1381 | | - sizeof(indio_dev->chan_attr_group.attrs[0]), |
|---|
| 1382 | | - GFP_KERNEL); |
|---|
| 1383 | | - if (indio_dev->chan_attr_group.attrs == NULL) { |
|---|
| 1470 | + iio_dev_opaque->chan_attr_group.attrs = |
|---|
| 1471 | + kcalloc(attrcount + 1, |
|---|
| 1472 | + sizeof(iio_dev_opaque->chan_attr_group.attrs[0]), |
|---|
| 1473 | + GFP_KERNEL); |
|---|
| 1474 | + if (iio_dev_opaque->chan_attr_group.attrs == NULL) { |
|---|
| 1384 | 1475 | ret = -ENOMEM; |
|---|
| 1385 | 1476 | goto error_clear_attrs; |
|---|
| 1386 | 1477 | } |
|---|
| 1387 | 1478 | /* Copy across original attributes */ |
|---|
| 1388 | 1479 | if (indio_dev->info->attrs) |
|---|
| 1389 | | - memcpy(indio_dev->chan_attr_group.attrs, |
|---|
| 1480 | + memcpy(iio_dev_opaque->chan_attr_group.attrs, |
|---|
| 1390 | 1481 | indio_dev->info->attrs->attrs, |
|---|
| 1391 | | - sizeof(indio_dev->chan_attr_group.attrs[0]) |
|---|
| 1482 | + sizeof(iio_dev_opaque->chan_attr_group.attrs[0]) |
|---|
| 1392 | 1483 | *attrcount_orig); |
|---|
| 1393 | 1484 | attrn = attrcount_orig; |
|---|
| 1394 | 1485 | /* Add all elements from the list. */ |
|---|
| 1395 | | - list_for_each_entry(p, &indio_dev->channel_attr_list, l) |
|---|
| 1396 | | - indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; |
|---|
| 1486 | + list_for_each_entry(p, &iio_dev_opaque->channel_attr_list, l) |
|---|
| 1487 | + iio_dev_opaque->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; |
|---|
| 1397 | 1488 | if (indio_dev->name) |
|---|
| 1398 | | - indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; |
|---|
| 1489 | + iio_dev_opaque->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; |
|---|
| 1490 | + if (indio_dev->label) |
|---|
| 1491 | + iio_dev_opaque->chan_attr_group.attrs[attrn++] = &dev_attr_label.attr; |
|---|
| 1399 | 1492 | if (clk) |
|---|
| 1400 | | - indio_dev->chan_attr_group.attrs[attrn++] = clk; |
|---|
| 1493 | + iio_dev_opaque->chan_attr_group.attrs[attrn++] = clk; |
|---|
| 1401 | 1494 | |
|---|
| 1402 | 1495 | indio_dev->groups[indio_dev->groupcounter++] = |
|---|
| 1403 | | - &indio_dev->chan_attr_group; |
|---|
| 1496 | + &iio_dev_opaque->chan_attr_group; |
|---|
| 1404 | 1497 | |
|---|
| 1405 | 1498 | return 0; |
|---|
| 1406 | 1499 | |
|---|
| 1407 | 1500 | error_clear_attrs: |
|---|
| 1408 | | - iio_free_chan_devattr_list(&indio_dev->channel_attr_list); |
|---|
| 1501 | + iio_free_chan_devattr_list(&iio_dev_opaque->channel_attr_list); |
|---|
| 1409 | 1502 | |
|---|
| 1410 | 1503 | return ret; |
|---|
| 1411 | 1504 | } |
|---|
| 1412 | 1505 | |
|---|
| 1413 | 1506 | static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) |
|---|
| 1414 | 1507 | { |
|---|
| 1508 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
|---|
| 1415 | 1509 | |
|---|
| 1416 | | - iio_free_chan_devattr_list(&indio_dev->channel_attr_list); |
|---|
| 1417 | | - kfree(indio_dev->chan_attr_group.attrs); |
|---|
| 1418 | | - indio_dev->chan_attr_group.attrs = NULL; |
|---|
| 1510 | + iio_free_chan_devattr_list(&iio_dev_opaque->channel_attr_list); |
|---|
| 1511 | + kfree(iio_dev_opaque->chan_attr_group.attrs); |
|---|
| 1512 | + iio_dev_opaque->chan_attr_group.attrs = NULL; |
|---|
| 1419 | 1513 | } |
|---|
| 1420 | 1514 | |
|---|
| 1421 | 1515 | static void iio_dev_release(struct device *device) |
|---|
| 1422 | 1516 | { |
|---|
| 1423 | 1517 | struct iio_dev *indio_dev = dev_to_iio_dev(device); |
|---|
| 1518 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
|---|
| 1519 | + |
|---|
| 1424 | 1520 | if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES) |
|---|
| 1425 | 1521 | iio_device_unregister_trigger_consumer(indio_dev); |
|---|
| 1426 | 1522 | iio_device_unregister_eventset(indio_dev); |
|---|
| .. | .. |
|---|
| 1429 | 1525 | iio_buffer_put(indio_dev->buffer); |
|---|
| 1430 | 1526 | |
|---|
| 1431 | 1527 | ida_simple_remove(&iio_ida, indio_dev->id); |
|---|
| 1432 | | - kfree(indio_dev); |
|---|
| 1528 | + kfree(iio_dev_opaque); |
|---|
| 1433 | 1529 | } |
|---|
| 1434 | 1530 | |
|---|
| 1435 | 1531 | struct device_type iio_device_type = { |
|---|
| .. | .. |
|---|
| 1439 | 1535 | |
|---|
| 1440 | 1536 | /** |
|---|
| 1441 | 1537 | * iio_device_alloc() - allocate an iio_dev from a driver |
|---|
| 1538 | + * @parent: Parent device. |
|---|
| 1442 | 1539 | * @sizeof_priv: Space to allocate for private structure. |
|---|
| 1443 | 1540 | **/ |
|---|
| 1444 | | -struct iio_dev *iio_device_alloc(int sizeof_priv) |
|---|
| 1541 | +struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) |
|---|
| 1445 | 1542 | { |
|---|
| 1543 | + struct iio_dev_opaque *iio_dev_opaque; |
|---|
| 1446 | 1544 | struct iio_dev *dev; |
|---|
| 1447 | 1545 | size_t alloc_size; |
|---|
| 1448 | 1546 | |
|---|
| 1449 | | - alloc_size = sizeof(struct iio_dev); |
|---|
| 1547 | + alloc_size = sizeof(struct iio_dev_opaque); |
|---|
| 1450 | 1548 | if (sizeof_priv) { |
|---|
| 1451 | 1549 | alloc_size = ALIGN(alloc_size, IIO_ALIGN); |
|---|
| 1452 | 1550 | alloc_size += sizeof_priv; |
|---|
| 1453 | 1551 | } |
|---|
| 1454 | | - /* ensure 32-byte alignment of whole construct ? */ |
|---|
| 1455 | | - alloc_size += IIO_ALIGN - 1; |
|---|
| 1456 | 1552 | |
|---|
| 1457 | | - dev = kzalloc(alloc_size, GFP_KERNEL); |
|---|
| 1553 | + iio_dev_opaque = kzalloc(alloc_size, GFP_KERNEL); |
|---|
| 1554 | + if (!iio_dev_opaque) |
|---|
| 1555 | + return NULL; |
|---|
| 1458 | 1556 | |
|---|
| 1459 | | - if (dev) { |
|---|
| 1460 | | - dev->dev.groups = dev->groups; |
|---|
| 1461 | | - dev->dev.type = &iio_device_type; |
|---|
| 1462 | | - dev->dev.bus = &iio_bus_type; |
|---|
| 1463 | | - device_initialize(&dev->dev); |
|---|
| 1464 | | - dev_set_drvdata(&dev->dev, (void *)dev); |
|---|
| 1465 | | - mutex_init(&dev->mlock); |
|---|
| 1466 | | - mutex_init(&dev->info_exist_lock); |
|---|
| 1467 | | - INIT_LIST_HEAD(&dev->channel_attr_list); |
|---|
| 1557 | + dev = &iio_dev_opaque->indio_dev; |
|---|
| 1558 | + dev->priv = (char *)iio_dev_opaque + |
|---|
| 1559 | + ALIGN(sizeof(struct iio_dev_opaque), IIO_ALIGN); |
|---|
| 1468 | 1560 | |
|---|
| 1469 | | - dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); |
|---|
| 1470 | | - if (dev->id < 0) { |
|---|
| 1471 | | - /* cannot use a dev_err as the name isn't available */ |
|---|
| 1472 | | - pr_err("failed to get device id\n"); |
|---|
| 1473 | | - kfree(dev); |
|---|
| 1474 | | - return NULL; |
|---|
| 1475 | | - } |
|---|
| 1476 | | - dev_set_name(&dev->dev, "iio:device%d", dev->id); |
|---|
| 1477 | | - INIT_LIST_HEAD(&dev->buffer_list); |
|---|
| 1561 | + dev->dev.parent = parent; |
|---|
| 1562 | + dev->dev.groups = dev->groups; |
|---|
| 1563 | + dev->dev.type = &iio_device_type; |
|---|
| 1564 | + dev->dev.bus = &iio_bus_type; |
|---|
| 1565 | + device_initialize(&dev->dev); |
|---|
| 1566 | + dev_set_drvdata(&dev->dev, (void *)dev); |
|---|
| 1567 | + mutex_init(&dev->mlock); |
|---|
| 1568 | + mutex_init(&dev->info_exist_lock); |
|---|
| 1569 | + INIT_LIST_HEAD(&iio_dev_opaque->channel_attr_list); |
|---|
| 1570 | + |
|---|
| 1571 | + dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); |
|---|
| 1572 | + if (dev->id < 0) { |
|---|
| 1573 | + /* cannot use a dev_err as the name isn't available */ |
|---|
| 1574 | + pr_err("failed to get device id\n"); |
|---|
| 1575 | + kfree(iio_dev_opaque); |
|---|
| 1576 | + return NULL; |
|---|
| 1478 | 1577 | } |
|---|
| 1578 | + dev_set_name(&dev->dev, "iio:device%d", dev->id); |
|---|
| 1579 | + INIT_LIST_HEAD(&iio_dev_opaque->buffer_list); |
|---|
| 1479 | 1580 | |
|---|
| 1480 | 1581 | return dev; |
|---|
| 1481 | 1582 | } |
|---|
| .. | .. |
|---|
| 1497 | 1598 | iio_device_free(*(struct iio_dev **)res); |
|---|
| 1498 | 1599 | } |
|---|
| 1499 | 1600 | |
|---|
| 1500 | | -int devm_iio_device_match(struct device *dev, void *res, void *data) |
|---|
| 1501 | | -{ |
|---|
| 1502 | | - struct iio_dev **r = res; |
|---|
| 1503 | | - if (!r || !*r) { |
|---|
| 1504 | | - WARN_ON(!r || !*r); |
|---|
| 1505 | | - return 0; |
|---|
| 1506 | | - } |
|---|
| 1507 | | - return *r == data; |
|---|
| 1508 | | -} |
|---|
| 1509 | | -EXPORT_SYMBOL_GPL(devm_iio_device_match); |
|---|
| 1510 | | - |
|---|
| 1511 | 1601 | /** |
|---|
| 1512 | 1602 | * devm_iio_device_alloc - Resource-managed iio_device_alloc() |
|---|
| 1513 | | - * @dev: Device to allocate iio_dev for |
|---|
| 1603 | + * @parent: Device to allocate iio_dev for, and parent for this IIO device |
|---|
| 1514 | 1604 | * @sizeof_priv: Space to allocate for private structure. |
|---|
| 1515 | 1605 | * |
|---|
| 1516 | 1606 | * Managed iio_device_alloc. iio_dev allocated with this function is |
|---|
| 1517 | 1607 | * automatically freed on driver detach. |
|---|
| 1518 | 1608 | * |
|---|
| 1519 | | - * If an iio_dev allocated with this function needs to be freed separately, |
|---|
| 1520 | | - * devm_iio_device_free() must be used. |
|---|
| 1521 | | - * |
|---|
| 1522 | 1609 | * RETURNS: |
|---|
| 1523 | 1610 | * Pointer to allocated iio_dev on success, NULL on failure. |
|---|
| 1524 | 1611 | */ |
|---|
| 1525 | | -struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv) |
|---|
| 1612 | +struct iio_dev *devm_iio_device_alloc(struct device *parent, int sizeof_priv) |
|---|
| 1526 | 1613 | { |
|---|
| 1527 | 1614 | struct iio_dev **ptr, *iio_dev; |
|---|
| 1528 | 1615 | |
|---|
| .. | .. |
|---|
| 1531 | 1618 | if (!ptr) |
|---|
| 1532 | 1619 | return NULL; |
|---|
| 1533 | 1620 | |
|---|
| 1534 | | - iio_dev = iio_device_alloc(sizeof_priv); |
|---|
| 1621 | + iio_dev = iio_device_alloc(parent, sizeof_priv); |
|---|
| 1535 | 1622 | if (iio_dev) { |
|---|
| 1536 | 1623 | *ptr = iio_dev; |
|---|
| 1537 | | - devres_add(dev, ptr); |
|---|
| 1624 | + devres_add(parent, ptr); |
|---|
| 1538 | 1625 | } else { |
|---|
| 1539 | 1626 | devres_free(ptr); |
|---|
| 1540 | 1627 | } |
|---|
| .. | .. |
|---|
| 1542 | 1629 | return iio_dev; |
|---|
| 1543 | 1630 | } |
|---|
| 1544 | 1631 | EXPORT_SYMBOL_GPL(devm_iio_device_alloc); |
|---|
| 1545 | | - |
|---|
| 1546 | | -/** |
|---|
| 1547 | | - * devm_iio_device_free - Resource-managed iio_device_free() |
|---|
| 1548 | | - * @dev: Device this iio_dev belongs to |
|---|
| 1549 | | - * @iio_dev: the iio_dev associated with the device |
|---|
| 1550 | | - * |
|---|
| 1551 | | - * Free iio_dev allocated with devm_iio_device_alloc(). |
|---|
| 1552 | | - */ |
|---|
| 1553 | | -void devm_iio_device_free(struct device *dev, struct iio_dev *iio_dev) |
|---|
| 1554 | | -{ |
|---|
| 1555 | | - int rc; |
|---|
| 1556 | | - |
|---|
| 1557 | | - rc = devres_release(dev, devm_iio_device_release, |
|---|
| 1558 | | - devm_iio_device_match, iio_dev); |
|---|
| 1559 | | - WARN_ON(rc); |
|---|
| 1560 | | -} |
|---|
| 1561 | | -EXPORT_SYMBOL_GPL(devm_iio_device_free); |
|---|
| 1562 | 1632 | |
|---|
| 1563 | 1633 | /** |
|---|
| 1564 | 1634 | * iio_chrdev_open() - chrdev file open for buffer access and ioctls |
|---|
| .. | .. |
|---|
| 1623 | 1693 | } |
|---|
| 1624 | 1694 | |
|---|
| 1625 | 1695 | static const struct file_operations iio_buffer_fileops = { |
|---|
| 1626 | | - .read = iio_buffer_read_first_n_outer_addr, |
|---|
| 1696 | + .read = iio_buffer_read_outer_addr, |
|---|
| 1627 | 1697 | .release = iio_chrdev_release, |
|---|
| 1628 | 1698 | .open = iio_chrdev_open, |
|---|
| 1629 | 1699 | .poll = iio_buffer_poll_addr, |
|---|
| 1630 | 1700 | .owner = THIS_MODULE, |
|---|
| 1631 | 1701 | .llseek = noop_llseek, |
|---|
| 1632 | 1702 | .unlocked_ioctl = iio_ioctl, |
|---|
| 1633 | | - .compat_ioctl = iio_ioctl, |
|---|
| 1703 | + .compat_ioctl = compat_ptr_ioctl, |
|---|
| 1634 | 1704 | }; |
|---|
| 1635 | 1705 | |
|---|
| 1636 | 1706 | static int iio_check_unique_scan_index(struct iio_dev *indio_dev) |
|---|
| .. | .. |
|---|
| 1662 | 1732 | { |
|---|
| 1663 | 1733 | int ret; |
|---|
| 1664 | 1734 | |
|---|
| 1735 | + if (!indio_dev->info) |
|---|
| 1736 | + return -EINVAL; |
|---|
| 1737 | + |
|---|
| 1665 | 1738 | indio_dev->driver_module = this_mod; |
|---|
| 1666 | 1739 | /* If the calling driver did not initialize of_node, do it here */ |
|---|
| 1667 | 1740 | if (!indio_dev->dev.of_node && indio_dev->dev.parent) |
|---|
| 1668 | 1741 | indio_dev->dev.of_node = indio_dev->dev.parent->of_node; |
|---|
| 1742 | + |
|---|
| 1743 | + indio_dev->label = of_get_property(indio_dev->dev.of_node, "label", |
|---|
| 1744 | + NULL); |
|---|
| 1669 | 1745 | |
|---|
| 1670 | 1746 | ret = iio_check_unique_scan_index(indio_dev); |
|---|
| 1671 | 1747 | if (ret < 0) |
|---|
| .. | .. |
|---|
| 1674 | 1750 | /* configure elements for the chrdev */ |
|---|
| 1675 | 1751 | indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); |
|---|
| 1676 | 1752 | |
|---|
| 1677 | | - ret = iio_device_register_debugfs(indio_dev); |
|---|
| 1678 | | - if (ret) { |
|---|
| 1679 | | - dev_err(indio_dev->dev.parent, |
|---|
| 1680 | | - "Failed to register debugfs interfaces\n"); |
|---|
| 1681 | | - return ret; |
|---|
| 1682 | | - } |
|---|
| 1753 | + iio_device_register_debugfs(indio_dev); |
|---|
| 1683 | 1754 | |
|---|
| 1684 | 1755 | ret = iio_buffer_alloc_sysfs_and_mask(indio_dev); |
|---|
| 1685 | 1756 | if (ret) { |
|---|
| .. | .. |
|---|
| 1779 | 1850 | return ret; |
|---|
| 1780 | 1851 | } |
|---|
| 1781 | 1852 | EXPORT_SYMBOL_GPL(__devm_iio_device_register); |
|---|
| 1782 | | - |
|---|
| 1783 | | -/** |
|---|
| 1784 | | - * devm_iio_device_unregister - Resource-managed iio_device_unregister() |
|---|
| 1785 | | - * @dev: Device this iio_dev belongs to |
|---|
| 1786 | | - * @indio_dev: the iio_dev associated with the device |
|---|
| 1787 | | - * |
|---|
| 1788 | | - * Unregister iio_dev registered with devm_iio_device_register(). |
|---|
| 1789 | | - */ |
|---|
| 1790 | | -void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev) |
|---|
| 1791 | | -{ |
|---|
| 1792 | | - int rc; |
|---|
| 1793 | | - |
|---|
| 1794 | | - rc = devres_release(dev, devm_iio_device_unreg, |
|---|
| 1795 | | - devm_iio_device_match, indio_dev); |
|---|
| 1796 | | - WARN_ON(rc); |
|---|
| 1797 | | -} |
|---|
| 1798 | | -EXPORT_SYMBOL_GPL(devm_iio_device_unregister); |
|---|
| 1799 | 1853 | |
|---|
| 1800 | 1854 | /** |
|---|
| 1801 | 1855 | * iio_device_claim_direct_mode - Keep device in direct mode |
|---|