From 9777a02c7540fdec145feb948b4bbf1cd44c3352 Mon Sep 17 00:00:00 2001 From: fulup Date: Sun, 13 Aug 2017 16:50:34 +0200 Subject: Fix AFB_MESSAGE with null arguments --- Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c | 5 +- Alsa-Plugin/Alsa-Policy-Hook/README.md | 6 +- Alsa-afb/Alsa-ApiHat.c | 10 + Controler-afb/CMakeLists.txt | 4 +- Controler-afb/ctl-apidef.h | 123 ++++--- Controler-afb/ctl-apidef.json | 50 ++- Controler-afb/ctl-binding.c | 3 + Controler-afb/ctl-binding.h | 19 +- Controler-afb/ctl-dispatch.c | 396 ++++++++++++++-------- Controler-afb/ctl-events.c | 2 +- Controler-afb/ctl-lua.c | 325 ++++++++++-------- Controler-afb/ctl-misc.c | 115 +++++++ Controler-afb/ctl-misc2.c | 74 ++++ Controler-afb/ctl-plugin-sample.c | 21 +- HAL-afb/CMakeLists.txt | 2 +- conf.d/CMakeLists.txt | 10 +- conf.d/cmake/config.cmake | 16 +- conf.d/ctl-rules/CMakeLists.txt | 44 --- conf.d/ctl-rules/helloworld-lua-script.lua | 41 --- conf.d/ctl-rules/onload-control-policy.json | 108 ------ conf.d/ctl-rules/onload-control-script.lua | 96 ------ conf.d/project/CMakeLists.txt | 24 ++ conf.d/project/config.d/CMakeLists.txt | 40 +++ conf.d/project/config.d/onload-audio-control.json | 116 +++++++ conf.d/project/lua.d/CMakeLists.txt | 40 +++ conf.d/project/lua.d/helloworld-lua-script.lua | 41 +++ conf.d/project/lua.d/onload-audio-policy.lua | 49 +++ conf.d/project/lua.d/onload-audio-samples.lua | 93 +++++ nbproject/configurations.xml | 261 +++----------- 29 files changed, 1255 insertions(+), 879 deletions(-) create mode 100644 Controler-afb/ctl-misc.c create mode 100644 Controler-afb/ctl-misc2.c delete mode 100644 conf.d/ctl-rules/CMakeLists.txt delete mode 100644 conf.d/ctl-rules/helloworld-lua-script.lua delete mode 100644 conf.d/ctl-rules/onload-control-policy.json delete mode 100644 conf.d/ctl-rules/onload-control-script.lua create mode 100644 conf.d/project/CMakeLists.txt create mode 100644 conf.d/project/config.d/CMakeLists.txt create mode 100644 conf.d/project/config.d/onload-audio-control.json create mode 100644 conf.d/project/lua.d/CMakeLists.txt create mode 100644 conf.d/project/lua.d/helloworld-lua-script.lua create mode 100644 conf.d/project/lua.d/onload-audio-policy.lua create mode 100644 conf.d/project/lua.d/onload-audio-samples.lua diff --git a/Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c b/Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c index 501ebf9..3b52f5b 100644 --- a/Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c +++ b/Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c @@ -58,9 +58,8 @@ #endif // Currently not implemented -#define UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) -#define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x -void OnRequestCB(void* UNUSED(handle) , const char* UNUSED(api), const char* UNUSED(verb), struct afb_wsj1_msg*UNUSED(msg)) {} +#define UNUSED_ARG(x) UNUSED_ ## x __attribute__((__unused__)) +void OnRequestCB(void* UNUSED_ARG(handle) , const char* UNUSED_ARG(api), const char* UNUSED_ARG(verb), struct afb_wsj1_msg*UNUSED_ARG(msg)) {} typedef struct { const char *api; diff --git a/Alsa-Plugin/Alsa-Policy-Hook/README.md b/Alsa-Plugin/Alsa-Policy-Hook/README.md index ce0553c..537418d 100644 --- a/Alsa-Plugin/Alsa-Policy-Hook/README.md +++ b/Alsa-Plugin/Alsa-Policy-Hook/README.md @@ -40,17 +40,17 @@ pcm.MyNavigationHook { request { # Request autorisation to write on navigation RequestNavigation { - api "polctl" + api "control" verb "navigation" } # subscribe to Audio Agent Event SubscriveEvents { - api "polctl" + api "control" verb "monitor" } # force PCM stop after 10s TestAutoStop { - api "polctl" + api "control" verb "event_test" query "{'label':'stop', 'delay':10000}" } diff --git a/Alsa-afb/Alsa-ApiHat.c b/Alsa-afb/Alsa-ApiHat.c index 2c3c5c1..1e9f5ad 100644 --- a/Alsa-afb/Alsa-ApiHat.c +++ b/Alsa-afb/Alsa-ApiHat.c @@ -25,9 +25,18 @@ #include #include #include +#include + #include "Alsa-ApiHat.h" +STATIC int AlsaInit(void) { + int rc= prctl(PR_SET_NAME, "afb-audio-agent\0",NULL,NULL,NULL); + if (rc) AFB_ERROR("ERROR: AlsaCore fail to rename process"); + + return rc; +} + /* * array of the verbs exported to afb-daemon */ @@ -56,4 +65,5 @@ static const struct afb_verb_v2 api_verbs[] = { const struct afb_binding_v2 afbBindingV2 = { .api = "alsacore", .verbs = api_verbs, + .init = AlsaInit, }; diff --git a/Controler-afb/CMakeLists.txt b/Controler-afb/CMakeLists.txt index 64ea5e1..4fb97b2 100644 --- a/Controler-afb/CMakeLists.txt +++ b/Controler-afb/CMakeLists.txt @@ -33,7 +33,7 @@ endmacro(SET_TARGET_GENSKEL) PROJECT_TARGET_ADD(control-afb) # Define project Targets - ADD_LIBRARY(${TARGET_NAME} MODULE ctl-binding.c ctl-events.c ctl-dispatch.c ctl-lua.c) + ADD_LIBRARY(${TARGET_NAME} MODULE ctl-binding.c ctl-events.c ctl-dispatch.c ctl-lua.c ctl-misc.c) # Generate API-v2 hat from OpenAPI json definition SET_TARGET_GENSKEL(${TARGET_NAME} ctl-apidef) @@ -56,7 +56,7 @@ PROJECT_TARGET_ADD(control-afb) INSTALL(TARGETS ${TARGET_NAME} LIBRARY DESTINATION CMAKE_INSTALL_PREFIX ) -PROJECT_TARGET_ADD(ctl-plugin-sample) +PROJECT_TARGET_ADD(audio-plugin-sample) # Define targets ADD_LIBRARY(${TARGET_NAME} MODULE ctl-plugin-sample.c) diff --git a/Controler-afb/ctl-apidef.h b/Controler-afb/ctl-apidef.h index 0ab4cd2..0f801cb 100644 --- a/Controler-afb/ctl-apidef.h +++ b/Controler-afb/ctl-apidef.h @@ -1,61 +1,66 @@ static const char _afb_description_v2_control[] = "{\"openapi\":\"3.0.0\",\"$schema\":\"http:iot.bzh/download/openapi/schem" - "a-3.0/default-schema.json\",\"info\":{\"description\":\"\",\"title\":\"p" - "olctl\",\"version\":\"1.0\",\"x-binding-c-generator\":{\"api\":\"control" - "\",\"version\":2,\"prefix\":\"ctlapi_\",\"postfix\":\"\",\"start\":null," - "\"onevent\":null,\"init\":\"CtlBindingInit\",\"scope\":\"\",\"private\":" - "false}},\"servers\":[{\"url\":\"ws://{host}:{port}/api/polctl\",\"descri" - "ption\":\"Unicens2 API.\",\"variables\":{\"host\":{\"default\":\"localho" - "st\"},\"port\":{\"default\":\"1234\"}},\"x-afb-events\":[{\"$ref\":\"#/c" - "omponents/schemas/afb-event\"}]}],\"components\":{\"schemas\":{\"afb-rep" - "ly\":{\"$ref\":\"#/components/schemas/afb-reply-v2\"},\"afb-event\":{\"$" - "ref\":\"#/components/schemas/afb-event-v2\"},\"afb-reply-v2\":{\"title\"" - ":\"Generic response.\",\"type\":\"object\",\"required\":[\"jtype\",\"req" - "uest\"],\"properties\":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-r" - "eply\"},\"request\":{\"type\":\"object\",\"required\":[\"status\"],\"pro" - "perties\":{\"status\":{\"type\":\"string\"},\"info\":{\"type\":\"string\"" - "},\"token\":{\"type\":\"string\"},\"uuid\":{\"type\":\"string\"},\"reqid" - "\":{\"type\":\"string\"}}},\"response\":{\"type\":\"object\"}}},\"afb-ev" - "ent-v2\":{\"type\":\"object\",\"required\":[\"jtype\",\"event\"],\"prope" - "rties\":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-event\"},\"event" - "\":{\"type\":\"string\"},\"data\":{\"type\":\"object\"}}}},\"x-permissio" - "ns\":{\"monitor\":{\"permission\":\"urn:AGL:permission:audio:public:moni" - "tor\"},\"multimedia\":{\"permission\":\"urn:AGL:permission:audio:public:" - "monitor\"},\"navigation\":{\"permission\":\"urn:AGL:permission:audio:pub" - "lic:monitor\"},\"emergency\":{\"permission\":\"urn:AGL:permission:audio:" - "public:emergency\"}},\"responses\":{\"200\":{\"description\":\"A complex" - " object array response\",\"content\":{\"application/json\":{\"schema\":{" - "\"$ref\":\"#/components/schemas/afb-reply\"}}}}}},\"paths\":{\"/monitor\"" - ":{\"description\":\"Subcribe Audio Agent Policy Control End\",\"get\":{\"" - "x-permissions\":{\"$ref\":\"#/components/x-permissions/monitor\"},\"para" - "meters\":[{\"in\":\"query\",\"name\":\"event_patern\",\"required\":true," - "\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/" - "components/responses/200\"}}}},\"/event_test\":{\"description\":\"Pause " - "Resume Test\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-perm" - "issions/monitor\"},\"parameters\":[{\"in\":\"query\",\"name\":\"delay\"," - "\"required\":false,\"schema\":{\"type\":\"interger\"}},{\"in\":\"query\"" - ",\"name\":\"count\",\"required\":false,\"schema\":{\"type\":\"interger\"" - "}}],\"responses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}}," - "\"/navigation\":{\"description\":\"Request Access to Navigation Audio Ch" - "annel.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissio" - "ns/navigation\"},\"parameters\":[{\"in\":\"query\",\"name\":\"zone\",\"r" - "equired\":false,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\"" - ":{\"$ref\":\"#/components/responses/200\"}}}},\"/lua_docall\":{\"descrip" - "tion\":\"Execute LUA string script.\",\"get\":{\"x-permissions\":{\"$ref" - "\":\"#/components/x-permissions/navigation\"},\"parameters\":[{\"in\":\"" - "query\",\"name\":\"func\",\"required\":true,\"schema\":{\"type\":\"strin" - "g\"}},{\"in\":\"query\",\"name\":\"args\",\"required\":false,\"schema\":" - "{\"type\":\"array\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/r" - "esponses/200\"}}}},\"/lua_dostring\":{\"description\":\"Execute LUA stri" - "ng script.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permi" - "ssions/navigation\"},\"parameters\":[{\"in\":\"query\",\"required\":true" - ",\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#" - "/components/responses/200\"}}}},\"/lua_doscript\":{\"description\":\"Exe" - "cute LUA string script.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/compo" + "a-3.0/default-schema.json\",\"info\":{\"description\":\"\",\"title\":\"c" + "ontroler\",\"version\":\"1.0\",\"x-binding-c-generator\":{\"api\":\"cont" + "rol\",\"version\":2,\"prefix\":\"ctlapi_\",\"postfix\":\"\",\"start\":nu" + "ll,\"onevent\":\"DispatchOneEvent\",\"init\":\"CtlBindingInit\",\"scope\"" + ":\"\",\"private\":false}},\"servers\":[{\"url\":\"ws://{host}:{port}/api" + "/polctl\",\"description\":\"Unicens2 API.\",\"variables\":{\"host\":{\"d" + "efault\":\"localhost\"},\"port\":{\"default\":\"1234\"}},\"x-afb-events\"" + ":[{\"$ref\":\"#/components/schemas/afb-event\"}]}],\"components\":{\"sch" + "emas\":{\"afb-reply\":{\"$ref\":\"#/components/schemas/afb-reply-v2\"},\"" + "afb-event\":{\"$ref\":\"#/components/schemas/afb-event-v2\"},\"afb-reply" + "-v2\":{\"title\":\"Generic response.\",\"type\":\"object\",\"required\":" + "[\"jtype\",\"request\"],\"properties\":{\"jtype\":{\"type\":\"string\",\"" + "const\":\"afb-reply\"},\"request\":{\"type\":\"object\",\"required\":[\"" + "status\"],\"properties\":{\"status\":{\"type\":\"string\"},\"info\":{\"t" + "ype\":\"string\"},\"token\":{\"type\":\"string\"},\"uuid\":{\"type\":\"s" + "tring\"},\"reqid\":{\"type\":\"string\"}}},\"response\":{\"type\":\"obje" + "ct\"}}},\"afb-event-v2\":{\"type\":\"object\",\"required\":[\"jtype\",\"" + "event\"],\"properties\":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-" + "event\"},\"event\":{\"type\":\"string\"},\"data\":{\"type\":\"object\"}}" + "}},\"x-permissions\":{\"monitor\":{\"permission\":\"urn:AGL:permission:a" + "udio:public:monitor\"},\"multimedia\":{\"permission\":\"urn:AGL:permissi" + "on:audio:public:monitor\"},\"navigation\":{\"permission\":\"urn:AGL:perm" + "ission:audio:public:monitor\"},\"emergency\":{\"permission\":\"urn:AGL:p" + "ermission:audio:public:emergency\"}},\"responses\":{\"200\":{\"descripti" + "on\":\"A complex object array response\",\"content\":{\"application/json" + "\":{\"schema\":{\"$ref\":\"#/components/schemas/afb-reply\"}}}}}},\"path" + "s\":{\"/monitor\":{\"description\":\"Subcribe Audio Agent Policy Control" + " End\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions" + "/monitor\"},\"parameters\":[{\"in\":\"query\",\"name\":\"event_patern\"," + "\"required\":true,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"20" + "0\":{\"$ref\":\"#/components/responses/200\"}}}},\"/event_test\":{\"desc" + "ription\":\"Pause Resume Test\",\"get\":{\"x-permissions\":{\"$ref\":\"#" + "/components/x-permissions/monitor\"},\"parameters\":[{\"in\":\"query\",\"" + "name\":\"delay\",\"required\":false,\"schema\":{\"type\":\"interger\"}}," + "{\"in\":\"query\",\"name\":\"count\",\"required\":false,\"schema\":{\"ty" + "pe\":\"interger\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/res" + "ponses/200\"}}}},\"/navigation\":{\"description\":\"Request Access to Na" + "vigation Audio Channel.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/compo" "nents/x-permissions/navigation\"},\"parameters\":[{\"in\":\"query\",\"na" - "me\":\"filename\",\"required\":true,\"schema\":{\"type\":\"string\"}}],\"" - "responses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}}}}" + "me\":\"zone\",\"required\":false,\"schema\":{\"type\":\"string\"}}],\"re" + "sponses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/multi" + "media\":{\"description\":\"Request Access to Navigation Audio Channel.\"" + ",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions/navig" + "ation\"},\"parameters\":[{\"in\":\"query\",\"name\":\"zone\",\"required\"" + ":false,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref" + "\":\"#/components/responses/200\"}}}},\"/lua_docall\":{\"description\":\"" + "Execute LUA string script.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/co" + "mponents/x-permissions/navigation\"},\"parameters\":[{\"in\":\"query\",\"" + "name\":\"func\",\"required\":true,\"schema\":{\"type\":\"string\"}},{\"i" + "n\":\"query\",\"name\":\"args\",\"required\":false,\"schema\":{\"type\":" + "\"array\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/responses/2" + "00\"}}}},\"/lua_dostring\":{\"description\":\"Execute LUA string script." + "\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions/nav" + "igation\"},\"parameters\":[{\"in\":\"query\",\"required\":true,\"schema\"" + ":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components" + "/responses/200\"}}}},\"/lua_doscript\":{\"description\":\"Execute LUA st" + "ring script.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-per" + "missions/navigation\"},\"parameters\":[{\"in\":\"query\",\"name\":\"file" + "name\",\"required\":true,\"schema\":{\"type\":\"string\"}}],\"responses\"" + ":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}}}}" ; static const struct afb_auth _afb_auths_v2_control[] = { @@ -65,6 +70,7 @@ static const struct afb_auth _afb_auths_v2_control[] = { void ctlapi_monitor(struct afb_req req); void ctlapi_event_test(struct afb_req req); void ctlapi_navigation(struct afb_req req); + void ctlapi_multimedia(struct afb_req req); void ctlapi_lua_docall(struct afb_req req); void ctlapi_lua_dostring(struct afb_req req); void ctlapi_lua_doscript(struct afb_req req); @@ -91,6 +97,13 @@ static const struct afb_verb_v2 _afb_verbs_v2_control[] = { .info = NULL, .session = AFB_SESSION_NONE_V2 }, + { + .verb = "multimedia", + .callback = ctlapi_multimedia, + .auth = &_afb_auths_v2_control[0], + .info = NULL, + .session = AFB_SESSION_NONE_V2 + }, { .verb = "lua_docall", .callback = ctlapi_lua_docall, @@ -122,7 +135,7 @@ const struct afb_binding_v2 afbBindingV2 = { .verbs = _afb_verbs_v2_control, .preinit = NULL, .init = CtlBindingInit, - .onevent = NULL, + .onevent = DispatchOneEvent, .noconcurrency = 0 }; diff --git a/Controler-afb/ctl-apidef.json b/Controler-afb/ctl-apidef.json index fddf301..438a9ef 100644 --- a/Controler-afb/ctl-apidef.json +++ b/Controler-afb/ctl-apidef.json @@ -3,7 +3,7 @@ "$schema": "http:iot.bzh/download/openapi/schema-3.0/default-schema.json", "info": { "description": "", - "title": "polctl", + "title": "controler", "version": "1.0", "x-binding-c-generator": { "api": "control", @@ -11,7 +11,7 @@ "prefix": "ctlapi_", "postfix": "", "start": null, - "onevent": null, + "onevent": "DispatchOneEvent", "init": "CtlBindingInit", "scope": "", "private": false @@ -201,6 +201,52 @@ } } }, + "/multimedia": { + "description": "Request Access to Navigation Audio Channel.", + "get": { + "x-permissions": { + "$ref": "#/components/x-permissions/navigation" + }, + "parameters": [ + { + "in": "query", + "name": "zone", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "$ref": "#/components/responses/200" + } + } + } + }, + "/navigation": { + "description": "Request Access to Navigation Audio Channel.", + "get": { + "x-permissions": { + "$ref": "#/components/x-permissions/navigation" + }, + "parameters": [ + { + "in": "query", + "name": "zone", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "$ref": "#/components/responses/200" + } + } + } + }, "/lua_docall": { "description": "Execute LUA string script.", "get": { diff --git a/Controler-afb/ctl-binding.c b/Controler-afb/ctl-binding.c index dc225a4..19f97eb 100644 --- a/Controler-afb/ctl-binding.c +++ b/Controler-afb/ctl-binding.c @@ -68,6 +68,9 @@ PUBLIC int CtlBindingInit () { errcount += DispatchInit(); errcount += LuaLibInit(); + // now that everything is initialised execute the onload action + errcount += DispatchOneOnLoad(CONTROL_ONLOAD_DEFAULT); + AFB_DEBUG ("Audio Policy Control Binding Done errcount=%d", errcount); return errcount; } diff --git a/Controler-afb/ctl-binding.h b/Controler-afb/ctl-binding.h index deef93c..01840b8 100644 --- a/Controler-afb/ctl-binding.h +++ b/Controler-afb/ctl-binding.h @@ -28,6 +28,11 @@ #endif #define STATIC static +#ifndef UNUSED_ARG +#define UNUSED_ARG(x) UNUSED_ ## x __attribute__((__unused__)) +#define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x +#endif + // sharelib ctl-plugin* typedef struct { long magic; @@ -36,6 +41,9 @@ typedef struct { #define CTL_PLUGIN_REGISTER(pluglabel) CtlPluginMagicT CtlPluginMagic={.magic=CTL_PLUGIN_MAGIC,.label=pluglabel}; struct afb_binding_data_v2; +// ctl-misc.c + + // polctl-binding.c PUBLIC int CtlBindingInit (); @@ -49,12 +57,14 @@ PUBLIC void ctlapi_event_test (afb_req request); // ctl-policy // ----------- - typedef enum { CTL_SCAN_FLAT=0, CTL_SCAN_RECURSIVE=1, } CtlScanDirModeT; +PUBLIC json_object* ScanForConfig (char* searchPath, CtlScanDirModeT mode, char *pre, char *ext); +PUBLIC const char *GetBinderName(); + typedef enum { CTL_MODE_NONE=0, CTL_MODE_API, @@ -70,10 +80,12 @@ typedef struct DispatchActionS{ const char* call; json_object *argsJ; int timeout; - int (*actionCB)(afb_req request, struct DispatchActionS *action, void *context); + int (*actionCB)(struct DispatchActionS *action, json_object *queryJ, void *context); } DispatchActionT; PUBLIC int DispatchInit(void); +PUBLIC int DispatchOneOnLoad(const char *onLoadLabel); +PUBLIC void DispatchOneEvent(const char *evtLabel, json_object *eventJ); PUBLIC void ctlapi_dispatch (char* control, afb_req request); // ctl-lua.c @@ -85,8 +97,7 @@ typedef enum { } LuaDoActionT; PUBLIC int LuaLibInit (); -PUBLIC json_object* ScanForConfig (char* searchPath, CtlScanDirModeT mode, char *pre, char *ext); -PUBLIC int LuaCallFunc (afb_req request, DispatchActionT *action); +PUBLIC int LuaCallFunc (DispatchActionT *action, json_object *queryJ); PUBLIC void ctlapi_lua_docall (afb_req request); PUBLIC void ctlapi_lua_dostring (afb_req request); PUBLIC void ctlapi_lua_doscript (afb_req request); diff --git a/Controler-afb/ctl-dispatch.c b/Controler-afb/ctl-dispatch.c index 8fdf46e..7d6a31d 100644 --- a/Controler-afb/ctl-dispatch.c +++ b/Controler-afb/ctl-dispatch.c @@ -28,6 +28,14 @@ typedef void*(*DispatchPluginInstallCbT)(const char* label, const char*version, const char*info); +static afb_req NULL_AFBREQ={}; + +typedef enum { + CTL_DISPATCH_ONLOAD, + CTL_DISPATCH_CONTROL, + CTL_DISPATCH_EVENT, +} DispatchClassT; + typedef struct { const char* label; const char *info; @@ -41,39 +49,36 @@ typedef struct { void *context; char *plugin; void *dlHandle; - DispatchHandleT *onload; - DispatchHandleT *events; + DispatchHandleT **onloads; + DispatchHandleT **events; DispatchHandleT **controls; } DispatchConfigT; // global config handle STATIC DispatchConfigT *configHandle = NULL; -STATIC int DispatchControlToIndex(char* controlLabel) { - DispatchHandleT **controls=configHandle->controls; +STATIC int DispatchControlToIndex(DispatchHandleT **controls, const char* controlLabel) { + for (int idx=0; controls[idx]; idx++) { if (!strcasecmp(controlLabel, controls[idx]->label)) return idx; } - return 0; + return -1; } -PUBLIC void ctlapi_dispatch (char* controlLabel, afb_req request) { - DispatchHandleT **controls=configHandle->controls; +STATIC int DispatchOneControl (DispatchHandleT **controls, const char* controlLabel, json_object *queryJ, afb_req request) { int err; if(!configHandle->controls) { AFB_ERROR ("DISPATCH-CTL-API: No Control Action in Json config label=%s version=%s", configHandle->label, configHandle->version); - goto OnErrorExit; + goto OnErrorExit; } - int index=DispatchControlToIndex(controlLabel); - if (!index || !controls[index]->actions) { - AFB_ERROR ("DISPATCH-CTL-API:NotFound label=%s index=%d", controlLabel, index); + int index=DispatchControlToIndex(controls, controlLabel); + if (index<0 || !controls[index]->actions) { + AFB_ERROR ("DISPATCH-CTL-API:NotFound label=%s in Json Control Config File", controlLabel); goto OnErrorExit; - } else { - AFB_NOTICE("DISPATCH-CTL-API:Found Control=%s", controls[index]->label); - } - + } + // loop on action for this control DispatchActionT *actions=controls[index]->actions; for (int idx=0; actions[idx].label; idx++) { @@ -85,50 +90,80 @@ PUBLIC void ctlapi_dispatch (char* controlLabel, afb_req request) { json_object_get( actions[idx].argsJ); // make sure afb_service_call does not free the argsJ int err = afb_service_call_sync(actions[idx].api, actions[idx].call, actions[idx].argsJ, &returnJ); if (err) { - AFB_NOTICE ("DISPATCH-CTL-MODE:Api api=%s verb=%s args=%s", actions[idx].api, actions[idx].call, actions[idx].label); - afb_req_fail_f(request, "DISPATCH-CTL-MODE:Api", "label=%s api=%s verb=%s", actions[idx].label, actions[idx].api, actions[idx].call); + static const char*format="DispatchOneControl Api api=%s verb=%s args=%s"; + if (afb_req_is_valid(request))afb_req_fail_f(request, "DISPATCH-CTL-MODE:API", format, actions[idx].label, actions[idx].api, actions[idx].call); + else AFB_ERROR (format, actions[idx].api, actions[idx].call, actions[idx].label); goto OnErrorExit; } break; } case CTL_MODE_LUA: - err= LuaCallFunc (request, &actions[idx]); + err= LuaCallFunc (&actions[idx], queryJ); if (err) { - afb_req_fail_f(request, "DISPATCH-CTL-MODE:Lua", "func=%s args=%s", actions[idx].call, json_object_get_string(actions[idx].argsJ)); + static const char*format= "DispatchOneControl func=%s args=%s"; + if (afb_req_is_valid(request)) afb_req_fail_f(request, "DISPATCH-CTL-MODE:Lua", format, actions[idx].call, json_object_get_string(actions[idx].argsJ)); + else AFB_ERROR (format, actions[idx].call, json_object_get_string(actions[idx].argsJ)); goto OnErrorExit; } break; case CTL_MODE_CB: - err= (*actions[idx].actionCB) (request, &actions[idx], configHandle->context); + err= (*actions[idx].actionCB) (&actions[idx], queryJ, configHandle->context); if (err) { - afb_req_fail_f(request, "DISPATCH-CTL-MODE:Cb", "func=%s args=%s", actions[idx].call, json_object_get_string(actions[idx].argsJ)); + static const char*format="DispatchOneControl func=%s args=%s"; + if (afb_req_is_valid(request)) afb_req_fail_f(request, "DISPATCH-CTL-MODE:Cb", format, actions[idx].call, json_object_get_string(actions[idx].argsJ)); + else AFB_ERROR (format, actions[idx].call, json_object_get_string(actions[idx].argsJ)); goto OnErrorExit; } break; - default: - AFB_ERROR ("DISPATCH-CTL-API:control=%s action=%s", controls[index]->label, actions[idx].label); - afb_req_fail_f(request, "DISPATCH-CTL-MODE:Unknown", "control=%s action=%s", controls[index]->label, actions[idx].label); + default:{ + static const char*format="DispatchOneControl unknown mode control=%s action=%s"; + AFB_ERROR (format, controls[index]->label, actions[idx].label); + if (afb_req_is_valid(request))afb_req_fail_f(request, "DISPATCH-CTL-MODE:Unknown", format, controls[index]->label, actions[idx].label); + } } } // everything when fine - afb_req_success(request,NULL,controls[index]->label); - return; + if(afb_req_is_valid(request))afb_req_success(request,NULL,controls[index]->label); + return 0; - OnErrorExit: - return; + OnErrorExit: + return -1; +} + + +// Event name is mapped on control label and executed as a standard control +PUBLIC void DispatchOneEvent(const char *evtLabel, json_object *eventJ){ + DispatchHandleT **events=configHandle->events; + + (void)DispatchOneControl(events, evtLabel, eventJ, NULL_AFBREQ); +} + +// Event name is mapped on control label and executed as a standard control +PUBLIC int DispatchOneOnLoad(const char *onLoadLabel){ + DispatchHandleT **onloads=configHandle->onloads; + + int err=DispatchOneControl(onloads, onLoadLabel, NULL, NULL_AFBREQ); + return err; } +PUBLIC void ctlapi_dispatch (char* controlLabel, afb_req request) { + DispatchHandleT **controls=configHandle->controls; + + json_object* queryJ = afb_req_json(request); + (void)DispatchOneControl(controls, controlLabel, queryJ, request); +} + // List Avaliable Configuration Files PUBLIC void ctlapi_config (struct afb_req request) { json_object*tmpJ; char *dirList; - json_object* argsJ = afb_req_json(request); - if (argsJ && json_object_object_get_ex (argsJ, "cfgpath" , &tmpJ)) { + json_object* queryJ = afb_req_json(request); + if (queryJ && json_object_object_get_ex (queryJ, "cfgpath" , &tmpJ)) { dirList = strdup (json_object_get_string(tmpJ)); } else { dirList = strdup (CONTROL_CONFIG_PATH); @@ -228,6 +263,118 @@ STATIC DispatchActionT *DispatchLoadActions (DispatchConfigT *controlConfig, jso } +STATIC DispatchHandleT *DispatchLoadControl (DispatchConfigT *controlConfig, json_object *controlJ) { + json_object *actionsJ; + int err; + + DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT)); + err= wrap_json_unpack(controlJ, "{ss,s?s,so !}", "label",&dispatchHandle->label, "info",&dispatchHandle->info, "actions",&actionsJ); + if (err) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROL Missing something label|[info]|actions in %s", json_object_get_string(controlJ)); + goto OnErrorExit; + } + + dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ); + if (!dispatchHandle->actions) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROL Error when parsing actions %s", dispatchHandle->label); + goto OnErrorExit; + } + return dispatchHandle; + + OnErrorExit: + return NULL; +} + +STATIC DispatchHandleT *DispatchLoadOnload (DispatchConfigT *controlConfig, json_object *onloadJ) { + json_object *actionsJ=NULL, *requireJ=NULL; + int err; + + DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT)); + err= wrap_json_unpack(onloadJ, "{ss,s?s,s?s,s?o,s?o !}", + "label",&dispatchHandle->label, "info",&dispatchHandle->info, "plugin", &controlConfig->plugin, "require", &requireJ, "actions",&actionsJ); + if (err) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:ONLOAD Missing something label|[info]|[plugin]|[actions] in %s", json_object_get_string(onloadJ)); + goto OnErrorExit; + } + + // best effort to initialise everything before starting + if (requireJ) { + + void DispatchRequireOneApi (json_object *bindindJ) { + const char* requireBinding = json_object_get_string(bindindJ); + err = afb_daemon_require_api(requireBinding, 1); + if (err) { + AFB_WARNING ("DISPATCH-LOAD-CONFIG:REQUIRE Fail to get=%s", requireBinding); + } + } + + if (json_object_get_type(requireJ) == json_type_array) { + for (int idx=0; idx < json_object_array_length(requireJ); idx++) { + DispatchRequireOneApi (json_object_array_get_idx(requireJ, idx)); + } + } else { + DispatchRequireOneApi (requireJ); + } + } + + if (controlConfig->plugin) { + + // search for default policy config file + json_object *pluginPathJ = ScanForConfig(CONTROL_PLUGIN_PATH , CTL_SCAN_RECURSIVE, controlConfig->plugin, NULL); + if (!pluginPathJ || json_object_array_length(pluginPathJ) == 0) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN Missing plugin=%s in path=%s", controlConfig->plugin, CONTROL_PLUGIN_PATH); + goto OnErrorExit; + } + + char *filename; char*fullpath; + err= wrap_json_unpack (json_object_array_get_idx(pluginPathJ,0), "{s:s, s:s !}", "fullpath", &fullpath,"filename", &filename); + if (err) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN HOOPs invalid plugin file path = %s", json_object_get_string(pluginPathJ)); + goto OnErrorExit; + } + + if (json_object_array_length(pluginPathJ) > 1) { + AFB_WARNING ("DISPATCH-LOAD-CONFIG:PLUGIN plugin multiple instances in searchpath will use %s/%s", fullpath, filename); + } + + char pluginpath[CONTROL_MAXPATH_LEN]; + strncpy(pluginpath, fullpath, sizeof(pluginpath)); + strncat(pluginpath, "/", sizeof(pluginpath)); + strncat(pluginpath, filename, sizeof(pluginpath)); + controlConfig->dlHandle = dlopen(pluginpath, RTLD_NOW); + if (!controlConfig->dlHandle) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN Fail to load pluginpath=%s err= %s", pluginpath, dlerror()); + goto OnErrorExit; + } + + CtlPluginMagicT *ctlPluginMagic = (CtlPluginMagicT*)dlsym(controlConfig->dlHandle, "CtlPluginMagic"); + if (!ctlPluginMagic || ctlPluginMagic->magic != CTL_PLUGIN_MAGIC) { + AFB_ERROR("DISPATCH-LOAD-CONFIG:Plugin symbol'CtlPluginMagic' missing or != CTL_PLUGIN_MAGIC plugin=%s", pluginpath); + goto OnErrorExit; + } else { + AFB_NOTICE("DISPATCH-LOAD-CONFIG:Plugin %s successfully registered", ctlPluginMagic->label); + } + + // Jose hack to make verbosity visible from sharelib + struct afb_binding_data_v2 *afbHidenData = dlsym(controlConfig->dlHandle, "afbBindingV2data"); + if (afbHidenData) *afbHidenData = afbBindingV2data; + + DispatchPluginInstallCbT ctlPluginOnload = dlsym(controlConfig->dlHandle, "CtlPluginOnload"); + if (ctlPluginOnload) { + controlConfig->context = (*ctlPluginOnload) (controlConfig->label, controlConfig->version, controlConfig->info); + } + } + + dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ); + if (!dispatchHandle->actions) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:ONLOAD Error when parsing actions %s", dispatchHandle->label); + goto OnErrorExit; + } + return dispatchHandle; + + OnErrorExit: + return NULL; +} STATIC DispatchConfigT *DispatchLoadConfig (const char* filepath) { json_object *controlConfigJ, *ignoreJ; @@ -242,8 +389,8 @@ STATIC DispatchConfigT *DispatchLoadConfig (const char* filepath) { AFB_INFO ("DISPATCH-LOAD-CONFIG: loading config filepath=%s", filepath); - json_object *metadataJ=NULL, *onloadJ=NULL, *controlsJ=NULL, *eventsJ=NULL; - err= wrap_json_unpack(controlConfigJ, "{s?o,so,s?o,s?o,s?o !}", "$schema", &ignoreJ, "metadata",&metadataJ, "onload",&onloadJ, "controls",&controlsJ, "events",&eventsJ); + json_object *metadataJ=NULL, *onloadsJ=NULL, *controlsJ=NULL, *eventsJ=NULL; + err= wrap_json_unpack(controlConfigJ, "{s?o,so,s?o,s?o,s?o !}", "$schema", &ignoreJ, "metadata",&metadataJ, "onload",&onloadsJ, "controls",&controlsJ, "events",&eventsJ); if (err) { AFB_ERROR ("DISPATCH-LOAD-CONFIG Missing something metadata|[onload]|[controls]|[events] in %s", json_object_get_string(controlConfigJ)); goto OnErrorExit; @@ -258,117 +405,61 @@ STATIC DispatchConfigT *DispatchLoadConfig (const char* filepath) { } } - if (onloadJ) { - json_object * actionsJ; - DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT)); - err= wrap_json_unpack(onloadJ, "{so,s?s,s?s,s?o !}", "label",&dispatchHandle->label, "info",&dispatchHandle->info, "plugin", &controlConfig->plugin, "actions",&actionsJ); - if (err) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:ONLOAD Missing something label|[info]|[plugin]|[actions] in %s", json_object_get_string(onloadJ)); - goto OnErrorExit; - } + if (onloadsJ) { + DispatchHandleT *dispatchHandle; - if (controlConfig->plugin) { - - // search for default policy config file - json_object *pluginPathJ = ScanForConfig(CONTROL_PLUGIN_PATH , CTL_SCAN_RECURSIVE, controlConfig->plugin, NULL); - if (!pluginPathJ || json_object_array_length(pluginPathJ) == 0) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN Missing plugin=%s in path=%s", controlConfig->plugin, CONTROL_PLUGIN_PATH); - goto OnErrorExit; - } - - char *filename; char*fullpath; - err= wrap_json_unpack (json_object_array_get_idx(pluginPathJ,0), "{s:s, s:s !}", "fullpath", &fullpath,"filename", &filename); - if (err) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN HOOPs invalid plugin file path = %s", json_object_get_string(pluginPathJ)); - goto OnErrorExit; - } - - if (json_object_array_length(pluginPathJ) > 1) { - AFB_WARNING ("DISPATCH-LOAD-CONFIG:PLUGIN plugin multiple instances in searchpath will use %s/%s", fullpath, filepath); - } - - char pluginpath[CONTROL_MAXPATH_LEN]; - strncpy(pluginpath, fullpath, sizeof(pluginpath)); - strncat(pluginpath, "/", sizeof(pluginpath)); - strncat(pluginpath, filename, sizeof(pluginpath)); - controlConfig->dlHandle = dlopen(pluginpath, RTLD_NOW); - if (!controlConfig->dlHandle) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN Fail to load pluginpath=%s err= %s", pluginpath, dlerror()); - goto OnErrorExit; - } - - CtlPluginMagicT *ctlPluginMagic = (CtlPluginMagicT*)dlsym(controlConfig->dlHandle, "CtlPluginMagic"); - if (!ctlPluginMagic || ctlPluginMagic->magic != CTL_PLUGIN_MAGIC) { - AFB_ERROR("DISPATCH-LOAD-CONFIG:Plugin symbol'CtlPluginMagic' missing or != CTL_PLUGIN_MAGIC plugin=%s", pluginpath); - goto OnErrorExit; - } else { - AFB_NOTICE("DISPATCH-LOAD-CONFIG:Plugin %s successfully registered", ctlPluginMagic->label); - } - - // Jose hack to make verbosity visible from sharelib - struct afb_binding_data_v2 *afbHidenData = dlsym(controlConfig->dlHandle, "afbBindingV2data"); - if (afbHidenData) *afbHidenData = afbBindingV2data; - - DispatchPluginInstallCbT ctlPluginOnload = dlsym(controlConfig->dlHandle, "CtlPluginOnload"); - if (ctlPluginOnload) { - controlConfig->context = (*ctlPluginOnload) (controlConfig->label, controlConfig->version, controlConfig->info); + if (json_object_get_type(onloadsJ) != json_type_array) { + controlConfig->onloads = (DispatchHandleT**) calloc (2, sizeof(void*)); + dispatchHandle = DispatchLoadOnload (controlConfig, onloadsJ); + controlConfig->onloads[0]= dispatchHandle; + } else { + int length= json_object_array_length(onloadsJ); + controlConfig->onloads = (DispatchHandleT**) calloc (length+1, sizeof(void*)); + + for (int jdx=0; jdx< length; jdx++) { + json_object *onloadJ = json_object_array_get_idx(onloadsJ,jdx); + dispatchHandle = DispatchLoadOnload (controlConfig, onloadJ); + controlConfig->onloads[jdx]= dispatchHandle; } - } - - dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ); - if (!dispatchHandle->actions) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:ONLOAD Error when parsing actions %s", dispatchHandle->label); - goto OnErrorExit; - } - controlConfig->onload= dispatchHandle; - + } } if (controlsJ) { - json_object * actionsJ; - - if (json_object_get_type(controlsJ) != json_type_array) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROLS invalid JSON array in %s", json_object_get_string(controlsJ)); - goto OnErrorExit; - } - - int length= json_object_array_length(controlsJ); - controlConfig->controls = (DispatchHandleT**) calloc (length+1, sizeof(void*)); + DispatchHandleT *dispatchHandle; - for (int jdx=0; jdx< length; jdx++) { - DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT)); - json_object *controlJ = json_object_array_get_idx(controlsJ,jdx); - err= wrap_json_unpack(controlJ, "{ss,s?s,so !}", "label",&dispatchHandle->label, "info",&dispatchHandle->info, "actions",&actionsJ); - if (err) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROLS Missing something label|[info]|actions in %s", json_object_get_string(controlJ)); - goto OnErrorExit; - } - - dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ); - if (!dispatchHandle->actions) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROLS Error when parsing actions %s", dispatchHandle->label); - goto OnErrorExit; + if (json_object_get_type(controlsJ) != json_type_array) { + controlConfig->controls = (DispatchHandleT**) calloc (2, sizeof(void*)); + dispatchHandle = DispatchLoadControl (controlConfig, controlsJ); + controlConfig->controls[0]= dispatchHandle; + } else { + int length= json_object_array_length(controlsJ); + controlConfig->controls = (DispatchHandleT**) calloc (length+1, sizeof(void*)); + + for (int jdx=0; jdx< length; jdx++) { + json_object *controlJ = json_object_array_get_idx(controlsJ,jdx); + dispatchHandle = DispatchLoadControl (controlConfig, controlJ); + controlConfig->controls[jdx]= dispatchHandle; } - controlConfig->controls[jdx]= dispatchHandle; - } - + } } if (eventsJ) { - json_object * actionsJ; - DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT)); + DispatchHandleT *dispatchHandle; + + if (json_object_get_type(eventsJ) != json_type_array) { + controlConfig->events = (DispatchHandleT**) calloc (2, sizeof(void*)); + dispatchHandle = DispatchLoadControl (controlConfig, eventsJ); + controlConfig->events[0]= dispatchHandle; + } else { + int length= json_object_array_length(eventsJ); + controlConfig->events = (DispatchHandleT**) calloc (length+1, sizeof(void*)); - err= wrap_json_unpack(eventsJ, "{so,s?s,so !}", "label",&dispatchHandle->label, "info",&dispatchHandle->info, "actions",&actionsJ); - if (err) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:EVENTS Missing something label|[info]|actions in %s", json_object_get_string(eventsJ)); - goto OnErrorExit; - } - dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ); - if (!dispatchHandle->actions) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:EVENTS Error when parsing actions %s", dispatchHandle->label); - goto OnErrorExit; + for (int jdx=0; jdx< length; jdx++) { + json_object *eventJ = json_object_array_get_idx(eventsJ,jdx); + dispatchHandle = DispatchLoadControl (controlConfig, eventJ); + controlConfig->events[jdx]= dispatchHandle; } - controlConfig->events= dispatchHandle; + } } return controlConfig; @@ -377,14 +468,20 @@ OnErrorExit: return NULL; } + // Load default config file at init PUBLIC int DispatchInit () { - int index, err; + int index, err, luaLoaded=0; + char controlFile [CONTROL_MAXPATH_LEN]; + strncpy (controlFile,CONTROL_CONFIG_PRE, CONTROL_MAXPATH_LEN); + strncat (controlFile,"-", CONTROL_MAXPATH_LEN); + strncat (controlFile,GetBinderName(), CONTROL_MAXPATH_LEN); // search for default dispatch config file - json_object* responseJ = ScanForConfig(CONTROL_CONFIG_PATH, CTL_SCAN_RECURSIVE,"onload", "json"); - + json_object* responseJ = ScanForConfig(CONTROL_CONFIG_PATH, CTL_SCAN_RECURSIVE,controlFile, "json"); + + // We load 1st file others are just warnings for (index=0; index < json_object_array_length(responseJ); index++) { json_object *entryJ=json_object_array_get_idx(responseJ, index); @@ -394,24 +491,29 @@ PUBLIC int DispatchInit () { AFB_ERROR ("DISPATCH-INIT HOOPs invalid JSON entry= %s", json_object_get_string(entryJ)); goto OnErrorExit; } - - if (strcasestr(filename, CONTROL_CONFIG_FILE)) { - char filepath[CONTROL_MAXPATH_LEN]; - strncpy(filepath, fullpath, sizeof(filepath)); - strncat(filepath, "/", sizeof(filepath)); - strncat(filepath, filename, sizeof(filepath)); - configHandle = DispatchLoadConfig (filepath); - if (!configHandle) { - AFB_ERROR ("DISPATCH-INIT:ERROR No File to load [%s]", filepath); - goto OnErrorExit; + + if (index == 0) { + if (strcasestr(filename, controlFile)) { + char filepath[CONTROL_MAXPATH_LEN]; + strncpy(filepath, fullpath, sizeof(filepath)); + strncat(filepath, "/", sizeof(filepath)); + strncat(filepath, filename, sizeof(filepath)); + configHandle = DispatchLoadConfig (filepath); + if (!configHandle) { + AFB_ERROR ("DISPATCH-INIT:ERROR Fail loading [%s]", filepath); + goto OnErrorExit; + } + luaLoaded=1; + break; } - break; + } else { + AFB_WARNING ("DISPATCH-INIT:WARNING Secondary Control Config Ignored %s/%s", fullpath, filename); } } // no dispatch config found remove control API from binder - if (index == 0) { - AFB_WARNING ("DISPATCH-INIT:WARNING No Control dispatch file [%s]", CONTROL_CONFIG_FILE); + if (!luaLoaded) { + AFB_WARNING ("DISPATCH-INIT:WARNING Not Found Control dispatch file [%s]", controlFile); } AFB_NOTICE ("DISPATCH-INIT:SUCCES: Audio Control Dispatch Init"); diff --git a/Controler-afb/ctl-events.c b/Controler-afb/ctl-events.c index 6f710e3..f76feca 100644 --- a/Controler-afb/ctl-events.c +++ b/Controler-afb/ctl-events.c @@ -143,7 +143,7 @@ PUBLIC void ctlapi_event_test (afb_req request) { PUBLIC int TimerEvtInit () { // create binder event to send test pause/resume - afbevt = afb_daemon_make_event("request"); + afbevt = afb_daemon_make_event("control"); if (!afb_event_is_valid(afbevt)) { AFB_ERROR ("POLCTL_INIT: Cannot register ctl-events"); return 1; diff --git a/Controler-afb/ctl-lua.c b/Controler-afb/ctl-lua.c index 71ef8b0..c1bc5f3 100644 --- a/Controler-afb/ctl-lua.c +++ b/Controler-afb/ctl-lua.c @@ -17,12 +17,12 @@ * http://www.troubleshooters.com/codecorn/lua/lua_c_calls_lua.htm#_Anatomy_of_a_Lua_Call * http://acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/ * https://john.nachtimwald.com/2014/07/12/wrapping-a-c-library-in-lua/ + * https://gist.github.com/SONIC3D/10388137 */ #define _GNU_SOURCE #include #include -#include #include "lua.h" #include "lauxlib.h" @@ -31,15 +31,21 @@ #include "ctl-binding.h" #include "wrap-json.h" -#define LUA_FIRST_ARG 2 // when using luaL_newlib calllback receive libtable as 1st arg +#define LUA_FIST_ARG 2 // when using luaL_newlib calllback receive libtable as 1st arg #define LUA_MSG_MAX_LENGTH 255 static lua_State* luaState; - #define CTX_MAGIC 123456789 #define CTX_TOKEN "AFB_ctx" +typedef struct { + char *name; + int count; + afb_event event; +} LuaAfbEvent; +static LuaAfbEvent *luaDefaultEvt; + typedef struct { int ctxMagic; afb_req request; @@ -47,8 +53,8 @@ typedef struct { } LuaAfbContextT; typedef struct { - const char *callback; - const char *handle; + const char *callback; + json_object *context; } LuaCallServiceT; typedef enum { @@ -65,67 +71,6 @@ typedef enum { * https://stackoverflow.com/questions/45596493/lua-using-lua-newuserdata-from-lua-pcall */ -// List Avaliable Configuration Files -PUBLIC json_object* ScanForConfig (char* searchPath, CtlScanDirModeT mode, char *pre, char *ext) { - json_object *responseJ; - char *dirPath; - char* dirList= strdup(searchPath); - size_t extLen=0; - - void ScanDir (char *searchPath) { - DIR *dirHandle; - struct dirent *dirEnt; - dirHandle = opendir (searchPath); - if (!dirHandle) { - AFB_NOTICE ("CONFIG-SCANNING dir=%s not readable", searchPath); - return; - } - - //AFB_NOTICE ("CONFIG-SCANNING:ctl_listconfig scanning: %s", searchPath); - while ((dirEnt = readdir(dirHandle)) != NULL) { - - // recursively search embedded directories ignoring any directory starting by '.' or '_' - if (dirEnt->d_type == DT_DIR && mode == CTL_SCAN_RECURSIVE) { - char newpath[CONTROL_MAXPATH_LEN]; - if (dirEnt->d_name[0]=='.' || dirEnt->d_name[0]=='_') continue; - - strncpy(newpath, searchPath, sizeof(newpath)); - strncat(newpath, "/", sizeof(newpath)); - strncat(newpath, dirEnt->d_name, sizeof(newpath)); - ScanDir(newpath); - continue; - } - - // Unknown type is accepted to support dump filesystems - if (dirEnt->d_type == DT_REG || dirEnt->d_type == DT_UNKNOWN) { - - // check prefix and extention - size_t extIdx=strlen(dirEnt->d_name)-extLen; - if (extIdx <= 0) continue; - if (pre && !strcasestr (dirEnt->d_name, pre)) continue; - if (ext && strcasecmp (ext, &dirEnt->d_name[extIdx])) continue; - - struct json_object *pathJ = json_object_new_object(); - json_object_object_add(pathJ, "fullpath", json_object_new_string(searchPath)); - json_object_object_add(pathJ, "filename", json_object_new_string(dirEnt->d_name)); - json_object_array_add(responseJ, pathJ); - } - } - closedir(dirHandle); - } - - if (ext) extLen=strlen(ext); - responseJ = json_object_new_array(); - - // loop recursively on dir - for (dirPath= strtok(dirList, ":"); dirPath && *dirPath; dirPath=strtok(NULL,":")) { - ScanDir (dirPath); - } - - free (dirList); - return (responseJ); -} - STATIC LuaAfbContextT *LuaCtxCheck (lua_State *luaState, int index) { LuaAfbContextT *afbContext; //luaL_checktype(luaState, index, LUA_TUSERDATA); @@ -159,37 +104,80 @@ STATIC void LuaCtxFree (LuaAfbContextT *afbContext) { free (afbContext->info); } -STATIC int LuaPushArgument (json_object *arg) { - - switch (json_object_get_type(arg)) { - case json_type_object: + +STATIC void LuaDumpArgs(lua_State* luaState, int start) { + int count = lua_gettop(luaState); + + for (int idx=start; idx <= count; idx++) { + int luaType = lua_type(luaState, idx); + switch(luaType) { + case LUA_TNUMBER: + AFB_NOTICE ("idx=%d type=%s value=%d", idx, lua_typename(luaState, luaType), (int)lua_tonumber(luaState, idx)); + break; + case LUA_TBOOLEAN: + AFB_NOTICE ("idx=%d type=%s value=%d", idx, lua_typename(luaState, luaType), lua_toboolean(luaState, idx)); + break; + case LUA_TSTRING: + AFB_NOTICE ("idx=%d type=%s value=%s", idx, lua_typename(luaState, luaType), lua_tostring(luaState, idx)); + break; + case LUA_TTABLE: { + AFB_NOTICE ("-++-- START luatable idx=%d ", idx); + (void)LuaDumpArgs(luaState, idx+1); + AFB_NOTICE ("-++-- END luatable idx=%d ", idx); + break; + } + default: + AFB_NOTICE ("PopOneArg: script returned Unknown/Unsupported idx=%d type:%d/%s", idx, luaType, lua_typename(luaState, luaType)); + } + } +} + +// Push a json structure on the stack as a LUA table +STATIC int LuaPushArgument (json_object *argsJ) { + + json_type jtype= json_object_get_type(argsJ); + switch (jtype) { + case json_type_object: { lua_newtable (luaState); - json_object_object_foreach (arg, key, val) { + json_object_object_foreach (argsJ, key, val) { int done = LuaPushArgument (val); if (done) { - lua_pushstring(luaState, key); // table.key = val - lua_settable(luaState, -3); + lua_setfield(luaState,-2, key); } } - break; + } + case json_type_array: { + int length= json_object_array_length(argsJ); + lua_newtable (luaState); + for (int idx=0; idx < length; idx ++) { + json_object *val=json_object_array_get_idx(argsJ, idx); + LuaPushArgument (val); + lua_seti (luaState,-2, idx); + } + break; + } case json_type_int: - lua_pushinteger(luaState, json_object_get_int(arg)); + lua_pushinteger(luaState, json_object_get_int(argsJ)); break; case json_type_string: - lua_pushstring(luaState, json_object_get_string(arg)); + lua_pushstring(luaState, json_object_get_string(argsJ)); break; case json_type_boolean: - lua_pushboolean(luaState, json_object_get_boolean(arg)); + lua_pushboolean(luaState, json_object_get_boolean(argsJ)); break; case json_type_double: - lua_pushnumber(luaState, json_object_get_double(arg)); + lua_pushnumber(luaState, json_object_get_double(argsJ)); break; + case json_type_null: + AFB_WARNING("LuaPushArgument: NULL object type %s", json_object_get_string(argsJ)); + return 0; + break; + default: - AFB_ERROR("LuaPushArgument: unsupported Json object type %s", json_object_get_string(arg)); + AFB_ERROR("LuaPushArgument: unsupported Json object type %s", json_object_get_string(argsJ)); return 0; - } - + } return 1; } @@ -251,7 +239,7 @@ static json_object *LuaPopArgs (lua_State* luaState, int start) { json_object *responseJ; int stop = lua_gettop(luaState); - if(stop-start <=0) return NULL; + if(stop-start <0) return NULL; // start at 2 because we are using a function array lib if (start == stop) { @@ -267,15 +255,16 @@ static json_object *LuaPopArgs (lua_State* luaState, int start) { return responseJ; } - STATIC void LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) { char *message; - json_object *responseJ= LuaPopArgs(luaState, LUA_FIRST_ARG); + json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG); if (!responseJ) { - message="--"; + message="-- Empty Message ???"; goto PrintMessage; - } + } + + AFB_NOTICE ("**** responseJ=%s", json_object_get_string(responseJ)); // if we have only on argument just return the value. if (json_object_get_type(responseJ)!=json_type_array || json_object_array_length(responseJ) <2) { @@ -297,15 +286,18 @@ STATIC void LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) { switch (format[++idx]) { case 'd': - targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%d", json_object_get_int(slotJ)); + if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%d", json_object_get_int(slotJ)); + else targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"Nil"); break; case 'f': - targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%f", json_object_get_double(slotJ)); + if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%f", json_object_get_double(slotJ)); + else targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"Nil"); break; case 's': default: - targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%s", json_object_get_string(slotJ)); + if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%s", json_object_get_string(slotJ)); + else targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"Nil"); } } else { @@ -359,11 +351,11 @@ STATIC int LuaPrintDebug(lua_State* luaState) { } STATIC int LuaAfbSuccess(lua_State* luaState) { - LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIRST_ARG); + LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG); if (!afbContext) goto OnErrorExit; // ignore context argument - json_object *responseJ= LuaPopArgs(luaState, LUA_FIRST_ARG+1); + json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1); afb_req_success(afbContext->request, responseJ, NULL); @@ -376,10 +368,10 @@ STATIC int LuaAfbSuccess(lua_State* luaState) { } STATIC int LuaAfbFail(lua_State* luaState) { - LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIRST_ARG); + LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG); if (!afbContext) goto OnErrorExit; - json_object *responseJ= LuaPopArgs(luaState, LUA_FIRST_ARG+1); + json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1); afb_req_fail(afbContext->request, afbContext->info, json_object_get_string(responseJ)); @@ -393,51 +385,43 @@ STATIC int LuaAfbFail(lua_State* luaState) { STATIC void LuaAfbServiceCB(void *handle, int iserror, struct json_object *responseJ) { LuaCallServiceT *contextCB= (LuaCallServiceT*)handle; + int count=1; - // load function (should exist in CONTROL_PATH_LUA lua_getglobal(luaState, contextCB->callback); - + // push error status & response lua_pushboolean(luaState, iserror); - (void)LuaPushArgument(responseJ); + count+= LuaPushArgument(responseJ); + count+= LuaPushArgument(contextCB->context); + + AFB_NOTICE ("*** context=%s", json_object_get_string(contextCB->context)); - int err=lua_pcall(luaState, 2, LUA_MULTRET, 0); + + int err=lua_pcall(luaState, count, LUA_MULTRET, 0); if (err) { AFB_ERROR ("LUA-SERICE-CB:FAIL response=%s err=%s", json_object_get_string(responseJ), lua_tostring(luaState,-1) ); } } + STATIC int LuaAfbService(lua_State* luaState) { int count = lua_gettop(luaState); - // retrieve userdate context - LuaAfbContextT *afbContext= luaL_checkudata(luaState, 1, "CTX_TOKEN"); - if (!afbContext) { - lua_pushliteral (luaState, "LuaAfbServiceCall-Hoops no CTX_TOKEN"); - goto OnErrorExit; - } - + // note: argument start at 2 because of AFB: table if (count <5 || !lua_isstring(luaState, 2) || !lua_isstring(luaState, 3) || !lua_istable(luaState, 4) || !lua_isstring(luaState, 5)) { - lua_pushliteral (luaState, "LuaAfbServiceCall-Syntax is AFB_service_call (api, verb, query, callback, handle"); + lua_pushliteral (luaState, "LuaAfbServiceCall-Syntax is AFB:service_call (api, verb, query, callback, handle ...."); goto OnErrorExit; } + // get api/verb+query + const char *api = lua_tostring(luaState,2); + const char *verb= lua_tostring(luaState,3); + json_object *queryJ= LuaTableToJson(luaState, 4); + LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT)); + contextCB->callback= lua_tostring(luaState, 5); + contextCB->context = LuaPopArgs(luaState, 6); - // get api/verb+query - const char *api = lua_tostring(luaState,1); - const char *verb= lua_tostring(luaState,2); - json_object *queryJ= LuaTableToJson(luaState, 3); - if (!queryJ) goto OnErrorExit; - - if (count >= 6) { - if (!lua_istable(luaState, 6)) { - lua_pushliteral (luaState, "LuaAfbServiceCall-Syntax optional handle should be a table"); - goto OnErrorExit; - } - contextCB->handle= lua_tostring(luaState, 5); - } - afb_service_call(api, verb, queryJ, LuaAfbServiceCB, contextCB); return 0; // no value return @@ -445,26 +429,84 @@ STATIC int LuaAfbService(lua_State* luaState) { OnErrorExit: lua_error(luaState); return 1; +} +STATIC int LuaAfbMakeEvent(lua_State* luaState) { + int count = lua_gettop(luaState); + LuaAfbEvent *afbevt=calloc(1,sizeof(LuaAfbEvent)); + + if (count != 1 || !lua_isstring(luaState, 1)) { + lua_pushliteral (luaState, "LuaAfbMakeEvent-Syntax is evtHandle= AFB:event ('myEventName')"); + goto OnErrorExit; + } + + // event name should be the only argument + afbevt->name= strdup (lua_tostring(luaState,1)); + + // create a new binder event + afbevt->event = afb_daemon_make_event(afbevt->name); + if (!afb_event_is_valid(afbevt->event)) { + lua_pushliteral (luaState, "LuaAfbMakeEvent-Fail to Create Binder event"); + goto OnErrorExit; + } + + // push event handler as a LUA opaque handle + lua_pushlightuserdata(luaState, afbevt); + return 1; + + OnErrorExit: + lua_error(luaState); + return 1; +} + +STATIC int LuaAfbPushEvent(lua_State* luaState) { + LuaAfbEvent *afbevt; + int index; + + // if no private event handle then use default binding event + if (lua_islightuserdata(luaState, 1)) { + afbevt = (LuaAfbEvent*) lua_touserdata(luaState, 1); + index=1; + } else { + index=2; + afbevt=luaDefaultEvt; + } + + if (!lua_isstring(luaState, index)) { + lua_pushliteral (luaState, "LuaAfbPushEvent-Syntax is AFB:signal ([evtHandle], 'myEventName', 'data-1', ... 'data-n')"); + goto OnErrorExit; + } + + // use every other arguments as event parameters + index++; + json_object *ctlEventJ= LuaTableToJson(luaState, index); + + int done = afb_event_push(afbevt->event, ctlEventJ); + if (!done) { + lua_pushliteral (luaState, "LuaAfbPushEvent-Fail to Push Binder event"); + AFB_ERROR ("LuaAfbPushEvent-Fail to Push Binder event=%s count=%d", afbevt->name, afbevt->count); + goto OnErrorExit; + } + afbevt->count++; + return 0; + + OnErrorExit: + lua_error(luaState); + return 1; } // Generated some fake event based on watchdog/counter -PUBLIC int LuaCallFunc (afb_req request, DispatchActionT *action) { +PUBLIC int LuaCallFunc (DispatchActionT *action, json_object *queryJ) { int err, count=0; - json_object* queryJ = afb_req_json(request); json_object* argsJ = action->argsJ; const char* func = action->call; // load function (should exist in CONTROL_PATH_LUA lua_getglobal(luaState, func); - // Push AFB client context on the stack - LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, func); - if (!afbContext) goto OnErrorExit; - // push argsJ on the stack if (json_object_get_type(argsJ) != json_type_array) { count+= LuaPushArgument (argsJ); @@ -473,7 +515,7 @@ PUBLIC int LuaCallFunc (afb_req request, DispatchActionT *action) { count += LuaPushArgument (json_object_array_get_idx(argsJ, idx)); } } - + // push queryJ on the stack if (json_object_get_type(queryJ) != json_type_array) { count+= LuaPushArgument (queryJ); @@ -483,8 +525,8 @@ PUBLIC int LuaCallFunc (afb_req request, DispatchActionT *action) { } } - // effectively exec LUA code (afb_reply/fail done later from callback) - err=lua_pcall(luaState, count+1, 1, 0); + // effectively exec LUA script code + err=lua_pcall(luaState, count, 1, 0); if (err) { AFB_ERROR("LuaCallFunc Fail calling %s error=%s", func, lua_tostring(luaState,-1)); goto OnErrorExit; @@ -498,7 +540,8 @@ PUBLIC int LuaCallFunc (afb_req request, DispatchActionT *action) { return -1; } -// Generated some fake event based on watchdog/counter + +// Execute LUA code from recieved API request STATIC void LuaDoAction (LuaDoActionT action, afb_req request) { int err, count=0; @@ -551,7 +594,7 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) { break; } - case LUA_DOSCRIPT: { + case LUA_DOSCRIPT: { // Fulup need to fix argument passing const char *script; json_object *args; int index; @@ -655,15 +698,24 @@ static const luaL_Reg afbFunction[] = { {"service", LuaAfbService}, {"success", LuaAfbSuccess}, {"fail" , LuaAfbFail}, + {"event" , LuaAfbMakeEvent}, + {"signal" , LuaAfbPushEvent}, + {NULL, NULL} /* sentinel */ }; // Create Binding Event at Init PUBLIC int LuaLibInit () { int err, index; - + // search for default policy config file - json_object *luaScriptPathJ = ScanForConfig(CONTROL_LUA_PATH , CTL_SCAN_RECURSIVE, "onload", "lua"); + char fullprefix[CONTROL_MAXPATH_LEN]; + strncpy (fullprefix, CONTROL_CONFIG_PRE, sizeof(fullprefix)); + strncat (fullprefix, "-", sizeof(fullprefix)); + strncat (fullprefix, GetBinderName(), sizeof(fullprefix)); + strncat (fullprefix, "-", sizeof(fullprefix)); + + json_object *luaScriptPathJ = ScanForConfig(CONTROL_LUA_PATH , CTL_SCAN_RECURSIVE, fullprefix, "lua"); // open a new LUA interpretor luaState = luaL_newstate(); @@ -679,6 +731,15 @@ PUBLIC int LuaLibInit () { luaL_newlib(luaState, afbFunction); lua_setglobal(luaState, "AFB"); + // create default lua event to send test pause/resume + luaDefaultEvt=calloc(1,sizeof(LuaAfbEvent)); + luaDefaultEvt->name=CONTROL_LUA_EVENT; + luaDefaultEvt->event = afb_daemon_make_event(CONTROL_LUA_EVENT); + if (!afb_event_is_valid(luaDefaultEvt->event)) { + AFB_ERROR ("POLCTL_INIT: Cannot register lua-events=%s ", CONTROL_LUA_EVENT); + goto OnErrorExit;; + } + // load+exec any file found in LUA search path for (index=0; index < json_object_array_length(luaScriptPathJ); index++) { json_object *entryJ=json_object_array_get_idx(luaScriptPathJ, index); diff --git a/Controler-afb/ctl-misc.c b/Controler-afb/ctl-misc.c new file mode 100644 index 0000000..a022b38 --- /dev/null +++ b/Controler-afb/ctl-misc.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Fulup Ar Foll + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#include "audio-common.h" +#include "ctl-binding.h" + + + +// List Avaliable Configuration Files +PUBLIC json_object* ScanForConfig (char* searchPath, CtlScanDirModeT mode, char *pre, char *ext) { + json_object *responseJ; + char *dirPath; + char* dirList= strdup(searchPath); + size_t extLen=0; + + void ScanDir (char *searchPath) { + DIR *dirHandle; + struct dirent *dirEnt; + dirHandle = opendir (searchPath); + if (!dirHandle) { + AFB_DEBUG ("CONFIG-SCANNING dir=%s not readable", searchPath); + return; + } + + //AFB_NOTICE ("CONFIG-SCANNING:ctl_listconfig scanning: %s", searchPath); + while ((dirEnt = readdir(dirHandle)) != NULL) { + + // recursively search embedded directories ignoring any directory starting by '.' or '_' + if (dirEnt->d_type == DT_DIR && mode == CTL_SCAN_RECURSIVE) { + char newpath[CONTROL_MAXPATH_LEN]; + if (dirEnt->d_name[0]=='.' || dirEnt->d_name[0]=='_') continue; + + strncpy(newpath, searchPath, sizeof(newpath)); + strncat(newpath, "/", sizeof(newpath)); + strncat(newpath, dirEnt->d_name, sizeof(newpath)); + ScanDir(newpath); + continue; + } + + // Unknown type is accepted to support dump filesystems + if (dirEnt->d_type == DT_REG || dirEnt->d_type == DT_UNKNOWN) { + + // check prefix and extention + size_t extIdx=strlen(dirEnt->d_name)-extLen; + if (extIdx <= 0) continue; + if (pre && !strcasestr (dirEnt->d_name, pre)) continue; + if (ext && strcasecmp (ext, &dirEnt->d_name[extIdx])) continue; + + struct json_object *pathJ = json_object_new_object(); + json_object_object_add(pathJ, "fullpath", json_object_new_string(searchPath)); + json_object_object_add(pathJ, "filename", json_object_new_string(dirEnt->d_name)); + json_object_array_add(responseJ, pathJ); + } + } + closedir(dirHandle); + } + + if (ext) extLen=strlen(ext); + responseJ = json_object_new_array(); + + // loop recursively on dir + for (dirPath= strtok(dirList, ":"); dirPath && *dirPath; dirPath=strtok(NULL,":")) { + ScanDir (dirPath); + } + + free (dirList); + return (responseJ); +} + +PUBLIC const char *GetBinderName() { + char psName[17]; + static char *binderName=NULL; + + if (binderName) return binderName; + + // retrieve binder name from process name afb-name-trailer + prctl(PR_GET_NAME, psName,NULL,NULL,NULL); + for (int idx=0; idx < sizeof(psName); idx++) { + int start; + if (psName[idx] == '-') { + start=idx+1; + for (int jdx=start; jdx < sizeof(psName); jdx++) { + if (psName[jdx] == '-') { + psName[jdx] = '\0'; + binderName=strdup(&psName[start]); + break; + } + } + break; + } + } + + return binderName; +} \ No newline at end of file diff --git a/Controler-afb/ctl-misc2.c b/Controler-afb/ctl-misc2.c new file mode 100644 index 0000000..dc225a4 --- /dev/null +++ b/Controler-afb/ctl-misc2.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Fulup Ar Foll + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE +#include +#include +#include + +#include "audio-common.h" +#include "ctl-binding.h" + + + +// Include Binding Stub generated from Json OpenAPI +#include "ctl-apidef.h" + + +PUBLIC void ctlapi_navigation (afb_req request) { + + ctlapi_dispatch ("NAVIGATION", request); +} + +PUBLIC void ctlapi_multimedia (afb_req request) { + + ctlapi_dispatch ("MULTIMEDIA", request); +} + +PUBLIC void ctlapi_emergency (afb_req request) { + + ctlapi_dispatch ("EMERGENCY", request); +} + +PUBLIC void ctlapi_monitor (afb_req request) { + + // subscribe Client to event + int err = afb_req_subscribe(request, TimerEvtGet()); + if (err != 0) { + afb_req_fail_f(request, "register-event", "Fail to subscribe binder event"); + goto OnErrorExit; + } + + afb_req_success(request, NULL, NULL); + + OnErrorExit: + return; +} + +// Create Binding Event at Init +PUBLIC int CtlBindingInit () { + + int errcount=0; + + errcount += TimerEvtInit(); + errcount += DispatchInit(); + errcount += LuaLibInit(); + + AFB_DEBUG ("Audio Policy Control Binding Done errcount=%d", errcount); + return errcount; +} + diff --git a/Controler-afb/ctl-plugin-sample.c b/Controler-afb/ctl-plugin-sample.c index ebcaee4..837ad9d 100644 --- a/Controler-afb/ctl-plugin-sample.c +++ b/Controler-afb/ctl-plugin-sample.c @@ -54,15 +54,19 @@ PUBLIC void* CtlPluginOnload(char* label, char* version, char* info) { return (void*)pluginCtx; } -PUBLIC int SamplePolicyInit (afb_req request, DispatchActionT *action, void *context) { +PUBLIC int SamplePolicyInit (DispatchActionT *action, json_object *argsJ, void *context) { MyPluginCtxT *pluginCtx= (MyPluginCtxT*)context; + if (!context || pluginCtx->magic != MY_PLUGIN_MAGIC) { + AFB_ERROR("CONTROLER-PLUGIN-SAMPLE:SamplePolicyInit (Hoops) Invalid Sample Plugin Context"); + return -1; + }; pluginCtx->count = 0; AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:Init label=%s args=%s\n", action->label, jsonToString(action->argsJ)); return 0; } -PUBLIC int sampleControlMultimedia (afb_req request, DispatchActionT *action, void *context) { +PUBLIC int sampleControlMultimedia (DispatchActionT *action, json_object *queryJ, void *context) { MyPluginCtxT *pluginCtx= (MyPluginCtxT*)context; if (!context || pluginCtx->magic != MY_PLUGIN_MAGIC) { @@ -70,11 +74,12 @@ PUBLIC int sampleControlMultimedia (afb_req request, DispatchActionT *action, vo return -1; }; pluginCtx->count++; - AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:sampleControlMultimedia SamplePolicyCount action=%s args=%s count=%d", action->label, jsonToString(action->argsJ), pluginCtx->count); + AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:sampleControlMultimedia SamplePolicyCount action=%s args=%s query=%s count=%d" + , action->label, jsonToString(action->argsJ), jsonToString(queryJ), pluginCtx->count); return 0; } -PUBLIC int sampleControlNavigation (afb_req request, DispatchActionT *action, void *context) { +PUBLIC int sampleControlNavigation (DispatchActionT *action, json_object *queryJ, void *context) { MyPluginCtxT *pluginCtx= (MyPluginCtxT*)context; if (!context || pluginCtx->magic != MY_PLUGIN_MAGIC) { @@ -82,11 +87,12 @@ PUBLIC int sampleControlNavigation (afb_req request, DispatchActionT *action, vo return -1; }; pluginCtx->count++; - AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:sampleControlNavigation SamplePolicyCount action=%s args=%s count=%d", action->label, jsonToString(action->argsJ), pluginCtx->count); + AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:sampleControlNavigation SamplePolicyCount action=%s args=%s query=%s count=%d" + ,action->label, jsonToString(action->argsJ), jsonToString(queryJ), pluginCtx->count); return 0; } -PUBLIC int SampleControlEvent (afb_req request, DispatchActionT *action, void *context) { +PUBLIC int SampleControlEvent (DispatchActionT *action, json_object *queryJ, void *context) { MyPluginCtxT *pluginCtx= (MyPluginCtxT*)context; if (!context || pluginCtx->magic != MY_PLUGIN_MAGIC) { @@ -94,6 +100,7 @@ PUBLIC int SampleControlEvent (afb_req request, DispatchActionT *action, void *c return -1; }; pluginCtx->count++; - AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:sampleControlMultimedia SamplePolicyCount action=%s args=%s count=%d", action->label, jsonToString(action->argsJ), pluginCtx->count); + AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:sampleControlMultimedia SamplePolicyCount action=%s args=%s query=%s count=%d" + ,action->label, jsonToString(action->argsJ), jsonToString(queryJ), pluginCtx->count); return 0; } diff --git a/HAL-afb/CMakeLists.txt b/HAL-afb/CMakeLists.txt index b0c2e6a..201d407 100644 --- a/HAL-afb/CMakeLists.txt +++ b/HAL-afb/CMakeLists.txt @@ -17,7 +17,7 @@ ########################################################################### -# Include any directory starting with a Capital letter +# Include any directory not starting with _ # ----------------------------------------------------- PROJECT_SUBDIRS_ADD(${PROJECT_SRC_DIR_PATTERN}) diff --git a/conf.d/CMakeLists.txt b/conf.d/CMakeLists.txt index 413fe8e..28a0609 100644 --- a/conf.d/CMakeLists.txt +++ b/conf.d/CMakeLists.txt @@ -17,10 +17,6 @@ ########################################################################### - -# Define subproject targets -ADD_SUBDIRECTORY(ctl-rules) - - - - +# Include any directory not starting with _ +# ----------------------------------------------------- +PROJECT_SUBDIRS_ADD(${PROJECT_SRC_DIR_PATTERN}) diff --git a/conf.d/cmake/config.cmake b/conf.d/cmake/config.cmake index e70fb62..510eb70 100644 --- a/conf.d/cmake/config.cmake +++ b/conf.d/cmake/config.cmake @@ -67,17 +67,19 @@ set (PKG_REQUIRED_LIST # Define CONTROL_CDEV_NAME should match MOST driver values # --------------------------------------------------------- + add_compile_options(-DCONTROL_ONLOAD_DEFAULT="onload-default") add_compile_options(-DCONTROL_MAXPATH_LEN=255) - add_compile_options(-DCONTROL_CONFIG_FILE="onload-control-policy.json") - add_compile_options(-DCONTROL_CONFIG_PATH="${CMAKE_SOURCE_DIR}/conf.d:${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/config") - - add_compile_options(-DCONTROL_LUA_PATH="${CMAKE_SOURCE_DIR}/conf.d:/etc/default/${PROJECT_NAME}/lua:${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lua") + add_compile_options(-DCONTROL_CONFIG_PRE="onload") + add_compile_options(-DCONTROL_CONFIG_POST="control" ) + add_compile_options(-DCONTROL_CONFIG_PATH="${CMAKE_SOURCE_DIR}/conf.d/project/config.d:${CMAKE_INSTALL_PREFIX}/controler/config.d") + add_compile_options(-DCONTROL_LUA_EVENT="luaevt") + add_compile_options(-DCONTROL_LUA_PATH="${CMAKE_SOURCE_DIR}/conf.d/project/lua.d:${CMAKE_INSTALL_PREFIX}/controler/ctl-lua.d") - set (CTL_PLUGIN_PRE "audio-") - set (CTL_PLUGIN_EXT ".ctlso") + set (CTL_PLUGIN_PRE "ctl-" cache "Prefix for Controler share plugin") + set (CTL_PLUGIN_EXT ".ctlso" cache "Postfix for Controler share plugin") add_compile_options(-DCTL_PLUGIN_MAGIC=2468013579) - add_compile_options(-DCONTROL_PLUGIN_PATH="${BINDINGS_INSTALL_DIR}/controler:/usr/lib/${PROJECT_NAME}") + add_compile_options(-DCONTROL_PLUGIN_PATH="${CMAKE_BINARY_DIR}:${BINDINGS_INSTALL_DIR}/ctlplug:/usr/lib/afb/ctlplug") # Print a helper message when every thing is finished # ---------------------------------------------------- diff --git a/conf.d/ctl-rules/CMakeLists.txt b/conf.d/ctl-rules/CMakeLists.txt deleted file mode 100644 index 51a3a46..0000000 --- a/conf.d/ctl-rules/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -########################################################################### -# Copyright 2017 IoT.bzh -# -# author: Fulup Ar Foll -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -########################################################################### - - -################################################## -# Control Policy Config file -################################################## -PROJECT_TARGET_ADD(control-rules) - - file(GLOB XML_FILES "*.json" "*.lua") - - add_custom_target(${TARGET_NAME} - DEPENDS ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} - ) - - # check XML schema before pushing config - add_custom_command( - DEPENDS ${XML_FILES} - OUTPUT ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} - # COMMAND xmllint -schema ${XML_SCHEMA} ${XML_FILES} --noout (Fulup we miss this for JSON) - COMMAND mkdir -p ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} - COMMAND touch ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} - COMMAND cp -r ${XML_FILES} ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} - ) - - SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES - LABELS "DATA" - OUTPUT_NAME ${TARGET_NAME} - ) diff --git a/conf.d/ctl-rules/helloworld-lua-script.lua b/conf.d/ctl-rules/helloworld-lua-script.lua deleted file mode 100644 index 7dd0459..0000000 --- a/conf.d/ctl-rules/helloworld-lua-script.lua +++ /dev/null @@ -1,41 +0,0 @@ ---[[ - Copyright (C) 2016 "IoT.bzh" - Author Fulup Ar Foll - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - Simple API script ---]] - - -- retrieve calling arguments - args= ... - - print ("Helloworld script arguments:") - - - for key,value in pairs(args) - do - print("args: ", key,value) - end - - -- loop on script arguments - --for i=1,#args - --do - -- print(" -- ", i, args[i]) - --end - - - -- return two arguments on top of status - return true, 1234, "ABCD", 5678 - diff --git a/conf.d/ctl-rules/onload-control-policy.json b/conf.d/ctl-rules/onload-control-policy.json deleted file mode 100644 index b5d4503..0000000 --- a/conf.d/ctl-rules/onload-control-policy.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "$schema": "ToBeDone", - "metadata": { - "label": "sample-audio-control", - "info": "Provide Default Audio Policy for Multimedia, Navigation and Emergency", - "version": "1.0" - }, - "onload": { - "label": "onload-config", - "info": "onload initialisation config", - "plugin": "audio-ctl-plugin-sample.ctlso", - "actions": [ - { - "label": "onload-sample-cb", - "info": "Call control sharelib install entrypoint", - "callback": "SamplePolicyInit", - "args": { - "arg1": "first_arg", - "nextarg": "second arg value" - } - }, { - "label": "onload-sample-api", - "info": "Assert AlsaCore Presence", - "api": "alsacore", - "verb": "ping", - "args": "test" - }, { - "label": "onload-sample-lua", - "info": "Assert LUA Engine", - "lua": "Test_Lua_Engine", - "args": "ping" - } - ] - }, - "controls": - [ - { - "label": "multimedia", - "actions": [ - { - "label": "multimedia-control-cb", - "info": "Call Sharelib Sample Callback", - "callback": "sampleControlMultimedia", - "args": { - "arg1": "snoopy", - "arg2": "toto" - } - }, { - "label": "multimedia-control-ucm", - "info": "Subcall AlSA UCM navigation", - "api": "alsacore", - "verb": "ping", - "args": { - "select": "multimedia" - } - }] - }, { - "label": "navigation", - "actions": [ { - "label": "multimedia-control-cb", - "info": "Call Sharelib Sample Callback", - "callback": "sampleControlNavigation", - "args": { - "arg1": "snoopy", - "arg2": "toto" - } - }, { - "label": "navigation-control-ucm", - "api": "alsacore", - "verb": "ping", - "args": { - "select": "navigation" - } - }] - }, { - "label": "emergency", - "actions": [{ - "label": "emergency-control-ucm", - "api": "alsacore", - "verb": "ping", - "args": { - "select": "emergency" - } - }] - } - ], - "events": - { - "label": "SampleEvent", - "info": "define action when receiving a given event", - "actions": [ - { - "label": "Event Callback-1", - "callback": "SampleControlEvent", - "args": { - "arg": "action-1" - } - }, { - "label": "Event Callback-2", - "callback": "SampleControlEvent", - "args": { - "arg": "action-2" - } - } - ] - } -} - diff --git a/conf.d/ctl-rules/onload-control-script.lua b/conf.d/ctl-rules/onload-control-script.lua deleted file mode 100644 index 6cc85fa..0000000 --- a/conf.d/ctl-rules/onload-control-script.lua +++ /dev/null @@ -1,96 +0,0 @@ ---[[ - Copyright (C) 2016 "IoT.bzh" - Author Fulup Ar Foll - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - Provide sample policy function for AGL Advance Audio Agent ---]] - -count=0 - --- Adjust Volume function of vehicle speed -function Adjust_Volume_Speed (request, speed_meters_second) - - AFB:notice("In Adjust_Volume_Speed speed=%d", speed_meters_second); - - print (string.format("*****(From Lua) Adjust_Volume_Speed speed=%d count=%d", speed_meters_second, count)); - - -- compute volume - volume = speed_meters_second * 2 - count=count+1 - - AFB:success (request, 1234, volume, count, 5678) -end - - -function Test_Binder_CB (result, context) - - local myTable= { ["arg1"] = "myString", ["arg2"] = 1234, ["arg4"] = true, ["arg5"] = 3.1416 } - - AFB:notice ("In Test_Binder_CB", result, context) - - AFB:success (1234, "ABCD", myTable, 5678) - -end - -function Test_Binder_Call_Async () - - local query= { - ["arg1"] = "myString", - ["arg2"] = 1234, - ["arg4"] = true, - ["arg5"] = 3.1416, - } - - AFB:service("alsacore","ping", query, Test_Binder_CB, "myContext") - -end - -function Test_Binder_Call_Sync () - - local query= { - ["arg1"] = "myString", - ["arg2"] = 1234, - ["arg4"] = true, - ["arg5"] = 3.1416, - } - - err= AFB:service_sync ("alsacore","ping", query) - - if (err) then - AFB:fail ("AFB:service_call_sync fail"); - else - AFB:success (1234, "ABCD", myTable) - end - - -end - - -function Test_Lua_Engine(request, ...) - - AFB:NOTICE ("In est_Lua_Engine"); - print ("Ping_Test script arguments:"); - - for i,v in ipairs(arg) - do - print(" -- ", tostring(v)) - end - - -- return OK - return 0 -end - - diff --git a/conf.d/project/CMakeLists.txt b/conf.d/project/CMakeLists.txt new file mode 100644 index 0000000..fd4d454 --- /dev/null +++ b/conf.d/project/CMakeLists.txt @@ -0,0 +1,24 @@ +########################################################################### +# Copyright 2015, 2016, 2017 IoT.bzh +# +# author: Fulup Ar Foll +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################### + + + +# Include anything not starting with _ +PROJECT_SUBDIRS_ADD(${PROJECT_SRC_DIR_PATTERN}) + + diff --git a/conf.d/project/config.d/CMakeLists.txt b/conf.d/project/config.d/CMakeLists.txt new file mode 100644 index 0000000..229cf2d --- /dev/null +++ b/conf.d/project/config.d/CMakeLists.txt @@ -0,0 +1,40 @@ +########################################################################### +# Copyright 2017 IoT.bzh +# +# author: Fulup Ar Foll +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################### + + +################################################## +# Control Policy Config file +################################################## +PROJECT_TARGET_ADD(ctl-config.d) + + file(GLOB XML_FILES "*.json") + + add_custom_target(${TARGET_NAME} + DEPENDS ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} + ) + + # check XML schema before pushing config + add_custom_command( + DEPENDS ${XML_FILES} + OUTPUT ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} + # COMMAND xmllint -schema ${XML_SCHEMA} ${XML_FILES} --noout (Fulup we miss this for JSON) + COMMAND mkdir -p ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} + COMMAND touch ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} + COMMAND cp -r ${XML_FILES} ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} + ) + diff --git a/conf.d/project/config.d/onload-audio-control.json b/conf.d/project/config.d/onload-audio-control.json new file mode 100644 index 0000000..aecf1b3 --- /dev/null +++ b/conf.d/project/config.d/onload-audio-control.json @@ -0,0 +1,116 @@ +{ + "$schema": "ToBeDone", + "metadata": { + "label": "sample-audio-control", + "info": "Provide Default Audio Policy for Multimedia, Navigation and Emergency", + "version": "1.0" + }, + "onload": [{ + "label": "onload-default", + "info": "onload initialisation config", + "plugin": "ctl-audio-plugin-sample.ctlso", + "require": ["intel-hda", "jabra-usb", "scarlett-usb"], + "actions": [ + { + "label": "onload-sample-cb", + "info": "Call control sharelib install entrypoint", + "callback": "SamplePolicyInit", + "args": { + "arg1": "first_arg", + "nextarg": "second arg value" + } + }, { + "label": "onload-sample-api", + "info": "Assert AlsaCore Presence", + "api": "alsacore", + "verb": "ping", + "args": "test" + }, { + "label": "onload-hal-lua", + "info": "Load avaliable HALs", + "lua": "Audio_Init_Hal" + } + ] + }], + "controls": + [ + { + "label": "multimedia", + "actions": [{ + "label": "multimedia-control-lua", + "info": "Call Lua Script function Test_Lua_Engin", + "lua": "Audio_Set_Use_Case_Multimedia", + }] + }, { + "label": "navigation", + "actions": [{ + "label": "multimedia-control-cb", + "info": "Call Sharelib Sample Callback", + "callback": "sampleControlNavigation", + "args": { + "arg1": "snoopy", + "arg2": "toto" + } + }, { + "label": "navigation-control-ucm", + "api": "alsacore", + "verb": "ping", + "args": { + "test": "navigation" + } + }, { + "label": "navigation-control-lua", + "info": "Call Lua Script to set Navigation", + "lua": "Audio_Set_Use_Case_Navigation", + }] + }, { + "label": "emergency", + "actions": [{ + "label": "emergency-control-ucm", + "lua": "Audio_Set_Use_Case_Emergency", + }] + } + ], + "events": + [ + { + "label": "SampleEvent1", + "info": "define action when receiving a given event", + "actions": [ + { + "label": "Event Callback-1", + "callback": "SampleControlEvent", + "args": { + "arg": "action-1" + } + }, { + "label": "Event Callback-2", + "callback": "SampleControlEvent", + "args": { + "arg": "action-2" + } + } + ] + }, + { + "label": "SampleEvent2", + "info": "define action when receiving a given event", + "actions": [ + { + "label": "Event Callback-1", + "callback": "SampleControlEvent", + "args": { + "arg": "action-1" + } + }, { + "label": "Event Callback-2", + "callback": "SampleControlEvent", + "args": { + "arg": "action-2" + } + } + ] + } + ] +} + diff --git a/conf.d/project/lua.d/CMakeLists.txt b/conf.d/project/lua.d/CMakeLists.txt new file mode 100644 index 0000000..db54742 --- /dev/null +++ b/conf.d/project/lua.d/CMakeLists.txt @@ -0,0 +1,40 @@ +########################################################################### +# Copyright 2017 IoT.bzh +# +# author: Fulup Ar Foll +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################### + + +################################################## +# Control Policy Config file +################################################## +PROJECT_TARGET_ADD(ctl-lua.d) + + file(GLOB XML_FILES "*.lua") + + add_custom_target(${TARGET_NAME} + DEPENDS ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} + ) + + # check XML schema before pushing config + add_custom_command( + DEPENDS ${XML_FILES} + OUTPUT ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} + # COMMAND xmllint -schema ${XML_SCHEMA} ${XML_FILES} --noout (Fulup we miss this for JSON) + COMMAND mkdir -p ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} + COMMAND touch ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} + COMMAND cp -r ${XML_FILES} ${PROJECT_PKG_BUILD_DIR}/${TARGET_NAME} + ) + diff --git a/conf.d/project/lua.d/helloworld-lua-script.lua b/conf.d/project/lua.d/helloworld-lua-script.lua new file mode 100644 index 0000000..7dd0459 --- /dev/null +++ b/conf.d/project/lua.d/helloworld-lua-script.lua @@ -0,0 +1,41 @@ +--[[ + Copyright (C) 2016 "IoT.bzh" + Author Fulup Ar Foll + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Simple API script +--]] + + -- retrieve calling arguments + args= ... + + print ("Helloworld script arguments:") + + + for key,value in pairs(args) + do + print("args: ", key,value) + end + + -- loop on script arguments + --for i=1,#args + --do + -- print(" -- ", i, args[i]) + --end + + + -- return two arguments on top of status + return true, 1234, "ABCD", 5678 + diff --git a/conf.d/project/lua.d/onload-audio-policy.lua b/conf.d/project/lua.d/onload-audio-policy.lua new file mode 100644 index 0000000..0b7c358 --- /dev/null +++ b/conf.d/project/lua.d/onload-audio-policy.lua @@ -0,0 +1,49 @@ +--[[ + Copyright (C) 2016 "IoT.bzh" + Author Fulup Ar Foll + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Provide sample policy function for AGL Advance Audio Agent +--]] + +function Audio_Init_CB (status, result, context) + print ("***** result=", Dump_Table(result)) + print ("***** context=", Dump_Table(context)) + + -- AFB:notice ("--LUA:Audio_Init_Hal result=%s context=%s", result, context) + +end + +-- Function call at binding load time +function Audio_Init_Hal(args, query) + AFB:notice ("--LUA:Audio_Init_Hal args=%s query=%s", args, query); + + -- query asynchronously loaded HAL + AFB:service ('alsacore', 'hallist', {}, "Audio_Init_CB", {arg1=1234, arg2="toto"}) + +end + +function Audio_Set_Navigation(args, query) + + AFB:notice ("--LUA:Audio_Set_Use_Case args=%s query=%s", args, query, {myint=1234, mystring="abcd"}); + -- Print_Table("args", args) + + + + -- return OK + return 0 +end + + diff --git a/conf.d/project/lua.d/onload-audio-samples.lua b/conf.d/project/lua.d/onload-audio-samples.lua new file mode 100644 index 0000000..055a15d --- /dev/null +++ b/conf.d/project/lua.d/onload-audio-samples.lua @@ -0,0 +1,93 @@ +--[[ + Copyright (C) 2016 "IoT.bzh" + Author Fulup Ar Foll + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Provide sample policy function for AGL Advance Audio Agent +--]] + +count=0 + +-- Adjust Volume function of vehicle speed +function Adjust_Volume_Speed (request, speed_meters_second) + + AFB:notice("In Adjust_Volume_Speed speed=%d", speed_meters_second); + + print (string.format("*****(From Lua) Adjust_Volume_Speed speed=%d count=%d", speed_meters_second, count)); + + -- compute volume + volume = speed_meters_second * 2 + count=count+1 + + AFB:success (request, 1234, volume, count, 5678) +end + + +function Test_Binder_CB (result, context) + + local myTable= { ["arg1"] = "myString", ["arg2"] = 1234, ["arg4"] = true, ["arg5"] = 3.1416 } + + AFB:notice ("In Test_Binder_CB", result, context) + + AFB:success (1234, "ABCD", myTable, 5678) + +end + +function Test_Binder_Call_Async () + + local query= { + ["arg1"] = "myString", + ["arg2"] = 1234, + ["arg4"] = true, + ["arg5"] = 3.1416, + } + + AFB:service("alsacore","ping", query, Test_Binder_CB, "myContext") + +end + +function Test_Binder_Call_Sync () + + local query= { + ["arg1"] = "myString", + ["arg2"] = 1234, + ["arg4"] = true, + ["arg5"] = 3.1416, + } + + err= AFB:service_sync ("alsacore","ping", query) + + if (err) then + AFB:fail ("AFB:service_call_sync fail"); + else + AFB:success (1234, "ABCD", myTable) + end + + +end + +-- return serialised version of printable table +function Dump_Table(o) + if type(o) == 'table' then + local s = '{ ' + for k,v in pairs(o) do + if type(k) ~= 'number' then k = '"'..k..'"' end + s = s .. '['..k..'] = ' .. Dump_Table(v) .. ',' + end + return s .. '} ' + else + return tostring(o) + end +end diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml index b476df7..2cf8b1c 100644 --- a/nbproject/configurations.xml +++ b/nbproject/configurations.xml @@ -44,10 +44,7 @@ ctl-binding.c - ctl-dispatch.c - ctl-events.c ctl-lua.c - ctl-plugin-sample.c @@ -132,7 +129,31 @@ ${MAKE} -f Makefile install ${MAKE} -f Makefile clean build/CMakeFiles/feature_tests.bin - + + + ../../../opt/include + ../../../opt/include/alsa + /usr/include/p11-kit-1 + /usr/include/json-c + /usr/include/lua5.3 + Audio-Common + build/Controler-afb + + + CONTROL_CONFIG_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d/project/config.d:/usr/local/controler/config.d" + CONTROL_CONFIG_POST="control" + CONTROL_CONFIG_PRE="onload" + CONTROL_LUA_EVENT="luaevt" + CONTROL_LUA_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d/project/lua.d:/usr/local/controler/ctl-lua.d" + CONTROL_MAXPATH_LEN=255 + CONTROL_ONLOAD_DEFAULT="onload-default" + CONTROL_PLUGIN_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/build:/home/fulup/opt/audio-bindings/ctlplug:/usr/lib/afb/ctlplug" + CTL_PLUGIN_MAGIC=2468013579 + MAX_LINEAR_DB_SCALE=24 + MAX_SND_CARD=16 + TLV_BYTE_SIZE=256 + control_afb_EXPORTS + @@ -180,58 +201,12 @@ - + - - Audio-Common - build/Controler-afb - - - control_afb_EXPORTS - - - - - - - Audio-Common - build/Controler-afb - - - control_afb_EXPORTS - - - - - - - Audio-Common - build/Controler-afb - - - control_afb_EXPORTS - - + - - Audio-Common - build/Controler-afb - - - control_afb_EXPORTS - - - - - - - build/Controler-afb - - - ctl_plugin_sample_EXPORTS - Shared-Interface HAL-afb/HAL-interface - ../../../opt/include build/HAL-afb/Unicens-USB @@ -294,21 +268,10 @@ - - Shared-Interface - ../../../opt/include - build/HighLevel-afb - - - /usr/include/json-c - Shared-Interface - ../../../opt/include - build/HighLevel-afb - @@ -348,24 +311,11 @@ - ../../../opt/include - ../../../opt/include/alsa - /usr/include/p11-kit-1 - /usr/include/json-c - /usr/include/lua5.3 build/Alsa-Plugin/Alsa-Policy-Hook - CONTROL_CONFIG_FILE="onload-control-policy.json" - CONTROL_CONFIG_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/usr/local/audio-bindings/config" - CONTROL_LUA_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/etc/default/audio-bindings/lua:/usr/local/audio-bindings/lua" - CONTROL_MAXPATH_LEN=255 - CONTROL_PLUGIN_PATH="/home/fulup/opt/audio-bindings/controler:/usr/lib/audio-bindings" - CTL_PLUGIN_MAGIC=2468013579 - MAX_LINEAR_DB_SCALE=24 - MAX_SND_CARD=16 PIC - TLV_BYTE_SIZE=256 + audio_plugin_sample_EXPORTS policy_hook_cb_EXPORTS @@ -373,49 +323,21 @@ - ../../../opt/include - ../../../opt/include/alsa - /usr/include/p11-kit-1 - /usr/include/json-c - /usr/include/lua5.3 - Audio-Common build/Alsa-afb - CONTROL_CONFIG_FILE="onload-control-policy.json" - CONTROL_CONFIG_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/usr/local/audio-bindings/config" - CONTROL_LUA_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/etc/default/audio-bindings/lua:/usr/local/audio-bindings/lua" - CONTROL_MAXPATH_LEN=255 - CONTROL_PLUGIN_PATH="/home/fulup/opt/audio-bindings/controler:/usr/lib/audio-bindings" - CTL_PLUGIN_MAGIC=2468013579 - MAX_LINEAR_DB_SCALE=24 - MAX_SND_CARD=16 - TLV_BYTE_SIZE=256 alsa_lowlevel_EXPORTS + audio_plugin_sample_EXPORTS - ../../../opt/include - ../../../opt/include/alsa - /usr/include/p11-kit-1 - /usr/include/json-c - /usr/include/lua5.3 - Audio-Common build/Audio-Common - CONTROL_CONFIG_FILE="onload-control-policy.json" - CONTROL_CONFIG_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/usr/local/audio-bindings/config" - CONTROL_LUA_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/etc/default/audio-bindings/lua:/usr/local/audio-bindings/lua" - CONTROL_MAXPATH_LEN=255 - CONTROL_PLUGIN_PATH="/home/fulup/opt/audio-bindings/controler:/usr/lib/audio-bindings" - CTL_PLUGIN_MAGIC=2468013579 - MAX_LINEAR_DB_SCALE=24 - MAX_SND_CARD=16 - TLV_BYTE_SIZE=256 + audio_plugin_sample_EXPORTS @@ -424,36 +346,12 @@ build/HAL-afb/HAL-plugin /usr/include/alsa - ../../../opt/include - /usr/include/json-c build/Common CONTROL_CDEV_RX="/dev/inic-usb-crx" CONTROL_CDEV_TX="/dev/inic-usb-ctx" - MAX_SND_CARD=16 - - - - - - - ../../../opt/include - ../../../opt/include/alsa - /usr/include/p11-kit-1 - /usr/include/json-c - /usr/include/lua5.3 - - - CONTROL_CONFIG_FILE="onload-control-policy.json" - CONTROL_CONFIG_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/usr/local/audio-bindings/config" - CONTROL_LUA_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/etc/default/audio-bindings/lua:/usr/local/audio-bindings/lua" - CONTROL_MAXPATH_LEN=255 - CONTROL_PLUGIN_PATH="/home/fulup/opt/audio-bindings/controler:/usr/lib/audio-bindings" - CTL_PLUGIN_MAGIC=2468013579 - MAX_LINEAR_DB_SCALE=24 - MAX_SND_CARD=16 - TLV_BYTE_SIZE=256 + audio_plugin_sample_EXPORTS @@ -464,39 +362,22 @@ ../../../opt/include/afb - MAX_SND_CARD=16 + audio_plugin_sample_EXPORTS - ../../../opt/include - ../../../opt/include/alsa - /usr/include/p11-kit-1 - /usr/include/json-c - /usr/include/lua5.3 HAL-afb/HAL-interface - Audio-Common build/HAL-afb/HAL-interface - - CONTROL_CONFIG_FILE="onload-control-policy.json" - CONTROL_CONFIG_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/usr/local/audio-bindings/config" - CONTROL_LUA_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/etc/default/audio-bindings/lua:/usr/local/audio-bindings/lua" - CONTROL_MAXPATH_LEN=255 - CONTROL_PLUGIN_PATH="/home/fulup/opt/audio-bindings/controler:/usr/lib/audio-bindings" - CTL_PLUGIN_MAGIC=2468013579 - MAX_LINEAR_DB_SCALE=24 - TLV_BYTE_SIZE=256 - HAL-afb/HAL-plugin - ../../../opt/include/alsa CONTROL_CDEV_RX="/dev/inic-usb-crx" @@ -507,24 +388,10 @@ - ../../../opt/include - ../../../opt/include/alsa - /usr/include/p11-kit-1 - /usr/include/json-c - /usr/include/lua5.3 HAL-afb/HAL-interface - Audio-Common build/HAL-afb/HDA-intel - CONTROL_CONFIG_FILE="onload-control-policy.json" - CONTROL_CONFIG_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/usr/local/audio-bindings/config" - CONTROL_LUA_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/etc/default/audio-bindings/lua:/usr/local/audio-bindings/lua" - CONTROL_MAXPATH_LEN=255 - CONTROL_PLUGIN_PATH="/home/fulup/opt/audio-bindings/controler:/usr/lib/audio-bindings" - CTL_PLUGIN_MAGIC=2468013579 - MAX_LINEAR_DB_SCALE=24 - TLV_BYTE_SIZE=256 hal_intel_hda_EXPORTS @@ -532,24 +399,10 @@ - ../../../opt/include - ../../../opt/include/alsa - /usr/include/p11-kit-1 - /usr/include/json-c - /usr/include/lua5.3 HAL-afb/HAL-interface - Audio-Common build/HAL-afb/Jabra-Solemate - CONTROL_CONFIG_FILE="onload-control-policy.json" - CONTROL_CONFIG_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/usr/local/audio-bindings/config" - CONTROL_LUA_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/etc/default/audio-bindings/lua:/usr/local/audio-bindings/lua" - CONTROL_MAXPATH_LEN=255 - CONTROL_PLUGIN_PATH="/home/fulup/opt/audio-bindings/controler:/usr/lib/audio-bindings" - CTL_PLUGIN_MAGIC=2468013579 - MAX_LINEAR_DB_SCALE=24 - TLV_BYTE_SIZE=256 hal_jabra_usb_EXPORTS @@ -557,24 +410,10 @@ - ../../../opt/include - ../../../opt/include/alsa - /usr/include/p11-kit-1 - /usr/include/json-c - /usr/include/lua5.3 HAL-afb/HAL-interface - Audio-Common build/HAL-afb/Scarlett-Focusrite - CONTROL_CONFIG_FILE="onload-control-policy.json" - CONTROL_CONFIG_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/usr/local/audio-bindings/config" - CONTROL_LUA_PATH="/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/conf.d:/etc/default/audio-bindings/lua:/usr/local/audio-bindings/lua" - CONTROL_MAXPATH_LEN=255 - CONTROL_PLUGIN_PATH="/home/fulup/opt/audio-bindings/controler:/usr/lib/audio-bindings" - CTL_PLUGIN_MAGIC=2468013579 - MAX_LINEAR_DB_SCALE=24 - TLV_BYTE_SIZE=256 hal_scalett_usb_EXPORTS @@ -583,7 +422,6 @@ HAL-afb/Unicens-USB - /usr/include/json-c CONTROL_CDEV_RX="/dev/inic-usb-crx" @@ -597,7 +435,12 @@ build/HAL-afb/HAL-plugin ../../../opt/include/afb HighLevel-afb + Shared-Interface + build/HighLevel-afb + + audio_plugin_sample_EXPORTS + @@ -605,6 +448,9 @@ build/HAL-afb/HAL-plugin + + audio_plugin_sample_EXPORTS + @@ -988,6 +834,8 @@ ${MAKE} ${MAKE} clean + + build @@ -1074,10 +922,6 @@ - - - - - - - - ../../../opt/include - ../../../opt/include/alsa - /usr/include/p11-kit-1 - /usr/include/json-c - Shared-Interface - build/PolicyCtl-afb - - - CONTROL_CDEV_RX="/dev/inic-usb-crx" - CONTROL_CDEV_TX="/dev/inic-usb-ctx" - MAX_LINEAR_DB_SCALE=24 - MAX_SND_CARD=16 - NATIVE_LINUX - TLV_BYTE_SIZE=256 - polctl_afb_EXPORTS - - - -- cgit 1.2.3-korg