2 * Copyright (c) 2012, Intel Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Intel Corporation nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #ifndef __MURPHY_PLUGIN_H__
31 #define __MURPHY_PLUGIN_H__
36 #include <murphy/common/macros.h>
37 #include <murphy/common/mm.h>
38 #include <murphy/common/log.h>
39 #include <murphy/common/list.h>
40 #include <murphy/common/refcnt.h>
41 #include <murphy/common/json.h>
42 #include <murphy/core/context.h>
43 #include <murphy/core/console-command.h>
45 typedef struct mrp_plugin_s mrp_plugin_t;
47 #include <murphy/core/method.h>
49 #ifndef MRP_DEFAULT_PLUGIN_DIR
50 # define MRP_DEFAULT_PLUGIN_DIR LIBDIR"/murphy/plugins"
53 #define MRP_PLUGIN_DESCRIPTOR "mrp_get_plugin_descriptor"
57 * names of plugin-related events we emit
60 #define MRP_PLUGIN_BUS "plugin-bus"
61 #define MRP_PLUGIN_EVENT_LOADED "plugin-loaded"
62 #define MRP_PLUGIN_EVENT_STARTED "plugin-started"
63 #define MRP_PLUGIN_EVENT_FAILED "plugin-failed"
64 #define MRP_PLUGIN_EVENT_STOPPING "plugin-stopping"
65 #define MRP_PLUGIN_EVENT_STOPPED "plugin-stopped"
66 #define MRP_PLUGIN_EVENT_UNLOADED "plugin-unloaded"
70 * event message data tags
73 #define MRP_PLUGIN_TAG_PLUGIN ((uint16_t)1) /* plugin name string */
74 #define MRP_PLUGIN_TAG_INSTANCE ((uint16_t)2) /* plugin instance string */
82 MRP_PLUGIN_ARG_TYPE_UNKNOWN = 0,
83 MRP_PLUGIN_ARG_TYPE_STRING,
84 MRP_PLUGIN_ARG_TYPE_BOOL,
85 MRP_PLUGIN_ARG_TYPE_UINT32,
86 MRP_PLUGIN_ARG_TYPE_INT32,
87 MRP_PLUGIN_ARG_TYPE_DOUBLE,
88 MRP_PLUGIN_ARG_TYPE_OBJECT,
89 MRP_PLUGIN_ARG_TYPE_UNDECL,
90 /* add more as needed */
91 } mrp_plugin_arg_type_t;
93 typedef struct mrp_plugin_arg_s mrp_plugin_arg_t;
95 struct mrp_plugin_arg_s {
96 char *key; /* plugin argument name */
97 mrp_plugin_arg_type_t type; /* plugin argument type */
98 union { /* default/supplied value */
99 char *str; /* string values */
100 bool bln; /* boolean values */
101 uint32_t u32; /* 32-bit unsigned values */
102 int32_t i32; /* 32-bit signed values */
103 double dbl; /* double prec. floating pt. values */
104 struct { /* a JSON object */
108 struct { /* other undeclared arguments */
109 mrp_plugin_arg_t *args;
116 /** Macro for declaring a plugin argument table. */
117 #define MRP_PLUGIN_ARGUMENTS(table, ...) \
118 static mrp_plugin_arg_t table[] = \
122 /** Convenience macros for setting up argument tables with type and defaults. */
123 #define MRP_PLUGIN_ARG_STRING(name, defval) \
124 { key: name, type: MRP_PLUGIN_ARG_TYPE_STRING, { str: defval } }
126 #define MRP_PLUGIN_ARG_BOOL(name, defval) \
127 { key: name, type: MRP_PLUGIN_ARG_TYPE_BOOL , { bln: !!defval } }
129 #define MRP_PLUGIN_ARG_UINT32(name, defval) \
130 { key: name, type: MRP_PLUGIN_ARG_TYPE_UINT32, { u32: defval } }
132 #define MRP_PLUGIN_ARG_INT32(name, defval) \
133 { key: name, type: MRP_PLUGIN_ARG_TYPE_INT32 , { i32: defval } }
135 #define MRP_PLUGIN_ARG_DOUBLE(name, defval) \
136 { key: name, type: MRP_PLUGIN_ARG_TYPE_DOUBLE, { dbl: defval } }
138 #define MRP_PLUGIN_ARG_OBJECT(name, defval) \
139 { key: name, type: MRP_PLUGIN_ARG_TYPE_OBJECT, \
140 { obj: { str: defval, json: NULL } } }
142 #define MRP_PLUGIN_ARG_UNDECL(name, defval) \
143 { key: "*", type: MRP_PLUGIN_ARG_TYPE_UNDECL, { str: NULL } }
145 /** Similar convenience macros for indexed argument access. */
146 #define MRP_PLUGIN_ARGIDX_STRING(idx, name, defval) \
147 [idx] MRP_PLUGIN_ARG_STRING(name, defval)
149 #define MRP_PLUGIN_ARGIDX_STRING(idx, name, defval) \
150 [idx] MRP_PLUGIN_ARG_STRING(name, defval)
152 #define MRP_PLUGIN_ARGIDX_BOOL(idx, name, defval) \
153 [idx] MRP_PLUGIN_ARG_BOOL(name, defval)
155 #define MRP_PLUGIN_ARGIDX_UINT32(idx, name, defval) \
156 [idx] MRP_PLUGIN_ARG_UINT32(name, defval)
158 #define MRP_PLUGIN_ARGIDX_INT32(idx, name, defval) \
159 [idx] MRP_PLUGIN_ARG_INT32(name, defval)
161 #define MRP_PLUGIN_ARGIDX_DOUBLE(idx, name, defval) \
162 [idx] MRP_PLUGIN_ARG_DOUBLE(name, defval)
164 #define MRP_PLUGIN_ARGIDX_OBJECT(idx, name, defval) \
165 [idx] MRP_PLUGIN_ARG_OBJECT(name, defval)
167 #define MRP_PLUGIN_ARGIDX_UNDECL(idx, name, defval) \
168 [idx] MRP_PLUGIN_ARG_UNDECL(name, defval)
170 /** Macro for looping through all collected undeclared arguments. */
171 #define mrp_plugin_foreach_undecl_arg(_undecl, _arg) \
172 for ((_arg) = (_undecl)->rest.args; \
173 (_arg) - (_undecl)->rest.args < (_undecl)->rest.narg; \
178 * Generic convenience macro for indexed argument access.
180 * Here is how you can use these macros to declare and access your plugin
183 * #define TEST_HELP "Just a stupid test..."
184 * #define TEST_DESCRIPTION "A test plugin."
185 * #define TEST_AUTHORS "D. Duck <donald.duck@ducksburg.org>"
194 * mrp_plugin_arg_t test_args[] = {
195 * MRP_PLUGIN_ARGIDX(ARG_FOO , STRING, "foo" , "default foo"),
196 * MRP_PLUGIN_ARGIDX(ARG_BAR , BOOL , "bar" , FALSE ),
197 * MRP_PLUGIN_ARGIDX(ARG_FOOBAR, UINT32, "foobar", 1984 ),
198 * MRP_PLUGIN_ARGIDX(ARG_BARFOO, DOUBLE, "barfoo", 3.141 ),
201 * static int test_init(mrp_plugin_t *plugin)
203 * mrp_plugin_arg_t *args = plugin->args;
205 * if (args[ARG_BAR].bln) {
206 * mrp_log_info(" foo: %s", args[ARG_FOO].str);
207 * mrp_log_info("foobar: %u", args[ARG_FOOBAR].u32);
208 * mrp_log_info("barfoo: %f", args[ARG_BARFOO].dbl);
211 * mrp_log_info("I was not asked to dump my arguments...");
215 * MURPHY_REGISTER_PLUGIN("test", TEST_DESCRIPTION, TEST_AUTHORS, TEST_HELP,
216 * MRP_MULTIPLE, test_init, test_exit, test_args);
219 #define MRP_PLUGIN_ARGIDX(idx, type, name, defval) \
220 [idx] MRP_PLUGIN_ARG_##type(name, defval)
227 #define MRP_PLUGIN_API_MAJOR 0
228 #define MRP_PLUGIN_API_MINOR 1
230 #define MRP_PLUGIN_API_VERSION \
231 MRP_VERSION_INT(MRP_PLUGIN_API_MAJOR, MRP_PLUGIN_API_MINOR, 0)
233 #define MRP_PLUGIN_API_VERSION_STRING \
234 MRP_VERSION_STRING(MRP_PLUGIN_API_MAJOR, MRP_PLUGIN_API_MINOR, 0)
242 typedef int (*mrp_plugin_init_t)(mrp_plugin_t *);
243 typedef void (*mrp_plugin_exit_t)(mrp_plugin_t *);
245 #define MRP_SINGLETON TRUE
246 #define MRP_MULTIPLE FALSE
249 char *name; /* plugin name */
250 char *path; /* plugin path */
251 mrp_plugin_init_t init; /* initialize plugin */
252 mrp_plugin_exit_t exit; /* cleanup plugin */
253 mrp_plugin_arg_t *args; /* table of valid arguments */
254 int narg; /* number of valid arguments */
255 int core : 1; /* is this a core plugin? */
256 int singleton : 1; /* deny multiple instances? */
257 int ninstance; /* number of instances */
258 /* miscallaneous plugin metadata */
259 int version; /* plugin version */
260 int mrp_version; /* murphy API version */
261 const char *description; /* plugin description */
262 const char *authors; /* plugin authors */
263 const char *help; /* plugin help string */
264 mrp_console_group_t *cmds; /* default console commands */
265 mrp_method_descr_t *exports; /* exported methods */
266 int nexport; /* number of exported methods */
267 mrp_method_descr_t *imports; /* imported methods */
268 int nimport; /* number of imported methods */
269 } mrp_plugin_descr_t;
277 MRP_PLUGIN_LOADED = 0, /* has been loaded */
278 MRP_PLUGIN_RUNNING, /* has been started */
279 MRP_PLUGIN_STOPPED, /* has been stopped */
280 } mrp_plugin_state_t;
282 struct mrp_plugin_s {
283 char *path; /* plugin path */
284 char *instance; /* plugin instance */
285 mrp_list_hook_t hook; /* hook to list of plugins */
286 mrp_context_t *ctx; /* murphy context */
287 mrp_plugin_descr_t *descriptor; /* plugin descriptor */
288 void *handle; /* DSO handle */
289 mrp_plugin_state_t state; /* plugin state */
290 mrp_refcnt_t refcnt; /* reference count */
291 void *data; /* private plugin data */
292 mrp_plugin_arg_t *args; /* plugin arguments */
293 mrp_console_group_t *cmds; /* default console commands */
294 int may_fail : 1; /* load / start may fail */
298 #ifdef __MURPHY_BUILTIN_PLUGIN__
299 /* statically linked in plugins */
300 # define __MURPHY_REGISTER_PLUGIN(_name, \
317 static void register_plugin(void) __attribute__((constructor)); \
319 static void register_plugin(void) { \
320 char *path = __FILE__, *base; \
321 static mrp_plugin_descr_t descriptor = { \
323 .version = _version, \
324 .description = _description, \
325 .authors = _authors, \
326 .mrp_version = MRP_PLUGIN_API_VERSION, \
331 .singleton = _single, \
336 .exports = _exports, \
337 .nexport = _nexport, \
338 .imports = _imports, \
339 .nimport = _nimport, \
342 if ((base = strrchr(path, '/')) != NULL) \
343 descriptor.path = base + 1; \
345 descriptor.path = (char *)path; \
347 mrp_register_builtin_plugin(&descriptor); \
349 struct mrp_allow_trailing_semicolon
350 #else /* dynamically loaded plugins */
351 # define __MURPHY_REGISTER_PLUGIN(_name, \
368 mrp_plugin_descr_t *mrp_get_plugin_descriptor(void) { \
369 static mrp_plugin_descr_t descriptor = { \
371 .version = _version, \
372 .description = _description, \
373 .authors = _authors, \
374 .mrp_version = MRP_PLUGIN_API_VERSION, \
379 .singleton = _single, \
384 .exports = _exports, \
385 .nexport = _nexport, \
386 .imports = _imports, \
387 .nimport = _nimport, \
390 return &descriptor; \
392 struct mrp_allow_trailing_semicolon
396 #define MURPHY_REGISTER_PLUGIN(_n, _v, _d, _a, _h, _s, _i, _e, \
398 _exports, _nexport, \
399 _imports, _nimport, \
401 __MURPHY_REGISTER_PLUGIN(_n, _v, _d, _a, _h, FALSE, _s, _i, _e, \
403 _exports, _nexport, \
404 _imports, _nimport, \
407 #define MURPHY_REGISTER_CORE_PLUGIN(_n, _v, _d, _a, _h, _s, _i, _e, \
409 _exports, _nexport, \
410 _imports, _nimport, \
412 __MURPHY_REGISTER_PLUGIN(_n, _v, _d, _a, _h, TRUE, _s, _i, _e, \
414 _exports, _nexport, \
415 _imports, _nimport, \
418 #define MRP_REGISTER_PLUGIN MURPHY_REGISTER_PLUGIN
419 #define MRP_REGISTER_CORE_PLUGIN MURPHY_REGISTER_CORE_PLUGIN
422 int mrp_register_builtin_plugin(mrp_plugin_descr_t *descr);
423 int mrp_plugin_exists(mrp_context_t *ctx, const char *name);
424 mrp_plugin_t *mrp_load_plugin(mrp_context_t *ctx, const char *name,
425 const char *instance, mrp_plugin_arg_t *args,
427 int mrp_load_all_plugins(mrp_context_t *ctx);
428 int mrp_unload_plugin(mrp_plugin_t *plugin);
429 int mrp_plugin_loaded(mrp_context_t *ctx, const char *name);
430 int mrp_start_plugins(mrp_context_t *ctx);
431 int mrp_start_plugin(mrp_plugin_t *plugin);
432 int mrp_plugin_running(mrp_context_t *ctx, const char *name);
433 int mrp_stop_plugin(mrp_plugin_t *plugin);
434 int mrp_request_plugin(mrp_context_t *ctx, const char *name,
435 const char *instance);
436 void mrp_block_blacklisted_plugins(mrp_context_t *ctx);
438 mrp_plugin_arg_t *mrp_plugin_find_undecl_arg(mrp_plugin_arg_t *undecl,
440 mrp_plugin_arg_type_t type);
443 static inline mrp_plugin_t *mrp_ref_plugin(mrp_plugin_t *plugin)
445 return mrp_ref_obj(plugin, refcnt);
449 static inline int mrp_unref_plugin(mrp_plugin_t *plugin)
451 return mrp_unref_obj(plugin, refcnt);
455 #endif /* __MURPHY_PLUGIN_H__ */