summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2014-03-14 23:15:16 +0100
committerThomas Martitz <kugel@rockbox.org>2014-03-14 23:36:30 +0100
commit470989bd708d9a425dbbf2d83b8fcbd0a8d0f488 (patch)
treef3bef37bc0f8ff7da4beddad9903209ced1bc25a /firmware
parent50f0dd80d660b332a1739e07a630c2cef1b678c6 (diff)
downloadrockbox-470989bd708d9a425dbbf2d83b8fcbd0a8d0f488.tar.gz
rockbox-470989bd708d9a425dbbf2d83b8fcbd0a8d0f488.zip
events: Rework event subsystem (add_event, send_event) to be more versatile.
add_event_ex is added that takes an extra user_data pointer. This pointer is passed to the callback (add_event and add_event_ex have slightly different callbacks types). All callbacks also get the event id passed. Events added with add_event_ex must be removed with remove_event_ex because the user_data pointer must match in addition to the callback pointer. On the other add_event is simplified to omit the oneshort parameter which was almost always false (still there with add_event_ex). As a side effect the ata_idle_notify callbacks are changed as well, they do not take a data parameter anymore which was always NULL anyway. This commit also adds some documentation to events.h Change-Id: I13e29a0f88ef908f175b376d83550f9e0231f772
Diffstat (limited to 'firmware')
-rw-r--r--firmware/ata_idle_notify.c20
-rw-r--r--firmware/events.c61
-rw-r--r--firmware/export/ata_idle_notify.h4
-rw-r--r--firmware/export/events.h69
-rw-r--r--firmware/logf.c5
5 files changed, 128 insertions, 31 deletions
diff --git a/firmware/ata_idle_notify.c b/firmware/ata_idle_notify.c
index 35d192bee0..ee9f3c035f 100644
--- a/firmware/ata_idle_notify.c
+++ b/firmware/ata_idle_notify.c
@@ -25,12 +25,20 @@
25#include "kernel.h" 25#include "kernel.h"
26#include "string.h" 26#include "string.h"
27 27
28void register_storage_idle_func(void (*function)(void *data)) 28static void wrapper(unsigned short id, void *ev_data, void *user_data)
29{
30 (void)id;
31 (void)ev_data;
32 void (*func)(void) = user_data;
33 func();
34}
35
36void register_storage_idle_func(void (*function)(void))
29{ 37{
30#if USING_STORAGE_CALLBACK 38#if USING_STORAGE_CALLBACK
31 add_event(DISK_EVENT_SPINUP, true, function); 39 add_event_ex(DISK_EVENT_SPINUP, true, wrapper, function);
32#else 40#else
33 function(NULL); /* just call the function now */ 41 function(); /* just call the function now */
34/* this _may_ cause problems later if the calling function 42/* this _may_ cause problems later if the calling function
35 sets a variable expecting the callback to unset it, because 43 sets a variable expecting the callback to unset it, because
36 the callback will be run before this function exits, so before the var is set */ 44 the callback will be run before this function exits, so before the var is set */
@@ -38,12 +46,12 @@ void register_storage_idle_func(void (*function)(void *data))
38} 46}
39 47
40#if USING_STORAGE_CALLBACK 48#if USING_STORAGE_CALLBACK
41void unregister_storage_idle_func(void (*func)(void *data), bool run) 49void unregister_storage_idle_func(void (*func)(void), bool run)
42{ 50{
43 remove_event(DISK_EVENT_SPINUP, func); 51 remove_event_ex(DISK_EVENT_SPINUP, wrapper, func);
44 52
45 if (run) 53 if (run)
46 func(NULL); 54 func();
47} 55}
48 56
49bool call_storage_idle_notifys(bool force) 57bool call_storage_idle_notifys(bool force)
diff --git a/firmware/events.c b/firmware/events.c
index 74172e1fa0..4a51e7ae87 100644
--- a/firmware/events.c
+++ b/firmware/events.c
@@ -28,30 +28,41 @@
28struct sysevent { 28struct sysevent {
29 unsigned short id; 29 unsigned short id;
30 bool oneshot; 30 bool oneshot;
31 void (*callback)(void *data); 31 bool has_user_data;
32 union {
33 void (*callback)(unsigned short id, void *event_data);
34 struct {
35 void (*callback2)(unsigned short id, void *event_data, void *user_data);
36 void *user_data;
37 };
38 } handler;
32}; 39};
33 40
34static struct sysevent events[MAX_SYS_EVENTS]; 41static struct sysevent events[MAX_SYS_EVENTS];
35 42
36bool add_event(unsigned short id, bool oneshot, void (*handler)(void *data)) 43static bool do_add_event(unsigned short id, bool oneshot, bool user_data_valid,
44 void *handler, void *user_data)
37{ 45{
38 int i; 46 int i;
39 47
40 /* Check if the event already exists. */ 48 /* Check if the event already exists. */
41 for (i = 0; i < MAX_SYS_EVENTS; i++) 49 for (i = 0; i < MAX_SYS_EVENTS; i++)
42 { 50 {
43 if (events[i].callback == handler && events[i].id == id) 51 if (events[i].handler.callback == handler && events[i].id == id
52 && (!user_data_valid || (user_data == events[i].handler.callback)))
44 return false; 53 return false;
45 } 54 }
46 55
47 /* Try to find a free slot. */ 56 /* Try to find a free slot. */
48 for (i = 0; i < MAX_SYS_EVENTS; i++) 57 for (i = 0; i < MAX_SYS_EVENTS; i++)
49 { 58 {
50 if (events[i].callback == NULL) 59 if (events[i].handler.callback == NULL)
51 { 60 {
52 events[i].id = id; 61 events[i].id = id;
53 events[i].oneshot = oneshot; 62 events[i].oneshot = oneshot;
54 events[i].callback = handler; 63 if ((events[i].has_user_data = user_data_valid))
64 events[i].handler.user_data = user_data;
65 events[i].handler.callback = handler;
55 return true; 66 return true;
56 } 67 }
57 } 68 }
@@ -60,33 +71,59 @@ bool add_event(unsigned short id, bool oneshot, void (*handler)(void *data))
60 return false; 71 return false;
61} 72}
62 73
63void remove_event(unsigned short id, void (*handler)(void *data)) 74bool add_event(unsigned short id, void (*handler)(unsigned short id, void *data))
75{
76 return do_add_event(id, false, false, handler, NULL);
77}
78
79bool add_event_ex(unsigned short id, bool oneshot, void (*handler)(unsigned short id, void *event_data, void *user_data), void *user_data)
80{
81 return do_add_event(id, oneshot, true, handler, user_data);
82}
83
84void do_remove_event(unsigned short id, bool user_data_valid,
85 void *handler, void *user_data)
64{ 86{
65 int i; 87 int i;
66 88
67 for (i = 0; i < MAX_SYS_EVENTS; i++) 89 for (i = 0; i < MAX_SYS_EVENTS; i++)
68 { 90 {
69 if (events[i].id == id && events[i].callback == handler) 91 if (events[i].id == id && events[i].handler.callback == handler
92 && (!user_data_valid || (user_data == events[i].handler.callback)))
70 { 93 {
71 events[i].callback = NULL; 94 events[i].handler.callback = NULL;
72 return; 95 return;
73 } 96 }
74 } 97 }
75} 98}
76 99
100void remove_event(unsigned short id, void (*handler)(unsigned short id, void *data))
101{
102 do_remove_event(id, false, handler, NULL);
103}
104
105void remove_event_ex(unsigned short id,
106 void (*handler)(unsigned short id, void *event_data, void *user_data),
107 void *user_data)
108{
109 do_remove_event(id, true, handler, user_data);
110}
111
77void send_event(unsigned short id, void *data) 112void send_event(unsigned short id, void *data)
78{ 113{
79 int i; 114 int i;
80 115
81 for (i = 0; i < MAX_SYS_EVENTS; i++) 116 for (i = 0; i < MAX_SYS_EVENTS; i++)
82 { 117 {
83 if (events[i].id == id && events[i].callback != NULL) 118 if (events[i].id == id && events[i].handler.callback != NULL)
84 { 119 {
85 events[i].callback(data); 120 if (events[i].has_user_data)
121 events[i].handler.callback2(id, data, events[i].handler.user_data);
122 else
123 events[i].handler.callback(id, data);
86 124
87 if (events[i].oneshot) 125 if (events[i].oneshot)
88 events[i].callback = NULL; 126 events[i].handler.callback = NULL;
89 } 127 }
90 } 128 }
91} 129}
92
diff --git a/firmware/export/ata_idle_notify.h b/firmware/export/ata_idle_notify.h
index 93a53eee34..0443f8e516 100644
--- a/firmware/export/ata_idle_notify.h
+++ b/firmware/export/ata_idle_notify.h
@@ -48,9 +48,9 @@ enum {
48 */ 48 */
49#define USING_STORAGE_CALLBACK !defined(BOOTLOADER) && !defined(APPLICATION) && !defined(__PCTOOL__) 49#define USING_STORAGE_CALLBACK !defined(BOOTLOADER) && !defined(APPLICATION) && !defined(__PCTOOL__)
50 50
51extern void register_storage_idle_func(void (*function)(void *data)); 51extern void register_storage_idle_func(void (*function)(void));
52#if USING_STORAGE_CALLBACK 52#if USING_STORAGE_CALLBACK
53extern void unregister_storage_idle_func(void (*function)(void *data), bool run); 53extern void unregister_storage_idle_func(void (*function)(void), bool run);
54extern bool call_storage_idle_notifys(bool force); 54extern bool call_storage_idle_notifys(bool force);
55#else 55#else
56#define unregister_storage_idle_func(f,r) 56#define unregister_storage_idle_func(f,r)
diff --git a/firmware/export/events.h b/firmware/export/events.h
index 859901c0b4..fd7f9df42e 100644
--- a/firmware/export/events.h
+++ b/firmware/export/events.h
@@ -23,12 +23,24 @@
23#define _EVENTS_H 23#define _EVENTS_H
24 24
25#include <stdbool.h> 25#include <stdbool.h>
26
27/** Only CLASS defines and firmware/ level events should be defined here.
28 * apps/ level events are defined in apps/appevents.h
29 */
30
31/** 26/**
27 * Synchronouos event system.
28 *
29 * Callbacks are subscribed with add_event() or add_event_ex(). events
30 * are fired using send_event().
31 *
32 * Events are always dispatched synchronously: the callbacks are called
33 * in the thread context of the event sender, without context switch. This
34 * also means that callbacks should be as simple as possible to avoid
35 * blocking the sender and other callbacks
36 *
37 * Use the kernel-level event_queue for cross-thread event dispatching.
38 * */
39
40/*
41 * Only CLASS defines and firmware/ level events should be defined here.
42 * apps/ level events are defined in apps/appevents.h
43 *
32 * High byte = Event class definition 44 * High byte = Event class definition
33 * Low byte = Event ID 45 * Low byte = Event ID
34 */ 46 */
@@ -40,9 +52,50 @@
40#define EVENT_CLASS_RECORDING 0x1000 52#define EVENT_CLASS_RECORDING 0x1000
41#define EVENT_CLASS_LCD 0x2000 53#define EVENT_CLASS_LCD 0x2000
42 54
43bool add_event(unsigned short id, bool oneshot, void (*handler)(void *data)); 55/**
44void remove_event(unsigned short id, void (*handler)(void *data)); 56 * Subscribe to an event with a simple callback. The callback will be called
57 * synchronously everytime the event fires, passing the event id and data to
58 * the callback.
59 *
60 * Must be removed with remove_event().
61 */
62bool add_event(unsigned short id, void (*handler)(unsigned short id, void *event_data));
63
64/**
65 * Subscribe to an event with a detailed callback. The callback will be called
66 * synchronously everytime the event fires, passing the event id and data, as
67 * well as the user_data pointer passed here, to the callback.
68 *
69 * With oneshot == true, the callback is unsubscribed automatically after
70 * the event fired for the first time. In this case the event need not to be
71 * removed with remove_event_ex().
72 *
73 * Must be removed with remove_event_ex(). remove_event() will never remove
74 * events added with this function.
75 */
76bool add_event_ex(unsigned short id, bool oneshot, void (*handler)(unsigned short id, void *event_data, void *user_data), void *user_data);
77
78/**
79 * Unsubscribe a callback from an event. The handler pointer is matched.
80 *
81 * This will only work for subscriptions made with add_event().
82 */
83void remove_event(unsigned short id, void (*handler)(unsigned short id, void *data));
84
85/**
86 * Unsubscribe a callback from an event. The handler and user_data pointers
87 * are matched. That means the same user_data that was passed to add_event_ex()
88 * must be passed to this too.
89 *
90 * This will only work for subscriptions made with add_event_ex().
91 */
92void remove_event_ex(unsigned short id, void (*handler)(unsigned short id, void *event_data, void *user_data), void *user_data);
93
94/**
95 * Fire an event, which synchronously calls all subscribed callbacks. The
96 * event id and data pointer are passed to the callbacks as well, and
97 * optionally the user_data pointer from add_event_ex().
98 */
45void send_event(unsigned short id, void *data); 99void send_event(unsigned short id, void *data);
46 100
47#endif 101#endif
48
diff --git a/firmware/logf.c b/firmware/logf.c
index a24a635570..ade5458ca9 100644
--- a/firmware/logf.c
+++ b/firmware/logf.c
@@ -322,7 +322,7 @@ static int logdiskf_push(void *userp, unsigned char c)
322 return true; 322 return true;
323} 323}
324 324
325static void flush_buffer(void* data); 325static void flush_buffer(void);
326 326
327void _logdiskf(const char* file, const char level, const char *fmt, ...) 327void _logdiskf(const char* file, const char level, const char *fmt, ...)
328{ 328{
@@ -350,9 +350,8 @@ void _logdiskf(const char* file, const char level, const char *fmt, ...)
350 register_storage_idle_func(flush_buffer); 350 register_storage_idle_func(flush_buffer);
351} 351}
352 352
353static void flush_buffer(void* data) 353static void flush_buffer(void)
354{ 354{
355 (void)data;
356 int fd; 355 int fd;
357 if(logdiskfindex < 1) 356 if(logdiskfindex < 1)
358 return; 357 return;