summaryrefslogtreecommitdiff
path: root/firmware/events.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/events.c')
-rw-r--r--firmware/events.c83
1 files changed, 41 insertions, 42 deletions
diff --git a/firmware/events.c b/firmware/events.c
index 8124f92b20..9b810c5d0d 100644
--- a/firmware/events.c
+++ b/firmware/events.c
@@ -28,42 +28,43 @@
28struct sysevent { 28struct sysevent {
29 unsigned short id; 29 unsigned short id;
30 bool oneshot; 30 bool oneshot;
31 bool has_user_data;
32 union { 31 union {
33 void (*callback)(unsigned short id, void *event_data); 32 void (*cb)(unsigned short id, void *event_data);
34 struct { 33 void (*cb_ex)(unsigned short id, void *event_data, void *user_data);
35 void (*callback2)(unsigned short id, void *event_data, void *user_data);
36 void *user_data;
37 };
38 } handler; 34 } handler;
35 void *user_data;
39}; 36};
40 37
41static struct sysevent events[MAX_SYS_EVENTS]; 38static struct sysevent events[MAX_SYS_EVENTS];
39static int invalid_userdata;
42 40
43static bool do_add_event(unsigned short id, bool oneshot, bool user_data_valid, 41static bool do_add_event(unsigned short id, bool oneshot,
44 void *handler, void *user_data) 42 void *handler, void *user_data)
45{ 43{
46 int free = -1; 44 size_t free = MAX_SYS_EVENTS;
45 struct sysevent *ev;
47 /* Check if the event already exists. & lowest free slot available */ 46 /* Check if the event already exists. & lowest free slot available */
48 for (int i = MAX_SYS_EVENTS - 1; i >= 0; i--) 47 for (size_t i = MAX_SYS_EVENTS - 1; i < MAX_SYS_EVENTS; i--)
49 { 48 {
50 if (events[i].handler.callback == handler && events[i].id == id 49 ev = &events[i];
51 && (!user_data_valid || (user_data == events[i].handler.user_data))) 50 if (ev->handler.cb == NULL)
51 free = i;
52
53 if (ev->id == id && ev->handler.cb == handler && user_data == ev->user_data)
52 { 54 {
53 return false; 55 return false;
54 } 56 }
55 else if (events[i].handler.callback == NULL)
56 free = i;
57 } 57 }
58 58
59 /* is there a free slot? */ 59 /* is there a free slot? */
60 if (free >= 0) 60 if (free < MAX_SYS_EVENTS)
61 { 61 {
62 events[free].id = id; 62 ev = &events[free];
63 events[free].oneshot = oneshot; 63 ev->id = id;
64 if ((events[free].has_user_data = user_data_valid)) 64 ev->handler.cb = handler;
65 events[free].handler.user_data = user_data; 65 ev->user_data = user_data;
66 events[free].handler.callback = handler; 66 ev->oneshot = oneshot;
67
67 return true; 68 return true;
68 } 69 }
69 70
@@ -73,25 +74,23 @@ static bool do_add_event(unsigned short id, bool oneshot, bool user_data_valid,
73 74
74bool add_event(unsigned short id, void (*handler)(unsigned short id, void *data)) 75bool add_event(unsigned short id, void (*handler)(unsigned short id, void *data))
75{ 76{
76 return do_add_event(id, false, false, handler, NULL); 77 return do_add_event(id, false, handler, &invalid_userdata);
77} 78}
78 79
79bool add_event_ex(unsigned short id, bool oneshot, void (*handler)(unsigned short id, void *event_data, void *user_data), void *user_data) 80bool add_event_ex(unsigned short id, bool oneshot,
81 void (*handler)(unsigned short id, void *event_data, void *user_data), void *user_data)
80{ 82{
81 return do_add_event(id, oneshot, true, handler, user_data); 83 return do_add_event(id, oneshot, handler, user_data);
82} 84}
83 85
84static void do_remove_event(unsigned short id, bool user_data_valid, 86static void do_remove_event(unsigned short id, void *handler, void *user_data)
85 void *handler, void *user_data)
86{ 87{
87 int i; 88 for (size_t i = 0; i < MAX_SYS_EVENTS; i++)
88
89 for (i = 0; i < MAX_SYS_EVENTS; i++)
90 { 89 {
91 if (events[i].id == id && events[i].handler.callback == handler 90 struct sysevent *ev = &events[i];
92 && (!user_data_valid || (user_data == events[i].handler.user_data))) 91 if (ev->id == id && ev->handler.cb == handler && user_data == ev->user_data)
93 { 92 {
94 events[i].handler.callback = NULL; 93 ev->handler.cb = NULL;
95 return; 94 return;
96 } 95 }
97 } 96 }
@@ -99,31 +98,31 @@ static void do_remove_event(unsigned short id, bool user_data_valid,
99 98
100void remove_event(unsigned short id, void (*handler)(unsigned short id, void *data)) 99void remove_event(unsigned short id, void (*handler)(unsigned short id, void *data))
101{ 100{
102 do_remove_event(id, false, handler, NULL); 101 do_remove_event(id, handler, &invalid_userdata);
103} 102}
104 103
105void remove_event_ex(unsigned short id, 104void remove_event_ex(unsigned short id,
106 void (*handler)(unsigned short id, void *event_data, void *user_data), 105 void (*handler)(unsigned short id, void *event_data, void *user_data),
107 void *user_data) 106 void *user_data)
108{ 107{
109 do_remove_event(id, true, handler, user_data); 108 do_remove_event(id, handler, user_data);
110} 109}
111 110
112void send_event(unsigned short id, void *data) 111void send_event(unsigned short id, void *data)
113{ 112{
114 int i; 113 for (size_t i = 0; i < MAX_SYS_EVENTS; i++)
115
116 for (i = 0; i < MAX_SYS_EVENTS; i++)
117 { 114 {
118 if (events[i].id == id && events[i].handler.callback != NULL) 115 struct sysevent *ev = &events[i];
116 if (ev->id == id && ev->handler.cb != NULL)
119 { 117 {
120 if (events[i].has_user_data) 118 if (ev->user_data != &invalid_userdata)
121 events[i].handler.callback2(id, data, events[i].handler.user_data); 119 {
120 ev->handler.cb_ex(id, data, ev->user_data);
121 if (ev->oneshot) /* only _ex events have option of oneshot */
122 ev->handler.cb = NULL;
123 }
122 else 124 else
123 events[i].handler.callback(id, data); 125 ev->handler.cb(id, data);
124
125 if (events[i].oneshot)
126 events[i].handler.callback = NULL;
127 } 126 }
128 } 127 }
129} 128}