industrialio-core.c revision f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0
1847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* The industrial I/O core 2847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * 3847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * Copyright (c) 2008 Jonathan Cameron 4847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * 5847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * This program is free software; you can redistribute it and/or modify it 6847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * under the terms of the GNU General Public License version 2 as published by 7847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * the Free Software Foundation. 8847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * 9847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * Based on elements of hwmon and input subsystems. 10847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron */ 11847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 12847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/kernel.h> 13847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/module.h> 14847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/idr.h> 15847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/kdev_t.h> 16847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/err.h> 17847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/device.h> 18847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/fs.h> 19847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/poll.h> 20ffc18afa11f32d59839b5f3c605c64c63d38c218Jonathan Cameron#include <linux/sched.h> 214439c9353589f4def506b94f8f6344433333a4b9Jeff Mahoney#include <linux/wait.h> 22847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/cdev.h> 235a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 248e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron#include <linux/anon_inodes.h> 25847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include "iio.h" 26df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameron#include "iio_core.h" 276aea1c364cde5b28b551844b7b8925f523310a18Jonathan Cameron#include "iio_core_trigger.h" 287ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron#include "chrdev.h" 299dd1cb303c18f4508abc69f5b40f423ff36a9626Jonathan Cameron#include "sysfs.h" 309dd1cb303c18f4508abc69f5b40f423ff36a9626Jonathan Cameron 3147c24fdd4253a2c8d730b978a186923b1af5e879Jonathan Cameron/* IDA to assign each registered device a unique id*/ 32b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronstatic DEFINE_IDA(iio_ida); 33847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 34f625cb97d4d58f311a9606a4bcf9d9a334ca9952Jonathan Cameronstatic dev_t iio_devt; 35847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 36847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#define IIO_DEV_MAX 256 375aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronstruct bus_type iio_bus_type = { 38847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .name = "iio", 39847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}; 405aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan CameronEXPORT_SYMBOL(iio_bus_type); 41847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 421e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameronstatic const char * const iio_data_type_name[] = { 431e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron [IIO_RAW] = "raw", 441e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron [IIO_PROCESSED] = "input", 451e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron}; 461e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 47c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameronstatic const char * const iio_direction[] = { 48c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron [0] = "in", 49c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron [1] = "out", 50c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron}; 51c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron 52ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameronstatic const char * const iio_chan_type_name_spec[] = { 53c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron [IIO_VOLTAGE] = "voltage", 54faf290e867fd51e227165d0bef113b022520a58fMichael Hennerich [IIO_CURRENT] = "current", 55faf290e867fd51e227165d0bef113b022520a58fMichael Hennerich [IIO_POWER] = "power", 569bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_ACCEL] = "accel", 5741ea040c7b6daf05d4884097b0168e7b74c6c0d0Jonathan Cameron [IIO_ANGL_VEL] = "anglvel", 581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_MAGN] = "magn", 599bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_LIGHT] = "illuminance", 609bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_INTENSITY] = "intensity", 61f09f2c8142d275b0d9321d2ea93c8bd0d8dc32ecBryan Freed [IIO_PROXIMITY] = "proximity", 629bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_TEMP] = "temp", 631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_INCLI] = "incli", 641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_ROT] = "rot", 651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_ANGL] = "angl", 669bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_TIMESTAMP] = "timestamp", 6766dbe70437b561c241d1117dd291c11db21072fdJonathan Cameron [IIO_CAPACITANCE] = "capacitance", 681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 70330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameronstatic const char * const iio_modifier_names[] = { 711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_MOD_X] = "x", 721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_MOD_Y] = "y", 731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_MOD_Z] = "z", 74330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron [IIO_MOD_LIGHT_BOTH] = "both", 75330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron [IIO_MOD_LIGHT_IR] = "ir", 761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron/* relies on pairs of these shared then separate */ 791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_chan_info_postfix[] = { 801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_CHAN_INFO_SCALE_SHARED/2] = "scale", 811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_CHAN_INFO_OFFSET_SHARED/2] = "offset", 821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_CHAN_INFO_CALIBSCALE_SHARED/2] = "calibscale", 831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_CHAN_INFO_CALIBBIAS_SHARED/2] = "calibbias", 84eb7fea53e53ed47e82b4cc9911dd8fdc7f953de5Jonathan Cameron [IIO_CHAN_INFO_PEAK_SHARED/2] = "peak_raw", 85eb7fea53e53ed47e82b4cc9911dd8fdc7f953de5Jonathan Cameron [IIO_CHAN_INFO_PEAK_SCALE_SHARED/2] = "peak_scale", 867d43817803c6a1786d60834ea1a110360b098085Jonathan Cameron [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED/2] 877d43817803c6a1786d60834ea1a110360b098085Jonathan Cameron = "quadrature_correction_raw", 8866dbe70437b561c241d1117dd291c11db21072fdJonathan Cameron [IIO_CHAN_INFO_AVERAGE_RAW_SHARED/2] = "mean_raw", 891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 917ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron/** 927ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * struct iio_detected_event_list - list element for events that have occurred 937ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @list: linked list header 947ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @ev: the event itself 957ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron */ 967ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameronstruct iio_detected_event_list { 977ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron struct list_head list; 987ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron struct iio_event_data ev; 997ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron}; 1007ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron 1017ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron/** 1027ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * struct iio_event_interface - chrdev interface for an event line 1037ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @dev: device assocated with event interface 1047ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @wait: wait queue to allow blocking reads of events 1057ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @event_list_lock: mutex to protect the list of detected events 1067ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @det_events: list of detected events 1077ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @max_events: maximum number of events before new ones are dropped 1087ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @current_events: number of events in detected list 1096356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron * @flags: file operations related flags including busy flag. 1107ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron */ 1117ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameronstruct iio_event_interface { 1127ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron wait_queue_head_t wait; 1137ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron struct mutex event_list_lock; 1147ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron struct list_head det_events; 1157ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron int max_events; 1167ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron int current_events; 1177ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron struct list_head dev_attr_list; 1186356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron unsigned long flags; 11926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron struct attribute_group group; 1207ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron}; 1217ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron 122f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronint iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) 123847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 124f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron struct iio_event_interface *ev_int = indio_dev->event_interface; 125847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct iio_detected_event_list *ev; 126847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron int ret = 0; 127847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 128847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron /* Does anyone care? */ 129847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_lock(&ev_int->event_list_lock); 1306356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { 13175c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron if (ev_int->current_events == ev_int->max_events) { 13275c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 133847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 13475c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron } 135847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ev = kmalloc(sizeof(*ev), GFP_KERNEL); 136847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ev == NULL) { 137847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ret = -ENOMEM; 13875c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 139847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_ret; 140847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ev->ev.id = ev_code; 142847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ev->ev.timestamp = timestamp; 143847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1443b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron list_add_tail(&ev->list, &ev_int->det_events); 145847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ev_int->current_events++; 146847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 147847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron wake_up_interruptible(&ev_int->wait); 148847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } else 149847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 150847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 151847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret: 152847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 153847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 154847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_push_event); 155847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 156847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* This turns up an awful lot */ 157847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronssize_t iio_read_const_attr(struct device *dev, 158847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct device_attribute *attr, 159847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron char *buf) 160847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 161847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string); 162847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 163847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_read_const_attr); 164847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 16577712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic ssize_t iio_event_chrdev_read(struct file *filep, 16677712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown char __user *buf, 16777712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown size_t count, 16877712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown loff_t *f_ps) 169847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 170847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct iio_event_interface *ev_int = filep->private_data; 171847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct iio_detected_event_list *el; 172847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron int ret; 173847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron size_t len; 1746356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron 175847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_lock(&ev_int->event_list_lock); 1763b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron if (list_empty(&ev_int->det_events)) { 177847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (filep->f_flags & O_NONBLOCK) { 178847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ret = -EAGAIN; 179847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_mutex_unlock; 180847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 181847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 182847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron /* Blocking on device; waiting for something to be there */ 183847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ret = wait_event_interruptible(ev_int->wait, 184847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron !list_empty(&ev_int 1853b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron ->det_events)); 186847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret) 187847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_ret; 18825985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* Single access device so no one else can get the data */ 189847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_lock(&ev_int->event_list_lock); 190847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 191847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1923b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron el = list_first_entry(&ev_int->det_events, 193847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct iio_detected_event_list, 194847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron list); 195847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron len = sizeof el->ev; 196847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (copy_to_user(buf, &(el->ev), len)) { 197847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ret = -EFAULT; 198847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_mutex_unlock; 199847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 200847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron list_del(&el->list); 201847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ev_int->current_events--; 202847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 203847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron kfree(el); 204847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 205847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return len; 206847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 207847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_mutex_unlock: 208847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 209847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret: 210847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 211847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 212847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 213847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 21477712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic int iio_event_chrdev_release(struct inode *inode, struct file *filep) 215847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 2168e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron struct iio_event_interface *ev_int = filep->private_data; 217847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct iio_detected_event_list *el, *t; 2186356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron 219847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_lock(&ev_int->event_list_lock); 2206356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); 221847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron /* 222847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * In order to maintain a clean state for reopening, 223847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * clear out any awaiting events. The mask will prevent 224847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * any new __iio_push_event calls running. 225847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron */ 2263b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron list_for_each_entry_safe(el, t, &ev_int->det_events, list) { 227847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron list_del(&el->list); 228847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron kfree(el); 229847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 2308e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron ev_int->current_events = 0; 231847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 232847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 233847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 234847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 235847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 236847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic const struct file_operations iio_event_chrdev_fileops = { 237847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .read = iio_event_chrdev_read, 238847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .release = iio_event_chrdev_release, 239847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .owner = THIS_MODULE, 2406038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann .llseek = noop_llseek, 241847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}; 242847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 2431aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_event_getfd(struct iio_dev *indio_dev) 2448e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron{ 2455aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron if (indio_dev->event_interface == NULL) 2468e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron return -ENODEV; 2478e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron 2485aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron mutex_lock(&indio_dev->event_interface->event_list_lock); 2498e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron if (test_and_set_bit(IIO_BUSY_BIT_POS, 2505aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron &indio_dev->event_interface->flags)) { 2515aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron mutex_unlock(&indio_dev->event_interface->event_list_lock); 2528e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron return -EBUSY; 2538e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron } 2545aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron mutex_unlock(&indio_dev->event_interface->event_list_lock); 2558e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron return anon_inode_getfd("iio:event", 2568e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron &iio_event_chrdev_fileops, 2575aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron indio_dev->event_interface, O_RDONLY); 2588e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron} 2598e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron 260847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic int __init iio_init(void) 261847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 262847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron int ret; 263847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 2645aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron /* Register sysfs bus */ 2655aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron ret = bus_register(&iio_bus_type); 266847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret < 0) { 267847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron printk(KERN_ERR 2685aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron "%s could not register bus type\n", 269847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron __FILE__); 270847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_nothing; 271847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 272847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 2739aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); 2749aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron if (ret < 0) { 2759aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron printk(KERN_ERR "%s: failed to allocate char dev region\n", 2769aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron __FILE__); 2775aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron goto error_unregister_bus_type; 2789aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron } 279847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 280847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 281847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 2825aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronerror_unregister_bus_type: 2835aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron bus_unregister(&iio_bus_type); 284847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_nothing: 285847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 286847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 287847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 288847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void __exit iio_exit(void) 289847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 2909aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron if (iio_devt) 2919aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron unregister_chrdev_region(iio_devt, IIO_DEV_MAX); 2925aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron bus_unregister(&iio_bus_type); 293847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 294847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 2951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_read_channel_info(struct device *dev, 2961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 2971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf) 298847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 2991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 3001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 3011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int val, val2; 3026fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, 3036fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron &val, &val2, this_attr->address); 3041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 3061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 307847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 3081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret == IIO_VAL_INT) 3091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "%d\n", val); 3101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else if (ret == IIO_VAL_INT_PLUS_MICRO) { 3111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (val2 < 0) 3121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "-%d.%06u\n", val, -val2); 3131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 3141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "%d.%06u\n", val, val2); 31571646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich } else if (ret == IIO_VAL_INT_PLUS_NANO) { 31671646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich if (val2 < 0) 31771646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich return sprintf(buf, "-%d.%09u\n", val, -val2); 31871646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich else 31971646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich return sprintf(buf, "%d.%09u\n", val, val2); 3201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else 3211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 3221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 3231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_write_channel_info(struct device *dev, 3251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 3261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 3271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len) 3281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 3291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 3301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 3315c04af04835269c194662be63fe168893fad667fMichael Hennerich int ret, integer = 0, fract = 0, fract_mult = 100000; 3321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron bool integer_part = true, negative = false; 3331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron /* Assumes decimal - precision based on number of digits */ 3356fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron if (!indio_dev->info->write_raw) 3361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return -EINVAL; 3375c04af04835269c194662be63fe168893fad667fMichael Hennerich 3385c04af04835269c194662be63fe168893fad667fMichael Hennerich if (indio_dev->info->write_raw_get_fmt) 3395c04af04835269c194662be63fe168893fad667fMichael Hennerich switch (indio_dev->info->write_raw_get_fmt(indio_dev, 3405c04af04835269c194662be63fe168893fad667fMichael Hennerich this_attr->c, this_attr->address)) { 3415c04af04835269c194662be63fe168893fad667fMichael Hennerich case IIO_VAL_INT_PLUS_MICRO: 3425c04af04835269c194662be63fe168893fad667fMichael Hennerich fract_mult = 100000; 3435c04af04835269c194662be63fe168893fad667fMichael Hennerich break; 3445c04af04835269c194662be63fe168893fad667fMichael Hennerich case IIO_VAL_INT_PLUS_NANO: 3455c04af04835269c194662be63fe168893fad667fMichael Hennerich fract_mult = 100000000; 3465c04af04835269c194662be63fe168893fad667fMichael Hennerich break; 3475c04af04835269c194662be63fe168893fad667fMichael Hennerich default: 3485c04af04835269c194662be63fe168893fad667fMichael Hennerich return -EINVAL; 3495c04af04835269c194662be63fe168893fad667fMichael Hennerich } 3505c04af04835269c194662be63fe168893fad667fMichael Hennerich 3511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (buf[0] == '-') { 3521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron negative = true; 3531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron buf++; 3541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3555c04af04835269c194662be63fe168893fad667fMichael Hennerich 3561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron while (*buf) { 3571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if ('0' <= *buf && *buf <= '9') { 3581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (integer_part) 3591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron integer = integer*10 + *buf - '0'; 3601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else { 3615c04af04835269c194662be63fe168893fad667fMichael Hennerich fract += fract_mult*(*buf - '0'); 3625c04af04835269c194662be63fe168893fad667fMichael Hennerich if (fract_mult == 1) 3631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron break; 3645c04af04835269c194662be63fe168893fad667fMichael Hennerich fract_mult /= 10; 3651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else if (*buf == '\n') { 3671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (*(buf + 1) == '\0') 3681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron break; 3691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 3701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return -EINVAL; 3711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else if (*buf == '.') { 3721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron integer_part = false; 3731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else { 3741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return -EINVAL; 3751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron buf++; 3771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (negative) { 3791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (integer) 3801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron integer = -integer; 3811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 3825c04af04835269c194662be63fe168893fad667fMichael Hennerich fract = -fract; 3831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3856fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron ret = indio_dev->info->write_raw(indio_dev, this_attr->c, 3865c04af04835269c194662be63fe168893fad667fMichael Hennerich integer, fract, this_attr->address); 3871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 3881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 3891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return len; 3911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 3921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 393df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic 3941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_device_attr_init(struct device_attribute *dev_attr, 3951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *postfix, 3961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan, 3971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*readfunc)(struct device *dev, 3981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 3991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf), 4001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*writefunc)(struct device *dev, 4011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 4021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 4031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len), 4041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron bool generic) 4051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 4061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int ret; 4071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *name_format, *full_postfix; 4081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron sysfs_attr_init(&dev_attr->attr); 4091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 410ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron /* Build up postfix of <extend_name>_<modifier>_postfix */ 411ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (chan->modified) { 412ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (chan->extend_name) 413ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", 414ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_modifier_names[chan 415ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ->channel2], 416ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->extend_name, 417ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron postfix); 418ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else 419ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kasprintf(GFP_KERNEL, "%s_%s", 420ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_modifier_names[chan 421ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ->channel2], 422ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron postfix); 423ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } else { 424ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (chan->extend_name == NULL) 425ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kstrdup(postfix, GFP_KERNEL); 426ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else 427ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kasprintf(GFP_KERNEL, 428ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron "%s_%s", 429ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->extend_name, 430ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron postfix); 431ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 432ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (full_postfix == NULL) { 433ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ret = -ENOMEM; 434ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron goto error_ret; 435ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 4361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 437ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (chan->differential) { /* Differential can not have modifier */ 438ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (generic) 439ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 440ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s-%s_%s", 441ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 442ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 443ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 444ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 445ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else if (chan->indexed) 446ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 447ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s", 448ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 449ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 450ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel, 451ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 452ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel2, 453ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 454ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else { 455ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron WARN_ON("Differential channels must be indexed\n"); 456ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ret = -EINVAL; 457ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron goto error_free_full_postfix; 458ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 459ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } else { /* Single ended */ 460ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (generic) 461ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 462ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s_%s", 463ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 464ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 465ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 466ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else if (chan->indexed) 467ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 468ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s%d_%s", 469ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 470ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 471ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel, 472ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 473ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else 474ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 475ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s_%s", 476ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 477ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 478ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 479ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 4801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (name_format == NULL) { 4811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 4821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_free_full_postfix; 4831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 4841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->attr.name = kasprintf(GFP_KERNEL, 4851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron name_format, 4861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron chan->channel, 4871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron chan->channel2); 4881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (dev_attr->attr.name == NULL) { 4891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 4901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_free_name_format; 4911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 4921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 4931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (readfunc) { 4941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->attr.mode |= S_IRUGO; 4951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->show = readfunc; 4961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 4971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 4981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (writefunc) { 4991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->attr.mode |= S_IWUSR; 5001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->store = writefunc; 5011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(name_format); 5031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(full_postfix); 5041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 5061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_name_format: 5081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(name_format); 5091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_full_postfix: 5101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(full_postfix); 5111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 5121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 5131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 5141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 515df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic void __iio_device_attr_deinit(struct device_attribute *dev_attr) 5161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 5171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(dev_attr->attr.name); 5181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 5191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_add_chan_devattr(const char *postfix, 5211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan, 5221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*readfunc)(struct device *dev, 5231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 5241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf), 5251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*writefunc)(struct device *dev, 5261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 5271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 5281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len), 529e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron u64 mask, 5301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron bool generic, 5311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device *dev, 5321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct list_head *attr_list) 5331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 5341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int ret; 5351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *iio_attr, *t; 5361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL); 5381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (iio_attr == NULL) { 5391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 5401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 5411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = __iio_device_attr_init(&iio_attr->dev_attr, 5431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron postfix, chan, 5441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron readfunc, writefunc, generic); 5451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 5461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_iio_dev_attr_free; 5471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr->c = chan; 5481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr->address = mask; 5491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_for_each_entry(t, attr_list, l) 5501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (strcmp(t->dev_attr.attr.name, 5511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr->dev_attr.attr.name) == 0) { 5521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (!generic) 5531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_err(dev, "tried to double register : %s\n", 5541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron t->dev_attr.attr.name); 5551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -EBUSY; 5561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_device_attr_deinit; 5571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_add(&iio_attr->l, attr_list); 5591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 5611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_device_attr_deinit: 5631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron __iio_device_attr_deinit(&iio_attr->dev_attr); 5641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_iio_dev_attr_free: 5651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(iio_attr); 5661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 5671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 5681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 5691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 570f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, 5711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan) 5721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 57326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron int ret, i, attrcount = 0; 5741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (chan->channel < 0) 5761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 5771e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 5781e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron ret = __iio_add_chan_devattr(iio_data_type_name[chan->processed_val], 57926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron chan, 5801e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron &iio_read_channel_info, 581c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron (chan->output ? 5821e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron &iio_write_channel_info : NULL), 5831e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 0, 5841e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 0, 585f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->dev, 586f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channel_attr_list); 5871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 5881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 58926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 5901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) { 5921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2], 59326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron chan, 5941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron &iio_read_channel_info, 5951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron &iio_write_channel_info, 5961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron (1 << i), 5971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron !(i%2), 598f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->dev, 599f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channel_attr_list); 6001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret == -EBUSY && (i%2 == 0)) { 6011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = 0; 6021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron continue; 6031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 6041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 6051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 60626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 6071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 60826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = attrcount; 6091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 6101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 6111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 6121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 613f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev, 6141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p) 6151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 6161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(p->dev_attr.attr.name); 6171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(p); 6181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 6191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 6201b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic ssize_t iio_show_dev_name(struct device *dev, 6211b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron struct device_attribute *attr, 6221b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron char *buf) 6231b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron{ 6241b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 6251b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron return sprintf(buf, "%s\n", indio_dev->name); 6261b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron} 6271b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron 6281b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); 6291b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron 630f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_register_sysfs(struct iio_dev *indio_dev) 6311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 63226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron int i, ret = 0, attrcount, attrn, attrcount_orig = 0; 6331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p, *n; 63426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron struct attribute **attr; 6351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 63626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* First count elements in any existing group */ 637f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->info->attrs) { 638f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron attr = indio_dev->info->attrs->attrs; 63926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron while (*attr++ != NULL) 64026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount_orig++; 641847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 64226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount = attrcount_orig; 6431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron /* 6441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron * New channel registration method - relies on the fact a group does 6451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron * not need to be initialized if it is name is NULL. 6461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron */ 647f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron INIT_LIST_HEAD(&indio_dev->channel_attr_list); 648f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->channels) 649f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron for (i = 0; i < indio_dev->num_channels; i++) { 650f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_add_channel_sysfs(indio_dev, 651f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev 6521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ->channels[i]); 6531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 6541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_clear_attrs; 65526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount += ret; 6561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 65726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 658f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->name) 65926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 66026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 661f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chan_attr_group.attrs 662f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron = kzalloc(sizeof(indio_dev->chan_attr_group.attrs[0])* 66326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron (attrcount + 1), 66426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron GFP_KERNEL); 665f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->chan_attr_group.attrs == NULL) { 66626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = -ENOMEM; 66726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_clear_attrs; 6681b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron } 66926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* Copy across original attributes */ 670f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->info->attrs) 671f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron memcpy(indio_dev->chan_attr_group.attrs, 672f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->info->attrs->attrs, 673f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron sizeof(indio_dev->chan_attr_group.attrs[0]) 67426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron *attrcount_orig); 67526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrn = attrcount_orig; 67626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* Add all elements from the list. */ 677f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron list_for_each_entry(p, &indio_dev->channel_attr_list, l) 678f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; 679f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->name) 680f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; 68126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 682f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->groups[indio_dev->groupcounter++] = 683f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->chan_attr_group; 68426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 6851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 6861b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron 6871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs: 6881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_for_each_entry_safe(p, n, 689f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channel_attr_list, l) { 6901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_del(&p->l); 691f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_remove_and_free_read_attr(indio_dev, p); 6921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 6931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 69426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron return ret; 695847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 696847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 697f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_unregister_sysfs(struct iio_dev *indio_dev) 698847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 6991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p, *n; 70126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 702f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) { 7031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_del(&p->l); 704f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_remove_and_free_read_attr(indio_dev, p); 7051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 706f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kfree(indio_dev->chan_attr_group.attrs); 707847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 708847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 7091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_ev_type_text[] = { 7101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_EV_TYPE_THRESH] = "thresh", 7111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_EV_TYPE_MAG] = "mag", 7128ce7375be7036d6e536b6341ec83e5db849cda6eJonathan Cameron [IIO_EV_TYPE_ROC] = "roc", 7138ce7375be7036d6e536b6341ec83e5db849cda6eJonathan Cameron [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", 7148ce7375be7036d6e536b6341ec83e5db849cda6eJonathan Cameron [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", 7151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 7161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_ev_dir_text[] = { 7181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_EV_DIR_EITHER] = "either", 7191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_EV_DIR_RISING] = "rising", 7201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_EV_DIR_FALLING] = "falling" 7211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 7221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_state_store(struct device *dev, 7241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 7251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 7261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len) 7271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 7281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 729aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 7301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int ret; 731c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron bool val; 732c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron 733c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron ret = strtobool(buf, &val); 734c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron if (ret < 0) 735c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron return ret; 7361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7376fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron ret = indio_dev->info->write_event_config(indio_dev, 7386fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron this_attr->address, 7396fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron val); 7401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return (ret < 0) ? ret : len; 7411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 7421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_state_show(struct device *dev, 7441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 7451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf) 7461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 7471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 748aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 7496fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron int val = indio_dev->info->read_event_config(indio_dev, 7506fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron this_attr->address); 7511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (val < 0) 7531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return val; 7541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 7551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "%d\n", val); 7561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 7571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_value_show(struct device *dev, 7591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 7601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf) 7611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 7621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 7631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 7641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int val, ret; 7651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7666fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron ret = indio_dev->info->read_event_value(indio_dev, 7676fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron this_attr->address, &val); 7681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 7691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 7701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "%d\n", val); 7721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 7731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_value_store(struct device *dev, 7751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 7761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 7771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len) 7781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 7791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 7801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 7811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron unsigned long val; 7821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int ret; 7831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = strict_strtoul(buf, 10, &val); 7851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 7861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 7871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7886fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron ret = indio_dev->info->write_event_value(indio_dev, this_attr->address, 7896fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron val); 7901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 7911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 7921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return len; 7941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 7951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 796f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_add_event_sysfs(struct iio_dev *indio_dev, 7971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan) 7981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 799e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron int ret = 0, i, attrcount = 0; 800e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron u64 mask = 0; 8011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *postfix; 8021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (!chan->event_mask) 8031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 8041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 8051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) { 8061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron postfix = kasprintf(GFP_KERNEL, "%s_%s_en", 807c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron iio_ev_type_text[i/IIO_EV_DIR_MAX], 808c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron iio_ev_dir_text[i%IIO_EV_DIR_MAX]); 8091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (postfix == NULL) { 8101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 8111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 8121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 813330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron if (chan->modified) 8141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel, 815c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron i/IIO_EV_DIR_MAX, 816c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron i%IIO_EV_DIR_MAX); 817ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else if (chan->differential) 818ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron mask = IIO_EVENT_CODE(chan->type, 819ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron 0, 0, 820ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron i%IIO_EV_DIR_MAX, 821ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron i/IIO_EV_DIR_MAX, 822ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron 0, 823ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel, 824ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel2); 825330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron else 826330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron mask = IIO_UNMOD_EVENT_CODE(chan->type, 827330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron chan->channel, 828c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron i/IIO_EV_DIR_MAX, 829c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron i%IIO_EV_DIR_MAX); 830330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron 831aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron ret = __iio_add_chan_devattr(postfix, 832aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron chan, 833aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron &iio_ev_state_show, 834aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron iio_ev_state_store, 835aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron mask, 836aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron 0, 837f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->dev, 838f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->event_interface-> 839aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron dev_attr_list); 8401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(postfix); 8411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 8421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 84326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 8441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron postfix = kasprintf(GFP_KERNEL, "%s_%s_value", 845c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron iio_ev_type_text[i/IIO_EV_DIR_MAX], 846c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron iio_ev_dir_text[i%IIO_EV_DIR_MAX]); 8471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (postfix == NULL) { 8481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 8491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 8501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 85126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = __iio_add_chan_devattr(postfix, chan, 8521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_ev_value_show, 8531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_ev_value_store, 8541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron mask, 8551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 0, 856f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->dev, 857f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->event_interface-> 8585aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron dev_attr_list); 8591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(postfix); 8601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 8611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 86226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 8631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 86426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = attrcount; 8651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 8661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 8671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 8681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 869f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic inline void __iio_remove_event_config_attrs(struct iio_dev *indio_dev) 8701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 8711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p, *n; 8721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_for_each_entry_safe(p, n, 873f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->event_interface-> 8741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr_list, l) { 8751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(p->dev_attr.attr.name); 8761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(p); 8771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 8781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 8791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 880f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) 881847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 88226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron int j, ret, attrcount = 0; 8831e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 884f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); 8851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron /* Dynically created from the channels array */ 886f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron for (j = 0; j < indio_dev->num_channels; j++) { 887f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_add_event_sysfs(indio_dev, 888f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channels[j]); 88926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron if (ret < 0) 8905aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron goto error_clear_attrs; 89126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount += ret; 8921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 89326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron return attrcount; 894847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 8951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs: 896f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron __iio_remove_event_config_attrs(indio_dev); 897847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 898847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 899847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 900847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 901f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) 9025aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron{ 9035aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron int j; 9041e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 905f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron for (j = 0; j < indio_dev->num_channels; j++) 906f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->channels[j].event_mask != 0) 9075aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron return true; 9085aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron return false; 9095aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron} 9105aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron 9111e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameronstatic void iio_setup_ev_int(struct iio_event_interface *ev_int) 9121e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron{ 9131e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron mutex_init(&ev_int->event_list_lock); 9141e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron /* discussion point - make this variable? */ 9151e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron ev_int->max_events = 10; 9161e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron ev_int->current_events = 0; 9171e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron INIT_LIST_HEAD(&ev_int->det_events); 9181e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron init_waitqueue_head(&ev_int->wait); 9191e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron} 9201e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 92126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronstatic const char *iio_event_group_name = "events"; 922f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_register_eventset(struct iio_dev *indio_dev) 923847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 92426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron struct iio_dev_attr *p; 92526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron int ret = 0, attrcount_orig = 0, attrcount, attrn; 92626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron struct attribute **attr; 927847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 928f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (!(indio_dev->info->event_attrs || 929f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_check_for_dynamic_events(indio_dev))) 930847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 931847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 932f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->event_interface = 9335aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); 934f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->event_interface == NULL) { 935847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ret = -ENOMEM; 936847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_ret; 937847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 938847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 939f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_setup_ev_int(indio_dev->event_interface); 940f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->info->event_attrs != NULL) { 941f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron attr = indio_dev->info->event_attrs->attrs; 94226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron while (*attr++ != NULL) 94326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount_orig++; 9445aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron } 94526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount = attrcount_orig; 946f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->channels) { 947f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = __iio_add_event_config_attrs(indio_dev); 94826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron if (ret < 0) 949cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron goto error_free_setup_event_lines; 95026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount += ret; 951847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 952847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 953f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->event_interface->group.name = iio_event_group_name; 954f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->event_interface->group.attrs = 955f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kzalloc(sizeof(indio_dev->event_interface->group.attrs[0]) 95626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron *(attrcount + 1), 95726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron GFP_KERNEL); 958f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->event_interface->group.attrs == NULL) { 95926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = -ENOMEM; 96026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_free_setup_event_lines; 96126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron } 962f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->info->event_attrs) 963f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron memcpy(indio_dev->event_interface->group.attrs, 964f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->info->event_attrs->attrs, 965f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron sizeof(indio_dev->event_interface->group.attrs[0]) 96626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron *attrcount_orig); 96726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrn = attrcount_orig; 96826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* Add all elements from the list. */ 96926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron list_for_each_entry(p, 970f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->event_interface->dev_attr_list, 97126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron l) 972f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->event_interface->group.attrs[attrn++] = 97326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron &p->dev_attr.attr; 97426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 975f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->groups[indio_dev->groupcounter++] = 976f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->event_interface->group; 97726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 978847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 979847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 980cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameronerror_free_setup_event_lines: 981f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron __iio_remove_event_config_attrs(indio_dev); 982f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kfree(indio_dev->event_interface); 983847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret: 984847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 985847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 986847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 987847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 988f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_unregister_eventset(struct iio_dev *indio_dev) 989847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 990f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->event_interface == NULL) 991847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return; 992f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron __iio_remove_event_config_attrs(indio_dev); 993f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kfree(indio_dev->event_interface->group.attrs); 994f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kfree(indio_dev->event_interface); 995847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 996847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 997847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_dev_release(struct device *device) 998847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 999f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev); 1000f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron cdev_del(&indio_dev->chrdev); 1001f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) 1002f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_trigger_consumer(indio_dev); 1003f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_eventset(indio_dev); 1004f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_sysfs(indio_dev); 1005f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ida_simple_remove(&iio_ida, indio_dev->id); 1006f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kfree(indio_dev); 1007847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 1008847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1009847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic struct device_type iio_dev_type = { 1010847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .name = "iio_device", 1011847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .release = iio_dev_release, 1012847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}; 1013847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 10146f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameronstruct iio_dev *iio_allocate_device(int sizeof_priv) 1015847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 10166f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron struct iio_dev *dev; 10176f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron size_t alloc_size; 10186f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron 10196f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size = sizeof(struct iio_dev); 10206f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron if (sizeof_priv) { 10216f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size = ALIGN(alloc_size, IIO_ALIGN); 10226f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size += sizeof_priv; 10236f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron } 10246f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron /* ensure 32-byte alignment of whole construct ? */ 10256f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size += IIO_ALIGN - 1; 10266f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron 10276f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron dev = kzalloc(alloc_size, GFP_KERNEL); 1028847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1029847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (dev) { 103026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron dev->dev.groups = dev->groups; 1031847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron dev->dev.type = &iio_dev_type; 10325aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron dev->dev.bus = &iio_bus_type; 1033847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron device_initialize(&dev->dev); 1034847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron dev_set_drvdata(&dev->dev, (void *)dev); 1035847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_init(&dev->mlock); 1036a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron 1037a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); 1038a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron if (dev->id < 0) { 1039a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron /* cannot use a dev_err as the name isn't available */ 1040a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron printk(KERN_ERR "Failed to get id\n"); 1041a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron kfree(dev); 1042a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron return NULL; 1043a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron } 1044a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron dev_set_name(&dev->dev, "iio:device%d", dev->id); 1045847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 1046847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1047847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return dev; 1048847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 1049847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_allocate_device); 1050847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1051847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_free_device(struct iio_dev *dev) 1052847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 1053a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron if (dev) { 1054a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron ida_simple_remove(&iio_ida, dev->id); 10551aa042783251c27a93e31929c24647729db326d4Jonathan Cameron kfree(dev); 1056a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron } 1057847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 1058847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_free_device); 1059847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 10601aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/** 106114555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_open() - chrdev file open for buffer access and ioctls 10621aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/ 10631aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_open(struct inode *inode, struct file *filp) 10641aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{ 1065f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron struct iio_dev *indio_dev = container_of(inode->i_cdev, 10661aa042783251c27a93e31929c24647729db326d4Jonathan Cameron struct iio_dev, chrdev); 1067f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron filp->private_data = indio_dev; 106830eb82f05dd1f12b18a0ad054401a0b5690fb3c3Jonathan Cameron 1069f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron return iio_chrdev_buffer_open(indio_dev); 10701aa042783251c27a93e31929c24647729db326d4Jonathan Cameron} 10711aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 10721aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/** 107314555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_release() - chrdev file close buffer access and ioctls 10741aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/ 10751aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_release(struct inode *inode, struct file *filp) 10761aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{ 107714555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron iio_chrdev_buffer_release(container_of(inode->i_cdev, 10781aa042783251c27a93e31929c24647729db326d4Jonathan Cameron struct iio_dev, chrdev)); 10791aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return 0; 10801aa042783251c27a93e31929c24647729db326d4Jonathan Cameron} 10811aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 10821aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/* Somewhat of a cross file organization violation - ioctls here are actually 10831aa042783251c27a93e31929c24647729db326d4Jonathan Cameron * event related */ 10841aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 10851aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{ 10861aa042783251c27a93e31929c24647729db326d4Jonathan Cameron struct iio_dev *indio_dev = filp->private_data; 10871aa042783251c27a93e31929c24647729db326d4Jonathan Cameron int __user *ip = (int __user *)arg; 10881aa042783251c27a93e31929c24647729db326d4Jonathan Cameron int fd; 10891aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 10901aa042783251c27a93e31929c24647729db326d4Jonathan Cameron if (cmd == IIO_GET_EVENT_FD_IOCTL) { 10911aa042783251c27a93e31929c24647729db326d4Jonathan Cameron fd = iio_event_getfd(indio_dev); 10921aa042783251c27a93e31929c24647729db326d4Jonathan Cameron if (copy_to_user(ip, &fd, sizeof(fd))) 10931aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return -EFAULT; 10941aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return 0; 10951aa042783251c27a93e31929c24647729db326d4Jonathan Cameron } 10961aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return -EINVAL; 10971aa042783251c27a93e31929c24647729db326d4Jonathan Cameron} 10981aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 109914555b14455f9acbdf0e500ae96140828a970796Jonathan Cameronstatic const struct file_operations iio_buffer_fileops = { 110014555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron .read = iio_buffer_read_first_n_outer_addr, 11011aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .release = iio_chrdev_release, 11021aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .open = iio_chrdev_open, 110314555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron .poll = iio_buffer_poll_addr, 11041aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .owner = THIS_MODULE, 11051aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .llseek = noop_llseek, 11061aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .unlocked_ioctl = iio_ioctl, 11071aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .compat_ioctl = iio_ioctl, 11081aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}; 11091aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 1110f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronint iio_device_register(struct iio_dev *indio_dev) 1111847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 1112847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron int ret; 1113847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 11141aa042783251c27a93e31929c24647729db326d4Jonathan Cameron /* configure elements for the chrdev */ 1115f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); 1116847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1117f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_register_sysfs(indio_dev); 1118847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret) { 1119f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron dev_err(indio_dev->dev.parent, 1120847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron "Failed to register sysfs interfaces\n"); 1121a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron goto error_ret; 1122847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 1123f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_register_eventset(indio_dev); 1124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret) { 1125f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron dev_err(indio_dev->dev.parent, 1126c849d2538ebeef1ac26fad7a10c18b1e0fc35161Roel Van Nyen "Failed to register event set\n"); 1127847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_free_sysfs; 1128847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 1129f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) 1130f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_register_trigger_consumer(indio_dev); 1131847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1132f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = device_add(&indio_dev->dev); 113326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron if (ret < 0) 113426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_unreg_eventset; 1135f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); 1136f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chrdev.owner = indio_dev->info->driver_module; 1137f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1); 113826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron if (ret < 0) 113926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_del_device; 1140847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 1141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1142847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_del_device: 1143f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron device_del(&indio_dev->dev); 114426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_unreg_eventset: 1145f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_eventset(indio_dev); 114626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_free_sysfs: 1147f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_sysfs(indio_dev); 1148847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret: 1149847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 1150847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 1151847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_register); 1152847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1153f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronvoid iio_device_unregister(struct iio_dev *indio_dev) 1154847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 1155f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron device_unregister(&indio_dev->dev); 1156847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 1157847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_unregister); 1158847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronsubsys_initcall(iio_init); 1159847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronmodule_exit(iio_exit); 1160847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1161847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); 1162847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_DESCRIPTION("Industrial I/O core"); 1163847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_LICENSE("GPL"); 1164