summaryrefslogtreecommitdiff
path: root/apps/plugins/plugin_crt0.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/plugin_crt0.c')
-rwxr-xr-xapps/plugins/plugin_crt0.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/apps/plugins/plugin_crt0.c b/apps/plugins/plugin_crt0.c
new file mode 100755
index 0000000000..ff117be002
--- /dev/null
+++ b/apps/plugins/plugin_crt0.c
@@ -0,0 +1,112 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2010 by Thomas Martitz
11*
12* This program is free software; you can redistribute it and/or
13* modify it under the terms of the GNU General Public License
14* as published by the Free Software Foundation; either version 2
15* of the License, or (at your option) any later version.
16*
17* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18* KIND, either express or implied.
19*
20****************************************************************************/
21
22
23#include "plugin.h"
24#include <setjmp.h>
25
26PLUGIN_HEADER
27
28/*
29 * EXIT_MAGIC magic, because 0 cannot be used due to setjmp()
30 * must be > 0
31 */
32#define EXIT_MAGIC 0x0CDEBABE
33
34extern enum plugin_status plugin_start(const void*);
35
36static jmp_buf __exit_env;
37/* only 1 atexit handler for now, chain in the exit handler if you need more */
38static void (*atexit_handler)(void);
39
40int atexit(void (*fn)(void))
41{
42 if (atexit_handler)
43 return -1;
44 atexit_handler = fn;
45 return 0;
46}
47
48void exit(int status)
49{ /* jump back in time to before starting the plugin */
50 longjmp(__exit_env, status != 0 ? status : EXIT_MAGIC);
51}
52
53void _exit(int status)
54{ /* don't call exit handler */
55 atexit_handler = NULL;
56 exit(status);
57}
58
59enum plugin_status plugin__start(const void *param)
60{
61 int exit_ret;
62 enum plugin_status ret;
63
64 /* we come back here if exit() was called or the plugin returned normally */
65 exit_ret = setjmp(__exit_env);
66 if (exit_ret == 0)
67 { /* start the plugin */
68 ret = plugin_start(param);
69 }
70 else
71 { /* plugin exit via exit() */
72 if (exit_ret == EXIT_MAGIC)
73 { /* exit(EXIT_SUCCESS) */
74 ret = PLUGIN_OK;
75 }
76 else if (exit_ret < INTERNAL_PLUGIN_RETVAL_START)
77 { /* exit(EXIT_FAILURE) */
78 ret = PLUGIN_ERROR;
79 }
80 else
81 { /* exit(PLUGIN_XXX) */
82 ret = (enum plugin_status)exit_ret;
83 }
84 }
85
86 /* before finishing, call the exit handler if there was one */
87 if (atexit_handler != NULL)
88 atexit_handler();
89
90 return ret;
91}
92
93static void cleanup_wrapper(void *param)
94{
95 (void)param;
96 if (atexit_handler)
97 atexit_handler();
98}
99
100void exit_on_usb(int button)
101{ /* the default handler will call the exit handler before
102 * showing the usb screen; after that we don't want the exit handler
103 * to be called a second time, hence _exit()
104 *
105 * if not usb, then the handler will only be called if powering off
106 * if poweroff, the plugin doesn't want to run any further so exit as well*/
107 long result = rb->default_event_handler_ex(button, cleanup_wrapper, NULL);
108 if (result == SYS_USB_CONNECTED)
109 _exit(PLUGIN_USB_CONNECTED);
110 else if (result == SYS_POWEROFF)
111 _exit(PLUGIN_POWEROFF);
112}