1 /*
2  * Copyright (c) 2019 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "sample_driver.h"
8 #include <string.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/logging/log.h>
11 
12 LOG_MODULE_REGISTER(sample_driver);
13 
14 /*
15  * Fake sample driver for demonstration purposes
16  *
17  * This is fake driver for demonstration purposes, showing how an application
18  * can make system calls to interact with it.
19  *
20  * The driver sets up a timer which is used to fake interrupts.
21  */
22 
23 struct sample_driver_foo_dev_data {
24 	const struct device *dev;
25 	sample_driver_callback_t cb;
26 	void *cb_context;
27 	struct k_timer timer; /* to fake 'interrupts' */
28 	uint32_t count;
29 };
30 
sample_driver_foo_write(const struct device * dev,void * buf)31 static int sample_driver_foo_write(const struct device *dev, void *buf)
32 {
33 	LOG_DBG("%s(%p, %p)", __func__, dev, buf);
34 
35 	return 0;
36 }
37 
sample_driver_foo_set_callback(const struct device * dev,sample_driver_callback_t cb,void * context)38 static int sample_driver_foo_set_callback(const struct device *dev,
39 					  sample_driver_callback_t cb,
40 					  void *context)
41 {
42 	struct sample_driver_foo_dev_data *data = dev->data;
43 	unsigned int key = irq_lock();
44 
45 	data->cb_context = context;
46 	data->cb = cb;
47 	irq_unlock(key);
48 
49 	return 0;
50 }
51 
sample_driver_foo_state_set(const struct device * dev,bool active)52 static int sample_driver_foo_state_set(const struct device *dev, bool active)
53 {
54 	struct sample_driver_foo_dev_data *data = dev->data;
55 
56 	LOG_DBG("%s(%p, %d)", __func__, dev, active);
57 
58 	data->timer.user_data = data;
59 	if (active) {
60 		k_timer_start(&data->timer, K_MSEC(100), K_MSEC(100));
61 	} else {
62 		k_timer_stop(&data->timer);
63 	}
64 
65 	return 0;
66 }
67 
68 static struct sample_driver_api sample_driver_foo_api = {
69 	.write = sample_driver_foo_write,
70 	.set_callback = sample_driver_foo_set_callback,
71 	.state_set = sample_driver_foo_state_set
72 };
73 
sample_driver_foo_isr(void * param)74 static void sample_driver_foo_isr(void *param)
75 {
76 	struct sample_driver_foo_dev_data *data = param;
77 
78 	char data_payload[SAMPLE_DRIVER_MSG_SIZE];
79 
80 	LOG_INF("%s: param=%p count=%u", __func__, param,
81 		data->count);
82 
83 	/* Just for demonstration purposes; the data payload is full of junk */
84 	if (data->cb) {
85 		data->cb(data->dev, data->cb_context, data_payload);
86 	}
87 
88 	data->count++;
89 }
90 
sample_driver_timer_cb(struct k_timer * timer)91 static void sample_driver_timer_cb(struct k_timer *timer)
92 {
93 	sample_driver_foo_isr(timer->user_data);
94 }
95 
sample_driver_foo_init(const struct device * dev)96 static int sample_driver_foo_init(const struct device *dev)
97 {
98 	struct sample_driver_foo_dev_data *data = dev->data;
99 
100 	k_timer_init(&data->timer, sample_driver_timer_cb, NULL);
101 
102 	LOG_DBG("initialized foo sample driver %p", dev);
103 
104 	data->dev = dev;
105 
106 	return 0;
107 }
108 
109 static struct sample_driver_foo_dev_data sample_driver_foo_dev_data_0;
110 
111 DEVICE_DEFINE(sample_driver_foo_0, SAMPLE_DRIVER_NAME_0,
112 		    &sample_driver_foo_init, NULL,
113 		    &sample_driver_foo_dev_data_0, NULL,
114 		    POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
115 		    &sample_driver_foo_api);
116