From 99fcc5f06fe8c8c72bbc3fd80a866b2beac3052d Mon Sep 17 00:00:00 2001 From: Jonathan Aillet Date: Thu, 3 May 2018 16:47:56 +0200 Subject: Pre-version of 4a-hal-manager Pre-version of 4a-hal manager that uses app-fwk DynAPI and app-controller. Current version : - Declare a new API for each HAL (each .json config file is used to generate one app-controller API) at startup. - Define verbs that will be provided by this API. - Provide verb to list and get info of loaded API. Change-Id: I7bb6e8b7539b1acd5556fd9275a1b536e129332d Signed-off-by: Jonathan Aillet --- .../4a-hal-controllers-api-loader.c | 239 +++++++++++++++++++++ .../4a-hal-controllers-api-loader.h | 40 ++++ 4a-hal/4a-hal-manager/4a-hal-manager-cb.c | 185 ++++++++++++++++ 4a-hal/4a-hal-manager/4a-hal-manager-cb.h | 38 ++++ 4a-hal/4a-hal-manager/4a-hal-manager-events.c | 29 +++ 4a-hal/4a-hal-manager/4a-hal-manager-events.h | 28 +++ 4a-hal/4a-hal-manager/4a-hal-manager.c | 148 +++++++++++++ 4a-hal/4a-hal-manager/4a-hal-manager.h | 29 +++ .../4a-hal-utilities/4a-hal-utilities-alsa-link.c | 27 +++ .../4a-hal-utilities/4a-hal-utilities-alsa-link.h | 25 +++ 4a-hal/4a-hal-utilities/4a-hal-utilities-data.c | 211 ++++++++++++++++++ 4a-hal/4a-hal-utilities/4a-hal-utilities-data.h | 74 +++++++ .../4a-hal-utilities-verbs-loader.c | 49 +++++ .../4a-hal-utilities-verbs-loader.h | 38 ++++ 14 files changed, 1160 insertions(+) create mode 100644 4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.c create mode 100644 4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.h create mode 100644 4a-hal/4a-hal-manager/4a-hal-manager-cb.c create mode 100644 4a-hal/4a-hal-manager/4a-hal-manager-cb.h create mode 100644 4a-hal/4a-hal-manager/4a-hal-manager-events.c create mode 100644 4a-hal/4a-hal-manager/4a-hal-manager-events.h create mode 100644 4a-hal/4a-hal-manager/4a-hal-manager.c create mode 100644 4a-hal/4a-hal-manager/4a-hal-manager.h create mode 100644 4a-hal/4a-hal-utilities/4a-hal-utilities-alsa-link.c create mode 100644 4a-hal/4a-hal-utilities/4a-hal-utilities-alsa-link.h create mode 100644 4a-hal/4a-hal-utilities/4a-hal-utilities-data.c create mode 100644 4a-hal/4a-hal-utilities/4a-hal-utilities-data.h create mode 100644 4a-hal/4a-hal-utilities/4a-hal-utilities-verbs-loader.c create mode 100644 4a-hal/4a-hal-utilities/4a-hal-utilities-verbs-loader.h (limited to '4a-hal') diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.c b/4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.c new file mode 100644 index 0000000..3401c93 --- /dev/null +++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.c @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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 + +#include "../4a-hal-utilities/4a-hal-utilities-verbs-loader.h" +#include "../4a-hal-manager/4a-hal-manager-cb.h" + +#include "4a-hal-controllers-api-loader.h" + +// Default api to print log when apihandle not available +afb_dynapi *AFB_default; + +/******************************************************************************* + * Json parsing functions using app controller * + ******************************************************************************/ + +// Config Section definition +static CtlSectionT ctrlSections[] = +{ + [CTL_SECTION_PLUGIN] = {.key="plugins" , .loadCB= PluginConfig}, + [CTL_SECTION_ONLOAD] = {.key="onload" , .loadCB= OnloadConfig}, + [CTL_SECTION_CONTROL] = {.key="controls", .loadCB= ControlConfig}, + [CTL_SECTION_EVENT] = {.key="events" , .loadCB= EventConfig}, + + [CTL_SECTION_ENDTAG] = {.key=NULL} +}; + +/******************************************************************************* + * Dynamic HAL verbs' functions * + ******************************************************************************/ + +// Every HAL export the same API & Interface Mapping from SndCard to AudioLogic is done through alsaHalSndCardT +static struct HalUtlApiVerb CtlHalDynApiStaticVerbs[] = +{ + /* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */ + { .verb = "ping", .callback = HalMgrPing, .info = "Ping test for DynApi"}, + { .verb = NULL } // Marker for end of the array +}; + +/******************************************************************************* + * Dynamic API functions for app controller * + * TODO JAI : Use API-V3 instead of API-PRE-V3 * + ******************************************************************************/ + +static int HalCtlsInitOneApi(afb_dynapi *apiHandle) +{ + int apiMetadataUnpackErr, apiHalmetadataUnpackErr; + + json_object *apiMetadata, *apiHalmetadata; + + CtlConfigT *ctrlConfig; + struct SpecificHalData *currentCtlHalData; + + 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 + ctrlConfig = (CtlConfigT *) afb_dynapi_get_userdata(apiHandle); + if(! ctrlConfig) + return -2; + + currentCtlHalData = ctrlConfig->external; + if(! currentCtlHalData) + return -3; + + // Fill SpecificHalDatadata structure + currentCtlHalData->internal = true; + currentCtlHalData->status = HAL_STATUS_UNAVAILABLE; + + if(! json_object_object_get_ex(ctrlConfig->configJ, "metadata", &apiMetadata)) + return -4; + + if(! json_object_object_get_ex(ctrlConfig->configJ, "hal-metadata", &apiHalmetadata)) + return -5; + + apiMetadataUnpackErr = wrap_json_unpack(apiMetadata, "{s:s s?:s s?:s s?:o s?:o !}", + "uid", NULL, + "version", ¤tCtlHalData->version, + "api", ¤tCtlHalData->name, + "info", NULL, + "require", NULL); + if(apiMetadataUnpackErr) + return -6; + + apiHalmetadataUnpackErr = wrap_json_unpack(apiHalmetadata, "{s:s s:s s:s !}", + "sndcard", ¤tCtlHalData->sndCard, + "author", ¤tCtlHalData->author, + "date", ¤tCtlHalData->date); + if(apiHalmetadataUnpackErr) + return -7; + + currentCtlHalData->apiHandle = apiHandle; + currentCtlHalData->ctrlConfig = ctrlConfig; + + // TODO JAI: Search for hw sndCard + // TODO JAI: Update alsa command of HalCtl to use alsa-softmixer/alsa-core data + // TODO JAI: handle refresh of hal status using /dev/snd/byId (or /dev/snd/byId) + + return CtlConfigExec(apiHandle, ctrlConfig); +} + +static int HalCtlsLoadOneApi(void *cbdata, afb_dynapi *apiHandle) +{ + int err; + CtlConfigT *ctrlConfig; + + if(! cbdata || ! apiHandle ) + return -1; + + ctrlConfig = (CtlConfigT*) cbdata; + + // Save closure as api's data context + afb_dynapi_set_userdata(apiHandle, ctrlConfig); + + // Add static controls verbs + if(HalUtlLoadStaticVerbs(apiHandle, CtlHalDynApiStaticVerbs)) { + AFB_DYNAPI_ERROR(apiHandle, "%s : load Section : fail to register static V2 verbs", __func__); + return 1; + } + + // Load section for corresponding Api + err = CtlLoadSections(apiHandle, ctrlConfig, ctrlSections); + + // Declare an event manager for this Api + afb_dynapi_on_event(apiHandle, CtrlDispatchApiEvent); + + // Init Api function (does not receive user closure ???) + afb_dynapi_on_init(apiHandle, HalCtlsInitOneApi); + + afb_dynapi_seal(apiHandle); + + return err; +} + +int HalCtlsCreateApi(afb_dynapi *apiHandle, char *path, struct HalMgrData *HalMgrGlobalData) +{ + CtlConfigT *ctrlConfig; + struct SpecificHalData *currentCtlHalData; + + if(! apiHandle || ! path || ! HalMgrGlobalData) + return -1; + + // Create one Api per file + ctrlConfig = CtlLoadMetaData(apiHandle, path); + if(! ctrlConfig) { + AFB_DYNAPI_ERROR(apiHandle, "%s: No valid control config file in:\n-- %s", __func__, path); + return -2; + } + + if(! ctrlConfig->api) { + AFB_DYNAPI_ERROR(apiHandle, "%s: API Missing from metadata in:\n-- %s", __func__, path); + return -3; + } + + currentCtlHalData = HalUtlAddHalApiToHalList(HalMgrGlobalData); + if(! currentCtlHalData) + return -4; + + ctrlConfig->external = (void *) currentCtlHalData; + + // Create one API (Pre-V3 return code ToBeChanged) + return afb_dynapi_new_api(apiHandle, ctrlConfig->api, ctrlConfig->info, 1, HalCtlsLoadOneApi, ctrlConfig); +} + +int HalCtlsCreateAllApi(afb_dynapi *apiHandle, struct HalMgrData *HalMgrGlobalData) +{ + int index, err, status; + char *dirList, *fileName, *fullPath; + char filePath[CONTROL_MAXPATH_LEN]; + + filePath[CONTROL_MAXPATH_LEN - 1] = '\0'; + + json_object *configJ, *entryJ; + + if(! apiHandle || ! HalMgrGlobalData) + return -1; + + // Hugely hack to make all V2 AFB_DEBUG to work in fileutils + AFB_default = apiHandle; + + AFB_DYNAPI_NOTICE(apiHandle, "In %s", __func__); + + dirList = getenv("CONTROL_CONFIG_PATH"); + if(! dirList) + dirList = CONTROL_CONFIG_PATH; + + configJ = CtlConfigScan(dirList, "4a"); + if(! configJ) { + AFB_DYNAPI_ERROR(apiHandle, "%s: No 4a*.json config file(s) found in %s ", __func__, dirList); + return -2; + } + + // We load 1st file others are just warnings + for(index = 0; index < json_object_array_length(configJ); index++) { + entryJ = json_object_array_get_idx(configJ, index); + + err = wrap_json_unpack(entryJ, "{s:s, s:s !}", "fullpath", &fullPath, "filename", &fileName); + if(err) { + AFB_DYNAPI_ERROR(apiHandle, "%s: HOOPs invalid JSON entry = %s", __func__, json_object_get_string(entryJ)); + return -1; + } + + strncpy(filePath, fullPath, sizeof(filePath) - 1); + strncat(filePath, "/", sizeof(filePath)); + strncat(filePath, fileName, sizeof(filePath)); + + if(HalCtlsCreateApi(apiHandle, filePath, HalMgrGlobalData) < 0) + status--; + } + + return status; +} \ No newline at end of file diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.h b/4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.h new file mode 100644 index 0000000..b2b42f3 --- /dev/null +++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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. + */ + +#ifndef _HAL_CTLS_API_LOADER_INCLUDE_ +#define _HAL_CTLS_API_LOADER_INCLUDE_ + +#include + +#define AFB_BINDING_VERSION dyn +#include + +#include "../4a-hal-utilities/4a-hal-utilities-data.h" + +// Api info definitions +#define HAL_CTLS_API_NAME_MAX_SIZE 32 +#define HAL_CTLS_API_INFO_MAX_SIZE 64 +#define HAL_CTLS_API_SNDCARD_MAX_SIZE 128 +#define HAL_CTLS_API_AUTHOR_MAX_SIZE 32 +#define HAL_CTLS_API_VERSION_MAX_SIZE 16 +#define HAL_CTLS_API_DATE_MAX_SIZE 16 + +// Verbs that can be use to create api +int HalCtlsCreateApi(afb_dynapi *apiHandle, char *path, struct HalMgrData *HalMgrGlobalData); +int HalCtlsCreateAllApi(afb_dynapi *apiHandle, struct HalMgrData *HalMgrGlobalData); + +#endif /* _HALMGR_HALCTL_DYNAPI_INCLUDE_ */ \ No newline at end of file diff --git a/4a-hal/4a-hal-manager/4a-hal-manager-cb.c b/4a-hal/4a-hal-manager/4a-hal-manager-cb.c new file mode 100644 index 0000000..a2d946b --- /dev/null +++ b/4a-hal/4a-hal-manager/4a-hal-manager-cb.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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 "../4a-hal-utilities/4a-hal-utilities-data.h" + +#include "4a-hal-manager-cb.h" +#include "4a-hal-manager-events.h" + +/******************************************************************************* + * HAL Manager event handler function * + ******************************************************************************/ + +// TODO JAI : to implement +void HalMgrDispatchApiEvent(afb_dynapi *apiHandle, const char *evtLabel, struct json_object *eventJ) +{ + AFB_DYNAPI_WARNING(apiHandle, "JAI :%s not implemented yet", __func__); + // Use "4a-hal-manager-events.h" to handle events +} + +/******************************************************************************* + * TODO JAI : Present for test, delete this function when validated * + ******************************************************************************/ + +void HalMgrPing(afb_request *request) +{ + static int count = 0; + + count++; + + if(request->dynapi) + AFB_REQUEST_NOTICE(request, "JAI :%s (%s): ping count = %d", request->api, request->dynapi->apiname, count); + else + AFB_REQUEST_NOTICE(request, "JAI: %s: ping count = %d", request->api, count); + + afb_request_success(request, json_object_new_int(count), NULL); + + return; +} + +/******************************************************************************* + * HAL Manager verbs functions * + ******************************************************************************/ + +void HalMgrLoaded(afb_request *request) +{ + int requestJsonErr; + uint64_t cpt, numberOfLoadedApi; + char *requestOption; + + afb_dynapi *apiHandle; + struct HalMgrData *HalMgrGlobalData; + struct SpecificHalData *currentHalData; + + struct json_object *requestJson; + struct json_object *requestAnswer; + struct json_object *apiObject; + + AFB_REQUEST_WARNING(request, "JAI :%s not completelly implemented yet", __func__); + + apiHandle = (afb_dynapi *) afb_request_get_dynapi(request); + if(! apiHandle) { + afb_request_fail(request, "ERROR", "Can't get HalManager Api handle"); + return; + } + + HalMgrGlobalData = (struct HalMgrData *) afb_dynapi_get_userdata(apiHandle); + if(! HalMgrGlobalData) { + afb_request_fail(request, "ERROR", "Can't get HalManager data"); + return; + } + + requestJson = afb_request_json(request); + if(! requestJson) { + afb_request_fail(request, "ERROR", "Can't get request json"); + return; + } + + numberOfLoadedApi = HalUtlGetNumberOfHalInList(HalMgrGlobalData); + if(! numberOfLoadedApi) { + afb_request_success(request, NULL, "No Hal Api loaded"); + return; + } + + requestAnswer = json_object_new_array(); + if(! requestAnswer) { + afb_request_fail(request, "ERROR", "Can't generate json answer"); + return; + } + + currentHalData = HalMgrGlobalData->first; + + // Get request option + requestJsonErr = wrap_json_unpack(requestJson, "{s:s}", "option", &requestOption); + + if(! requestJsonErr && ! strcmp(requestOption, "status")) { // Case if request option is 'status' + for(cpt = 0; cpt < numberOfLoadedApi; cpt++) { + wrap_json_pack(&apiObject, + "{s:i}", + currentHalData->name, + (unsigned int) currentHalData->status); + json_object_array_add(requestAnswer, apiObject); + + currentHalData = currentHalData->next; + } + } + else if(! requestJsonErr && ! strcmp(requestOption, "metadata")) { // Case if request option is 'metadata' + for(cpt = 0; cpt < numberOfLoadedApi; cpt++) { + wrap_json_pack(&apiObject, + "{s:s s:i s:s s:i s:s s:s s:s}", + "api", currentHalData->name, + "status", (int) currentHalData->status, + "sndcard", currentHalData->sndCard, + "internal", (int) currentHalData->internal, + "author", currentHalData->author, + "version", currentHalData->version, + "date", currentHalData->date); + json_object_array_add(requestAnswer, apiObject); + + currentHalData = currentHalData->next; + } + } + else { // Case if request option is empty or not valid + for(cpt = 0; cpt < numberOfLoadedApi; cpt++) { + json_object_array_add(requestAnswer, json_object_new_string(currentHalData->name)); + + currentHalData = currentHalData->next; + } + } + + afb_request_success(request, requestAnswer, "Requested data"); +} + +// TODO JAI : to implement +void HalMgrLoad(afb_request *request) +{ + AFB_REQUEST_WARNING(request, "JAI :%s not implemented yet", __func__); + + afb_request_success(request, json_object_new_boolean(false), NULL); +} + +// TODO JAI : to implement +void HalMgrUnload(afb_request *request) +{ + AFB_REQUEST_WARNING(request, "JAI :%s not implemented yet", __func__); + + afb_request_success(request, json_object_new_boolean(false), NULL); +} + +// TODO JAI : to implement +void HalMgrSubscribeEvent(afb_request *request) +{ + AFB_REQUEST_WARNING(request, "JAI :%s not implemented yet", __func__); + + afb_request_success(request, json_object_new_boolean(false), NULL); +} + +// TODO JAI : to implement +void HalMgrUnsubscribeEvent(afb_request *request) +{ + AFB_REQUEST_WARNING(request, "JAI :%s not implemented yet", __func__); + + afb_request_success(request, json_object_new_boolean(false), NULL); +} \ No newline at end of file diff --git a/4a-hal/4a-hal-manager/4a-hal-manager-cb.h b/4a-hal/4a-hal-manager/4a-hal-manager-cb.h new file mode 100644 index 0000000..f2f9ce0 --- /dev/null +++ b/4a-hal/4a-hal-manager/4a-hal-manager-cb.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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. + */ + +#ifndef _HALMGR_CB_INCLUDE_ +#define _HALMGR_CB_INCLUDE_ + +#include + +#define AFB_BINDING_VERSION dyn +#include + +// Event handler +void HalMgrDispatchApiEvent(afb_dynapi *apiHandle, const char *evtLabel, struct json_object *eventJ); + +// Exported verbs callbacks +void HalMgrPing(afb_request *request); + +void HalMgrLoaded(afb_request *request); +void HalMgrLoad(afb_request *request); +void HalMgrUnload(afb_request *request); +void HalMgrSubscribeEvent(afb_request *request); +void HalMgrUnsubscribeEvent(afb_request *request); + +#endif /* _HALMGR_CB_INCLUDE_ */ \ No newline at end of file diff --git a/4a-hal/4a-hal-manager/4a-hal-manager-events.c b/4a-hal/4a-hal-manager/4a-hal-manager-events.c new file mode 100644 index 0000000..0840bdd --- /dev/null +++ b/4a-hal/4a-hal-manager/4a-hal-manager-events.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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 "../4a-hal-utilities/4a-hal-utilities-data.h" +#include "4a-hal-manager-events.h" + +// TODO JAI: implement events handlers functions \ No newline at end of file diff --git a/4a-hal/4a-hal-manager/4a-hal-manager-events.h b/4a-hal/4a-hal-manager/4a-hal-manager-events.h new file mode 100644 index 0000000..d7f4b59 --- /dev/null +++ b/4a-hal/4a-hal-manager/4a-hal-manager-events.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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. + */ + +#ifndef _HALMGR_EVENTS_INCLUDE_ +#define _HALMGR_EVENTS_INCLUDE_ + +#include + +#define AFB_BINDING_VERSION dyn +#include + +// TODO JAI: declare events handlers functions + +#endif /* _HALMGR_EVENTS_INCLUDE_ */ \ No newline at end of file diff --git a/4a-hal/4a-hal-manager/4a-hal-manager.c b/4a-hal/4a-hal-manager/4a-hal-manager.c new file mode 100644 index 0000000..257aa38 --- /dev/null +++ b/4a-hal/4a-hal-manager/4a-hal-manager.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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 "../4a-hal-utilities/4a-hal-utilities-data.h" +#include "../4a-hal-utilities/4a-hal-utilities-verbs-loader.h" +#include "../4a-hal-controllers/4a-hal-controllers-api-loader.h" + +#include "4a-hal-manager.h" +#include "4a-hal-manager-cb.h" + +// Default api to print log when apihandle not available +afb_dynapi *AFB_default; + +/******************************************************************************* + * HAL Manager verbs table * + ******************************************************************************/ + +// Hal manager exported verbs +struct HalUtlApiVerb HalManagerApiStaticVerbs[] = +{ + /* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */ + { .verb = "ping", .callback = HalMgrPing, .info = "Ping test for DynApi"}, + { .verb = "loaded", .callback = HalMgrLoaded, .info = "Show loaded HAL"}, + { .verb = "load", .callback = HalMgrLoad, .info = "Load an external HAL to HAL Manager"}, + { .verb = "unload", .callback = HalMgrUnload, .info = "Unload an external HAL to HAL Manager"}, + { .verb = "subscribe", .callback = HalMgrSubscribeEvent, .info = "Subscribe to an event"}, + { .verb = "unsuscribe", .callback = HalMgrUnsubscribeEvent, .info = "Unsubscribe to an event"}, + { .verb = NULL } // Marker for end of the array +}; + +/******************************************************************************* + * Dynamic API functions for hal manager * + * TODO JAI : Use API-V3 instead of API-PRE-V3 * + ******************************************************************************/ + +static int HalMgrInitApi(afb_dynapi *apiHandle) +{ + struct HalMgrData *HalMgrGlobalData; + + 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 + HalMgrGlobalData = (struct HalMgrData *) afb_dynapi_get_userdata(apiHandle); + if(! HalMgrGlobalData) + return -2; + + if(HalUtlInitializeHalMgrData(apiHandle, HalMgrGlobalData, HAL_MANAGER_API_NAME, HAL_MANAGER_API_INFO)) + return -3; + + return 0; +} + +static int HalMgrLoadApi(void *cbdata, afb_dynapi *apiHandle) +{ + struct HalMgrData *HalMgrGlobalData; + + if(! cbdata || ! apiHandle) + return -1; + + HalMgrGlobalData = (struct HalMgrData *) cbdata; + + // Save closure as api's data context + afb_dynapi_set_userdata(apiHandle, HalMgrGlobalData); + + // Add static controls verbs + if(HalUtlLoadStaticVerbs(apiHandle, HalManagerApiStaticVerbs)) { + AFB_DYNAPI_ERROR(apiHandle, "%s : load section : fail to register static V2 verbs", __func__); + return 1; + } + + // Declare an event manager for Hal Manager + afb_dynapi_on_event(apiHandle, HalMgrDispatchApiEvent); + + // Init Api function (does not receive user closure ???) + afb_dynapi_on_init(apiHandle, HalMgrInitApi); + + afb_dynapi_seal(apiHandle); + + return 0; +} + +int HalMgrCreateApi(afb_dynapi *apiHandle, struct HalMgrData *HalMgrGlobalData) +{ + if(! apiHandle || ! HalMgrGlobalData) + return -1; + + // Create one API (Pre-V3 return code ToBeChanged) + return afb_dynapi_new_api(apiHandle, HAL_MANAGER_API_NAME, HAL_MANAGER_API_INFO, 1, HalMgrLoadApi, HalMgrGlobalData); +} + +/******************************************************************************* + * Startup function * + * TODO JAI : Use API-V3 instead of API-PRE-V3 * + ******************************************************************************/ + +int afbBindingVdyn(afb_dynapi *apiHandle) +{ + int status = 0, rc; + struct HalMgrData *HalMgrGlobalData; + + if(! apiHandle) + return -1; + + HalMgrGlobalData = (struct HalMgrData *) calloc(1, sizeof(struct HalMgrData)); + if(! HalMgrGlobalData) + return -2; + + // Hugely hack to make all V2 AFB_DEBUG to work in fileutils + AFB_default = apiHandle; + + AFB_DYNAPI_NOTICE(apiHandle, "In %s", __func__); + + // Load Hal-Manager using DynApi + rc = HalMgrCreateApi(apiHandle, HalMgrGlobalData); + if(rc < 0) + status--; + + // Load Hal-Ctls using DynApi + rc = HalCtlsCreateAllApi(apiHandle, HalMgrGlobalData); + if(rc < 0) + status -= rc; + + return status; +} \ No newline at end of file diff --git a/4a-hal/4a-hal-manager/4a-hal-manager.h b/4a-hal/4a-hal-manager/4a-hal-manager.h new file mode 100644 index 0000000..fb41ad1 --- /dev/null +++ b/4a-hal/4a-hal-manager/4a-hal-manager.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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. + */ + +#ifndef _HALMGR_BINDING_INCLUDE_ +#define _HALMGR_BINDING_INCLUDE_ + +#include + +// TODO JAI: use it +// #include + +#define HAL_MANAGER_API_NAME "4a-hal-manager" +#define HAL_MANAGER_API_INFO "Manager for 4A HAL APIs" + +#endif /* _HALMGR_BINDING_INCLUDE_ */ \ No newline at end of file diff --git a/4a-hal/4a-hal-utilities/4a-hal-utilities-alsa-link.c b/4a-hal/4a-hal-utilities/4a-hal-utilities-alsa-link.c new file mode 100644 index 0000000..8ff6c06 --- /dev/null +++ b/4a-hal/4a-hal-utilities/4a-hal-utilities-alsa-link.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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 "4a-hal-utilities-data.h" +#include "4a-hal-utilities-alsa-link.h" + +// TODO JAI: implement alsa link functions \ No newline at end of file diff --git a/4a-hal/4a-hal-utilities/4a-hal-utilities-alsa-link.h b/4a-hal/4a-hal-utilities/4a-hal-utilities-alsa-link.h new file mode 100644 index 0000000..5c15109 --- /dev/null +++ b/4a-hal/4a-hal-utilities/4a-hal-utilities-alsa-link.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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. + */ + +#ifndef _HAL_UTILITIES_ALSA_LINK_INCLUDE_ +#define _HAL_UTILITIES_ALSA_LINK_INCLUDE_ + +#include + +// TODO JAI: implement alsa link functions + +#endif /* _HAL_UTILITIES_DATA_INCLUDE_ */ \ No newline at end of file diff --git a/4a-hal/4a-hal-utilities/4a-hal-utilities-data.c b/4a-hal/4a-hal-utilities/4a-hal-utilities-data.c new file mode 100644 index 0000000..dafed90 --- /dev/null +++ b/4a-hal/4a-hal-utilities/4a-hal-utilities-data.c @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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 "4a-hal-utilities-data.h" + +/******************************************************************************* + * Specfic Hal data handling functions * + ******************************************************************************/ + +struct SpecificHalData *HalUtlAddHalApiToHalList(struct HalMgrData *HalMgrGlobalData) +{ + struct SpecificHalData *currentApi; + + if(! HalMgrGlobalData) + return NULL; + + currentApi = HalMgrGlobalData->first; + + if(! currentApi) { + currentApi = (struct SpecificHalData *) calloc(1, sizeof(struct SpecificHalData)); + if(! currentApi) + return NULL; + + HalMgrGlobalData->first = currentApi; + } + else { + while(currentApi->next) + currentApi = currentApi->next; + + currentApi->next = calloc(1, sizeof(struct SpecificHalData)); + if(! currentApi) + return NULL; + + currentApi = currentApi->next; + } + + currentApi->name = NULL; + currentApi->sndCard = NULL; + currentApi->author = NULL; + currentApi->version = NULL; + currentApi->date = NULL; + + currentApi->next = NULL; + + return currentApi; +} + +uint8_t HalUtlRemoveSelectedHalFromList(struct HalMgrData *HalMgrGlobalData, struct SpecificHalData *apiToRemove) +{ + struct SpecificHalData *currentApi, *matchingApi; + + if(! HalMgrGlobalData || ! apiToRemove) + return -1; + + currentApi = HalMgrGlobalData->first; + + if(currentApi == apiToRemove) { + HalMgrGlobalData->first = currentApi->next; + matchingApi = currentApi; + } + else { + while(currentApi && currentApi->next != apiToRemove) + currentApi = currentApi->next; + + if(currentApi) { + matchingApi = currentApi->next; + currentApi->next = currentApi->next->next; + } + else { + return -2; + } + } + + if(matchingApi->name) + free(matchingApi->name); + + if(matchingApi->sndCard) + free(matchingApi->sndCard); + + if(matchingApi->author) + free(matchingApi->author); + + if(matchingApi->version) + free(matchingApi->version); + + if(matchingApi->date) + free(matchingApi->date); + + free(matchingApi); + + return 0; +} + +uint64_t HalUtlRemoveAllHalFromList(struct HalMgrData *HalMgrGlobalData) +{ + uint8_t ret; + uint64_t CtlHalApiRemoved = 0; + + while(HalMgrGlobalData->first) { + ret = HalUtlRemoveSelectedHalFromList(HalMgrGlobalData, HalMgrGlobalData->first); + if(ret) + return (uint64_t) ret; + + CtlHalApiRemoved++; + } + + return CtlHalApiRemoved; +} + +uint64_t HalUtlGetNumberOfHalInList(struct HalMgrData *HalMgrGlobalData) +{ + uint64_t numberOfCtlHal = 0; + struct SpecificHalData *currentApi; + + if(! HalMgrGlobalData) + return -1; + + currentApi = HalMgrGlobalData->first; + + while(currentApi) { + currentApi = currentApi->next; + numberOfCtlHal++; + } + + return numberOfCtlHal; +} + +struct SpecificHalData *HalUtlSearchHalDataByApiName(struct HalMgrData *HalMgrGlobalData, char *name) +{ + struct SpecificHalData *currentApi; + + if(! HalMgrGlobalData || ! name) + return NULL; + + currentApi = HalMgrGlobalData->first; + + while(currentApi) { + if(! strcmp(name, currentApi->name)) + return currentApi; + + currentApi = currentApi->next; + } + + return NULL; +} + +/******************************************************************************* + * Hal Manager data handling functions * + ******************************************************************************/ + +uint8_t HalUtlInitializeHalMgrData(afb_dynapi *apiHandle, struct HalMgrData *HalMgrGlobalData, char *name, char *description) +{ + if(! apiHandle || ! HalMgrGlobalData || ! name || ! description) + return -1; + + // Allocate name and info strings + HalMgrGlobalData->name = (char *) calloc(strlen(name), sizeof(char)); + if(! HalMgrGlobalData->name) + return -2; + + HalMgrGlobalData->description = (char *) calloc(strlen(description), sizeof(char)); + if(! HalMgrGlobalData->name) + return -3; + + // Fill HalMgrGlobalData structure + strcpy(HalMgrGlobalData->name, name); + strcpy(HalMgrGlobalData->description, description); + + HalMgrGlobalData->apiHandle = apiHandle; + + return 0; +} + +void HalUtlRemoveHalMgrData(struct HalMgrData *HalMgrGlobalData) +{ + if(! HalMgrGlobalData) + return; + + if(HalMgrGlobalData->first) + HalUtlRemoveAllHalFromList(HalMgrGlobalData); + + if(HalMgrGlobalData->name) + free(HalMgrGlobalData->name); + + if(HalMgrGlobalData->description) + free(HalMgrGlobalData->description); + + free(HalMgrGlobalData); +} \ No newline at end of file diff --git a/4a-hal/4a-hal-utilities/4a-hal-utilities-data.h b/4a-hal/4a-hal-utilities/4a-hal-utilities-data.h new file mode 100644 index 0000000..75653e4 --- /dev/null +++ b/4a-hal/4a-hal-utilities/4a-hal-utilities-data.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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. + */ + +#ifndef _HAL_UTILITIES_DATA_INCLUDE_ +#define _HAL_UTILITIES_DATA_INCLUDE_ + +#include + +#define AFB_BINDING_VERSION dyn +#include + +#include + +// Enum for sharing hal (controller or external) status +enum HalStatus { + HAL_STATUS_UNAVAILABLE=0, + HAL_STATUS_AVAILABLE=1, +}; + +// Structure to store specific hal (controller or external) data +struct SpecificHalData { + char *name; + enum HalStatus status; + char *sndCard; + uint8_t internal; + + char *author; + char *version; + char *date; + + // Can be beefed up if needed + + afb_dynapi *apiHandle; // Can be NULL if external api + CtlConfigT *ctrlConfig; // Can be NULL if external api + + struct SpecificHalData *next; +}; + +// Structure to store hal manager data +struct HalMgrData { + char *name; + char *description; + + afb_dynapi *apiHandle; + + struct SpecificHalData *first; +}; + +// Exported verbs for 'struct SpecificHalData' handling +struct SpecificHalData *HalUtlAddHalApiToHalList(struct HalMgrData *HalMgrGlobalData); +uint8_t HalUtlRemoveSelectedHalFromList(struct HalMgrData *HalMgrGlobalData, struct SpecificHalData *ApiToRemove); +uint64_t HalUtlRemoveAllHalFromList(struct HalMgrData *HalMgrGlobalData); +uint64_t HalUtlGetNumberOfHalInList(struct HalMgrData *HalMgrGlobalData); +struct SpecificHalData *HalUtlSearchHalDataByApiName(struct HalMgrData *HalMgrGlobalData, char *name); + +// Exported verbs for 'struct HalMgrData' handling +uint8_t HalUtlInitializeHalMgrData(afb_dynapi *apiHandle, struct HalMgrData *HalMgrGlobalData, char *name, char *description); +void HalUtlRemoveHalMgrData(struct HalMgrData *HalMgrGlobalData); + +#endif /* _HAL_UTILITIES_DATA_INCLUDE_ */ \ No newline at end of file diff --git a/4a-hal/4a-hal-utilities/4a-hal-utilities-verbs-loader.c b/4a-hal/4a-hal-utilities/4a-hal-utilities-verbs-loader.c new file mode 100644 index 0000000..97c8df7 --- /dev/null +++ b/4a-hal/4a-hal-utilities/4a-hal-utilities-verbs-loader.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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 "4a-hal-utilities-verbs-loader.h" + +/******************************************************************************* + * Dynamic API common functions * + * TODO JAI : Use API-V3 instead of API-PRE-V3 * + ******************************************************************************/ + +int HalUtlLoadStaticVerbs(afb_dynapi *apiHandle, struct HalUtlApiVerb *verbs) +{ + int idx, errCount = 0; + + if(! apiHandle || ! verbs) + return -1; + + for (idx = 0; verbs[idx].verb; idx++) { + errCount+= afb_dynapi_add_verb(apiHandle, + verbs[idx].verb, + NULL, + verbs[idx].callback, + (void*) &verbs[idx], + verbs[idx].auth, + 0); + } + + return errCount; +}; \ No newline at end of file diff --git a/4a-hal/4a-hal-utilities/4a-hal-utilities-verbs-loader.h b/4a-hal/4a-hal-utilities/4a-hal-utilities-verbs-loader.h new file mode 100644 index 0000000..7accd80 --- /dev/null +++ b/4a-hal/4a-hal-utilities/4a-hal-utilities-verbs-loader.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Jonathan Aillet + * + * 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. + */ + +#ifndef _HAL_UTILITIES_VERBS_LOADER_INCLUDE_ +#define _HAL_UTILITIES_VERBS_LOADER_INCLUDE_ + +#include + +#define AFB_BINDING_VERSION dyn +#include + +// Structure to store data necessary to add a verb to a dynamic api +struct HalUtlApiVerb { + const char *verb; /* name of the verb, NULL only at end of the array */ + void (*callback)(afb_request *req); /* callback function implementing the verb */ + const struct afb_auth *auth; /* required authorisation, can be NULL */ + const char *info; /* some info about the verb, can be NULL */ + uint32_t session; +}; + +// Verb that allows to add verb to a dynamic api +int HalUtlLoadStaticVerbs(afb_dynapi *apiHandle, struct HalUtlApiVerb *verbs); + +#endif /* _HAL_UTILITIES_VERBS_LOADER_INCLUDE_ */ \ No newline at end of file -- cgit 1.2.3-korg