This source file includes following definitions.
- sensordev_install
- sensor_attach
- sensordev_deinstall
- sensor_detach
- sensordev_get
- sensor_find
- sensor_task_register
- sensor_task_unregister
- sensor_task_tick
- sensor_task_work
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <sys/param.h>
21 #include <sys/proc.h>
22 #include <sys/systm.h>
23 #include <sys/kernel.h>
24 #include <sys/malloc.h>
25 #include <sys/queue.h>
26 #include <sys/types.h>
27 #include <sys/device.h>
28 #include <sys/hotplug.h>
29 #include <sys/timeout.h>
30 #include <sys/workq.h>
31
32 #include <sys/sensors.h>
33 #include "hotplug.h"
34
35 int sensordev_count = 0;
36 SLIST_HEAD(, ksensordev) sensordev_list =
37 SLIST_HEAD_INITIALIZER(sensordev_list);
38
39 void
40 sensordev_install(struct ksensordev *sensdev)
41 {
42 struct ksensordev *v, *nv;
43 int s;
44
45 s = splhigh();
46 if (sensordev_count == 0) {
47 sensdev->num = 0;
48 SLIST_INSERT_HEAD(&sensordev_list, sensdev, list);
49 } else {
50 for (v = SLIST_FIRST(&sensordev_list);
51 (nv = SLIST_NEXT(v, list)) != NULL; v = nv)
52 if (nv->num - v->num > 1)
53 break;
54 sensdev->num = v->num + 1;
55 SLIST_INSERT_AFTER(v, sensdev, list);
56 }
57 sensordev_count++;
58 splx(s);
59
60 #if NHOTPLUG > 0
61 hotplug_device_attach(DV_DULL, "sensordev");
62 #endif
63 }
64
65 void
66 sensor_attach(struct ksensordev *sensdev, struct ksensor *sens)
67 {
68 struct ksensor *v, *nv;
69 struct ksensors_head *sh;
70 int s, i;
71
72 s = splhigh();
73 sh = &sensdev->sensors_list;
74 if (sensdev->sensors_count == 0) {
75 for (i = 0; i < SENSOR_MAX_TYPES; i++)
76 sensdev->maxnumt[i] = 0;
77 sens->numt = 0;
78 SLIST_INSERT_HEAD(sh, sens, list);
79 } else {
80 for (v = SLIST_FIRST(sh);
81 (nv = SLIST_NEXT(v, list)) != NULL; v = nv)
82 if (v->type == sens->type && (v->type != nv->type ||
83 (v->type == nv->type && nv->numt - v->numt > 1)))
84 break;
85
86 if (v->type == sens->type)
87 sens->numt = v->numt + 1;
88 else
89 sens->numt = 0;
90 SLIST_INSERT_AFTER(v, sens, list);
91 }
92
93
94
95 if (sensdev->maxnumt[sens->type] == sens->numt)
96 sensdev->maxnumt[sens->type]++;
97 sensdev->sensors_count++;
98 splx(s);
99 }
100
101 void
102 sensordev_deinstall(struct ksensordev *sensdev)
103 {
104 int s;
105
106 s = splhigh();
107 sensordev_count--;
108 SLIST_REMOVE(&sensordev_list, sensdev, ksensordev, list);
109 splx(s);
110
111 #if NHOTPLUG > 0
112 hotplug_device_detach(DV_DULL, "sensordev");
113 #endif
114 }
115
116 void
117 sensor_detach(struct ksensordev *sensdev, struct ksensor *sens)
118 {
119 struct ksensors_head *sh;
120 int s;
121
122 s = splhigh();
123 sh = &sensdev->sensors_list;
124 sensdev->sensors_count--;
125 SLIST_REMOVE(sh, sens, ksensor, list);
126
127
128
129 if (sens->numt == sensdev->maxnumt[sens->type] - 1)
130 sensdev->maxnumt[sens->type]--;
131 splx(s);
132 }
133
134 struct ksensordev *
135 sensordev_get(int num)
136 {
137 struct ksensordev *sd;
138
139 SLIST_FOREACH(sd, &sensordev_list, list)
140 if (sd->num == num)
141 return (sd);
142
143 return (NULL);
144 }
145
146 struct ksensor *
147 sensor_find(int dev, enum sensor_type type, int numt)
148 {
149 struct ksensor *s;
150 struct ksensordev *sensdev;
151 struct ksensors_head *sh;
152
153 sensdev = sensordev_get(dev);
154 if (sensdev == NULL)
155 return (NULL);
156
157 sh = &sensdev->sensors_list;
158 SLIST_FOREACH(s, sh, list)
159 if (s->type == type && s->numt == numt)
160 return (s);
161
162 return (NULL);
163 }
164
165 struct sensor_task {
166 void (*func)(void *);
167 void *arg;
168
169 int period;
170 struct timeout timeout;
171 volatile enum {
172 ST_TICKING,
173 ST_WORKQ,
174 ST_RUNNING,
175 ST_DYING,
176 ST_DEAD
177 } state;
178 };
179
180 void sensor_task_tick(void *);
181 void sensor_task_work(void *, void *);
182
183 struct sensor_task *
184 sensor_task_register(void *arg, void (*func)(void *), int period)
185 {
186 struct sensor_task *st;
187
188 st = malloc(sizeof(struct sensor_task), M_DEVBUF, M_NOWAIT);
189 if (st == NULL)
190 return (NULL);
191
192 st->func = func;
193 st->arg = arg;
194 st->period = period;
195 timeout_set(&st->timeout, sensor_task_tick, st);
196
197 sensor_task_tick(st);
198
199 return (st);
200 }
201
202 void
203 sensor_task_unregister(struct sensor_task *st)
204 {
205 timeout_del(&st->timeout);
206
207 switch (st->state) {
208 case ST_TICKING:
209 free(st, M_DEVBUF);
210 break;
211
212 case ST_WORKQ:
213 st->state = ST_DYING;
214 break;
215
216 case ST_RUNNING:
217 st->state = ST_DYING;
218 while (st->state != ST_DEAD)
219 tsleep(st, 0, "stunr", 0);
220 free(st, M_DEVBUF);
221 break;
222 default:
223 panic("sensor_task_unregister: unexpected state %d",
224 st->state);
225 }
226 }
227
228 void
229 sensor_task_tick(void *arg)
230 {
231 struct sensor_task *st = arg;
232
233
234 if (workq_add_task(NULL, 0, sensor_task_work, st, NULL) != 0)
235 timeout_add(&st->timeout, hz/2);
236
237 st->state = ST_WORKQ;
238 }
239
240 void
241 sensor_task_work(void *xst, void *arg)
242 {
243 struct sensor_task *st = xst;
244
245 if (st->state == ST_DYING) {
246 free(st, M_DEVBUF);
247 return;
248 }
249
250 st->state = ST_RUNNING;
251 st->func(st->arg);
252
253 if (st->state == ST_DYING) {
254 st->state = ST_DEAD;
255 wakeup(st);
256 } else {
257 st->state = ST_TICKING;
258 timeout_add(&st->timeout, hz * st->period);
259 }
260 }