Added WirelessManager, a port of wpa_supplicant.
[AROS.git] / workbench / network / WirelessManager / src / utils / eloop_amiga.c
bloba5315891282172df45a747f8ba3bdbac67f00638
1 /*
2 * Event loop for AmigaOS/MorphOS/AROS
3 * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
4 * Copyright (c) 2010-2011, Neil Cafferkey
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * Alternatively, this software may be distributed under the terms of BSD
11 * license.
13 * See README and COPYING for more details.
16 #include "includes.h"
18 #include "common.h"
19 #include "eloop.h"
21 #include <exec/types.h>
22 #include <exec/io.h>
23 #include <exec/memory.h>
24 #include <dos/dos.h>
25 #include <devices/timer.h>
27 #include <proto/exec.h>
28 #include <proto/timer.h>
31 struct eloop_sock {
32 int sock;
33 void *eloop_data;
34 void *user_data;
35 void (*handler)(int sock, void *eloop_ctx, void *sock_ctx);
38 struct eloop_timeout {
39 struct os_time time;
40 void *eloop_data;
41 void *user_data;
42 void (*handler)(void *eloop_ctx, void *sock_ctx);
43 struct eloop_timeout *next;
46 struct eloop_signal {
47 int sig;
48 void *user_data;
49 void (*handler)(int sig, void *signal_ctx);
50 int signaled;
53 struct eloop_data {
54 void *user_data;
56 int max_sock, reader_count;
57 struct eloop_sock *readers;
59 struct eloop_timeout *timeout;
61 int signal_count;
62 struct eloop_signal *signals;
63 int signaled;
64 int pending_terminate;
66 int terminate;
67 int reader_table_changed;
69 struct MsgPort *timer_port;
70 struct timerequest *timer_request;
73 static struct eloop_data eloop;
76 int eloop_init(void)
78 int err = 0;
80 memset(&eloop, 0, sizeof(eloop));
82 /* Open timer device */
84 if(err == 0)
86 eloop.timer_port = CreateMsgPort();
87 eloop.timer_request = (APTR)CreateIORequest(eloop.timer_port,
88 sizeof(struct timerequest));
89 if(eloop.timer_request == NULL)
90 err = 1;
93 if(err == 0)
95 if(OpenDevice((CONST_STRPTR)"timer.device", UNIT_VBLANK,
96 (APTR)eloop.timer_request, 0) != 0) {
97 err = 1;
98 DeleteIORequest((APTR)eloop.timer_request);
99 eloop.timer_request = NULL;
100 } else
101 eloop.timer_request->tr_node.io_Message.mn_Node.ln_Type
102 = NT_REPLYMSG;
105 /* Use request at least once to make shutdown easier */
107 if(err == 0)
109 eloop.timer_request->tr_node.io_Command =
110 TR_ADDREQUEST;
111 eloop.timer_request->tr_time.tv_secs = 0;
112 eloop.timer_request->tr_time.tv_micro = 0;
113 DoIO((APTR) eloop.timer_request);
116 return err;
120 int eloop_register_read_sock(int sock,
121 void (*handler)(int sock, void *eloop_ctx,
122 void *sock_ctx),
123 void *eloop_data, void *user_data)
125 struct eloop_sock *tmp;
127 tmp = (struct eloop_sock *)
128 realloc(eloop.readers,
129 (eloop.reader_count + 1) * sizeof(struct eloop_sock));
130 if (tmp == NULL)
131 return -1;
133 tmp[eloop.reader_count].sock = sock;
134 tmp[eloop.reader_count].eloop_data = eloop_data;
135 tmp[eloop.reader_count].user_data = user_data;
136 tmp[eloop.reader_count].handler = handler;
137 eloop.reader_count++;
138 eloop.readers = tmp;
139 if (sock > eloop.max_sock)
140 eloop.max_sock = sock;
141 eloop.reader_table_changed = 1;
143 return 0;
147 void eloop_unregister_read_sock(int sock)
149 int i;
151 if (eloop.readers == NULL || eloop.reader_count == 0)
152 return;
154 for (i = 0; i < eloop.reader_count; i++) {
155 if (eloop.readers[i].sock == sock)
156 break;
158 if (i == eloop.reader_count)
159 return;
160 if (i != eloop.reader_count - 1) {
161 memmove(&eloop.readers[i], &eloop.readers[i + 1],
162 (eloop.reader_count - i - 1) *
163 sizeof(struct eloop_sock));
165 eloop.reader_count--;
166 eloop.reader_table_changed = 1;
170 int eloop_register_timeout(unsigned int secs, unsigned int usecs,
171 void (*handler)(void *eloop_ctx, void *timeout_ctx),
172 void *eloop_data, void *user_data)
174 struct eloop_timeout *timeout, *tmp, *prev;
176 timeout = (struct eloop_timeout *) malloc(sizeof(*timeout));
177 if (timeout == NULL)
178 return -1;
179 os_get_time(&timeout->time);
180 timeout->time.sec += secs;
181 timeout->time.usec += usecs;
182 while (timeout->time.usec >= 1000000) {
183 timeout->time.sec++;
184 timeout->time.usec -= 1000000;
186 timeout->eloop_data = eloop_data;
187 timeout->user_data = user_data;
188 timeout->handler = handler;
189 timeout->next = NULL;
191 if (eloop.timeout == NULL) {
192 eloop.timeout = timeout;
193 return 0;
196 prev = NULL;
197 tmp = eloop.timeout;
198 while (tmp != NULL) {
199 if (os_time_before(&timeout->time, &tmp->time))
200 break;
201 prev = tmp;
202 tmp = tmp->next;
205 if (prev == NULL) {
206 timeout->next = eloop.timeout;
207 eloop.timeout = timeout;
208 } else {
209 timeout->next = prev->next;
210 prev->next = timeout;
213 return 0;
217 int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx),
218 void *eloop_data, void *user_data)
220 struct eloop_timeout *timeout, *prev, *next;
221 int removed = 0;
223 prev = NULL;
224 timeout = eloop.timeout;
225 while (timeout != NULL) {
226 next = timeout->next;
228 if (timeout->handler == handler &&
229 (timeout->eloop_data == eloop_data ||
230 eloop_data == ELOOP_ALL_CTX) &&
231 (timeout->user_data == user_data ||
232 user_data == ELOOP_ALL_CTX)) {
233 if (prev == NULL)
234 eloop.timeout = next;
235 else
236 prev->next = next;
237 free(timeout);
238 removed++;
239 } else
240 prev = timeout;
242 timeout = next;
245 return removed;
249 int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx,
250 void *timeout_ctx),
251 void *eloop_data, void *user_data)
253 struct eloop_timeout *tmp;
255 tmp = eloop.timeout;
256 while (tmp != NULL) {
257 if (tmp->handler == handler &&
258 tmp->eloop_data == eloop_data &&
259 tmp->user_data == user_data)
260 return 1;
262 tmp = tmp->next;
265 return 0;
269 static void eloop_handle_signals(u32 sigs)
271 int i;
273 eloop.signaled++;
274 for (i = 0; i < eloop.signal_count; i++) {
275 if (1 << eloop.signals[i].sig & sigs) {
276 eloop.signals[i].signaled++;
282 static void eloop_process_pending_signals(void)
284 int i;
286 if (eloop.signaled == 0)
287 return;
288 eloop.signaled = 0;
290 if (eloop.pending_terminate) {
291 eloop.pending_terminate = 0;
294 for (i = 0; i < eloop.signal_count; i++) {
295 if (eloop.signals[i].signaled) {
296 eloop.signals[i].signaled = 0;
297 eloop.signals[i].handler(eloop.signals[i].sig,
298 eloop.signals[i].user_data);
304 int eloop_register_signal(int sig,
305 void (*handler)(int sig, void *signal_ctx),
306 void *user_data)
308 struct eloop_signal *tmp;
310 tmp = (struct eloop_signal *)
311 realloc(eloop.signals,
312 (eloop.signal_count + 1) *
313 sizeof(struct eloop_signal));
314 if (tmp == NULL)
315 return -1;
317 tmp[eloop.signal_count].sig = sig;
318 tmp[eloop.signal_count].user_data = user_data;
319 tmp[eloop.signal_count].handler = handler;
320 tmp[eloop.signal_count].signaled = 0;
321 eloop.signal_count++;
322 eloop.signals = tmp;
324 return 0;
328 int eloop_register_signal_terminate(eloop_signal_handler handler,
329 void *user_data)
331 return eloop_register_signal(SIGBREAKB_CTRL_C, handler, user_data);
335 int eloop_register_signal_reconfig(eloop_signal_handler handler,
336 void *user_data)
338 #if 0
339 /* TODO: for example */
340 return eloop_register_signal(SIGHUP, handler, user_data);
341 #endif
342 return 0;
346 void eloop_run(void)
348 int i;
349 struct os_time tv, now;
350 u32 sig_mask, sigs;
351 struct timerequest *cur_timer_req = NULL;
353 while (!eloop.terminate) {
354 sig_mask = 0;
356 if (eloop.timeout && cur_timer_req == NULL) {
357 /* Send a timer request for the next timeout
358 * (even if it's already occurred) */
359 os_get_time(&now);
360 if (os_time_before(&now, &eloop.timeout->time))
361 os_time_sub(&eloop.timeout->time, &now, &tv);
362 else
363 tv.sec = tv.usec = 0;
364 eloop.timer_request->tr_node.io_Command =
365 TR_ADDREQUEST;
366 eloop.timer_request->tr_time.tv_secs =
367 tv.sec;
368 eloop.timer_request->tr_time.tv_micro =
369 tv.usec;
370 SendIO((APTR) eloop.timer_request);
371 cur_timer_req = eloop.timer_request;
373 if (eloop.timeout) {
374 sig_mask |= 1 << eloop.timer_port->mp_SigBit;
378 /* Add registered signals to signal mask */
379 for (i = 0; i < eloop.signal_count; i++)
380 sig_mask |= 1 << eloop.signals[i].sig;
382 /* Wait for something to happen */
383 sigs = Wait(sig_mask);
384 eloop_handle_signals(sigs);
385 eloop_process_pending_signals();
387 /* Check if some registered timeouts have occurred */
388 if (eloop.timeout) {
389 struct eloop_timeout *tmp;
391 os_get_time(&now);
392 if (sigs & 1 << eloop.timer_port->mp_SigBit) {
393 tmp = eloop.timeout;
394 eloop.timeout = eloop.timeout->next;
395 tmp->handler(tmp->eloop_data,
396 tmp->user_data);
397 free(tmp);
399 WaitIO((APTR) eloop.timer_request);
400 cur_timer_req = NULL;
408 void eloop_terminate(void)
410 eloop.terminate = 1;
414 void eloop_destroy(void)
416 struct eloop_timeout *timeout, *prev;
418 timeout = eloop.timeout;
419 while (timeout != NULL) {
420 prev = timeout;
421 timeout = timeout->next;
422 free(prev);
424 free(eloop.signals);
426 if(eloop.timer_request != NULL) {
427 AbortIO((APTR) eloop.timer_request);
428 WaitIO((APTR) eloop.timer_request);
429 CloseDevice((APTR) eloop.timer_request);
431 DeleteIORequest((APTR) eloop.timer_request);
432 DeleteMsgPort(eloop.timer_port);
436 int eloop_terminated(void)
438 return eloop.terminate;