1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/kernel.h>
18#include <linux/slab.h>
19#include <linux/module.h>
20
21#include <linux/iio/iio.h>
22#include <linux/iio/sysfs.h>
23#include <linux/iio/events.h>
24#include <linux/iio/buffer.h>
25#include "iio_simple_dummy.h"
26
27
28
29
30
31
32static unsigned instances = 1;
33module_param(instances, uint, 0);
34
35
36static struct iio_dev **iio_dummy_devs;
37
38
39static const char *iio_dummy_part_number = "iio_dummy_part_no";
40
41
42
43
44
45
46
47struct iio_dummy_accel_calibscale {
48 int val;
49 int val2;
50 int regval;
51};
52
53static const struct iio_dummy_accel_calibscale dummy_scales[] = {
54 { 0, 100, 0x8 },
55 { 0, 133, 0x7 },
56 { 733, 13, 0x9 },
57};
58
59#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
60
61
62
63
64
65static const struct iio_event_spec iio_dummy_event = {
66 .type = IIO_EV_TYPE_THRESH,
67 .dir = IIO_EV_DIR_RISING,
68 .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
69};
70
71
72
73
74static const struct iio_event_spec step_detect_event = {
75 .type = IIO_EV_TYPE_CHANGE,
76 .dir = IIO_EV_DIR_NONE,
77 .mask_separate = BIT(IIO_EV_INFO_ENABLE),
78};
79
80
81
82
83
84static const struct iio_event_spec iio_running_event = {
85 .type = IIO_EV_TYPE_THRESH,
86 .dir = IIO_EV_DIR_RISING,
87 .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
88};
89
90
91
92
93
94static const struct iio_event_spec iio_walking_event = {
95 .type = IIO_EV_TYPE_THRESH,
96 .dir = IIO_EV_DIR_FALLING,
97 .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
98};
99#endif
100
101
102
103
104
105
106
107static const struct iio_chan_spec iio_dummy_channels[] = {
108
109 {
110 .type = IIO_VOLTAGE,
111
112 .indexed = 1,
113 .channel = 0,
114
115 .info_mask_separate =
116
117
118
119
120
121 BIT(IIO_CHAN_INFO_RAW) |
122
123
124
125
126
127 BIT(IIO_CHAN_INFO_OFFSET) |
128
129
130
131
132
133 BIT(IIO_CHAN_INFO_SCALE),
134
135
136
137
138 .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
139
140 .scan_index = DUMMY_INDEX_VOLTAGE_0,
141 .scan_type = {
142 .sign = 'u',
143 .realbits = 13,
144 .storagebits = 16,
145 .shift = 0,
146 },
147#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
148 .event_spec = &iio_dummy_event,
149 .num_event_specs = 1,
150#endif
151 },
152
153 {
154 .type = IIO_VOLTAGE,
155 .differential = 1,
156
157
158
159
160 .indexed = 1,
161 .channel = 1,
162 .channel2 = 2,
163
164
165
166
167
168 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
169
170
171
172
173
174 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
175
176
177
178
179 .scan_index = DUMMY_INDEX_DIFFVOLTAGE_1M2,
180 .scan_type = {
181 .sign = 's',
182 .realbits = 12,
183 .storagebits = 16,
184 .shift = 0,
185 },
186 },
187
188 {
189 .type = IIO_VOLTAGE,
190 .differential = 1,
191 .indexed = 1,
192 .channel = 3,
193 .channel2 = 4,
194 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
195 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
196 .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
197 .scan_index = DUMMY_INDEX_DIFFVOLTAGE_3M4,
198 .scan_type = {
199 .sign = 's',
200 .realbits = 11,
201 .storagebits = 16,
202 .shift = 0,
203 },
204 },
205
206
207
208
209 {
210 .type = IIO_ACCEL,
211 .modified = 1,
212
213 .channel2 = IIO_MOD_X,
214 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
215
216
217
218
219
220
221 BIT(IIO_CHAN_INFO_CALIBSCALE) |
222 BIT(IIO_CHAN_INFO_CALIBBIAS),
223 .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
224 .scan_index = DUMMY_INDEX_ACCELX,
225 .scan_type = {
226 .sign = 's',
227 .realbits = 16,
228 .storagebits = 16,
229 .shift = 0,
230 },
231 },
232
233
234
235
236 IIO_CHAN_SOFT_TIMESTAMP(4),
237
238 {
239 .type = IIO_VOLTAGE,
240 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
241 .scan_index = -1,
242 .output = 1,
243 .indexed = 1,
244 .channel = 0,
245 },
246 {
247 .type = IIO_STEPS,
248 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_ENABLE) |
249 BIT(IIO_CHAN_INFO_CALIBHEIGHT),
250 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
251 .scan_index = -1,
252#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
253 .event_spec = &step_detect_event,
254 .num_event_specs = 1,
255#endif
256 },
257 {
258 .type = IIO_ACTIVITY,
259 .modified = 1,
260 .channel2 = IIO_MOD_RUNNING,
261 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
262 .scan_index = -1,
263#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
264 .event_spec = &iio_running_event,
265 .num_event_specs = 1,
266#endif
267 },
268 {
269 .type = IIO_ACTIVITY,
270 .modified = 1,
271 .channel2 = IIO_MOD_WALKING,
272 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
273 .scan_index = -1,
274#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
275 .event_spec = &iio_walking_event,
276 .num_event_specs = 1,
277#endif
278 },
279};
280
281
282
283
284
285
286
287
288
289
290static int iio_dummy_read_raw(struct iio_dev *indio_dev,
291 struct iio_chan_spec const *chan,
292 int *val,
293 int *val2,
294 long mask)
295{
296 struct iio_dummy_state *st = iio_priv(indio_dev);
297 int ret = -EINVAL;
298
299 mutex_lock(&st->lock);
300 switch (mask) {
301 case IIO_CHAN_INFO_RAW:
302 switch (chan->type) {
303 case IIO_VOLTAGE:
304 if (chan->output) {
305
306 *val = st->dac_val;
307 ret = IIO_VAL_INT;
308 } else if (chan->differential) {
309 if (chan->channel == 1)
310 *val = st->differential_adc_val[0];
311 else
312 *val = st->differential_adc_val[1];
313 ret = IIO_VAL_INT;
314 } else {
315 *val = st->single_ended_adc_val;
316 ret = IIO_VAL_INT;
317 }
318 break;
319 case IIO_ACCEL:
320 *val = st->accel_val;
321 ret = IIO_VAL_INT;
322 break;
323 default:
324 break;
325 }
326 break;
327 case IIO_CHAN_INFO_PROCESSED:
328 switch (chan->type) {
329 case IIO_STEPS:
330 *val = st->steps;
331 ret = IIO_VAL_INT;
332 break;
333 case IIO_ACTIVITY:
334 switch (chan->channel2) {
335 case IIO_MOD_RUNNING:
336 *val = st->activity_running;
337 ret = IIO_VAL_INT;
338 break;
339 case IIO_MOD_WALKING:
340 *val = st->activity_walking;
341 ret = IIO_VAL_INT;
342 break;
343 default:
344 break;
345 }
346 break;
347 default:
348 break;
349 }
350 break;
351 case IIO_CHAN_INFO_OFFSET:
352
353 *val = 7;
354 ret = IIO_VAL_INT;
355 break;
356 case IIO_CHAN_INFO_SCALE:
357 switch (chan->type) {
358 case IIO_VOLTAGE:
359 switch (chan->differential) {
360 case 0:
361
362 *val = 0;
363 *val2 = 1333;
364 ret = IIO_VAL_INT_PLUS_MICRO;
365 break;
366 case 1:
367
368 *val = 0;
369 *val2 = 1344;
370 ret = IIO_VAL_INT_PLUS_NANO;
371 }
372 break;
373 default:
374 break;
375 }
376 break;
377 case IIO_CHAN_INFO_CALIBBIAS:
378
379 *val = st->accel_calibbias;
380 ret = IIO_VAL_INT;
381 break;
382 case IIO_CHAN_INFO_CALIBSCALE:
383 *val = st->accel_calibscale->val;
384 *val2 = st->accel_calibscale->val2;
385 ret = IIO_VAL_INT_PLUS_MICRO;
386 break;
387 case IIO_CHAN_INFO_SAMP_FREQ:
388 *val = 3;
389 *val2 = 33;
390 ret = IIO_VAL_INT_PLUS_NANO;
391 break;
392 case IIO_CHAN_INFO_ENABLE:
393 switch (chan->type) {
394 case IIO_STEPS:
395 *val = st->steps_enabled;
396 ret = IIO_VAL_INT;
397 break;
398 default:
399 break;
400 }
401 break;
402 case IIO_CHAN_INFO_CALIBHEIGHT:
403 switch (chan->type) {
404 case IIO_STEPS:
405 *val = st->height;
406 ret = IIO_VAL_INT;
407 break;
408 default:
409 break;
410 }
411 break;
412
413 default:
414 break;
415 }
416 mutex_unlock(&st->lock);
417 return ret;
418}
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433static int iio_dummy_write_raw(struct iio_dev *indio_dev,
434 struct iio_chan_spec const *chan,
435 int val,
436 int val2,
437 long mask)
438{
439 int i;
440 int ret = 0;
441 struct iio_dummy_state *st = iio_priv(indio_dev);
442
443 switch (mask) {
444 case IIO_CHAN_INFO_RAW:
445 switch (chan->type) {
446 case IIO_VOLTAGE:
447 if (chan->output == 0)
448 return -EINVAL;
449
450
451 mutex_lock(&st->lock);
452 st->dac_val = val;
453 mutex_unlock(&st->lock);
454 return 0;
455 default:
456 return -EINVAL;
457 }
458 case IIO_CHAN_INFO_PROCESSED:
459 switch (chan->type) {
460 case IIO_STEPS:
461 mutex_lock(&st->lock);
462 st->steps = val;
463 mutex_unlock(&st->lock);
464 return 0;
465 case IIO_ACTIVITY:
466 if (val < 0)
467 val = 0;
468 if (val > 100)
469 val = 100;
470 switch (chan->channel2) {
471 case IIO_MOD_RUNNING:
472 st->activity_running = val;
473 return 0;
474 case IIO_MOD_WALKING:
475 st->activity_walking = val;
476 return 0;
477 default:
478 return -EINVAL;
479 }
480 break;
481 default:
482 return -EINVAL;
483 }
484 case IIO_CHAN_INFO_CALIBSCALE:
485 mutex_lock(&st->lock);
486
487 for (i = 0; i < ARRAY_SIZE(dummy_scales); i++)
488 if (val == dummy_scales[i].val &&
489 val2 == dummy_scales[i].val2)
490 break;
491 if (i == ARRAY_SIZE(dummy_scales))
492 ret = -EINVAL;
493 else
494 st->accel_calibscale = &dummy_scales[i];
495 mutex_unlock(&st->lock);
496 return ret;
497 case IIO_CHAN_INFO_CALIBBIAS:
498 mutex_lock(&st->lock);
499 st->accel_calibbias = val;
500 mutex_unlock(&st->lock);
501 return 0;
502 case IIO_CHAN_INFO_ENABLE:
503 switch (chan->type) {
504 case IIO_STEPS:
505 mutex_lock(&st->lock);
506 st->steps_enabled = val;
507 mutex_unlock(&st->lock);
508 return 0;
509 default:
510 return -EINVAL;
511 }
512 case IIO_CHAN_INFO_CALIBHEIGHT:
513 switch (chan->type) {
514 case IIO_STEPS:
515 st->height = val;
516 return 0;
517 default:
518 return -EINVAL;
519 }
520
521 default:
522 return -EINVAL;
523 }
524}
525
526
527
528
529static const struct iio_info iio_dummy_info = {
530 .driver_module = THIS_MODULE,
531 .read_raw = &iio_dummy_read_raw,
532 .write_raw = &iio_dummy_write_raw,
533#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
534 .read_event_config = &iio_simple_dummy_read_event_config,
535 .write_event_config = &iio_simple_dummy_write_event_config,
536 .read_event_value = &iio_simple_dummy_read_event_value,
537 .write_event_value = &iio_simple_dummy_write_event_value,
538#endif
539};
540
541
542
543
544
545
546
547
548static int iio_dummy_init_device(struct iio_dev *indio_dev)
549{
550 struct iio_dummy_state *st = iio_priv(indio_dev);
551
552 st->dac_val = 0;
553 st->single_ended_adc_val = 73;
554 st->differential_adc_val[0] = 33;
555 st->differential_adc_val[1] = -34;
556 st->accel_val = 34;
557 st->accel_calibbias = -7;
558 st->accel_calibscale = &dummy_scales[0];
559 st->steps = 47;
560 st->activity_running = 98;
561 st->activity_walking = 4;
562
563 return 0;
564}
565
566
567
568
569
570
571
572
573
574
575static int iio_dummy_probe(int index)
576{
577 int ret;
578 struct iio_dev *indio_dev;
579 struct iio_dummy_state *st;
580
581
582
583
584
585
586
587
588
589 indio_dev = iio_device_alloc(sizeof(*st));
590 if (!indio_dev) {
591 ret = -ENOMEM;
592 goto error_ret;
593 }
594
595 st = iio_priv(indio_dev);
596 mutex_init(&st->lock);
597
598 iio_dummy_init_device(indio_dev);
599
600
601
602
603
604
605
606
607
608
609
610
611 iio_dummy_devs[index] = indio_dev;
612
613
614
615
616
617
618
619
620
621
622 indio_dev->name = iio_dummy_part_number;
623
624
625 indio_dev->channels = iio_dummy_channels;
626 indio_dev->num_channels = ARRAY_SIZE(iio_dummy_channels);
627
628
629
630
631
632 indio_dev->info = &iio_dummy_info;
633
634
635 indio_dev->modes = INDIO_DIRECT_MODE;
636
637 ret = iio_simple_dummy_events_register(indio_dev);
638 if (ret < 0)
639 goto error_free_device;
640
641 ret = iio_simple_dummy_configure_buffer(indio_dev);
642 if (ret < 0)
643 goto error_unregister_events;
644
645 ret = iio_device_register(indio_dev);
646 if (ret < 0)
647 goto error_unconfigure_buffer;
648
649 return 0;
650error_unconfigure_buffer:
651 iio_simple_dummy_unconfigure_buffer(indio_dev);
652error_unregister_events:
653 iio_simple_dummy_events_unregister(indio_dev);
654error_free_device:
655 iio_device_free(indio_dev);
656error_ret:
657 return ret;
658}
659
660
661
662
663
664
665
666static void iio_dummy_remove(int index)
667{
668
669
670
671
672
673
674 struct iio_dev *indio_dev = iio_dummy_devs[index];
675
676
677 iio_device_unregister(indio_dev);
678
679
680
681
682 iio_simple_dummy_unconfigure_buffer(indio_dev);
683
684 iio_simple_dummy_events_unregister(indio_dev);
685
686
687 iio_device_free(indio_dev);
688}
689
690
691
692
693
694
695
696
697
698
699
700static __init int iio_dummy_init(void)
701{
702 int i, ret;
703
704 if (instances > 10) {
705 instances = 1;
706 return -EINVAL;
707 }
708
709
710 iio_dummy_devs = kcalloc(instances, sizeof(*iio_dummy_devs),
711 GFP_KERNEL);
712
713 for (i = 0; i < instances; i++) {
714 ret = iio_dummy_probe(i);
715 if (ret < 0)
716 goto error_remove_devs;
717 }
718 return 0;
719
720error_remove_devs:
721 while (i--)
722 iio_dummy_remove(i);
723
724 kfree(iio_dummy_devs);
725 return ret;
726}
727module_init(iio_dummy_init);
728
729
730
731
732
733
734
735static __exit void iio_dummy_exit(void)
736{
737 int i;
738
739 for (i = 0; i < instances; i++)
740 iio_dummy_remove(i);
741 kfree(iio_dummy_devs);
742}
743module_exit(iio_dummy_exit);
744
745MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
746MODULE_DESCRIPTION("IIO dummy driver");
747MODULE_LICENSE("GPL v2");
748