industrialio-core.c revision c8a9f8056f40f6201b84fdddb49a1c62630902c5
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" 289dd1cb303c18f4508abc69f5b40f423ff36a9626Jonathan Cameron#include "sysfs.h" 29af5046af1c812839f085030f358a01814666fc80Jonathan Cameron#include "events.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[] = { 80c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_SCALE] = "scale", 81c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_OFFSET] = "offset", 82c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_CALIBSCALE] = "calibscale", 83c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_CALIBBIAS] = "calibbias", 84c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_PEAK] = "peak_raw", 85c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_PEAK_SCALE] = "peak_scale", 86c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw", 87c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", 881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 907ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron/** 917ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * struct iio_detected_event_list - list element for events that have occurred 927ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @list: linked list header 937ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @ev: the event itself 947ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron */ 957ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameronstruct iio_detected_event_list { 967ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron struct list_head list; 977ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron struct iio_event_data ev; 987ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron}; 997ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron 1007ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron/** 1017ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * struct iio_event_interface - chrdev interface for an event line 1027ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @dev: device assocated with event interface 1037ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @wait: wait queue to allow blocking reads of events 1047ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @event_list_lock: mutex to protect the list of detected events 1057ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @det_events: list of detected events 1067ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @max_events: maximum number of events before new ones are dropped 1077ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @current_events: number of events in detected list 1086356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron * @flags: file operations related flags including busy flag. 1097ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron */ 1107ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameronstruct iio_event_interface { 1117ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron wait_queue_head_t wait; 1127ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron struct mutex event_list_lock; 1137ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron struct list_head det_events; 1147ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron int max_events; 1157ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron int current_events; 1167ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron struct list_head dev_attr_list; 1176356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron unsigned long flags; 11826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron struct attribute_group group; 1197ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron}; 1207ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron 121f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronint iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) 122847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 123f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron struct iio_event_interface *ev_int = indio_dev->event_interface; 124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct iio_detected_event_list *ev; 125847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron int ret = 0; 126847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 127847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron /* Does anyone care? */ 128847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_lock(&ev_int->event_list_lock); 1296356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { 13075c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron if (ev_int->current_events == ev_int->max_events) { 13175c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 132847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 13375c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron } 134847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ev = kmalloc(sizeof(*ev), GFP_KERNEL); 135847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ev == NULL) { 136847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ret = -ENOMEM; 13775c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 138847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_ret; 139847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 140847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ev->ev.id = ev_code; 141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ev->ev.timestamp = timestamp; 142847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1433b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron list_add_tail(&ev->list, &ev_int->det_events); 144847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ev_int->current_events++; 145847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 146847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron wake_up_interruptible(&ev_int->wait); 147847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } else 148847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 149847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 150847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret: 151847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 152847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 153847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_push_event); 154847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 155847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* This turns up an awful lot */ 156847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronssize_t iio_read_const_attr(struct device *dev, 157847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct device_attribute *attr, 158847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron char *buf) 159847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 160847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string); 161847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 162847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_read_const_attr); 163847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 16477712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic ssize_t iio_event_chrdev_read(struct file *filep, 16577712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown char __user *buf, 16677712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown size_t count, 16777712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown loff_t *f_ps) 168847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 169847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct iio_event_interface *ev_int = filep->private_data; 170847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct iio_detected_event_list *el; 171dc8f52643d494eaa844002ca866d30fda142db4fLars-Peter Clausen size_t len = sizeof(el->ev); 172847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron int ret; 173dc8f52643d494eaa844002ca866d30fda142db4fLars-Peter Clausen 174dc8f52643d494eaa844002ca866d30fda142db4fLars-Peter Clausen if (count < len) 175dc8f52643d494eaa844002ca866d30fda142db4fLars-Peter Clausen return -EINVAL; 1766356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron 177847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_lock(&ev_int->event_list_lock); 1783b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron if (list_empty(&ev_int->det_events)) { 179847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (filep->f_flags & O_NONBLOCK) { 180847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ret = -EAGAIN; 181847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_mutex_unlock; 182847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 183847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 184847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron /* Blocking on device; waiting for something to be there */ 185847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ret = wait_event_interruptible(ev_int->wait, 186847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron !list_empty(&ev_int 1873b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron ->det_events)); 188847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret) 189847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_ret; 19025985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* Single access device so no one else can get the data */ 191847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_lock(&ev_int->event_list_lock); 192847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 193847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1943b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron el = list_first_entry(&ev_int->det_events, 195847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct iio_detected_event_list, 196847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron list); 197847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (copy_to_user(buf, &(el->ev), len)) { 198847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ret = -EFAULT; 199847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_mutex_unlock; 200847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 201847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron list_del(&el->list); 202847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ev_int->current_events--; 203847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 204847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron kfree(el); 205847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 206847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return len; 207847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 208847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_mutex_unlock: 209847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 210847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret: 211847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 212847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 213847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 214847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 21577712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic int iio_event_chrdev_release(struct inode *inode, struct file *filep) 216847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 2178e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron struct iio_event_interface *ev_int = filep->private_data; 218847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct iio_detected_event_list *el, *t; 2196356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron 220847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_lock(&ev_int->event_list_lock); 2216356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); 222847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron /* 223847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * In order to maintain a clean state for reopening, 224847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * clear out any awaiting events. The mask will prevent 225847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * any new __iio_push_event calls running. 226847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron */ 2273b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron list_for_each_entry_safe(el, t, &ev_int->det_events, list) { 228847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron list_del(&el->list); 229847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron kfree(el); 230847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 2318e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron ev_int->current_events = 0; 232847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_unlock(&ev_int->event_list_lock); 233847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 234847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 235847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 236847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 237847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic const struct file_operations iio_event_chrdev_fileops = { 238847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .read = iio_event_chrdev_read, 239847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .release = iio_event_chrdev_release, 240847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .owner = THIS_MODULE, 2416038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann .llseek = noop_llseek, 242847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}; 243847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 2441aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_event_getfd(struct iio_dev *indio_dev) 2458e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron{ 246b46413367961c2e8bd827e067a231be982aaeee2Al Viro int fd; 247b46413367961c2e8bd827e067a231be982aaeee2Al Viro 2485aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron if (indio_dev->event_interface == NULL) 2498e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron return -ENODEV; 2508e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron 2515aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron mutex_lock(&indio_dev->event_interface->event_list_lock); 2528e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron if (test_and_set_bit(IIO_BUSY_BIT_POS, 2535aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron &indio_dev->event_interface->flags)) { 2545aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron mutex_unlock(&indio_dev->event_interface->event_list_lock); 2558e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron return -EBUSY; 2568e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron } 2575aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron mutex_unlock(&indio_dev->event_interface->event_list_lock); 258b46413367961c2e8bd827e067a231be982aaeee2Al Viro fd = anon_inode_getfd("iio:event", 2598e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron &iio_event_chrdev_fileops, 2605aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron indio_dev->event_interface, O_RDONLY); 261b46413367961c2e8bd827e067a231be982aaeee2Al Viro if (fd < 0) { 262b46413367961c2e8bd827e067a231be982aaeee2Al Viro mutex_lock(&indio_dev->event_interface->event_list_lock); 263f791cec85073298d00f18b8492b79a8b4e9b0580Greg Kroah-Hartman clear_bit(IIO_BUSY_BIT_POS, &indio_dev->event_interface->flags); 264b46413367961c2e8bd827e067a231be982aaeee2Al Viro mutex_unlock(&indio_dev->event_interface->event_list_lock); 265b46413367961c2e8bd827e067a231be982aaeee2Al Viro } 266b46413367961c2e8bd827e067a231be982aaeee2Al Viro return fd; 2678e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron} 2688e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron 269847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic int __init iio_init(void) 270847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 271847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron int ret; 272847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 2735aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron /* Register sysfs bus */ 2745aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron ret = bus_register(&iio_bus_type); 275847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret < 0) { 276847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron printk(KERN_ERR 2775aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron "%s could not register bus type\n", 278847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron __FILE__); 279847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_nothing; 280847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 281847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 2829aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); 2839aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron if (ret < 0) { 2849aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron printk(KERN_ERR "%s: failed to allocate char dev region\n", 2859aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron __FILE__); 2865aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron goto error_unregister_bus_type; 2879aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron } 288847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 289847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 290847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 2915aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronerror_unregister_bus_type: 2925aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron bus_unregister(&iio_bus_type); 293847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_nothing: 294847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 295847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 296847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 297847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void __exit iio_exit(void) 298847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 2999aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron if (iio_devt) 3009aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron unregister_chrdev_region(iio_devt, IIO_DEV_MAX); 3015aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron bus_unregister(&iio_bus_type); 302847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 303847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 3041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_read_channel_info(struct device *dev, 3051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 3061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf) 307847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 3081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 3091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 3101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int val, val2; 3116fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, 3126fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron &val, &val2, this_attr->address); 3131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 3151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 316847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 3171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret == IIO_VAL_INT) 3181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "%d\n", val); 3191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else if (ret == IIO_VAL_INT_PLUS_MICRO) { 3201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (val2 < 0) 3211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "-%d.%06u\n", val, -val2); 3221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 3231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "%d.%06u\n", val, val2); 32471646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich } else if (ret == IIO_VAL_INT_PLUS_NANO) { 32571646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich if (val2 < 0) 32671646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich return sprintf(buf, "-%d.%09u\n", val, -val2); 32771646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich else 32871646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich return sprintf(buf, "%d.%09u\n", val, val2); 3291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else 3301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 3311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 3321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_write_channel_info(struct device *dev, 3341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 3351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 3361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len) 3371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 3381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 3391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 3405c04af04835269c194662be63fe168893fad667fMichael Hennerich int ret, integer = 0, fract = 0, fract_mult = 100000; 3411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron bool integer_part = true, negative = false; 3421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron /* Assumes decimal - precision based on number of digits */ 3446fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron if (!indio_dev->info->write_raw) 3451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return -EINVAL; 3465c04af04835269c194662be63fe168893fad667fMichael Hennerich 3475c04af04835269c194662be63fe168893fad667fMichael Hennerich if (indio_dev->info->write_raw_get_fmt) 3485c04af04835269c194662be63fe168893fad667fMichael Hennerich switch (indio_dev->info->write_raw_get_fmt(indio_dev, 3495c04af04835269c194662be63fe168893fad667fMichael Hennerich this_attr->c, this_attr->address)) { 3505c04af04835269c194662be63fe168893fad667fMichael Hennerich case IIO_VAL_INT_PLUS_MICRO: 3515c04af04835269c194662be63fe168893fad667fMichael Hennerich fract_mult = 100000; 3525c04af04835269c194662be63fe168893fad667fMichael Hennerich break; 3535c04af04835269c194662be63fe168893fad667fMichael Hennerich case IIO_VAL_INT_PLUS_NANO: 3545c04af04835269c194662be63fe168893fad667fMichael Hennerich fract_mult = 100000000; 3555c04af04835269c194662be63fe168893fad667fMichael Hennerich break; 3565c04af04835269c194662be63fe168893fad667fMichael Hennerich default: 3575c04af04835269c194662be63fe168893fad667fMichael Hennerich return -EINVAL; 3585c04af04835269c194662be63fe168893fad667fMichael Hennerich } 3595c04af04835269c194662be63fe168893fad667fMichael Hennerich 3601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (buf[0] == '-') { 3611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron negative = true; 3621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron buf++; 3631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3645c04af04835269c194662be63fe168893fad667fMichael Hennerich 3651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron while (*buf) { 3661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if ('0' <= *buf && *buf <= '9') { 3671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (integer_part) 3681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron integer = integer*10 + *buf - '0'; 3691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else { 3705c04af04835269c194662be63fe168893fad667fMichael Hennerich fract += fract_mult*(*buf - '0'); 3715c04af04835269c194662be63fe168893fad667fMichael Hennerich if (fract_mult == 1) 3721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron break; 3735c04af04835269c194662be63fe168893fad667fMichael Hennerich fract_mult /= 10; 3741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else if (*buf == '\n') { 3761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (*(buf + 1) == '\0') 3771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron break; 3781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 3791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return -EINVAL; 3801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else if (*buf == '.') { 3811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron integer_part = false; 3821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else { 3831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return -EINVAL; 3841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron buf++; 3861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (negative) { 3881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (integer) 3891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron integer = -integer; 3901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 3915c04af04835269c194662be63fe168893fad667fMichael Hennerich fract = -fract; 3921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3946fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron ret = indio_dev->info->write_raw(indio_dev, this_attr->c, 3955c04af04835269c194662be63fe168893fad667fMichael Hennerich integer, fract, this_attr->address); 3961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 3971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 3981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return len; 4001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 4011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 402df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic 4031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_device_attr_init(struct device_attribute *dev_attr, 4041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *postfix, 4051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan, 4061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*readfunc)(struct device *dev, 4071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 4081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf), 4091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*writefunc)(struct device *dev, 4101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 4111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 4121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len), 4131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron bool generic) 4141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 4151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int ret; 4161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *name_format, *full_postfix; 4171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron sysfs_attr_init(&dev_attr->attr); 4181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 419ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron /* Build up postfix of <extend_name>_<modifier>_postfix */ 4200403e0d643809f1608448ada38a1877f26b7bf5dJonathan Cameron if (chan->modified && !generic) { 421ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (chan->extend_name) 422ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", 423ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_modifier_names[chan 424ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ->channel2], 425ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->extend_name, 426ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron postfix); 427ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else 428ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kasprintf(GFP_KERNEL, "%s_%s", 429ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_modifier_names[chan 430ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ->channel2], 431ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron postfix); 432ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } else { 433ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (chan->extend_name == NULL) 434ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kstrdup(postfix, GFP_KERNEL); 435ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else 436ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kasprintf(GFP_KERNEL, 437ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron "%s_%s", 438ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->extend_name, 439ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron postfix); 440ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 441ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (full_postfix == NULL) { 442ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ret = -ENOMEM; 443ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron goto error_ret; 444ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 4451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 446ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (chan->differential) { /* Differential can not have modifier */ 447ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (generic) 448ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 449ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s-%s_%s", 450ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 451ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 452ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 453ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 454ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else if (chan->indexed) 455ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 456ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s", 457ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 458ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 459ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel, 460ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 461ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel2, 462ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 463ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else { 464ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron WARN_ON("Differential channels must be indexed\n"); 465ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ret = -EINVAL; 466ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron goto error_free_full_postfix; 467ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 468ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } else { /* Single ended */ 469ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (generic) 470ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 471ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s_%s", 472ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 473ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 474ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 475ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else if (chan->indexed) 476ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 477ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s%d_%s", 478ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 479ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 480ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel, 481ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 482ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else 483ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 484ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s_%s", 485ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 486ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 487ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 488ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 4891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (name_format == NULL) { 4901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 4911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_free_full_postfix; 4921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 4931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->attr.name = kasprintf(GFP_KERNEL, 4941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron name_format, 4951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron chan->channel, 4961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron chan->channel2); 4971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (dev_attr->attr.name == NULL) { 4981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 4991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_free_name_format; 5001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (readfunc) { 5031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->attr.mode |= S_IRUGO; 5041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->show = readfunc; 5051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (writefunc) { 5081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->attr.mode |= S_IWUSR; 5091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->store = writefunc; 5101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(name_format); 5121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(full_postfix); 5131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 5151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_name_format: 5171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(name_format); 5181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_full_postfix: 5191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(full_postfix); 5201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 5211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 5221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 5231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 524df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic void __iio_device_attr_deinit(struct device_attribute *dev_attr) 5251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 5261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(dev_attr->attr.name); 5271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 5281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_add_chan_devattr(const char *postfix, 5301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan, 5311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*readfunc)(struct device *dev, 5321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 5331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf), 5341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*writefunc)(struct device *dev, 5351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 5361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 5371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len), 538e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron u64 mask, 5391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron bool generic, 5401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device *dev, 5411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct list_head *attr_list) 5421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 5431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int ret; 5441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *iio_attr, *t; 5451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL); 5471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (iio_attr == NULL) { 5481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 5491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 5501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = __iio_device_attr_init(&iio_attr->dev_attr, 5521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron postfix, chan, 5531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron readfunc, writefunc, generic); 5541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 5551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_iio_dev_attr_free; 5561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr->c = chan; 5571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr->address = mask; 5581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_for_each_entry(t, attr_list, l) 5591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (strcmp(t->dev_attr.attr.name, 5601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr->dev_attr.attr.name) == 0) { 5611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (!generic) 5621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_err(dev, "tried to double register : %s\n", 5631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron t->dev_attr.attr.name); 5641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -EBUSY; 5651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_device_attr_deinit; 5661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_add(&iio_attr->l, attr_list); 5681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 5701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_device_attr_deinit: 5721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron __iio_device_attr_deinit(&iio_attr->dev_attr); 5731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_iio_dev_attr_free: 5741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(iio_attr); 5751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 5761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 5771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 5781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 579f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, 5801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan) 5811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 58226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron int ret, i, attrcount = 0; 5831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (chan->channel < 0) 5851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 5861e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 5871e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron ret = __iio_add_chan_devattr(iio_data_type_name[chan->processed_val], 58826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron chan, 5891e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron &iio_read_channel_info, 590c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron (chan->output ? 5911e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron &iio_write_channel_info : NULL), 5921e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 0, 5931e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 0, 594f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->dev, 595f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channel_attr_list); 5961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 5971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 59826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 5991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 6001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) { 6011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2], 60226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron chan, 6031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron &iio_read_channel_info, 6041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron &iio_write_channel_info, 605c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron i/2, 6061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron !(i%2), 607f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->dev, 608f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channel_attr_list); 6091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret == -EBUSY && (i%2 == 0)) { 6101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = 0; 6111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron continue; 6121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 6131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 6141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 61526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 6161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 61726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = attrcount; 6181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 6191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 6201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 6211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 622f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev, 6231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p) 6241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 6251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(p->dev_attr.attr.name); 6261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(p); 6271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 6281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 6291b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic ssize_t iio_show_dev_name(struct device *dev, 6301b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron struct device_attribute *attr, 6311b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron char *buf) 6321b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron{ 6331b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 6341b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron return sprintf(buf, "%s\n", indio_dev->name); 6351b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron} 6361b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron 6371b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); 6381b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron 639f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_register_sysfs(struct iio_dev *indio_dev) 6401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 64126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron int i, ret = 0, attrcount, attrn, attrcount_orig = 0; 6421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p, *n; 64326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron struct attribute **attr; 6441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 64526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* First count elements in any existing group */ 646f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->info->attrs) { 647f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron attr = indio_dev->info->attrs->attrs; 64826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron while (*attr++ != NULL) 64926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount_orig++; 650847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 65126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount = attrcount_orig; 6521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron /* 6531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron * New channel registration method - relies on the fact a group does 6541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron * not need to be initialized if it is name is NULL. 6551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron */ 656f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron INIT_LIST_HEAD(&indio_dev->channel_attr_list); 657f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->channels) 658f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron for (i = 0; i < indio_dev->num_channels; i++) { 659f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_add_channel_sysfs(indio_dev, 660f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev 6611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ->channels[i]); 6621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 6631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_clear_attrs; 66426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount += ret; 6651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 66626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 667f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->name) 66826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 66926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 670f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chan_attr_group.attrs 671f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron = kzalloc(sizeof(indio_dev->chan_attr_group.attrs[0])* 67226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron (attrcount + 1), 67326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron GFP_KERNEL); 674f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->chan_attr_group.attrs == NULL) { 67526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = -ENOMEM; 67626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_clear_attrs; 6771b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron } 67826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* Copy across original attributes */ 679f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->info->attrs) 680f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron memcpy(indio_dev->chan_attr_group.attrs, 681f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->info->attrs->attrs, 682f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron sizeof(indio_dev->chan_attr_group.attrs[0]) 68326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron *attrcount_orig); 68426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrn = attrcount_orig; 68526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* Add all elements from the list. */ 686f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron list_for_each_entry(p, &indio_dev->channel_attr_list, l) 687f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; 688f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->name) 689f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; 69026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 691f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->groups[indio_dev->groupcounter++] = 692f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->chan_attr_group; 69326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 6941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 6951b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron 6961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs: 6971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_for_each_entry_safe(p, n, 698f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channel_attr_list, l) { 6991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_del(&p->l); 700f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_remove_and_free_read_attr(indio_dev, p); 7011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 7021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 70326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron return ret; 704847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 705847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 706f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_unregister_sysfs(struct iio_dev *indio_dev) 707847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 7081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p, *n; 71026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 711f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) { 7121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_del(&p->l); 713f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_remove_and_free_read_attr(indio_dev, p); 7141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 715f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kfree(indio_dev->chan_attr_group.attrs); 716847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 717847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 7181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_ev_type_text[] = { 7191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_EV_TYPE_THRESH] = "thresh", 7201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_EV_TYPE_MAG] = "mag", 7218ce7375be7036d6e536b6341ec83e5db849cda6eJonathan Cameron [IIO_EV_TYPE_ROC] = "roc", 7228ce7375be7036d6e536b6341ec83e5db849cda6eJonathan Cameron [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", 7238ce7375be7036d6e536b6341ec83e5db849cda6eJonathan Cameron [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", 7241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 7251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_ev_dir_text[] = { 7271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_EV_DIR_EITHER] = "either", 7281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_EV_DIR_RISING] = "rising", 7291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_EV_DIR_FALLING] = "falling" 7301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 7311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_state_store(struct device *dev, 7331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 7341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 7351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len) 7361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 7371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 738aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 7391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int ret; 740c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron bool val; 741c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron 742c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron ret = strtobool(buf, &val); 743c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron if (ret < 0) 744c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron return ret; 7451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7466fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron ret = indio_dev->info->write_event_config(indio_dev, 7476fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron this_attr->address, 7486fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron val); 7491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return (ret < 0) ? ret : len; 7501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 7511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_state_show(struct device *dev, 7531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 7541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf) 7551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 7561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 757aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 7586fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron int val = indio_dev->info->read_event_config(indio_dev, 7596fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron this_attr->address); 7601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (val < 0) 7621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return val; 7631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 7641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "%d\n", val); 7651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 7661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_value_show(struct device *dev, 7681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 7691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf) 7701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 7711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 7721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 7731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int val, ret; 7741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7756fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron ret = indio_dev->info->read_event_value(indio_dev, 7766fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron this_attr->address, &val); 7771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 7781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 7791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "%d\n", val); 7811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 7821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_value_store(struct device *dev, 7841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 7851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 7861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len) 7871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 7881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 7891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 7901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron unsigned long val; 7911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int ret; 7921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = strict_strtoul(buf, 10, &val); 7941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 7951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 7961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7976fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron ret = indio_dev->info->write_event_value(indio_dev, this_attr->address, 7986fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron val); 7991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 8001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 8011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 8021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return len; 8031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 8041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 805f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_add_event_sysfs(struct iio_dev *indio_dev, 8061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan) 8071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 808e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron int ret = 0, i, attrcount = 0; 809e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron u64 mask = 0; 8101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *postfix; 8111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (!chan->event_mask) 8121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 8131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 8141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) { 8151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron postfix = kasprintf(GFP_KERNEL, "%s_%s_en", 816c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron iio_ev_type_text[i/IIO_EV_DIR_MAX], 817c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron iio_ev_dir_text[i%IIO_EV_DIR_MAX]); 8181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (postfix == NULL) { 8191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 8201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 8211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 822330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron if (chan->modified) 8231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel, 824c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron i/IIO_EV_DIR_MAX, 825c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron i%IIO_EV_DIR_MAX); 826ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else if (chan->differential) 827ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron mask = IIO_EVENT_CODE(chan->type, 828ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron 0, 0, 829ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron i%IIO_EV_DIR_MAX, 830ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron i/IIO_EV_DIR_MAX, 831ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron 0, 832ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel, 833ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel2); 834330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron else 835330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron mask = IIO_UNMOD_EVENT_CODE(chan->type, 836330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron chan->channel, 837c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron i/IIO_EV_DIR_MAX, 838c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron i%IIO_EV_DIR_MAX); 839330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron 840aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron ret = __iio_add_chan_devattr(postfix, 841aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron chan, 842aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron &iio_ev_state_show, 843aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron iio_ev_state_store, 844aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron mask, 845aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron 0, 846f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->dev, 847f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->event_interface-> 848aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron dev_attr_list); 8491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(postfix); 8501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 8511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 85226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 8531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron postfix = kasprintf(GFP_KERNEL, "%s_%s_value", 854c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron iio_ev_type_text[i/IIO_EV_DIR_MAX], 855c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron iio_ev_dir_text[i%IIO_EV_DIR_MAX]); 8561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (postfix == NULL) { 8571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 8581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 8591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 86026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = __iio_add_chan_devattr(postfix, chan, 8611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_ev_value_show, 8621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_ev_value_store, 8631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron mask, 8641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 0, 865f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->dev, 866f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->event_interface-> 8675aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron dev_attr_list); 8681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(postfix); 8691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 8701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 87126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 8721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 87326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = attrcount; 8741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 8751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 8761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 8771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 878f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic inline void __iio_remove_event_config_attrs(struct iio_dev *indio_dev) 8791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 8801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p, *n; 8811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_for_each_entry_safe(p, n, 882f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->event_interface-> 8831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr_list, l) { 8841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(p->dev_attr.attr.name); 8851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(p); 8861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 8871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 8881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 889f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) 890847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 89126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron int j, ret, attrcount = 0; 8921e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 893f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); 8941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron /* Dynically created from the channels array */ 895f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron for (j = 0; j < indio_dev->num_channels; j++) { 896f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_add_event_sysfs(indio_dev, 897f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channels[j]); 89826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron if (ret < 0) 8995aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron goto error_clear_attrs; 90026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount += ret; 9011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 90226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron return attrcount; 903847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 9041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs: 905f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron __iio_remove_event_config_attrs(indio_dev); 906847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 907847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 908847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 909847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 910f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) 9115aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron{ 9125aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron int j; 9131e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 914f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron for (j = 0; j < indio_dev->num_channels; j++) 915f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->channels[j].event_mask != 0) 9165aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron return true; 9175aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron return false; 9185aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron} 9195aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron 9201e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameronstatic void iio_setup_ev_int(struct iio_event_interface *ev_int) 9211e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron{ 9221e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron mutex_init(&ev_int->event_list_lock); 9231e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron /* discussion point - make this variable? */ 9241e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron ev_int->max_events = 10; 9251e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron ev_int->current_events = 0; 9261e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron INIT_LIST_HEAD(&ev_int->det_events); 9271e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron init_waitqueue_head(&ev_int->wait); 9281e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron} 9291e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 93026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronstatic const char *iio_event_group_name = "events"; 931f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_register_eventset(struct iio_dev *indio_dev) 932847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 93326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron struct iio_dev_attr *p; 93426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron int ret = 0, attrcount_orig = 0, attrcount, attrn; 93526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron struct attribute **attr; 936847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 937f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (!(indio_dev->info->event_attrs || 938f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_check_for_dynamic_events(indio_dev))) 939847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 940847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 941f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->event_interface = 9425aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); 943f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->event_interface == NULL) { 944847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron ret = -ENOMEM; 945847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_ret; 946847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 947847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 948f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_setup_ev_int(indio_dev->event_interface); 949f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->info->event_attrs != NULL) { 950f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron attr = indio_dev->info->event_attrs->attrs; 95126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron while (*attr++ != NULL) 95226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount_orig++; 9535aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron } 95426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount = attrcount_orig; 955f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->channels) { 956f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = __iio_add_event_config_attrs(indio_dev); 95726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron if (ret < 0) 958cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron goto error_free_setup_event_lines; 95926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount += ret; 960847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 961847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 962f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->event_interface->group.name = iio_event_group_name; 963f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->event_interface->group.attrs = 964f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kzalloc(sizeof(indio_dev->event_interface->group.attrs[0]) 96526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron *(attrcount + 1), 96626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron GFP_KERNEL); 967f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->event_interface->group.attrs == NULL) { 96826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = -ENOMEM; 96926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_free_setup_event_lines; 97026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron } 971f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->info->event_attrs) 972f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron memcpy(indio_dev->event_interface->group.attrs, 973f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->info->event_attrs->attrs, 974f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron sizeof(indio_dev->event_interface->group.attrs[0]) 97526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron *attrcount_orig); 97626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrn = attrcount_orig; 97726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* Add all elements from the list. */ 97826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron list_for_each_entry(p, 979f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->event_interface->dev_attr_list, 98026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron l) 981f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->event_interface->group.attrs[attrn++] = 98226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron &p->dev_attr.attr; 983f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->groups[indio_dev->groupcounter++] = 984f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->event_interface->group; 98526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 986847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 987847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 988cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameronerror_free_setup_event_lines: 989f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron __iio_remove_event_config_attrs(indio_dev); 990f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kfree(indio_dev->event_interface); 991847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret: 992847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 993847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 994847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 995847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 996f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_unregister_eventset(struct iio_dev *indio_dev) 997847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 998f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->event_interface == NULL) 999847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return; 1000f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron __iio_remove_event_config_attrs(indio_dev); 1001f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kfree(indio_dev->event_interface->group.attrs); 1002f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kfree(indio_dev->event_interface); 1003847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 1004847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1005847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_dev_release(struct device *device) 1006847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 1007f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev); 1008f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron cdev_del(&indio_dev->chrdev); 1009f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) 1010f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_trigger_consumer(indio_dev); 1011f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_eventset(indio_dev); 1012f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_sysfs(indio_dev); 1013847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 1014847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1015847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic struct device_type iio_dev_type = { 1016847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .name = "iio_device", 1017847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .release = iio_dev_release, 1018847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}; 1019847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 10206f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameronstruct iio_dev *iio_allocate_device(int sizeof_priv) 1021847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 10226f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron struct iio_dev *dev; 10236f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron size_t alloc_size; 10246f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron 10256f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size = sizeof(struct iio_dev); 10266f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron if (sizeof_priv) { 10276f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size = ALIGN(alloc_size, IIO_ALIGN); 10286f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size += sizeof_priv; 10296f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron } 10306f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron /* ensure 32-byte alignment of whole construct ? */ 10316f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size += IIO_ALIGN - 1; 10326f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron 10336f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron dev = kzalloc(alloc_size, GFP_KERNEL); 1034847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1035847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (dev) { 103626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron dev->dev.groups = dev->groups; 1037847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron dev->dev.type = &iio_dev_type; 10385aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron dev->dev.bus = &iio_bus_type; 1039847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron device_initialize(&dev->dev); 1040847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron dev_set_drvdata(&dev->dev, (void *)dev); 1041847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_init(&dev->mlock); 1042a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron 1043a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); 1044a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron if (dev->id < 0) { 1045a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron /* cannot use a dev_err as the name isn't available */ 1046a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron printk(KERN_ERR "Failed to get id\n"); 1047a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron kfree(dev); 1048a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron return NULL; 1049a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron } 1050a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron dev_set_name(&dev->dev, "iio:device%d", dev->id); 1051847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 1052847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1053847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return dev; 1054847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 1055847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_allocate_device); 1056847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1057847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_free_device(struct iio_dev *dev) 1058847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 1059a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron if (dev) { 1060a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron ida_simple_remove(&iio_ida, dev->id); 10611aa042783251c27a93e31929c24647729db326d4Jonathan Cameron kfree(dev); 1062a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron } 1063847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 1064847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_free_device); 1065847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 10661aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/** 106714555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_open() - chrdev file open for buffer access and ioctls 10681aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/ 10691aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_open(struct inode *inode, struct file *filp) 10701aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{ 1071f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron struct iio_dev *indio_dev = container_of(inode->i_cdev, 10721aa042783251c27a93e31929c24647729db326d4Jonathan Cameron struct iio_dev, chrdev); 1073f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron filp->private_data = indio_dev; 107430eb82f05dd1f12b18a0ad054401a0b5690fb3c3Jonathan Cameron 1075f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron return iio_chrdev_buffer_open(indio_dev); 10761aa042783251c27a93e31929c24647729db326d4Jonathan Cameron} 10771aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 10781aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/** 107914555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_release() - chrdev file close buffer access and ioctls 10801aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/ 10811aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_release(struct inode *inode, struct file *filp) 10821aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{ 108314555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron iio_chrdev_buffer_release(container_of(inode->i_cdev, 10841aa042783251c27a93e31929c24647729db326d4Jonathan Cameron struct iio_dev, chrdev)); 10851aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return 0; 10861aa042783251c27a93e31929c24647729db326d4Jonathan Cameron} 10871aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 10881aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/* Somewhat of a cross file organization violation - ioctls here are actually 10891aa042783251c27a93e31929c24647729db326d4Jonathan Cameron * event related */ 10901aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 10911aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{ 10921aa042783251c27a93e31929c24647729db326d4Jonathan Cameron struct iio_dev *indio_dev = filp->private_data; 10931aa042783251c27a93e31929c24647729db326d4Jonathan Cameron int __user *ip = (int __user *)arg; 10941aa042783251c27a93e31929c24647729db326d4Jonathan Cameron int fd; 10951aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 10961aa042783251c27a93e31929c24647729db326d4Jonathan Cameron if (cmd == IIO_GET_EVENT_FD_IOCTL) { 10971aa042783251c27a93e31929c24647729db326d4Jonathan Cameron fd = iio_event_getfd(indio_dev); 10981aa042783251c27a93e31929c24647729db326d4Jonathan Cameron if (copy_to_user(ip, &fd, sizeof(fd))) 10991aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return -EFAULT; 11001aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return 0; 11011aa042783251c27a93e31929c24647729db326d4Jonathan Cameron } 11021aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return -EINVAL; 11031aa042783251c27a93e31929c24647729db326d4Jonathan Cameron} 11041aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 110514555b14455f9acbdf0e500ae96140828a970796Jonathan Cameronstatic const struct file_operations iio_buffer_fileops = { 110614555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron .read = iio_buffer_read_first_n_outer_addr, 11071aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .release = iio_chrdev_release, 11081aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .open = iio_chrdev_open, 110914555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron .poll = iio_buffer_poll_addr, 11101aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .owner = THIS_MODULE, 11111aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .llseek = noop_llseek, 11121aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .unlocked_ioctl = iio_ioctl, 11131aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .compat_ioctl = iio_ioctl, 11141aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}; 11151aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 1116f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronint iio_device_register(struct iio_dev *indio_dev) 1117847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 1118847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron int ret; 1119847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 11201aa042783251c27a93e31929c24647729db326d4Jonathan Cameron /* configure elements for the chrdev */ 1121f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); 1122847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1123f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_register_sysfs(indio_dev); 1124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret) { 1125f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron dev_err(indio_dev->dev.parent, 1126847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron "Failed to register sysfs interfaces\n"); 1127a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron goto error_ret; 1128847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 1129f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_register_eventset(indio_dev); 1130847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret) { 1131f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron dev_err(indio_dev->dev.parent, 1132c849d2538ebeef1ac26fad7a10c18b1e0fc35161Roel Van Nyen "Failed to register event set\n"); 1133847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_free_sysfs; 1134847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 1135f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) 1136f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_register_trigger_consumer(indio_dev); 1137847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1138f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = device_add(&indio_dev->dev); 113926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron if (ret < 0) 114026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_unreg_eventset; 1141f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); 1142f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chrdev.owner = indio_dev->info->driver_module; 1143f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1); 114426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron if (ret < 0) 114526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_del_device; 1146847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 1147847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1148847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_del_device: 1149f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron device_del(&indio_dev->dev); 115026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_unreg_eventset: 1151f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_eventset(indio_dev); 115226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_free_sysfs: 1153f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_sysfs(indio_dev); 1154847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret: 1155847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 1156847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 1157847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_register); 1158847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1159f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronvoid iio_device_unregister(struct iio_dev *indio_dev) 1160847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 1161f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron device_unregister(&indio_dev->dev); 1162847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 1163847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_unregister); 1164847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronsubsys_initcall(iio_init); 1165847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronmodule_exit(iio_exit); 1166847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1167847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); 1168847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_DESCRIPTION("Industrial I/O core"); 1169847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_LICENSE("GPL"); 1170