summaryrefslogtreecommitdiffstats
path: root/4a-hal/4a-internals-hal/4a-internals-hal-api-loader.c
diff options
context:
space:
mode:
Diffstat (limited to '4a-hal/4a-internals-hal/4a-internals-hal-api-loader.c')
-rw-r--r--4a-hal/4a-internals-hal/4a-internals-hal-api-loader.c243
1 files changed, 243 insertions, 0 deletions
diff --git a/4a-hal/4a-internals-hal/4a-internals-hal-api-loader.c b/4a-hal/4a-internals-hal/4a-internals-hal-api-loader.c
new file mode 100644
index 0000000..94891b8
--- /dev/null
+++ b/4a-hal/4a-internals-hal/4a-internals-hal-api-loader.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2018 "IoT.bzh"
+ * Author Jonathan Aillet <jonathan.aillet@iot.bzh>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+
+#include <filescan-utils.h>
+#include <wrap-json.h>
+
+#include <afb/afb-binding.h>
+
+#include <ctl-config.h>
+
+#include "4a-hal-utilities-verbs-loader.h"
+#include "4a-internals-hal-api-loader.h"
+#include "4a-internals-hal-alsacore-link.h"
+#include "4a-internals-hal-cb.h"
+#include "4a-internals-hal-mixer-link.h"
+
+// Default api to print log when apihandle not available
+afb_api_t AFB_default;
+
+/*******************************************************************************
+ * Json parsing functions using controller *
+ ******************************************************************************/
+
+// Config Section definition
+static CtlSectionT ctrlSectionsDefault[] =
+{
+ { .key = "resources", .loadCB = PluginConfig },
+ { .key = "halmixer", .loadCB = InternalHalHalMixerConfig },
+ { .key = "onload", .loadCB = OnloadConfig },
+ { .key = "controls", .loadCB = ControlConfig },
+ { .key = "events", .loadCB = EventConfig },
+ { .key = "halmap", .loadCB = InternalHalHalMapConfig },
+ { .key = NULL }
+};
+
+/*******************************************************************************
+ * Dynamic HAL verbs' functions *
+ ******************************************************************************/
+
+// Every HAL export the same API & Interface Mapping from SndCard to AudioLogic is done through alsaHalSndCardT
+static afb_verb_t InternalHalApiStaticVerbs[] =
+{
+ /* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */
+ { .verb = "info", .callback = InternalHalInfo, .info = "List available streams/playbacks/captures/controls for this api" },
+ { .verb = "subscribe", .callback = InternalHalSubscribe, .info = "Subscribe to event(s) for values changes (streams/playbacks/captures/controls) for this api" },
+ { .verb = "unsubscribe", .callback = InternalHalUnsubscribe, .info = "Unsubscribe to event(s) for values changes (streams/playbacks/captures/controls) for this api" },
+ { .verb = NULL } // Marker for end of the array
+};
+
+/*******************************************************************************
+ * Dynamic API functions for internals hal *
+ ******************************************************************************/
+
+static int InternalHalInitOneApi(afb_api_t apiHandle)
+{
+ CtlConfigT *ctrlConfig;
+ struct HalData *currentHalData;
+
+ if(! apiHandle)
+ return -1;
+
+ // Hugely hack to make all V2 AFB_DEBUG to work in fileutils
+ AFB_default = apiHandle;
+
+ // Retrieve section config from api handle
+ if(! (ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle)))
+ return -2;
+
+ currentHalData = (struct HalData *) getExternalData(ctrlConfig);
+ if(! currentHalData)
+ return -3;
+
+ // Fill HalDatadata structure
+ currentHalData->internal = 1;
+
+ currentHalData->sndCardPath = (char *) ctrlConfig->uid;
+ currentHalData->info = (char *) ctrlConfig->info;
+
+ currentHalData->author = (char *) ctrlConfig->author;
+ currentHalData->version = (char *) ctrlConfig->version;
+ currentHalData->date = (char *) ctrlConfig->date;
+
+ currentHalData->internalHalData->apiHandle = apiHandle;
+ currentHalData->internalHalData->ctrlConfig = ctrlConfig;
+
+ currentHalData->sndCardId = InternalHalGetCardIdByCardPath(apiHandle, currentHalData->sndCardPath);
+
+ currentHalData->internalHalData->streamUpdates = afb_api_make_event(apiHandle, HAL_STREAM_UPDATES_EVENT_NAME);
+ if(! currentHalData->internalHalData->streamUpdates)
+ return -4;
+
+ if(currentHalData->sndCardId < 0)
+ currentHalData->status = HAL_STATUS_UNAVAILABLE;
+ else
+ currentHalData->status = HAL_STATUS_AVAILABLE;
+
+ // TBD JAI: handle refresh of hal status for dynamic card (/dev/by-id)
+
+ return CtlConfigExec(apiHandle, ctrlConfig);
+}
+
+static int InternalHalLoadOneApi(void *cbdata, afb_api_t apiHandle)
+{
+ int err;
+ CtlConfigT *ctrlConfig;
+ CtlSectionT *ctrlCurrentSections;
+
+ if(! cbdata || ! apiHandle)
+ return -1;
+
+ ctrlConfig = (CtlConfigT*) cbdata;
+
+ // Save closure as api's data context
+ afb_api_set_userdata(apiHandle, ctrlConfig);
+
+ // Add static controls verbs
+ if(HalUtlLoadVerbs(apiHandle, InternalHalApiStaticVerbs)) {
+ AFB_API_ERROR(apiHandle, "Load Section : fail to register static V2 verbs");
+ return 1;
+ }
+
+ ctrlCurrentSections = malloc(sizeof(ctrlSectionsDefault));
+ memcpy(ctrlCurrentSections, ctrlSectionsDefault, sizeof(ctrlSectionsDefault));
+
+ // Load section for corresponding Api
+ if((err = CtlLoadSections(apiHandle, ctrlConfig, ctrlCurrentSections)))
+ return err;
+
+ // Declare an event manager for this Api
+ afb_api_on_event(apiHandle, InternalHalDispatchApiEvent);
+
+ // Init Api function (does not receive user closure ???)
+ afb_api_on_init(apiHandle, InternalHalInitOneApi);
+
+ return 0;
+}
+
+int InternalHalCreateApi(afb_api_t apiHandle, char *path, struct HalMgrData *halMgrData)
+{
+ CtlConfigT *ctrlConfig;
+ struct HalData *currentHalData;
+
+ if(! apiHandle || ! path || ! halMgrData)
+ return -1;
+
+ // Create one Api per file
+ ctrlConfig = CtlLoadMetaData(apiHandle, path);
+ if(! ctrlConfig) {
+ AFB_API_ERROR(apiHandle, "No valid control config file in:\n-- %s", path);
+ return -2;
+ }
+
+ if(! ctrlConfig->api) {
+ AFB_API_ERROR(apiHandle, "API Missing from metadata in:\n-- %s", path);
+ return -3;
+ }
+
+ // Allocation of current hal controller data
+ currentHalData = HalUtlAddHalToHalList(&halMgrData->halDataList);
+ if(! currentHalData)
+ return -4;
+
+ currentHalData->apiName = (char *) ctrlConfig->api;
+
+ // Stores hal data in controller config
+ setExternalData(ctrlConfig, (void *) currentHalData);
+
+ // Allocation of the structure that will be used to store internal hal data
+ currentHalData->internalHalData = calloc(1, sizeof(struct InternalHalData));
+
+ // Create one API
+ if(! afb_api_new_api(apiHandle, ctrlConfig->api, ctrlConfig->info, 1, InternalHalLoadOneApi, ctrlConfig))
+ return -5;
+
+ return 0;
+}
+
+int InternalHalCreateAllApi(afb_api_t apiHandle, struct HalMgrData *halMgrData)
+{
+ int index, status = 0;
+ char *dirList, *fileName, *fullPath;
+ char filePath[CONTROL_MAXPATH_LEN];
+
+ filePath[CONTROL_MAXPATH_LEN - 1] = '\0';
+
+ json_object *configJ, *entryJ;
+
+ if(! apiHandle || ! halMgrData)
+ return -1;
+
+ // Hugely hack to make all V2 AFB_DEBUG to work in fileutils
+ AFB_default = apiHandle;
+
+ AFB_API_NOTICE(apiHandle, "Begining to create all APIs");
+
+ dirList = getenv("CONTROL_CONFIG_PATH");
+ if(! dirList)
+ dirList = CONTROL_CONFIG_PATH;
+
+ configJ = CtlConfigScan(dirList, "hal");
+ if(! configJ) {
+ AFB_API_WARNING(apiHandle, "No hal-(binder-middle-name)*.json config file(s) found in %s, 4a-hal-manager will only works with external hal", dirList);
+ return 0;
+ }
+
+ // We load 1st file others are just warnings
+ for(index = 0; index < (int) json_object_array_length(configJ); index++) {
+ entryJ = json_object_array_get_idx(configJ, index);
+
+ if(wrap_json_unpack(entryJ, "{s:s, s:s !}", "fullpath", &fullPath, "filename", &fileName)) {
+ AFB_API_ERROR(apiHandle, "HOOPs invalid JSON entry = %s", json_object_get_string(entryJ));
+ return -2;
+ }
+
+ strncpy(filePath, fullPath, sizeof(filePath) - 1);
+ strncat(filePath, "/", sizeof(filePath) - 1);
+ strncat(filePath, fileName, sizeof(filePath) - 1);
+
+ if(InternalHalCreateApi(apiHandle, filePath, halMgrData) < 0)
+ status--;
+ }
+
+ return status;
+} \ No newline at end of file