diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/ata_idle_notify.c | 20 | ||||
-rw-r--r-- | firmware/events.c | 61 | ||||
-rw-r--r-- | firmware/export/ata_idle_notify.h | 4 | ||||
-rw-r--r-- | firmware/export/events.h | 69 | ||||
-rw-r--r-- | firmware/logf.c | 5 |
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 | ||
28 | void register_storage_idle_func(void (*function)(void *data)) | 28 | static 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 | |||
36 | void 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 |
41 | void unregister_storage_idle_func(void (*func)(void *data), bool run) | 49 | void 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 | ||
49 | bool call_storage_idle_notifys(bool force) | 57 | bool 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 @@ | |||
28 | struct sysevent { | 28 | struct 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 | ||
34 | static struct sysevent events[MAX_SYS_EVENTS]; | 41 | static struct sysevent events[MAX_SYS_EVENTS]; |
35 | 42 | ||
36 | bool add_event(unsigned short id, bool oneshot, void (*handler)(void *data)) | 43 | static 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 | ||
63 | void remove_event(unsigned short id, void (*handler)(void *data)) | 74 | bool 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 | |||
79 | bool 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 | |||
84 | void 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 | ||
100 | void remove_event(unsigned short id, void (*handler)(unsigned short id, void *data)) | ||
101 | { | ||
102 | do_remove_event(id, false, handler, NULL); | ||
103 | } | ||
104 | |||
105 | void 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 | |||
77 | void send_event(unsigned short id, void *data) | 112 | void 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 | ||
51 | extern void register_storage_idle_func(void (*function)(void *data)); | 51 | extern void register_storage_idle_func(void (*function)(void)); |
52 | #if USING_STORAGE_CALLBACK | 52 | #if USING_STORAGE_CALLBACK |
53 | extern void unregister_storage_idle_func(void (*function)(void *data), bool run); | 53 | extern void unregister_storage_idle_func(void (*function)(void), bool run); |
54 | extern bool call_storage_idle_notifys(bool force); | 54 | extern 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 | ||
43 | bool add_event(unsigned short id, bool oneshot, void (*handler)(void *data)); | 55 | /** |
44 | void 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 | */ | ||
62 | bool 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 | */ | ||
76 | bool 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 | */ | ||
83 | void 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 | */ | ||
92 | void 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 | */ | ||
45 | void send_event(unsigned short id, void *data); | 99 | void 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 | ||
325 | static void flush_buffer(void* data); | 325 | static void flush_buffer(void); |
326 | 326 | ||
327 | void _logdiskf(const char* file, const char level, const char *fmt, ...) | 327 | void _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 | ||
353 | static void flush_buffer(void* data) | 353 | static 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; |