0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/slab.h>
0009 #include <linux/interrupt.h>
0010 #include <linux/irq.h>
0011
0012 #include <linux/iio/iio.h>
0013 #include <linux/iio/sysfs.h>
0014 #include <linux/iio/events.h>
0015 #include "iio_simple_dummy.h"
0016
0017
0018 #include "iio_dummy_evgen.h"
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev,
0031 const struct iio_chan_spec *chan,
0032 enum iio_event_type type,
0033 enum iio_event_direction dir)
0034 {
0035 struct iio_dummy_state *st = iio_priv(indio_dev);
0036
0037 return st->event_en;
0038 }
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
0053 const struct iio_chan_spec *chan,
0054 enum iio_event_type type,
0055 enum iio_event_direction dir,
0056 int state)
0057 {
0058 struct iio_dummy_state *st = iio_priv(indio_dev);
0059
0060
0061
0062
0063
0064 switch (chan->type) {
0065 case IIO_VOLTAGE:
0066 switch (type) {
0067 case IIO_EV_TYPE_THRESH:
0068 if (dir == IIO_EV_DIR_RISING)
0069 st->event_en = state;
0070 else
0071 return -EINVAL;
0072 break;
0073 default:
0074 return -EINVAL;
0075 }
0076 break;
0077 case IIO_ACTIVITY:
0078 switch (type) {
0079 case IIO_EV_TYPE_THRESH:
0080 st->event_en = state;
0081 break;
0082 default:
0083 return -EINVAL;
0084 }
0085 break;
0086 case IIO_STEPS:
0087 switch (type) {
0088 case IIO_EV_TYPE_CHANGE:
0089 st->event_en = state;
0090 break;
0091 default:
0092 return -EINVAL;
0093 }
0094 break;
0095 default:
0096 return -EINVAL;
0097 }
0098
0099 return 0;
0100 }
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev,
0119 const struct iio_chan_spec *chan,
0120 enum iio_event_type type,
0121 enum iio_event_direction dir,
0122 enum iio_event_info info,
0123 int *val, int *val2)
0124 {
0125 struct iio_dummy_state *st = iio_priv(indio_dev);
0126
0127 *val = st->event_val;
0128
0129 return IIO_VAL_INT;
0130 }
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142 int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev,
0143 const struct iio_chan_spec *chan,
0144 enum iio_event_type type,
0145 enum iio_event_direction dir,
0146 enum iio_event_info info,
0147 int val, int val2)
0148 {
0149 struct iio_dummy_state *st = iio_priv(indio_dev);
0150
0151 st->event_val = val;
0152
0153 return 0;
0154 }
0155
0156 static irqreturn_t iio_simple_dummy_get_timestamp(int irq, void *private)
0157 {
0158 struct iio_dev *indio_dev = private;
0159 struct iio_dummy_state *st = iio_priv(indio_dev);
0160
0161 st->event_timestamp = iio_get_time_ns(indio_dev);
0162 return IRQ_WAKE_THREAD;
0163 }
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private)
0176 {
0177 struct iio_dev *indio_dev = private;
0178 struct iio_dummy_state *st = iio_priv(indio_dev);
0179
0180 dev_dbg(&indio_dev->dev, "id %x event %x\n",
0181 st->regs->reg_id, st->regs->reg_data);
0182
0183 switch (st->regs->reg_data) {
0184 case 0:
0185 iio_push_event(indio_dev,
0186 IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0,
0187 IIO_EV_DIR_RISING,
0188 IIO_EV_TYPE_THRESH, 0, 0, 0),
0189 st->event_timestamp);
0190 break;
0191 case 1:
0192 if (st->activity_running > st->event_val)
0193 iio_push_event(indio_dev,
0194 IIO_EVENT_CODE(IIO_ACTIVITY, 0,
0195 IIO_MOD_RUNNING,
0196 IIO_EV_DIR_RISING,
0197 IIO_EV_TYPE_THRESH,
0198 0, 0, 0),
0199 st->event_timestamp);
0200 break;
0201 case 2:
0202 if (st->activity_walking < st->event_val)
0203 iio_push_event(indio_dev,
0204 IIO_EVENT_CODE(IIO_ACTIVITY, 0,
0205 IIO_MOD_WALKING,
0206 IIO_EV_DIR_FALLING,
0207 IIO_EV_TYPE_THRESH,
0208 0, 0, 0),
0209 st->event_timestamp);
0210 break;
0211 case 3:
0212 iio_push_event(indio_dev,
0213 IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
0214 IIO_EV_DIR_NONE,
0215 IIO_EV_TYPE_CHANGE, 0, 0, 0),
0216 st->event_timestamp);
0217 break;
0218 default:
0219 break;
0220 }
0221
0222 return IRQ_HANDLED;
0223 }
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236 int iio_simple_dummy_events_register(struct iio_dev *indio_dev)
0237 {
0238 struct iio_dummy_state *st = iio_priv(indio_dev);
0239 int ret;
0240
0241
0242 st->event_irq = iio_dummy_evgen_get_irq();
0243 if (st->event_irq < 0) {
0244 ret = st->event_irq;
0245 goto error_ret;
0246 }
0247 st->regs = iio_dummy_evgen_get_regs(st->event_irq);
0248
0249 ret = request_threaded_irq(st->event_irq,
0250 &iio_simple_dummy_get_timestamp,
0251 &iio_simple_dummy_event_handler,
0252 IRQF_ONESHOT,
0253 "iio_simple_event",
0254 indio_dev);
0255 if (ret < 0)
0256 goto error_free_evgen;
0257 return 0;
0258
0259 error_free_evgen:
0260 iio_dummy_evgen_release_irq(st->event_irq);
0261 error_ret:
0262 return ret;
0263 }
0264
0265
0266
0267
0268
0269 void iio_simple_dummy_events_unregister(struct iio_dev *indio_dev)
0270 {
0271 struct iio_dummy_state *st = iio_priv(indio_dev);
0272
0273 free_irq(st->event_irq, indio_dev);
0274
0275 iio_dummy_evgen_release_irq(st->event_irq);
0276 }