summaryrefslogtreecommitdiffstats
path: root/lib/4a-hal-utilities
diff options
context:
space:
mode:
Diffstat (limited to 'lib/4a-hal-utilities')
-rw-r--r--lib/4a-hal-utilities/4a-hal-utilities-alsa-data.c51
-rw-r--r--lib/4a-hal-utilities/4a-hal-utilities-alsa-data.h74
-rw-r--r--lib/4a-hal-utilities/4a-hal-utilities-data.c344
-rw-r--r--lib/4a-hal-utilities/4a-hal-utilities-data.h116
-rw-r--r--lib/4a-hal-utilities/4a-hal-utilities-hal-streams-handler.c355
-rw-r--r--lib/4a-hal-utilities/4a-hal-utilities-hal-streams-handler.h51
-rw-r--r--lib/4a-hal-utilities/4a-hal-utilities-verbs-loader.c50
-rw-r--r--lib/4a-hal-utilities/4a-hal-utilities-verbs-loader.h28
-rw-r--r--lib/4a-hal-utilities/CMakeLists.txt33
9 files changed, 1102 insertions, 0 deletions
diff --git a/lib/4a-hal-utilities/4a-hal-utilities-alsa-data.c b/lib/4a-hal-utilities/4a-hal-utilities-alsa-data.c
new file mode 100644
index 0000000..6409253
--- /dev/null
+++ b/lib/4a-hal-utilities/4a-hal-utilities-alsa-data.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 "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 <afb/afb-binding.h>
+
+#include "4a-hal-utilities-alsa-data.h"
+
+/*******************************************************************************
+ * Free contents of 'InternalHalAlsaMapT' data structure *
+ ******************************************************************************/
+
+uint8_t HalUtlFreeAlsaCtlsMap(struct InternalHalAlsaMapT *alsaCtlsMap)
+{
+ int idx;
+
+ if(! alsaCtlsMap)
+ return -1;
+
+ if(alsaCtlsMap->ctlsCount > 0 && ! alsaCtlsMap->ctls)
+ return -2;
+
+ for(idx = 0; idx < alsaCtlsMap->ctlsCount; idx++) {
+ free(alsaCtlsMap->ctls[idx].action);
+ free(alsaCtlsMap->ctls[idx].ctl.alsaCtlProperties.enums);
+ free(alsaCtlsMap->ctls[idx].ctl.alsaCtlProperties.dbscale);
+ }
+
+ free(alsaCtlsMap->ctls);
+
+ free(alsaCtlsMap);
+
+ return 0;
+} \ No newline at end of file
diff --git a/lib/4a-hal-utilities/4a-hal-utilities-alsa-data.h b/lib/4a-hal-utilities/4a-hal-utilities-alsa-data.h
new file mode 100644
index 0000000..fe70210
--- /dev/null
+++ b/lib/4a-hal-utilities/4a-hal-utilities-alsa-data.h
@@ -0,0 +1,74 @@
+/*
+* Copyright (C) 2019 "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.
+*/
+
+#ifndef _HAL_UTILITIES_ALSA_DATA_INCLUDE_
+#define _HAL_UTILITIES_ALSA_DATA_INCLUDE_
+
+#include <stdio.h>
+
+#include <json-c/json.h>
+
+#include <alsa/asoundlib.h>
+
+#include <afb/afb-binding.h>
+
+#include <ctl-config.h>
+
+struct InternalHalAlsaDBScale {
+ int min;
+ int max;
+ int step;
+ int mute;
+};
+
+struct InternalHalAlsaCtlProperties {
+ snd_ctl_elem_type_t type;
+ int count;
+ int minval;
+ int maxval;
+ int step;
+ // TBD JAI : use them
+ const char **enums;
+ struct InternalHalAlsaDBScale *dbscale;
+};
+
+struct InternalHalAlsaCtl {
+ char *name;
+ int numid;
+ int value;
+ struct InternalHalAlsaCtlProperties alsaCtlProperties;
+ struct InternalHalAlsaCtlProperties *alsaCtlCreation;
+};
+
+struct InternalHalAlsaMap {
+ const char *uid;
+ char *info;
+ afb_event_t alsaControlEvent;
+ struct InternalHalAlsaCtl ctl;
+ json_object *actionJ;
+ CtlActionT *action;
+};
+
+struct InternalHalAlsaMapT {
+ struct InternalHalAlsaMap *ctls;
+ unsigned int ctlsCount;
+};
+
+// Free contents of 'CtlHalAlsaMapT' data structure
+uint8_t HalUtlFreeAlsaCtlsMap(struct InternalHalAlsaMapT *alsaCtlsMap);
+
+#endif /* _HAL_UTILITIES_ALSA_DATA_INCLUDE_ */ \ No newline at end of file
diff --git a/lib/4a-hal-utilities/4a-hal-utilities-data.c b/lib/4a-hal-utilities/4a-hal-utilities-data.c
new file mode 100644
index 0000000..314190f
--- /dev/null
+++ b/lib/4a-hal-utilities/4a-hal-utilities-data.c
@@ -0,0 +1,344 @@
+/*
+ * 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 <wrap-json.h>
+
+#include <afb/afb-binding.h>
+
+#include "4a-hal-utilities-data.h"
+#include "4a-hal-utilities-alsa-data.h"
+
+/*******************************************************************************
+ * Internal Hal - Streams data handling functions *
+ ******************************************************************************/
+
+struct InternalHalMixerData *HalUtlAddMixerDataToMixerDataList(struct InternalHalMixerData **mixerDataList)
+{
+ struct InternalHalMixerData *currentMixerData;
+
+ if(! mixerDataList)
+ return NULL;
+
+ currentMixerData = *mixerDataList;
+ if(! currentMixerData) {
+ currentMixerData = (struct InternalHalMixerData *) calloc(1, sizeof(struct InternalHalMixerData));
+ if(! currentMixerData)
+ return NULL;
+
+ *mixerDataList = currentMixerData;
+ }
+ else {
+ while(currentMixerData->next)
+ currentMixerData = currentMixerData->next;
+
+ currentMixerData->next = calloc(1, sizeof(struct InternalHalMixerData));
+ if(! currentMixerData->next)
+ return NULL;
+
+ currentMixerData = currentMixerData->next;
+ }
+
+ return currentMixerData;
+}
+
+int8_t HalUtlRemoveSelectedMixerData(struct InternalHalMixerData **mixerDataList, struct InternalHalMixerData *mixerDataToRemove)
+{
+ struct InternalHalMixerData *currentMixerData, *matchingMixerData;
+
+ if(! mixerDataList || ! *mixerDataList || ! mixerDataToRemove)
+ return -1;
+
+ currentMixerData = *mixerDataList;
+ if(currentMixerData == mixerDataToRemove) {
+ *mixerDataList = currentMixerData->next;
+ matchingMixerData = currentMixerData;
+ }
+ else {
+ while(currentMixerData && currentMixerData->next != mixerDataToRemove)
+ currentMixerData = currentMixerData->next;
+
+ if(currentMixerData) {
+ matchingMixerData = currentMixerData->next;
+ currentMixerData->next = currentMixerData->next->next;
+ }
+ else {
+ return -2;
+ }
+ }
+
+ free(matchingMixerData->verb);
+ free(matchingMixerData->verbToCall);
+ free(matchingMixerData->streamCardId);
+
+ free(matchingMixerData);
+
+ return 0;
+}
+
+int64_t HalUtlRemoveAllMixerData(struct InternalHalMixerData **mixerDataList)
+{
+ int8_t ret;
+ int64_t mixerDataRemoved = 0;
+
+ if(! mixerDataList)
+ return -1;
+
+ while(*mixerDataList) {
+ ret = HalUtlRemoveSelectedMixerData(mixerDataList, *mixerDataList);
+ if(ret)
+ return (int64_t) ret;
+
+ mixerDataRemoved++;
+ }
+
+ return mixerDataRemoved;
+}
+
+int64_t HalUtlGetNumberOfMixerDataInList(struct InternalHalMixerData **mixerDataList)
+{
+ int64_t numberOfMixerData = 0;
+ struct InternalHalMixerData *currentMixerData;
+
+ if(! mixerDataList)
+ return -1;
+
+ currentMixerData = *mixerDataList;
+ while(currentMixerData) {
+ currentMixerData = currentMixerData->next;
+ numberOfMixerData++;
+ }
+
+ return numberOfMixerData;
+}
+
+struct InternalHalMixerData *HalUtlSearchMixerDataByProperties(struct InternalHalMixerData **mixerDataList, char *verb, char *verbToCall, char *streamCardId)
+{
+ struct InternalHalMixerData *currentMixerData;
+
+ if(! mixerDataList || ! verb)
+ return NULL;
+
+ currentMixerData = *mixerDataList;
+
+ while(currentMixerData) {
+ if((! strcmp(verb, currentMixerData->verb)) &&
+ (! strcmp(verbToCall, currentMixerData->verbToCall)) &&
+ (! strcmp(streamCardId, currentMixerData->streamCardId)))
+ return currentMixerData;
+
+ currentMixerData = currentMixerData->next;
+ }
+
+ return NULL;
+}
+
+/*******************************************************************************
+ * Hal data handling functions *
+ ******************************************************************************/
+
+struct HalData *HalUtlAddHalToHalList(struct HalData **halDataList)
+{
+ struct HalData *currentHalData;
+
+ if(! halDataList)
+ return NULL;
+
+ currentHalData = *halDataList;
+ if(! currentHalData) {
+ currentHalData = (struct HalData *) calloc(1, sizeof(struct HalData));
+ if(! currentHalData)
+ return NULL;
+
+ *halDataList = currentHalData;
+ }
+ else {
+ while(currentHalData->next)
+ currentHalData = currentHalData->next;
+
+ currentHalData->next = calloc(1, sizeof(struct HalData));
+ if(! currentHalData->next)
+ return NULL;
+
+ currentHalData = currentHalData->next;
+ }
+
+ return currentHalData;
+}
+
+int8_t HalUtlRemoveSelectedHalFromList(struct HalData **halDataList, struct HalData *halToRemove)
+{
+ struct HalData *currentHalData, *matchingHal;
+
+ if(! halDataList || ! *halDataList || ! halToRemove)
+ return -1;
+
+ currentHalData = *halDataList;
+ if(currentHalData == halToRemove) {
+ *halDataList = currentHalData->next;
+ matchingHal = currentHalData;
+ }
+ else {
+ while(currentHalData && currentHalData->next != halToRemove)
+ currentHalData = currentHalData->next;
+
+ if(currentHalData) {
+ matchingHal = currentHalData->next;
+ currentHalData->next = currentHalData->next->next;
+ }
+ else {
+ return -2;
+ }
+ }
+
+ free(matchingHal->apiName);
+ free(matchingHal->sndCardPath);
+ free(matchingHal->info);
+ free(matchingHal->author);
+ free(matchingHal->version);
+ free(matchingHal->date);
+
+ if(matchingHal->internal) {
+ HalUtlRemoveAllMixerData(&matchingHal->internalHalData->streamsData);
+ HalUtlRemoveAllMixerData(&matchingHal->internalHalData->playbacksData);
+ HalUtlRemoveAllMixerData(&matchingHal->internalHalData->capturesData);
+
+ HalUtlFreeAlsaCtlsMap(matchingHal->internalHalData->alsaMapT);
+
+ free(matchingHal->internalHalData);
+ }
+
+ free(matchingHal);
+
+ return 0;
+}
+
+int64_t HalUtlRemoveAllHalFromList(struct HalData **halDataList)
+{
+ int8_t ret;
+ int64_t halRemoved = 0;
+
+ if(! halDataList)
+ return -1;
+
+ while(*halDataList) {
+ ret = HalUtlRemoveSelectedHalFromList(halDataList, *halDataList);
+ if(ret)
+ return (int64_t) ret;
+
+ halRemoved++;
+ }
+
+ return halRemoved;
+}
+
+int64_t HalUtlGetNumberOfHalInList(struct HalData **halDataList)
+{
+ int64_t numberOfHal = 0;
+ struct HalData *currentHalData;
+
+ if(! halDataList)
+ return -1;
+
+ currentHalData = *halDataList;
+
+ while(currentHalData) {
+ currentHalData = currentHalData->next;
+ numberOfHal++;
+ }
+
+ return numberOfHal;
+}
+
+struct HalData *HalUtlSearchHalDataByApiName(struct HalData **halDataList, char *apiName)
+{
+ struct HalData *currentHalData;
+
+ if(! halDataList || ! *halDataList || ! apiName)
+ return NULL;
+
+ currentHalData = *halDataList;
+
+ while(currentHalData) {
+ if(! strcmp(apiName, currentHalData->apiName))
+ return currentHalData;
+
+ currentHalData = currentHalData->next;
+ }
+
+ return NULL;
+}
+
+struct HalData *HalUtlSearchReadyHalDataByCardId(struct HalData **halDataList, int cardId)
+{
+ struct HalData *currentHalData;
+
+ if(! halDataList || ! *halDataList)
+ return NULL;
+
+ currentHalData = *halDataList;
+
+ while(currentHalData) {
+ if(currentHalData->status == HAL_STATUS_READY && currentHalData->sndCardId == cardId)
+ return currentHalData;
+
+ currentHalData = currentHalData->next;
+ }
+
+ return NULL;
+}
+
+/*******************************************************************************
+ * Hal Manager data handling functions *
+ ******************************************************************************/
+
+uint8_t HalUtlInitializeHalMgrData(afb_api_t apiHandle, struct HalMgrData *halMgrData, char *apiName, char *info)
+{
+ if(! apiHandle || ! halMgrData || ! apiName || ! info)
+ return -1;
+
+ // Allocate and fill apiName and info strings
+ halMgrData->apiName = strdup(apiName);
+ if(! halMgrData->apiName)
+ return -2;
+
+ halMgrData->info = strdup(info);
+ if(! halMgrData->info)
+ return -3;
+
+ halMgrData->apiHandle = apiHandle;
+
+ return 0;
+}
+
+void HalUtlRemoveHalMgrData(struct HalMgrData *halMgrData)
+{
+ if(! halMgrData)
+ return;
+
+ if(halMgrData->halDataList)
+ HalUtlRemoveAllHalFromList(&halMgrData->halDataList);
+
+ free(halMgrData->apiName);
+ free(halMgrData->info);
+
+ free(halMgrData);
+} \ No newline at end of file
diff --git a/lib/4a-hal-utilities/4a-hal-utilities-data.h b/lib/4a-hal-utilities/4a-hal-utilities-data.h
new file mode 100644
index 0000000..f3de1a6
--- /dev/null
+++ b/lib/4a-hal-utilities/4a-hal-utilities-data.h
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+#ifndef _HAL_UTILITIES_DATA_INCLUDE_
+#define _HAL_UTILITIES_DATA_INCLUDE_
+
+#include <stdio.h>
+
+#include <wrap-json.h>
+
+#include <afb/afb-binding.h>
+
+#include <ctl-config.h>
+
+#include "4a-hal-utilities-alsa-data.h"
+
+#define HAL_STREAM_UPDATES_EVENT_NAME "stream-updates"
+
+// Enum for hal status
+enum HalStatus {
+ HAL_STATUS_UNAVAILABLE=0,
+ HAL_STATUS_AVAILABLE=1,
+ HAL_STATUS_READY=2
+};
+
+// Structure to store stream data
+struct InternalHalMixerData {
+ char *verb;
+ char *verbToCall;
+ char *streamCardId;
+ afb_event_t event;
+
+ struct InternalHalMixerData *next;
+};
+
+// Structure to store specific internal hal data
+struct InternalHalData {
+ char *mixerApiName;
+ char *prefix;
+ json_object *halMixerJ;
+
+ struct InternalHalMixerData *streamsData;
+ afb_event_t streamUpdates;
+
+ struct InternalHalMixerData *playbacksData;
+ struct InternalHalMixerData *capturesData;
+
+ struct InternalHalAlsaMapT *alsaMapT;
+
+ afb_api_t apiHandle;
+ CtlConfigT *ctrlConfig;
+};
+
+// Structure to store specific hal (internal or external) data
+struct HalData {
+ char *apiName;
+ enum HalStatus status;
+ char *sndCardPath;
+ int sndCardId;
+ char *info;
+ unsigned int internal;
+
+ char *author;
+ char *version;
+ char *date;
+ // Can be beefed up if needed
+
+ struct InternalHalData *internalHalData; // Can be NULL if external api
+
+ struct HalData *next;
+};
+
+// Structure to store hal manager data
+struct HalMgrData {
+ char *apiName;
+ char *info;
+
+ afb_api_t apiHandle;
+
+ struct HalData *halDataList;
+};
+
+// Internal Hal - Streams data handling functions
+struct InternalHalMixerData *HalUtlAddMixerDataToMixerDataList(struct InternalHalMixerData **mixerDataList);
+int8_t HalUtlRemoveSelectedMixerData(struct InternalHalMixerData **mixerDataList, struct InternalHalMixerData *mixerDataToRemove);
+int64_t HalUtlRemoveAllMixerData(struct InternalHalMixerData **mixerDataList);
+int64_t HalUtlGetNumberOfMixerDataInList(struct InternalHalMixerData **mixerDataList);
+struct InternalHalMixerData *HalUtlSearchMixerDataByProperties(struct InternalHalMixerData **mixerDataList, char *verb, char *verbToCall, char *streamCardId);
+
+// Hal data handling functions
+struct HalData *HalUtlAddHalToHalList(struct HalData **halDataList);
+int8_t HalUtlRemoveSelectedHalFromList(struct HalData **halDataList, struct HalData *halToRemove);
+int64_t HalUtlRemoveAllHalFromList(struct HalData **halDataList);
+int64_t HalUtlGetNumberOfHalInList(struct HalData **halDataList);
+struct HalData *HalUtlSearchHalDataByApiName(struct HalData **halDataList, char *apiName);
+struct HalData *HalUtlSearchReadyHalDataByCardId(struct HalData **halDataList, int cardId);
+
+// Hal Manager data handling functions
+uint8_t HalUtlInitializeHalMgrData(afb_api_t apiHandle, struct HalMgrData *halMgrData, char *apiName, char *info);
+void HalUtlRemoveHalMgrData(struct HalMgrData *halMgrData);
+
+#endif /* _HAL_UTILITIES_DATA_INCLUDE_ */ \ No newline at end of file
diff --git a/lib/4a-hal-utilities/4a-hal-utilities-hal-streams-handler.c b/lib/4a-hal-utilities/4a-hal-utilities-hal-streams-handler.c
new file mode 100644
index 0000000..ed06b27
--- /dev/null
+++ b/lib/4a-hal-utilities/4a-hal-utilities-hal-streams-handler.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2019 "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 <json-c/json.h>
+
+#include <afb/afb-binding.h>
+
+#include <ctl-config.h>
+
+#include "4a-hal-utilities-data.h"
+#include "4a-hal-utilities-hal-streams-handler.h"
+
+/*******************************************************************************
+ * Actions to be call when a stream verb is called *
+ ******************************************************************************/
+
+void HalUtlActionOnMixer(afb_req_t request, enum ActionOnMixerType actionType)
+{
+ int idx, count;
+
+ char *apiToCall, *returnedError = NULL, *returnedInfo = NULL;
+
+ afb_api_t apiHandle;
+ CtlConfigT *ctrlConfig;
+
+ struct HalData *currentHalData;
+ struct InternalHalMixerData *currentMixerData = NULL;
+
+ json_object *requestJson, *responseJ = NULL, *toReturnJ = NULL;
+
+ if(! (apiHandle = afb_req_get_api(request))) {
+ afb_req_fail(request, "api_handle", "Can't get current hal controller api handle");
+ return;
+ }
+
+ if(! (ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle))) {
+ afb_req_fail(request, "hal_controller_config", "Can't get current hal controller config");
+ return;
+ }
+
+ currentHalData = (struct HalData *) getExternalData(ctrlConfig);
+ if(! currentHalData) {
+ afb_req_fail(request, "hal_controller_data", "Can't get current hal controller data");
+ return;
+ }
+
+ if(! (requestJson = afb_req_json(request))) {
+ afb_req_fail(request, "request_json", "Can't get request json");
+ return;
+ }
+
+ if(json_object_is_type(requestJson, json_type_object) && json_object_get_object(requestJson)->count > 0)
+ json_object_object_add(requestJson, "verbose", json_object_new_boolean(1));
+
+ apiToCall = currentHalData->internalHalData->mixerApiName;
+ if(! apiToCall) {
+ afb_req_fail(request, "mixer_api", "Can't get mixer api");
+ return;
+ }
+
+ if(currentHalData->status != HAL_STATUS_READY) {
+ afb_req_fail(request, "hal_not_ready", "Seems that hal is not ready");
+ return;
+ }
+
+ currentMixerData = (struct InternalHalMixerData *) afb_req_get_vcbdata(request);
+ if(! currentMixerData) {
+ afb_req_fail(request, "hal_call_data", "Can't get current call data");
+ return;
+ }
+
+ switch(actionType) {
+ case ACTION_ON_MIXER_STREAM:
+ count = 1;
+ break;
+
+ case ACTION_ON_MIXER_PLAYBACK:
+ case ACTION_ON_MIXER_CAPTURE:
+ case ACTION_ON_MIXER_ALL_STREAM:
+ count = (int) HalUtlGetNumberOfMixerDataInList(&currentMixerData);
+ toReturnJ = json_object_new_object();
+ break;
+
+ default:
+ afb_req_fail(request, "mixer_action_type", "Action type is unknown");
+ return;
+ }
+
+ for(idx = 0; idx < count; idx++) {
+ if(afb_api_call_sync(apiHandle,
+ apiToCall,
+ currentMixerData->verbToCall,
+ json_object_get(requestJson),
+ &responseJ,
+ &returnedError,
+ &returnedInfo)) {
+ if(responseJ)
+ json_object_put(responseJ);
+ if(toReturnJ)
+ json_object_put(toReturnJ);
+ afb_req_fail_f(request,
+ "mixer_call",
+ "Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s' (call to mixer %i out of %i)",
+ currentMixerData->verbToCall,
+ apiToCall,
+ returnedError ? returnedError : "not returned",
+ returnedInfo ? returnedInfo : "not returned",
+ idx,
+ count);
+ free(returnedError);
+ free(returnedInfo);
+ return;
+ }
+
+ if(! responseJ) {
+ if(toReturnJ)
+ json_object_put(toReturnJ);
+ afb_req_fail_f(request,
+ "mixer_call",
+ "Seems that %s call to api %s succeed but no response was returned (call to mixer %i out of %i)",
+ currentMixerData->verbToCall,
+ apiToCall,
+ idx,
+ count);
+ free(returnedError);
+ free(returnedInfo);
+ return;
+ }
+
+ // TBD JAI : When mixer events will be available, use them instead of generating events at calls
+ if((actionType == ACTION_ON_MIXER_STREAM ||
+ actionType == ACTION_ON_MIXER_ALL_STREAM) &&
+ ((! currentMixerData->event) ||
+ (afb_event_push(currentMixerData->event, json_object_get(responseJ)) < 0))) {
+ AFB_API_ERROR(apiHandle, "Could not generate an event for stream %s", currentMixerData->verb);
+ }
+
+ switch(actionType) {
+ case ACTION_ON_MIXER_STREAM:
+ toReturnJ = responseJ;
+ break;
+
+ case ACTION_ON_MIXER_PLAYBACK:
+ case ACTION_ON_MIXER_CAPTURE:
+ json_object_object_add(toReturnJ, currentMixerData->verbToCall, responseJ);
+ currentMixerData = currentMixerData->next;
+ break;
+
+ case ACTION_ON_MIXER_ALL_STREAM:
+ json_object_object_add(toReturnJ, currentMixerData->verb, responseJ);
+ currentMixerData = currentMixerData->next;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ switch(actionType) {
+ case ACTION_ON_MIXER_STREAM:
+ afb_req_success_f(request,
+ toReturnJ,
+ "Action %s correctly transferred to %s without any error raised",
+ currentMixerData->verbToCall,
+ apiToCall);
+ break;
+
+ case ACTION_ON_MIXER_PLAYBACK:
+ afb_req_success(request,
+ toReturnJ,
+ "Actions correctly transferred to all playbacks without any error raised");
+ break;
+
+ case ACTION_ON_MIXER_CAPTURE:
+ afb_req_success(request,
+ toReturnJ,
+ "Actions correctly transferred to all captures without any error raised");
+ break;
+
+ case ACTION_ON_MIXER_ALL_STREAM:
+ afb_req_success(request,
+ toReturnJ,
+ "Actions correctly transferred to all streams without any error raised");
+ break;
+
+ default:
+ break;
+ }
+}
+
+void HalUtlActionOnStream(afb_req_t request)
+{
+ HalUtlActionOnMixer(request, ACTION_ON_MIXER_STREAM);
+}
+
+void HalUtlActionOnPlayback(afb_req_t request)
+{
+ HalUtlActionOnMixer(request, ACTION_ON_MIXER_PLAYBACK);
+}
+
+void HalUtlActionOnCapture(afb_req_t request)
+{
+ HalUtlActionOnMixer(request, ACTION_ON_MIXER_CAPTURE);
+}
+
+void HalUtlActionOnAllStream(afb_req_t request)
+{
+ HalUtlActionOnMixer(request, ACTION_ON_MIXER_ALL_STREAM);
+}
+
+/*******************************************************************************
+ * Add stream data and verb function *
+ ******************************************************************************/
+
+struct InternalHalMixerData *HalUtlAddStreamDataAndCreateStreamVerb(afb_api_t apiHandle,
+ char *verb,
+ char *verbToCall,
+ char *streamCardId)
+{
+ json_object *streamAddedEventJ;
+
+ CtlConfigT *ctrlConfig;
+
+ struct HalData *currentHalData;
+ struct InternalHalMixerData *createdStreamData;
+
+ if(! apiHandle || ! verb || ! verbToCall || ! streamCardId)
+ return NULL;
+
+ ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
+ if(! ctrlConfig)
+ return NULL;
+
+ currentHalData = (struct HalData *) getExternalData(ctrlConfig);
+ if(! currentHalData ||
+ ! currentHalData->internalHalData)
+ return NULL;
+
+ createdStreamData = HalUtlAddMixerDataToMixerDataList(&currentHalData->internalHalData->streamsData);
+ if(! createdStreamData)
+ return NULL;
+
+ createdStreamData->verb = strdup(verb);
+ createdStreamData->verbToCall = strdup(verbToCall);
+ createdStreamData->streamCardId = strdup(streamCardId);
+
+ if((! createdStreamData->verb) ||
+ (! createdStreamData->verbToCall) ||
+ (! createdStreamData->streamCardId)) {
+ HalUtlRemoveSelectedMixerData(&currentHalData->internalHalData->streamsData, createdStreamData);
+ return NULL;
+ }
+
+ if(! (createdStreamData->event = afb_api_make_event(apiHandle, createdStreamData->verb))) {
+ HalUtlRemoveSelectedMixerData(&currentHalData->internalHalData->streamsData, createdStreamData);
+ return NULL;
+ }
+
+ if(afb_api_add_verb(apiHandle,
+ createdStreamData->verb,
+ "Stream action transferred to mixer",
+ HalUtlActionOnStream,
+ (void *) createdStreamData,
+ NULL,
+ 0,
+ 0)) {
+ AFB_API_ERROR(apiHandle,"Error while creating verb for stream : '%s'", createdStreamData->verb);
+ HalUtlRemoveSelectedMixerData(&currentHalData->internalHalData->streamsData, createdStreamData);
+ return NULL;
+ }
+
+ wrap_json_pack(&streamAddedEventJ,
+ "{s:s, s:s, s:s}",
+ "action", "added",
+ "name", createdStreamData->verb,
+ "cardId", createdStreamData->streamCardId);
+
+ afb_event_push(currentHalData->internalHalData->streamUpdates, streamAddedEventJ);
+
+ return createdStreamData;
+}
+
+int8_t HalUtlRemoveStreamDataAndDeleteStreamVerb(afb_api_t apiHandle,
+ char *verb,
+ char *verbToCall,
+ char *streamCardId)
+{
+ int8_t returnedErr = 0;
+
+ json_object *streamRemovedEventJ;
+
+ CtlConfigT *ctrlConfig;
+
+ struct HalData *currentHalData;
+ struct InternalHalMixerData *toRemoveStreamData;
+
+ if(! apiHandle || ! verb || ! verbToCall || ! streamCardId)
+ return -1;
+
+ ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
+ if(! ctrlConfig)
+ return -2;
+
+ currentHalData = (struct HalData *) getExternalData(ctrlConfig);
+ if(! currentHalData ||
+ ! currentHalData->internalHalData)
+ return -3;
+
+ toRemoveStreamData = HalUtlSearchMixerDataByProperties(&currentHalData->internalHalData->streamsData,
+ verb,
+ verbToCall,
+ streamCardId);
+ if(! toRemoveStreamData)
+ return -4;
+
+ wrap_json_pack(&streamRemovedEventJ,
+ "{s:s, s:s, s:s}",
+ "action", "removed",
+ "name", toRemoveStreamData->verb,
+ "cardId", toRemoveStreamData->streamCardId);
+
+ if(afb_api_del_verb(apiHandle, verb, NULL)) {
+ AFB_API_ERROR(apiHandle,"Error while deleting verb for stream : '%s'", verb);
+ json_object_put(streamRemovedEventJ);
+ return -5;
+ }
+
+ returnedErr = HalUtlRemoveSelectedMixerData(&currentHalData->internalHalData->streamsData, toRemoveStreamData);
+ if(returnedErr) {
+ AFB_API_ERROR(apiHandle,"Error %i while removing data for stream : '%s'", returnedErr, verb);
+ json_object_put(streamRemovedEventJ);
+ return -6;
+ }
+
+ afb_event_push(currentHalData->internalHalData->streamUpdates, streamRemovedEventJ);
+
+ return 0;
+} \ No newline at end of file
diff --git a/lib/4a-hal-utilities/4a-hal-utilities-hal-streams-handler.h b/lib/4a-hal-utilities/4a-hal-utilities-hal-streams-handler.h
new file mode 100644
index 0000000..028dd1f
--- /dev/null
+++ b/lib/4a-hal-utilities/4a-hal-utilities-hal-streams-handler.h
@@ -0,0 +1,51 @@
+/*
+* Copyright (C) 2019 "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.
+*/
+
+#ifndef _HAL_UTILITIES_HAL_STREAMS_CREATION_INCLUDE_
+#define _HAL_UTILITIES_HAL_STREAMS_CREATION_INCLUDE_
+
+#include <stdio.h>
+
+#include <afb/afb-binding.h>
+
+#include <ctl-config.h>
+
+// Enum for the type of action on mixer
+enum ActionOnMixerType {
+ ACTION_ON_MIXER_STREAM = 1,
+ ACTION_ON_MIXER_PLAYBACK = 2,
+ ACTION_ON_MIXER_CAPTURE = 3,
+ ACTION_ON_MIXER_ALL_STREAM = 4
+};
+
+// Actions to be call when a stream verb is called
+void HalUtlActionOnStream(afb_req_t request);
+void HalUtlActionOnPlayback(afb_req_t request);
+void HalUtlActionOnCapture(afb_req_t request);
+void HalUtlActionOnAllStream(afb_req_t request);
+
+// Add/Remove stream data and verb functions
+struct InternalHalMixerData *HalUtlAddStreamDataAndCreateStreamVerb(afb_api_t apiHandle,
+ char *verb,
+ char *verbToCall,
+ char *streamCardId);
+int8_t HalUtlRemoveStreamDataAndDeleteStreamVerb(afb_api_t apiHandle,
+ char *verb,
+ char *verbToCall,
+ char *streamCardId);
+
+#endif /* _HAL_UTILITIES_HAL_STREAMS_CREATION_INCLUDE_ */ \ No newline at end of file
diff --git a/lib/4a-hal-utilities/4a-hal-utilities-verbs-loader.c b/lib/4a-hal-utilities/4a-hal-utilities-verbs-loader.c
new file mode 100644
index 0000000..16c28c4
--- /dev/null
+++ b/lib/4a-hal-utilities/4a-hal-utilities-verbs-loader.c
@@ -0,0 +1,50 @@
+/*
+ * 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 <afb/afb-binding.h>
+
+#include "4a-hal-utilities-verbs-loader.h"
+
+/*******************************************************************************
+ * Dynamic API common functions *
+ ******************************************************************************/
+
+int HalUtlLoadVerbs(afb_api_t apiHandle, afb_verb_t *verbs)
+{
+ int idx, errCount = 0;
+
+ if(! apiHandle || ! verbs)
+ return -1;
+
+ for (idx = 0; verbs[idx].verb; idx++) {
+ errCount+= afb_api_add_verb(apiHandle,
+ verbs[idx].verb,
+ NULL,
+ verbs[idx].callback,
+ (void *) &verbs[idx],
+ verbs[idx].auth,
+ 0,
+ 0);
+ }
+
+ return errCount;
+} \ No newline at end of file
diff --git a/lib/4a-hal-utilities/4a-hal-utilities-verbs-loader.h b/lib/4a-hal-utilities/4a-hal-utilities-verbs-loader.h
new file mode 100644
index 0000000..9084595
--- /dev/null
+++ b/lib/4a-hal-utilities/4a-hal-utilities-verbs-loader.h
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+#ifndef _HAL_UTILITIES_VERBS_LOADER_INCLUDE_
+#define _HAL_UTILITIES_VERBS_LOADER_INCLUDE_
+
+#include <stdio.h>
+
+#include <afb/afb-binding.h>
+
+// Verb that allows to add verb to a dynamic api
+int HalUtlLoadVerbs(afb_api_t apiHandle, afb_verb_t *verbs);
+
+#endif /* _HAL_UTILITIES_VERBS_LOADER_INCLUDE_ */ \ No newline at end of file
diff --git a/lib/4a-hal-utilities/CMakeLists.txt b/lib/4a-hal-utilities/CMakeLists.txt
new file mode 100644
index 0000000..d90dd11
--- /dev/null
+++ b/lib/4a-hal-utilities/CMakeLists.txt
@@ -0,0 +1,33 @@
+###########################################################################
+# Copyright 2015, 2016, 2017, 2018, 2019 IoT.bzh
+#
+# author: Fulup Ar Foll <fulup@iot.bzh>
+# contrib: 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.
+###########################################################################
+
+# Add target to project dependency list
+PROJECT_TARGET_ADD(4a-hal-utilities)
+
+ # Define project Targets
+ ADD_LIBRARY(${TARGET_NAME} STATIC
+ 4a-hal-utilities-alsa-data.c
+ 4a-hal-utilities-data.c
+ 4a-hal-utilities-hal-streams-handler.c
+ 4a-hal-utilities-verbs-loader.c)
+
+ # Define target includes for this target client
+ TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ )