aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--4a-hal-cfg-example/hal-4a-example.json2
-rw-r--r--lib/4a-hal-utilities/4a-hal-utilities-data.c81
-rw-r--r--lib/4a-hal-utilities/4a-hal-utilities-data.h17
-rw-r--r--lib/4a-hal-utilities/4a-hal-utilities-ping.c2
-rw-r--r--src/4a-hal-manager/4a-hal-manager-cb.c87
-rw-r--r--src/4a-hal-manager/4a-hal-manager-cb.h2
-rw-r--r--src/4a-hal-manager/4a-hal-manager.c19
-rw-r--r--src/4a-internals-hal/4a-internals-hal-alsacore-link.c320
-rw-r--r--src/4a-internals-hal/4a-internals-hal-alsacore-link.h47
-rw-r--r--src/4a-internals-hal/4a-internals-hal-api-loader.c90
-rw-r--r--src/4a-internals-hal/4a-internals-hal-api-loader.h2
-rw-r--r--src/4a-internals-hal/4a-internals-hal-cb.c1457
-rw-r--r--src/4a-internals-hal/4a-internals-hal-cb.h44
-rw-r--r--src/4a-internals-hal/4a-internals-hal-mixer-link.c96
-rw-r--r--src/4a-internals-hal/4a-internals-hal-mixer-link.h4
15 files changed, 1536 insertions, 734 deletions
diff --git a/4a-hal-cfg-example/hal-4a-example.json b/4a-hal-cfg-example/hal-4a-example.json
index 9314b7b..4b23a4f 100644
--- a/4a-hal-cfg-example/hal-4a-example.json
+++ b/4a-hal-cfg-example/hal-4a-example.json
@@ -87,7 +87,7 @@
"step": 1
}
},
- "action": "api://4a-hal-csl-cm106-8ch-usb#ping"
+ "action": "api://4a-hal-example#ping"
}
]
},
diff --git a/lib/4a-hal-utilities/4a-hal-utilities-data.c b/lib/4a-hal-utilities/4a-hal-utilities-data.c
index 6d1afd0..865bebb 100644
--- a/lib/4a-hal-utilities/4a-hal-utilities-data.c
+++ b/lib/4a-hal-utilities/4a-hal-utilities-data.c
@@ -313,6 +313,26 @@ int HalUtlGetNumberOfProbedDevicesInList(struct cds_list_head *probedDevicesList
return HalUtlGetNumberOfNodesInList(probedDevicesListHead);
}
+int HalUtlGetNumberOfDynamicProbedDevicesInList(struct cds_list_head *probedDevicesListHead)
+{
+ int numberOfDynamicProbedDevicesInList = 0;
+
+ struct InternalHalProbedDevice *currentProbedDevice;
+
+ if(! probedDevicesListHead)
+ return -1;
+
+ if(cds_list_empty(probedDevicesListHead))
+ return 0;
+
+ cds_list_for_each_entry(currentProbedDevice, probedDevicesListHead, node) {
+ if(currentProbedDevice->deviceClass == DYNAMIC_PROBED_DEVICE)
+ numberOfDynamicProbedDevicesInList++;
+ }
+
+ return numberOfDynamicProbedDevicesInList;
+}
+
struct InternalHalProbedDevice *HalUtlSearchProbedDeviceDataById(struct cds_list_head *probedDevicesListHead,
char *uid)
{
@@ -467,8 +487,9 @@ json_object *HalUtlGetCompactJsonForSpecificDependencies(afb_api_t apiHandle,
cardNb = requestedProbedDevice->deviceData->extendedCardNb;
wrapRet = wrap_json_pack(&requestedProbedDeviceJ,
- "{s:s s:s}",
+ "{s:s, s:b, s:s}",
"uid", requestedProbedDevice->uid,
+ "available", cardNb ? 1 : 0,
"cardNb", cardNb ? cardNb : "none");
if(wrapRet) {
AFB_API_ERROR(apiHandle,
@@ -771,6 +792,64 @@ json_object *HalUtlGetJsonArrayForAllDependencies(afb_api_t apiHandle,
return requestedDependenciesInfoJ;
}
+json_object *HalUtlGetJsonArrayForAllDependenciesInfoWithHandledDependency(afb_api_t apiHandle,
+ struct cds_list_head *probedDevicesListHead,
+ enum DependencyInfoJsonFormat jsonFormat,
+ char *handledProbedDeviceUid)
+{
+ int err;
+ size_t idx, dependencyNb;
+ char *currentDependencyObjectUidString = NULL;
+
+ json_object *requestedDependenciesInfoJ, *currentDependencyObject;
+
+ if(! apiHandle) {
+ AFB_API_ERROR(apiHandle, "Api handle is not valid");
+ return NULL;
+ }
+
+ if(! probedDevicesListHead) {
+ AFB_API_ERROR(apiHandle, "Probed device list is not valid");
+ return NULL;
+ }
+
+ if(cds_list_empty(probedDevicesListHead)) {
+ AFB_API_INFO(apiHandle, "Probed device list is empty");
+ return NULL;
+ }
+
+ if(! handledProbedDeviceUid) {
+ AFB_API_ERROR(apiHandle, "Probed device uid is not valid");
+ return NULL;
+ }
+
+ requestedDependenciesInfoJ = HalUtlGetJsonArrayForAllDependencies(apiHandle,
+ probedDevicesListHead,
+ jsonFormat);
+ if(! requestedDependenciesInfoJ) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed get all devices (dependencies) info");
+ return NULL;
+ }
+
+ dependencyNb = json_object_array_length(requestedDependenciesInfoJ);
+ for(idx = 0; idx < dependencyNb; idx++) {
+ currentDependencyObject = json_object_array_get_idx(requestedDependenciesInfoJ, idx);
+
+ err = wrap_json_unpack(currentDependencyObject, "{s:s}", "uid", &currentDependencyObjectUidString);
+ if(err) {
+ AFB_API_ERROR(apiHandle, "Dependency object is malformed (no uid key)");
+ return NULL;
+ }
+
+ if(! strcmp(handledProbedDeviceUid, currentDependencyObjectUidString))
+ json_object_object_add(currentDependencyObject, "handled", json_object_new_boolean(1));
+ else
+ json_object_object_add(currentDependencyObject, "handled", json_object_new_boolean(0));
+ }
+
+ return requestedDependenciesInfoJ;
+}
+
/*******************************************************************************
* Internal Hal - Streams data handling functions *
******************************************************************************/
diff --git a/lib/4a-hal-utilities/4a-hal-utilities-data.h b/lib/4a-hal-utilities/4a-hal-utilities-data.h
index a2b28dd..69ba747 100644
--- a/lib/4a-hal-utilities/4a-hal-utilities-data.h
+++ b/lib/4a-hal-utilities/4a-hal-utilities-data.h
@@ -56,6 +56,16 @@ enum ProbedDeviceClasses {
MANDATORY_PROBED_DEVICE = 3
};
+// Enum for dependencies mixer link status
+enum DependencyMixerStatus {
+ DEPENDENCY_NO_MIXER_LINK = 0,
+ DEPENDENCY_MIXER_LINK_USELESS = 1,
+ DEPENDENCY_MIXER_ATTACH_SUCCEED = 2,
+ DEPENDENCY_MIXER_ATTACH_FAILED = 3,
+ DEPENDENCY_MIXER_DETACH_SUCCEED = 4,
+ DEPENDENCY_MIXER_DETACH_FAILED = 5
+};
+
// Enum for probed devices (dependencies) info format requested
enum DependencyInfoJsonFormat {
DEPENDENCY_COMPACT_JSON = 0,
@@ -91,6 +101,7 @@ struct InternalHalProbedDevice {
json_object *requestedDeviceJ;
struct InternalHalDeviceData *deviceData;
+ enum DependencyMixerStatus mixerLinkStatus;
struct cds_list_head node;
};
@@ -153,11 +164,13 @@ struct HalMgrData {
// Internal Hal - Probed devices structure handling functions
enum ProbedDeviceClasses HalUtlGetProbedDeviceClassFromString(char *probedDeviceString);
char *HalUtlGetProbedDeviceClassString(enum ProbedDeviceClasses deviceClass);
+void HalUtlFreeSelectedProbedDeviceDataAllocation(struct InternalHalDeviceData *probedDeviceDataToFree);
struct InternalHalProbedDevice *HalUtlAddProbedDeviceToProbedDeviceList(struct cds_list_head *probedDevicesListHead);
int HalUtlRemoveSelectedProbedDeviceFromList(struct cds_list_head *probedDevicesListHead,
struct InternalHalProbedDevice *probedDeviceToRemove);
int HalUtlRemoveAllProbedDevicesFromList(struct cds_list_head *probedDevicesListHead);
int HalUtlGetNumberOfProbedDevicesInList(struct cds_list_head *probedDevicesListHead);
+int HalUtlGetNumberOfDynamicProbedDevicesInList(struct cds_list_head *probedDevicesListHead);
struct InternalHalProbedDevice *HalUtlSearchProbedDeviceDataById(struct cds_list_head *probedDevicesListHead,
char *uid);
int HalUtlGetProbedDeviceCardNbUsingUid(struct cds_list_head *probedDevicesListHead, char *uid);
@@ -175,6 +188,10 @@ json_object *HalUtlGetJsonArrayForAvailableDependencies(afb_api_t apiHandle,
json_object *HalUtlGetJsonArrayForAllDependencies(afb_api_t apiHandle,
struct cds_list_head *probedDevicesListHead,
enum DependencyInfoJsonFormat jsonFormat);
+json_object *HalUtlGetJsonArrayForAllDependenciesInfoWithHandledDependency(afb_api_t apiHandle,
+ struct cds_list_head *probedDevicesListHead,
+ enum DependencyInfoJsonFormat jsonFormat,
+ char *handledProbedDeviceUid);
// Internal Hal - Streams data handling functions
struct InternalHalMixerData *HalUtlAddMixerDataToMixerDataList(struct cds_list_head *mixerDataListHead);
diff --git a/lib/4a-hal-utilities/4a-hal-utilities-ping.c b/lib/4a-hal-utilities/4a-hal-utilities-ping.c
index a40254f..4a3fc25 100644
--- a/lib/4a-hal-utilities/4a-hal-utilities-ping.c
+++ b/lib/4a-hal-utilities/4a-hal-utilities-ping.c
@@ -47,6 +47,4 @@ void HalUtlPing(afb_req_t request)
}
afb_req_success(request, countJ, "Ping count");
-
- return;
} \ No newline at end of file
diff --git a/src/4a-hal-manager/4a-hal-manager-cb.c b/src/4a-hal-manager/4a-hal-manager-cb.c
index 771ff50..67f46a9 100644
--- a/src/4a-hal-manager/4a-hal-manager-cb.c
+++ b/src/4a-hal-manager/4a-hal-manager-cb.c
@@ -26,6 +26,8 @@
#include "4a-hal-utilities-data.h"
+#include "../4a-internals-hal/4a-internals-hal-cb.h"
+
#include "4a-hal-manager-cb.h"
/*******************************************************************************
@@ -127,6 +129,91 @@ void HalMgrLoaded(afb_req_t request)
afb_req_success(request, requestAnswer, "Requested data");
}
+void HalMgrInfo(afb_req_t request)
+{
+ int err, wrapRet = 0;
+
+ afb_api_t apiHandle;
+ struct HalMgrData *halMgrData;
+ struct HalData *currentHalData;
+
+ json_object *requestJson, *toReturnJ, *returnedInfoJ, *transferredJson = NULL;
+
+ apiHandle = afb_req_get_api(request);
+ if(! apiHandle) {
+ afb_req_fail(request, "api_handle", "Can't get hal manager api handle");
+ return;
+ }
+
+ halMgrData = (struct HalMgrData *) afb_api_get_userdata(apiHandle);
+ if(! halMgrData) {
+ afb_req_fail(request, "hal_manager_data", "Can't get hal manager data");
+ return;
+ }
+
+ if(cds_list_empty(&halMgrData->halDataListHead)) {
+ afb_req_success(request, NULL, "No Hal Api loaded");
+ return;
+ }
+
+ requestJson = afb_req_json(request);
+ if(! requestJson) {
+ AFB_REQ_NOTICE(request, "Can't get request json, will use default verbose");
+ wrapRet = wrap_json_pack(&transferredJson, "{s:i}", "verbose", 0);
+ if(wrapRet) {
+ afb_req_fail(request, "json_request", "Didn't succeed to generate default json request");
+ return;
+ }
+ }
+ else {
+ AFB_REQ_DEBUG(request,
+ "Received request json ('%s') will be transferred to each hal 'info' verb",
+ json_object_get_string(requestJson));
+ transferredJson = requestJson;
+ }
+
+ toReturnJ = json_object_new_array();
+ if(! toReturnJ) {
+ afb_req_fail(request,
+ "response_json_array",
+ "Didn't succeed to allocate response json array");
+ if(! requestJson)
+ json_object_put(transferredJson);
+ return;
+ }
+
+ cds_list_for_each_entry(currentHalData, &halMgrData->halDataListHead, node) {
+ if(! currentHalData->internalHalData) {
+ AFB_REQ_INFO(request,
+ "'%s' hal is an external hal, will not be able to get info about it",
+ currentHalData->apiName);
+ continue;
+ }
+
+ err = GenerateInternalHalInfoJson(apiHandle,
+ currentHalData,
+ transferredJson,
+ &returnedInfoJ);
+ if(err){
+ AFB_REQ_INFO(request,
+ "Error %i happened when tried to generate hal '%s' information json",
+ err,
+ currentHalData->apiName);
+ json_object_put(toReturnJ);
+ if(! requestJson)
+ json_object_put(transferredJson);
+ return;
+ }
+
+ json_object_array_add(toReturnJ, returnedInfoJ);
+ }
+
+ if(! requestJson)
+ json_object_put(transferredJson);
+
+ afb_req_success(request, toReturnJ, "Requested data");
+}
+
void HalMgrLoad(afb_req_t request)
{
char *apiName, *uid, *info = NULL, *author = NULL, *version = NULL, *date = NULL;
diff --git a/src/4a-hal-manager/4a-hal-manager-cb.h b/src/4a-hal-manager/4a-hal-manager-cb.h
index e0e144f..d35f83e 100644
--- a/src/4a-hal-manager/4a-hal-manager-cb.h
+++ b/src/4a-hal-manager/4a-hal-manager-cb.h
@@ -26,8 +26,8 @@
void HalMgrDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json_object *eventJ);
// Exported verbs callbacks
-void HalMgrPing(afb_req_t request);
void HalMgrLoaded(afb_req_t request);
+void HalMgrInfo(afb_req_t request);
void HalMgrLoad(afb_req_t request);
void HalMgrUnload(afb_req_t request);
void HalMgrSubscribeEvent(afb_req_t request);
diff --git a/src/4a-hal-manager/4a-hal-manager.c b/src/4a-hal-manager/4a-hal-manager.c
index da33db8..e21b948 100644
--- a/src/4a-hal-manager/4a-hal-manager.c
+++ b/src/4a-hal-manager/4a-hal-manager.c
@@ -41,6 +41,7 @@ afb_verb_t HalManagerApiStaticVerbs[] =
/* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */
{ .verb = "ping", .callback = HalUtlPing, .info = "Ping for test"},
{ .verb = "loaded", .callback = HalMgrLoaded, .info = "Show loaded HAL"},
+ { .verb = "info", .callback = HalMgrInfo, .info = "List available dependencies/controls/streams for all hals"},
{ .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"},
@@ -78,30 +79,26 @@ static int HalMgrInitApi(afb_api_t apiHandle)
if(afb_api_require_api(apiHandle, currentHalData->apiName, 1) ||
currentHalData->status == HAL_STATUS_INIT_FAILED) {
- AFB_API_ERROR(apiHandle,
- "Error caught during '%s' api initialization, this api won't be reachable",
- currentHalData->apiName);
+ AFB_API_INFO(apiHandle,
+ "Error caught during '%s' api initialization, this api won't be reachable",
+ currentHalData->apiName);
toDeleteApiName = strdup(currentHalData->apiName);
if(! toDeleteApiName) {
AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'apiName' string");
- return -5;
+ return -4;
}
- err = HalUtlRemoveHalDataAndDeleteHalApi(apiHandle, currentHalData, &halMgrData->halDataListHead);
+ err = InternalHalDeleteApi(apiHandle, &halMgrData->halDataListHead, currentHalData);
if(err) {
AFB_API_ERROR(apiHandle,
- "Error %i happened while trying to delete '%s' api and to remove all its data",
+ "Error %i happened when tried to delete %s api",
err,
toDeleteApiName);
free(toDeleteApiName);
- return -6;
+ return -5;
}
- AFB_API_ERROR(apiHandle,
- "Api '%s' and all its data has been deleted",
- toDeleteApiName);
-
free(toDeleteApiName);
}
}
diff --git a/src/4a-internals-hal/4a-internals-hal-alsacore-link.c b/src/4a-internals-hal/4a-internals-hal-alsacore-link.c
index bb1c4c9..353383e 100644
--- a/src/4a-internals-hal/4a-internals-hal-alsacore-link.c
+++ b/src/4a-internals-hal/4a-internals-hal-alsacore-link.c
@@ -66,6 +66,177 @@ snd_ctl_elem_type_t InternalHalMapsAlsaTypeToEnum(const char *label)
}
/*******************************************************************************
+ * Internals HAL - Alsacore events handler function *
+ ******************************************************************************/
+
+enum aslacoreEventType InternalHalGetAlsaCoreEventType(const char *evtLabel)
+{
+ if(! evtLabel)
+ return ALSACORE_UNRECOGNIZED_EVENT;
+
+ if(! strncmp(&evtLabel[ALSACORE_EVENT_NAME_BEGIN],
+ ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX,
+ ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX_LENGTH))
+ return ALSACORE_EVENT_CARD_CONTROL_CHANGE;
+
+ return ALSACORE_UNRECOGNIZED_EVENT;
+}
+
+int InternalHalHandleAlsaCoreCardControlEvent(afb_api_t apiHandle,
+ const char *evtLabel,
+ json_object *eventJ,
+ struct HalData *currentHalData)
+{
+ int numid, cardidx, controlsUsingCardCount = 0, controlUsedCount = 0;
+
+ char cardNbString[6];
+
+ json_object *valuesJ, *normalizedValuesJ;
+
+ CtlSourceT source;
+
+ struct InternalHalAlsaMap *currentHalMapControl;
+
+ if(! apiHandle || ! evtLabel || ! eventJ || ! currentHalData) {
+ AFB_API_ERROR(apiHandle, "Invalid argument(s)");
+ return -1;
+ }
+
+ if(sscanf(&evtLabel[ALSACORE_CARD_CONTROL_EVENT_BEGIN], "%d", &cardidx) != 1) {
+ AFB_API_ERROR(apiHandle,
+ "Did not succeed to get ALSA card number of the modified control : evtname=%s [msg=%s]",
+ evtLabel,
+ json_object_get_string(eventJ));
+ return -2;
+ }
+
+ if(wrap_json_unpack(eventJ, "{s:i s:o}", "id", &numid, "val", &valuesJ)) {
+ AFB_API_ERROR(apiHandle,
+ "Invalid alsacore modified control event received label=%s value=%s",
+ evtLabel,
+ json_object_get_string(eventJ));
+ return -3;
+ }
+
+ if(cds_list_empty(&currentHalData->internalHalData->halMapListHead)) {
+ AFB_API_ERROR(apiHandle,
+ "No halmap data is available, cannot handle alsacore event label=%s value=%s",
+ evtLabel,
+ json_object_get_string(eventJ));
+ return -4;
+ }
+
+ // Search for corresponding numid in ALSA controls list, if found, launch callback (if available)
+ cds_list_for_each_entry(currentHalMapControl, &currentHalData->internalHalData->halMapListHead, node) {
+ if(currentHalMapControl->cardNb == cardidx)
+ controlsUsingCardCount++;
+
+ if(currentHalMapControl->cardNb != cardidx ||
+ ! currentHalMapControl->ctl.alsaCtlProperties ||
+ currentHalMapControl->ctl.numid != numid)
+ continue;
+
+ if(currentHalMapControl->action) {
+ memset(&source, 0, sizeof(CtlSourceT));
+ source.uid = currentHalMapControl->action->uid;
+ source.api = currentHalMapControl->action->api;
+
+ ActionExecOne(&source, currentHalMapControl->action, valuesJ);
+ }
+ else if(currentHalMapControl->actionJ) {
+ AFB_API_WARNING(apiHandle,
+ "The alsa control id '%i' is corresponding to a known control which "
+ "has a registered action, but action is not ready to be executed",
+ numid);
+ }
+ else {
+ AFB_API_NOTICE(apiHandle,
+ "The alsa control id '%i' is corresponding to a known control "
+ "but without any action registered",
+ numid);
+ }
+
+ if(! currentHalMapControl->alsaControlEvent ||
+ InternalHalConvertJsonValues(apiHandle,
+ currentHalMapControl->ctl.alsaCtlProperties,
+ valuesJ,
+ &normalizedValuesJ,
+ CONVERSION_ALSACORE_TO_NORMALIZED) ||
+ (afb_event_push(currentHalMapControl->alsaControlEvent, normalizedValuesJ) < 0)) {
+ AFB_API_ERROR(apiHandle,
+ "Couldn't generate an event for known halmap %s (alsa control id %i)",
+ currentHalMapControl->uid,
+ currentHalMapControl->ctl.numid);
+ }
+
+ controlUsedCount++;
+ }
+
+ if(! controlsUsingCardCount) {
+ AFB_API_INFO(apiHandle,
+ "Receiving events from not handle card %i, unscubscribe from these events",
+ cardidx);
+ snprintf(cardNbString, sizeof(cardNbString), "hw:%i", cardidx);
+ InternalHalUnsubscribeFromAlsacoreCardEvent(apiHandle, cardNbString);
+ return 1;
+ }
+
+ if(controlUsedCount)
+ return 0;
+
+ AFB_API_INFO(apiHandle,
+ "Alsacore event with an unrecognized numid: %i, evtname=%s [msg=%s]",
+ numid,
+ evtLabel,
+ json_object_get_string(eventJ));
+
+ return 2;
+
+}
+
+int InternalHalHandleAlsaCoreEvents(afb_api_t apiHandle,
+ const char *evtLabel,
+ json_object *eventJ,
+ struct HalData *currentHalData)
+{
+ int returned;
+
+ if(! apiHandle || ! evtLabel || ! eventJ || ! currentHalData) {
+ AFB_API_ERROR(apiHandle, "Invalid argument(s)");
+ return -1;
+ }
+
+ switch(InternalHalGetAlsaCoreEventType(evtLabel)) {
+ case ALSACORE_EVENT_CARD_CONTROL_CHANGE:
+ returned = InternalHalHandleAlsaCoreCardControlEvent(apiHandle, evtLabel, eventJ, currentHalData);
+ if(returned < 0) {
+ AFB_API_ERROR(apiHandle,
+ "Error %i caught when tried to handle alsacore card control event evtname=%s [msg=%s]",
+ returned,
+ evtLabel,
+ json_object_get_string(eventJ));
+ return -2;
+ }
+ else if(returned > 0) {
+ AFB_API_INFO(apiHandle,
+ "Warning %i raised when tried to handle alsacore card control event evtname=%s [msg=%s]",
+ returned,
+ evtLabel,
+ json_object_get_string(eventJ));
+ }
+ return 0;
+
+ case ALSACORE_UNRECOGNIZED_EVENT:
+ default:
+ AFB_API_NOTICE(apiHandle,
+ "Alsacore event with an unrecognized evtname=%s [msg=%s]",
+ evtLabel,
+ json_object_get_string(eventJ));
+ return 1;
+ }
+}
+
+/*******************************************************************************
* Internals HAL - Alsacore calls funtions *
******************************************************************************/
@@ -102,33 +273,31 @@ int InternalHalGetCardInfo(afb_api_t apiHandle, json_object *requestJ, json_obje
return errorToReturn;
}
-int InternalHalSubscribeToAlsaCardEvent(afb_api_t apiHandle, char *cardId)
+int InternalHalSubscribeUnscubscribeToAlsacoreEvent(afb_api_t apiHandle,
+ json_object *subscribeQueryJ,
+ enum AlsacoreSubscribeUnsubscribeType subscriptionType)
{
- int err = 0, wrapRet;
+ int err = 0;
char *returnedError = NULL, *returnedInfo = NULL;
- json_object *subscribeQueryJ, *responseJ = NULL;
+ json_object *responseJ = NULL;
- wrapRet = wrap_json_pack(&subscribeQueryJ,
- "{s:s, s:s}",
- "event", ALSACORE_CARD_CONTROL_EVENT_NAME,
- "devid", cardId);
- if(wrapRet) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to allocate subscription query json object");
+ if(! apiHandle || ! subscribeQueryJ) {
+ AFB_API_ERROR(apiHandle, "Invalid argument(s)");
return -1;
}
if(afb_api_call_sync(apiHandle,
ALSACORE_API,
- ALSACORE_SUBSCRIBE_VERB,
+ (subscriptionType == ALSACORE_SUBSCRIPTION) ? ALSACORE_SUBSCRIBE_VERB : ALSACORE_UNSUBSCRIBE_VERB,
subscribeQueryJ,
&responseJ,
&returnedError,
&returnedInfo)) {
AFB_API_ERROR(apiHandle,
"Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s'",
- ALSACORE_SUBSCRIBE_VERB,
+ (subscriptionType == ALSACORE_SUBSCRIPTION) ? ALSACORE_SUBSCRIBE_VERB : ALSACORE_UNSUBSCRIBE_VERB,
ALSACORE_API,
returnedError ? returnedError : "not returned",
returnedInfo ? returnedInfo : "not returned");
@@ -144,6 +313,47 @@ int InternalHalSubscribeToAlsaCardEvent(afb_api_t apiHandle, char *cardId)
return err;
}
+int InternalHalSubscribeUnscubscribeToAlsacoreCardEvent(afb_api_t apiHandle,
+ char *cardId,
+ enum AlsacoreSubscribeUnsubscribeType subscriptionType)
+{
+ int err, wrapRet;
+
+ json_object *subscribeQueryJ = NULL;
+
+ wrapRet = wrap_json_pack(&subscribeQueryJ,
+ "{s:s, s:s}",
+ "event", ALSACORE_CARD_CONTROL_EVENT_NAME,
+ "devid", cardId);
+ if(wrapRet) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to allocate subscription query json object");
+ return -1;
+ }
+
+ err = InternalHalSubscribeUnscubscribeToAlsacoreEvent(apiHandle, subscribeQueryJ, subscriptionType);
+ if(err) {
+ AFB_API_ERROR(apiHandle,
+ "Error %i happened when tried to subscribe to %s card event",
+ err,
+ ALSACORE_API);
+ if(! subscribeQueryJ)
+ json_object_put(subscribeQueryJ);
+ return -2;
+ }
+
+ return 0;
+}
+
+int InternalHalSubscribeToAlsacoreCardEvent(afb_api_t apiHandle, char *cardId)
+{
+ return InternalHalSubscribeUnscubscribeToAlsacoreCardEvent(apiHandle, cardId, ALSACORE_SUBSCRIPTION);
+}
+
+int InternalHalUnsubscribeFromAlsacoreCardEvent(afb_api_t apiHandle, char *cardId)
+{
+ return InternalHalSubscribeUnscubscribeToAlsacoreCardEvent(apiHandle, cardId, ALSACORE_UNSUBSCRIPTION);
+}
+
int InternalHalGetAlsaCtlInfo(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *currentAlsaCtl, json_object **returnedDataJ)
{
int wrapRet;
@@ -407,7 +617,7 @@ int InternalHalCreateAlsaCtl(afb_api_t apiHandle, char *cardId, struct InternalH
}
if(! alsaCtlToCreate->alsaCtlCreation) {
- AFB_API_ERROR(apiHandle, "Alsa control data for creation structure is not available");
+ AFB_API_ERROR(apiHandle, "Alsa control data structure for control creation is not available");
return -4;
}
@@ -469,6 +679,92 @@ int InternalHalCreateAlsaCtl(afb_api_t apiHandle, char *cardId, struct InternalH
return err;
}
+int InternalHalDeleteAlsaCtl(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *alsaCtlToDelete)
+{
+ int err = 0, wrapRet;
+
+ char *returnedError = NULL, *returnedInfo = NULL, *removedControlName = NULL;
+
+ json_object *queryJ, *responseJ = NULL;
+
+ if(! apiHandle) {
+ AFB_API_ERROR(apiHandle, "Api handle not available");
+ return -1;
+ }
+
+ if(! cardId) {
+ AFB_API_ERROR(apiHandle, "Card id is not available");
+ return -2;
+ }
+
+ if(! alsaCtlToDelete) {
+ AFB_API_ERROR(apiHandle, "Alsa control data structure is not available");
+ return -3;
+ }
+
+ if(! alsaCtlToDelete->alsaCtlCreation) {
+ AFB_API_ERROR(apiHandle, "Alsa control data structure for deletion is not available");
+ return -4;
+ }
+
+ if(alsaCtlToDelete->alsaCtlCreation != alsaCtlToDelete->alsaCtlProperties) {
+ AFB_API_ERROR(apiHandle, "Alsa control was not previously created");
+ return -5;
+ }
+
+ wrapRet = wrap_json_pack(&queryJ,
+ "{s:s s:{s:s}}",
+ "devid", cardId,
+ "ctl",
+ "name", alsaCtlToDelete->name);
+ if(wrapRet) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to allocate delete ALSA control query json object");
+ return -6;
+ }
+
+ if(afb_api_call_sync(apiHandle,
+ ALSACORE_API,
+ ALSACORE_REMOVECTL_VERB,
+ queryJ,
+ &responseJ,
+ &returnedError,
+ &returnedInfo)) {
+ AFB_API_ERROR(apiHandle,
+ "Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s'",
+ ALSACORE_REMOVECTL_VERB,
+ ALSACORE_API,
+ returnedError ? returnedError : "not returned",
+ returnedInfo ? returnedInfo : "not returned");
+ err = -6;
+ }
+ else if(! responseJ) {
+ AFB_API_ERROR(apiHandle,
+ "Seems that %s call to api %s succeed but no response was returned",
+ ALSACORE_REMOVECTL_VERB,
+ ALSACORE_API);
+ err = -7;
+ }
+ else if(wrap_json_unpack(responseJ, "{s:{s:s}}", "removed", "ctlName", &removedControlName)) {
+ AFB_API_ERROR(apiHandle,
+ "Can't get removed ALSA control name %s of %s api",
+ ALSACORE_REMOVECTL_VERB,
+ ALSACORE_API);
+ err = -8;
+ }
+
+ AFB_API_DEBUG(apiHandle, "Control %s successfully removed", removedControlName);
+
+ alsaCtlToDelete->alsaCtlProperties = NULL;
+
+ if(responseJ)
+ json_object_put(responseJ);
+
+ free(returnedError);
+ free(returnedInfo);
+
+ return err;
+}
+
/*******************************************************************************
* Internals HAL - Alsacore controls request callback *
******************************************************************************/
diff --git a/src/4a-internals-hal/4a-internals-hal-alsacore-link.h b/src/4a-internals-hal/4a-internals-hal-alsacore-link.h
index dccf266..39b535d 100644
--- a/src/4a-internals-hal/4a-internals-hal-alsacore-link.h
+++ b/src/4a-internals-hal/4a-internals-hal-alsacore-link.h
@@ -19,6 +19,7 @@
#define _INTERNALS_HAL_ALSACORE_LINK_INCLUDE_
#include <stdio.h>
+#include <string.h>
#include <wrap-json.h>
@@ -29,26 +30,56 @@
#include <ctl-config.h>
#include "4a-hal-utilities-alsa-data.h"
+#include "4a-hal-utilities-data.h"
-#define ALSACORE_API "alsacore"
+#define ALSACORE_API "alsacore"
+#define ALSACORE_API_NAME_LENGTH strlen(ALSACORE_API)
-#define ALSACORE_SUBSCRIBE_VERB "subscribe"
-#define ALSACORE_GETINFO_VERB "infoget"
-#define ALSACORE_CTLGET_VERB "ctlget"
-#define ALSACORE_CTLSET_VERB "ctlset"
-#define ALSACORE_ADDCTL_VERB "addcustomctl"
+#define ALSACORE_SUBSCRIBE_VERB "subscribe"
+#define ALSACORE_UNSUBSCRIBE_VERB "unsubscribe"
+#define ALSACORE_GETINFO_VERB "infoget"
+#define ALSACORE_CTLGET_VERB "ctlget"
+#define ALSACORE_CTLSET_VERB "ctlset"
+#define ALSACORE_ADDCTL_VERB "addcustomctl"
+#define ALSACORE_REMOVECTL_VERB "removecustomctl"
-#define ALSACORE_CARD_CONTROL_EVENT_NAME "controls"
+#define ALSACORE_CARD_CONTROL_EVENT_NAME "controls"
+
+#define ALSACORE_EVENT_NAME_BEGIN (ALSACORE_API_NAME_LENGTH + 1)
+#define ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX "hw:"
+#define ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX_LENGTH strlen(ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX)
+#define ALSACORE_CARD_CONTROL_EVENT_BEGIN (ALSACORE_EVENT_NAME_BEGIN + ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX_LENGTH)
+
+// Enum for handled alsacore events
+
+enum aslacoreEventType {
+ ALSACORE_EVENT_CARD_CONTROL_CHANGE = 0,
+ ALSACORE_UNRECOGNIZED_EVENT = 1
+};
+
+// Enum for the type of subscription/unsubscription to do with alsacore
+enum AlsacoreSubscribeUnsubscribeType {
+ ALSACORE_SUBSCRIPTION = 0,
+ ALSACORE_UNSUBSCRIPTION = 1
+};
// Alsa control types map from string function
snd_ctl_elem_type_t InternalHalMapsAlsaTypeToEnum(const char *label);
+// Internals HAL alsacore events handler function
+int InternalHalHandleAlsaCoreEvents(afb_api_t apiHandle,
+ const char *evtLabel,
+ json_object *eventJ,
+ struct HalData *currentHalData);
+
// Internals HAL alsacore calls funtions
int InternalHalGetCardInfo(afb_api_t apiHandle, json_object *requestJ, json_object **responseJ);
-int InternalHalSubscribeToAlsaCardEvent(afb_api_t apiHandle, char *cardId);
+int InternalHalSubscribeToAlsacoreCardEvent(afb_api_t apiHandle, char *cardId);
+int InternalHalUnsubscribeFromAlsacoreCardEvent(afb_api_t apiHandle, char *cardId);
int InternalHalUpdateAlsaCtlProperties(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *currentAlsaCtl);
int InternalHalSetAlsaCtlValue(afb_api_t apiHandle, char *cardId, int ctlId, json_object *valuesJ);
int InternalHalCreateAlsaCtl(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *alsaCtlToCreate);
+int InternalHalDeleteAlsaCtl(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *alsaCtlToDelete);
// Internals HAL alsacore controls request callback
void InternalHalActionOnAlsaCtl(afb_req_t request);
diff --git a/src/4a-internals-hal/4a-internals-hal-api-loader.c b/src/4a-internals-hal/4a-internals-hal-api-loader.c
index 5334bdf..b41c7b2 100644
--- a/src/4a-internals-hal/4a-internals-hal-api-loader.c
+++ b/src/4a-internals-hal/4a-internals-hal-api-loader.c
@@ -62,7 +62,7 @@ static afb_verb_t InternalHalApiStaticVerbs[] =
{
/* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */
{ .verb = "ping", .callback = HalUtlPing, .info = "Ping for test"},
- { .verb = "info", .callback = InternalHalInfo, .info = "List available streams/controls for this api" },
+ { .verb = "info", .callback = InternalHalInfoVerb, .info = "List available dependencies/streams/controls for this api" },
{ .verb = "subscribe", .callback = InternalHalSubscribe, .info = "Subscribe to event(s) for values changes (streams/controls) for this api" },
{ .verb = "unsubscribe", .callback = InternalHalUnsubscribe, .info = "Unsubscribe to event(s) for values changes (streams/controls) for this api" },
{ .verb = HAL_ALL_STREAMS_VERB, .callback = HalUtlActionOnAllStream, .info = "Send a stream action on all streams" },
@@ -199,6 +199,55 @@ int InternalHalCreateApi(afb_api_t apiHandle, char *path, struct HalMgrData *hal
return 0;
}
+int InternalHalDeleteApi(afb_api_t apiHandle, struct cds_list_head *halDataListHead, struct HalData *toDeleteHalData)
+{
+ int err;
+
+ char *toDeleteApiName;
+
+ if(! apiHandle || ! toDeleteHalData) {
+ AFB_API_ERROR(apiHandle, "Invalid argument(s)");
+ return -1;
+ }
+
+ err = InternalHalUnmanageAllHalMap(toDeleteHalData->internalHalData->apiHandle,
+ &toDeleteHalData->internalHalData->halMapListHead,
+ &toDeleteHalData->internalHalData->probedDevicesListHead);
+ if(err) {
+ AFB_API_ERROR(apiHandle,
+ "Error %i happened while trying to unmanage all halmap of '%s' hal api",
+ err,
+ toDeleteHalData->apiName);
+ return -2;
+ }
+
+ toDeleteApiName = strdup(toDeleteHalData->apiName);
+ if(! toDeleteApiName) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'apiName' string");
+ return -3;
+ }
+
+ err = HalUtlRemoveHalDataAndDeleteHalApi(toDeleteHalData->internalHalData->apiHandle,
+ toDeleteHalData,
+ halDataListHead);
+ if(err) {
+ AFB_API_ERROR(apiHandle,
+ "Error %i happened while trying to delete '%s' api and to remove all its data",
+ err,
+ toDeleteApiName);
+ free(toDeleteApiName);
+ return -4;
+ }
+
+ AFB_API_NOTICE(apiHandle,
+ "Api '%s' and all its data has been deleted",
+ toDeleteApiName);
+
+ free(toDeleteApiName);
+
+ return 0;
+}
+
int InternalHalCreateAllApi(afb_api_t apiHandle, struct HalMgrData *halMgrData)
{
int index;
@@ -242,4 +291,43 @@ int InternalHalCreateAllApi(afb_api_t apiHandle, struct HalMgrData *halMgrData)
}
return 0;
+}
+
+int InternalHalDeleteAllApi(afb_api_t apiHandle, struct HalMgrData *halMgrData)
+{
+ int err;
+
+ char *toDeleteApiName;
+
+ struct HalData *currentHalData;
+
+ if(! apiHandle || ! halMgrData) {
+ AFB_API_ERROR(apiHandle, "Invalid argument(s)");
+ return -1;
+ }
+
+ cds_list_for_each_entry(currentHalData, &halMgrData->halDataListHead, node) {
+ if(! currentHalData->apiName)
+ return -2;
+
+ toDeleteApiName = strdup(currentHalData->apiName);
+ if(! toDeleteApiName) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'apiName' string");
+ return -3;
+ }
+
+ err = InternalHalDeleteApi(apiHandle, &halMgrData->halDataListHead, currentHalData);
+ if(err) {
+ AFB_API_ERROR(apiHandle,
+ "Error %i happened when tried to delete %s api",
+ err,
+ toDeleteApiName);
+ free(toDeleteApiName);
+ return -4;
+ }
+
+ free(toDeleteApiName);
+ }
+
+ return 0;
} \ No newline at end of file
diff --git a/src/4a-internals-hal/4a-internals-hal-api-loader.h b/src/4a-internals-hal/4a-internals-hal-api-loader.h
index fa878e2..2a47555 100644
--- a/src/4a-internals-hal/4a-internals-hal-api-loader.h
+++ b/src/4a-internals-hal/4a-internals-hal-api-loader.h
@@ -26,6 +26,8 @@
// Verbs that can be use to create api
int InternalHalCreateApi(afb_api_t apiHandle, char *path, struct HalMgrData *halMgrData);
+int InternalHalDeleteApi(afb_api_t apiHandle, struct cds_list_head *halDataListHead, struct HalData *toDeleteHalData);
int InternalHalCreateAllApi(afb_api_t apiHandle, struct HalMgrData *halMgrData);
+int InternalHalDeleteAllApi(afb_api_t apiHandle, struct HalMgrData *halMgrData);
#endif /* _INTERNALS_HAL_API_LOADER_INCLUDE_ */ \ No newline at end of file
diff --git a/src/4a-internals-hal/4a-internals-hal-cb.c b/src/4a-internals-hal/4a-internals-hal-cb.c
index a81871c..c1078a9 100644
--- a/src/4a-internals-hal/4a-internals-hal-cb.c
+++ b/src/4a-internals-hal/4a-internals-hal-cb.c
@@ -37,15 +37,11 @@
void InternalHalDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json_object *eventJ)
{
- int numid, idx = 0, cardidx;
+ int error;
CtlConfigT *ctrlConfig;
- CtlSourceT source;
struct HalData *currentHalData;
- struct InternalHalAlsaMap *currentHalMapControl;
-
- json_object *valuesJ, *normalizedValuesJ;
AFB_API_DEBUG(apiHandle, "Evtname=%s [msg=%s]", evtLabel, json_object_get_string(eventJ));
@@ -61,79 +57,31 @@ void InternalHalDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json
return;
}
- // Extract sound card index from event
- while(evtLabel[idx] != '\0' && evtLabel[idx] != ':')
- idx++;
-
- if(evtLabel[idx] != '\0' &&
- (sscanf(&evtLabel[idx + 1], "%d", &cardidx) == 1)) {
- if(wrap_json_unpack(eventJ, "{s:i s:o}", "id", &numid, "val", &valuesJ)) {
+ if((strlen(evtLabel) > ALSACORE_API_NAME_LENGTH) &&
+ ! strncmp(evtLabel, ALSACORE_API, ALSACORE_API_NAME_LENGTH)) {
+ error = InternalHalHandleAlsaCoreEvents(apiHandle, evtLabel, eventJ, currentHalData);
+ if(error < 0) {
AFB_API_ERROR(apiHandle,
- "Invalid alsacore event received label=%s value=%s",
+ "Error %i caught when tried to handle alsacore event evtname=%s [msg=%s]",
+ error,
evtLabel,
json_object_get_string(eventJ));
return;
}
-
- if(cds_list_empty(&currentHalData->internalHalData->halMapListHead)) {
- AFB_API_ERROR(apiHandle, "No halmap data is available, cannot handle alsacore event");
- return;
+ else if(error > 0) {
+ AFB_API_INFO(apiHandle,
+ "Warning %i raised when tried to handle alsacore event evtname=%s [msg=%s]",
+ error,
+ evtLabel,
+ json_object_get_string(eventJ));
}
-
- // Search for corresponding numid in ALSA controls list, if found, launch callback (if available)
- cds_list_for_each_entry(currentHalMapControl, &currentHalData->internalHalData->halMapListHead, node) {
- if(currentHalMapControl->cardNb == cardidx &&
- currentHalMapControl->ctl.alsaCtlProperties &&
- currentHalMapControl->ctl.numid == numid) {
- if(currentHalMapControl->action) {
- memset(&source, 0, sizeof(CtlSourceT));
- source.uid = currentHalMapControl->action->uid;
- source.api = currentHalMapControl->action->api;
-
- (void) ActionExecOne(&source, currentHalMapControl->action, valuesJ);
- }
- else if(currentHalMapControl->actionJ) {
- AFB_API_WARNING(apiHandle,
- "The alsa control id '%i' is corresponding to a known control which "
- "has a registered action, but action is not ready to be executed",
- numid);
- return;
- }
- else {
- AFB_API_NOTICE(apiHandle,
- "The alsa control id '%i' is corresponding to a known control "
- "but without any action registered",
- numid);
- }
-
- if(! currentHalMapControl->alsaControlEvent ||
- InternalHalConvertJsonValues(apiHandle,
- currentHalMapControl->ctl.alsaCtlProperties,
- valuesJ,
- &normalizedValuesJ,
- CONVERSION_ALSACORE_TO_NORMALIZED) ||
- (afb_event_push(currentHalMapControl->alsaControlEvent, normalizedValuesJ) < 0)) {
- AFB_API_ERROR(apiHandle,
- "Couldn't generate an event for known halmap %s (alsa control id %i)",
- currentHalMapControl->uid,
- currentHalMapControl->ctl.numid);
- }
-
- return;
- }
+ else {
+ return;
}
-
- AFB_API_WARNING(apiHandle,
- "Alsacore event with an unrecognized numid: %i, evtname=%s [msg=%s]",
- numid,
- evtLabel,
- json_object_get_string(eventJ));
-
- return;
}
AFB_API_INFO(apiHandle,
- "Not an alsacore event '%s' [msg=%s]",
+ "Not an internally handled event '%s' [msg=%s]",
evtLabel,
json_object_get_string(eventJ));
@@ -141,559 +89,6 @@ void InternalHalDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json
}
/*******************************************************************************
- * Internals HAL - 'halmixer' section parsing/handling functions *
- ******************************************************************************/
-
-int InternalHalHalMixerConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *MixerJ)
-{
- int err = 0, wrapRet;
-
- char *mixerApiName, *prefix = NULL;
-
- CtlConfigT *ctrlConfig;
- struct HalData *currentHalData;
-
- if(! apiHandle || ! section)
- return -1;
-
- ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
- if(! ctrlConfig)
- return -2;
-
- currentHalData = (struct HalData *) getExternalData(ctrlConfig);
- if(! currentHalData)
- return -3;
-
- if(MixerJ) {
- if(json_object_is_type(MixerJ, json_type_object))
- currentHalData->internalHalData->halMixerJ = MixerJ;
- else
- return -4;
-
- wrapRet = wrap_json_unpack(MixerJ, "{s:s s?:s}", "mixerapi", &mixerApiName, "prefix", &prefix);
- if(wrapRet)
- return -5;
-
- currentHalData->internalHalData->mixerApiName = strdup(mixerApiName);
- if(! currentHalData->internalHalData->mixerApiName)
- return -6;
-
- if(prefix) {
- currentHalData->internalHalData->prefix = strdup(prefix);
- if(! currentHalData->internalHalData->prefix)
- return -7;
- }
- }
- else if(currentHalData->status == HAL_STATUS_AVAILABLE) {
- err = InternalHalAttachToMixer(apiHandle);
- if(err) {
- AFB_API_ERROR(apiHandle, "Error %i while attaching to mixer", err);
- return -8;
- }
- }
-
- return 0;
-}
-
-/*******************************************************************************
- * Internals HAL - 'halmap' section parsing/handling functions *
- ******************************************************************************/
-
-int InternalHalProcessOneHalMapControl(afb_api_t apiHandle,
- struct InternalHalAlsaMap *halMapData,
- json_object *halMapControlJ)
-{
- char *uid, *info = NULL, *action = NULL, *name = NULL, *typename = NULL;
-
- json_object *alsaJ = NULL, *createAlsaCtlJ = NULL;
-
- if(! apiHandle || ! halMapData || ! halMapControlJ) {
- AFB_API_ERROR(apiHandle, "Invalid argument(s)");
- return -1;
- }
-
- if(wrap_json_unpack(halMapControlJ,
- "{s:s s?:s s:o s?:s !}",
- "uid", &uid,
- "info", &info,
- "alsa", &alsaJ,
- "action", &action)) {
- AFB_API_ERROR(apiHandle,
- "Parsing error, control json should only contains "
- "[uid]|[info]|[alsa] in : '%s'",
- json_object_get_string(halMapControlJ));
- return -2;
- }
-
- halMapData->uid = strdup(uid);
- if(! halMapData->uid) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'uid' string");
- return -3;
- }
-
- if(info) {
- halMapData->info = strdup(info);
- if(! halMapData->info) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'info' string");
- return -4;
- }
- }
-
- if(wrap_json_unpack(alsaJ,
- "{s?:s s?:i s?:i s?:o !}",
- "name", &name,
- "numid", &halMapData->ctl.numid,
- "value", &halMapData->ctl.value,
- "create", &createAlsaCtlJ)) {
- AFB_API_ERROR(apiHandle,
- "Parsing error, alsa json should only contains "
- "[name]|[numid]||[value]|[create] in : '%s'",
- json_object_get_string(alsaJ));
- return -5;
- }
-
- if(name) {
- halMapData->ctl.name = strdup(name);
- if(! halMapData->ctl.name) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'info' string");
- return -6;
- }
- }
-
- if(createAlsaCtlJ) {
- halMapData->ctl.alsaCtlCreation = calloc(1, sizeof(struct InternalHalAlsaCtlProperties));
- if(! halMapData->ctl.alsaCtlCreation) {
- AFB_API_ERROR(apiHandle,
- "Didn't succeed to allocate alsa properties data structure for control to create");
- return -7;
- }
-
- if(wrap_json_unpack(createAlsaCtlJ,
- "{s:s s:i s:i s:i s:i !}",
- "type", &typename,
- "count", &halMapData->ctl.alsaCtlCreation->count,
- "minval", &halMapData->ctl.alsaCtlCreation->minval,
- "maxval", &halMapData->ctl.alsaCtlCreation->maxval,
- "step", &halMapData->ctl.alsaCtlCreation->step)) {
- AFB_API_ERROR(apiHandle,
- "Parsing error, alsa creation json should only contains "
- "[type]|[count]|[minval]|[maxval]|[step] in : '%s'",
- json_object_get_string(alsaJ));
- return -8;
- }
-
- if(typename) {
- halMapData->ctl.alsaCtlCreation->type = InternalHalMapsAlsaTypeToEnum(typename);
- if(halMapData->ctl.alsaCtlCreation->type == SND_CTL_ELEM_TYPE_NONE) {
- AFB_API_ERROR(apiHandle,
- "Couldn't get alsa type from string %s in : '%s'",
- typename,
- json_object_get_string(alsaJ));
- return -9;
- }
- }
-
- if(! halMapData->ctl.name)
- halMapData->ctl.name = halMapData->uid;
- }
- else if(halMapData->ctl.name && halMapData->ctl.numid > 0) {
- AFB_API_ERROR(apiHandle,
- "Can't have both a control name (%s) and a control uid (%i) in alsa object : '%s'",
- halMapData->ctl.name,
- halMapData->ctl.numid,
- json_object_get_string(alsaJ));
- return -10;
- }
- else if(! halMapData->ctl.name && halMapData->ctl.numid <= 0) {
- AFB_API_ERROR(apiHandle,
- "Need at least a control name or a control uid in alsa object : '%s'",
- json_object_get_string(alsaJ));
- return -11;
- }
-
- if(action)
- halMapData->actionJ = json_object_get(halMapControlJ);
-
- return 0;
-}
-
-int InternalHalProcessOneHalMapObject(afb_api_t apiHandle,
- json_object *halMapForTargetJ,
- struct cds_list_head *halMapListHead,
- struct cds_list_head *halDevicesToProbeListHead)
-{
- int idx, controlsCount, err = 0, halMapControlsJsonIsAnArray = 0;
-
- char *uid, *info = NULL, *target;
-
- struct InternalHalAlsaMap *currentHalMapData;
-
- json_object *controlsJ, *currentHalMapControlJ;
- json_type halMapControlsType;
-
- AFB_API_DEBUG(apiHandle, "halMapForTargetJ='%s'", json_object_get_string(halMapForTargetJ));
-
- if(wrap_json_unpack(halMapForTargetJ,
- "{s:s s?:s s:s s:o !}",
- "uid", &uid,
- "info", &info,
- "target", &target,
- "controls", &controlsJ)) {
- AFB_API_ERROR(apiHandle,
- "Parsing error, map should only contains "
- "[uid]|[info]|[target]|[controls] in : '%s'",
- json_object_get_string(halMapForTargetJ));
- return -1;
- }
-
- if(! HalUtlSearchProbedDeviceDataById(halDevicesToProbeListHead, target)) {
- AFB_API_ERROR(apiHandle,
- "Content of 'halmap' section is not valid because targeted dependency ('%s') is not present "
- "in 'haldependencies' section, json configuration file correction is needed",
- target);
- return -2;
- }
-
- halMapControlsType = json_object_get_type(controlsJ);
- switch(halMapControlsType) {
- case json_type_array:
- controlsCount = (int) json_object_array_length(controlsJ);
- halMapControlsJsonIsAnArray = 1;
- break;
-
- case json_type_object:
- controlsCount = 1;
- break;
-
- default:
- AFB_API_ERROR(apiHandle,
- "Content of 'halmap' controls section is not valid ('%s')",
- json_object_get_string(controlsJ));
- return -3;
- }
-
- for(idx = 0; idx < controlsCount; idx++) {
- currentHalMapControlJ = halMapControlsJsonIsAnArray ? json_object_array_get_idx(controlsJ, idx) : controlsJ;
-
- currentHalMapData = HalUtlAddHalMapDataToHalMapDataList(halMapListHead);
-
- currentHalMapData->targetUid = strdup(uid);
- if(! currentHalMapData->targetUid) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'targetUid' string");
- return -4;
- }
-
- if(info) {
- currentHalMapData->targetInfo = strdup(info);
- if(! currentHalMapData->targetInfo) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'targetInfo' string");
- return -5;
- }
- }
-
- currentHalMapData->targetedDependency = strdup(target);
- if(! currentHalMapData->targetedDependency) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'targetedDependency' string");
- return -6;
- }
-
- err = InternalHalProcessOneHalMapControl(apiHandle,
- currentHalMapData,
- currentHalMapControlJ);
- if(err) {
- AFB_API_ERROR(apiHandle,
- "Error %i was returned when tried to proccess halmap control %i ('%s')",
- err,
- idx,
- json_object_get_string(currentHalMapControlJ));
- HalUtlRemoveSelectedHalMapData(halMapListHead, currentHalMapData);
- return -7;
- }
- }
-
- return 0;
-}
-
-int InternalHalProcessAllHalMap(afb_api_t apiHandle,
- json_object *halMapJ,
- struct cds_list_head *halMapListHead,
- struct cds_list_head *halDevicesToProbeListHead)
-{
- int idx, targetCount, err = 0, halMapJsonIsAnArray = 0;
-
- json_object *currentHalMapTargetJ;
- json_type alsaMapType;
-
- AFB_API_DEBUG(apiHandle, "halMapJ='%s'", json_object_get_string(halMapJ));
-
- alsaMapType = json_object_get_type(halMapJ);
- switch(alsaMapType) {
- case json_type_array:
- targetCount = (int) json_object_array_length(halMapJ);
- halMapJsonIsAnArray = 1;
- break;
-
- case json_type_object:
- targetCount = 1;
- break;
-
- default:
- AFB_API_ERROR(apiHandle,
- "Content of 'halmap' section is not valid ('%s')",
- json_object_get_string(halMapJ));
- return -1;
- }
-
- for(idx = 0; idx < targetCount; idx++) {
- currentHalMapTargetJ = halMapJsonIsAnArray ? json_object_array_get_idx(halMapJ, idx) : halMapJ;
-
- err = InternalHalProcessOneHalMapObject(apiHandle,
- currentHalMapTargetJ,
- halMapListHead,
- halDevicesToProbeListHead);
- if(err) {
- AFB_API_ERROR(apiHandle,
- "Error %i was returned when tried to proccess halmap target %i ('%s')",
- err,
- idx,
- json_object_get_string(currentHalMapTargetJ));
- HalUtlRemoveAllHalMapData(halMapListHead);
- return -2;
- }
- }
-
- return 0;
-}
-
-int InternalHalHandleOneHalMapObject(afb_api_t apiHandle, struct InternalHalAlsaMap *halMapData)
-{
- int err;
-
- char cardNbString[6];
-
- json_object *valueJ, *convertedValueJ = NULL;
-
- CtlActionT *toLoadAction;
-
- halMapData->alsaControlEvent = afb_api_make_event(apiHandle, halMapData->uid);
- if(! halMapData->alsaControlEvent) {
- AFB_API_ERROR(apiHandle,
- "Didn't succeed to create event for alsa control with uid %s",
- halMapData->uid);
- return -1;
- }
-
- snprintf(cardNbString, sizeof(cardNbString), "hw:%i", halMapData->cardNb);
-
- if(halMapData->ctl.alsaCtlCreation) {
- if(InternalHalCreateAlsaCtl(apiHandle, cardNbString, &halMapData->ctl)) {
- AFB_API_ERROR(apiHandle, "An error happened when trying to create a new alsa control");
- return -2;
- }
- halMapData->ctl.alsaCtlProperties = halMapData->ctl.alsaCtlCreation;
- }
- else {
- halMapData->ctl.alsaCtlProperties = calloc(1, sizeof(struct InternalHalAlsaCtlProperties));
- if(! halMapData->ctl.alsaCtlProperties) {
- AFB_API_ERROR(apiHandle,
- "Didn't succeed to allocate alsa properties data structure for control");
- return -3;
- }
-
- if(InternalHalUpdateAlsaCtlProperties(apiHandle, cardNbString, &halMapData->ctl)) {
- AFB_API_ERROR(apiHandle, "An error happened when trying to get existing alsa control info");
- free(halMapData->ctl.alsaCtlProperties);
- halMapData->ctl.alsaCtlProperties = NULL;
- return -4;
- }
- }
-
- if(halMapData->actionJ) {
- toLoadAction = calloc(1, sizeof(CtlActionT));
- if(! toLoadAction) {
- AFB_API_ERROR(apiHandle,
- "Didn't succeed to allocate structure used to store action to perform "
- "when the corresponding ALSA control is detected");
- return -5;
- }
-
- if(ActionLoadOne(apiHandle, toLoadAction, halMapData->actionJ, 0)) {
- AFB_API_ERROR(apiHandle,
- "Didn't succeed to load action using alsa object : '%s'",
- json_object_get_string(halMapData->actionJ));
- free(toLoadAction);
- return -6;
- }
-
- halMapData->action = toLoadAction;
- }
-
- if(InternalHalSubscribeToAlsaCardEvent(apiHandle, cardNbString)) {
- AFB_API_ERROR(apiHandle, "Error when trying to subscribe to alsacore event for audio card '%s'", cardNbString);
- return -7;
- }
-
- if(halMapData->ctl.value) {
- // TBD JAI : handle alsa controls type
- valueJ = json_object_new_int(halMapData->ctl.value);
- if(! valueJ) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to allocate ALSA control value json string");
- return -8;
- }
-
- err = 0;
-
- if(InternalHalConvertJsonValues(apiHandle,
- halMapData->ctl.alsaCtlProperties,
- valueJ,
- &convertedValueJ,
- CONVERSION_NORMALIZED_TO_ALSACORE)) {
- AFB_API_ERROR(apiHandle, "Error when trying to convert initiate value json '%s'", json_object_get_string(valueJ));
- err = -9;
- }
- else if(InternalHalSetAlsaCtlValue(apiHandle, cardNbString, halMapData->ctl.numid, convertedValueJ)) {
- AFB_API_ERROR(apiHandle,
- "Error while trying to set initial value on alsa control %i, device '%s', value '%s'",
- halMapData->ctl.numid,
- cardNbString,
- json_object_get_string(valueJ));
- err = -10;
- }
-
- json_object_put(valueJ);
-
- if(convertedValueJ)
- json_object_put(convertedValueJ);
-
- if(err)
- return err;
- }
-
- if(afb_api_add_verb(apiHandle, halMapData->uid, NULL, InternalHalActionOnAlsaCtl, (void *) halMapData, NULL, 0, 0)) {
- AFB_API_ERROR(apiHandle,
- "Didn't succeed to create verb %s for alsa control named %s on card %i",
- halMapData->uid,
- halMapData->ctl.name ? halMapData->ctl.name : "'N/A'",
- halMapData->cardNb);
- return -10;
- }
-
- return 0;
-}
-
-int InternalHalHandleSelectedHalMapWithValidatedDependency(afb_api_t apiHandle,
- struct cds_list_head *halMapListHead,
- struct cds_list_head *halDevicesToProbeListHead,
- char *targetedDependency,
- enum DependenciesHandlingType halMapHandlingType)
-{
- int err = 0, validatedHalMap;
-
- struct InternalHalAlsaMap *currentHalMapData;
-
- if(cds_list_empty(halMapListHead)) {
- AFB_API_ERROR(apiHandle, "HalMap list is empty, nothing to handle");
- return 0;
- }
-
- if(halMapHandlingType == UID_CORRESPONDING_DEPENDENCIES &&
- ! targetedDependency) {
- AFB_API_ERROR(apiHandle, "Invalid targeted dependency");
- return -1;
- }
-
- cds_list_for_each_entry(currentHalMapData, halMapListHead, node) {
- validatedHalMap = 0;
- switch(halMapHandlingType) {
- case ALL_DEPENDENCIES:
- validatedHalMap = 1;
- break;
-
- case UID_CORRESPONDING_DEPENDENCIES:
- if(! strcmp(targetedDependency, currentHalMapData->targetedDependency))
- validatedHalMap = 1;
- break;
-
- default:
- AFB_API_ERROR(apiHandle, "Invalid dependencies enum type");
- return -2;
- }
-
- if(validatedHalMap) {
- currentHalMapData->cardNb = HalUtlGetProbedDeviceCardNbUsingUid(halDevicesToProbeListHead,
- currentHalMapData->targetedDependency);
- if(currentHalMapData->cardNb == HAL_UNKNOWN_DEVICE) {
- AFB_API_WARNING(apiHandle,
- "Current halmap control %s can't be handled because corresponding "
- "dependency ('%s') card is not available at the moment",
- currentHalMapData->uid,
- currentHalMapData->targetedDependency);
- continue;
- }
-
- err = InternalHalHandleOneHalMapObject(apiHandle, currentHalMapData);
- if(err) {
- AFB_API_ERROR(apiHandle,
- "Error %i was returned when tried to handle halmap control with uid %s",
- err,
- currentHalMapData->uid);
- return -3;
- }
- }
- }
-
- return 0;
-}
-
-int InternalHalHandleAllHalMapWithValidatedDependency(afb_api_t apiHandle,
- struct cds_list_head *halMapListHead,
- struct cds_list_head *halDevicesToProbeListHead)
-{
- return InternalHalHandleSelectedHalMapWithValidatedDependency(apiHandle,
- halMapListHead,
- halDevicesToProbeListHead,
- NULL,
- ALL_DEPENDENCIES);
-}
-
-int InternalHalHalMapConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *AlsaMapJ)
-{
- CtlConfigT *ctrlConfig;
- struct HalData *currentHalData;
-
- ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
- if(! ctrlConfig)
- return -1;
-
- currentHalData = (struct HalData *) getExternalData(ctrlConfig);
- if(! currentHalData)
- return -2;
-
- if(AlsaMapJ) {
- if(InternalHalProcessAllHalMap(apiHandle,
- AlsaMapJ,
- &currentHalData->internalHalData->halMapListHead,
- &currentHalData->internalHalData->probedDevicesListHead)) {
- AFB_API_ERROR(apiHandle, "Failed to process 'halmap' section");
- HalUtlRemoveAllHalMapData(&currentHalData->internalHalData->halMapListHead);
- return -4;
- }
- }
- else if(cds_list_empty(&currentHalData->internalHalData->halMapListHead)) {
- AFB_API_WARNING(apiHandle, "No alsa controls defined in 'halmap' section");
- return 1;
- }
- else if(InternalHalHandleAllHalMapWithValidatedDependency(apiHandle,
- &currentHalData->internalHalData->halMapListHead,
- &currentHalData->internalHalData->probedDevicesListHead)) {
- AFB_API_ERROR(apiHandle, "Failed to handle 'halmap' section");
- return -5;
- }
-
- return 0;
-}
-
-/*******************************************************************************
* Internals HAL - 'haldependencies' section parsing/handling functions *
******************************************************************************/
@@ -1084,21 +479,17 @@ int InternalHalHandleInfoGetResponse(afb_api_t apiHandle, json_object *currentRe
return ret;
}
-int InternalHalHandleOneHalDependencies(afb_api_t apiHandle, struct InternalHalProbedDevice **halDeviceToProbe)
+int InternalHalHandleOneHalDependencies(afb_api_t apiHandle, struct InternalHalProbedDevice *currentDeviceToProbe)
{
int ret, toReturn = 0;
- struct InternalHalProbedDevice *currentDeviceToProbe;
-
json_object *probedDeviceGetInfoResponseJ = NULL;
- if(! apiHandle || ! halDeviceToProbe || ! *halDeviceToProbe) {
+ if(! apiHandle || ! currentDeviceToProbe) {
AFB_API_ERROR(apiHandle, "Invalid argument(s)");
return -1;
}
- currentDeviceToProbe = *halDeviceToProbe;
-
if(! currentDeviceToProbe->uid ||
! currentDeviceToProbe->requestedDeviceJ) {
AFB_API_ERROR(apiHandle, "Specified device to probe is not valid (uid or request is not specified)");
@@ -1155,7 +546,7 @@ int InternalHalHandleOneHalDependencies(afb_api_t apiHandle, struct InternalHalP
int InternalHalHandleHalDependencies(afb_api_t apiHandle,
struct HalData *currentHalData,
struct cds_list_head *halDevicesToProbeListHead,
- enum DependenciesHandlingType dependenciesHandlingType,
+ enum DependencySelectionType dependencySelectionType,
char *uid)
{
int ret, validatedDepedency, validatedDependenciesNumber = 0;
@@ -1172,7 +563,7 @@ int InternalHalHandleHalDependencies(afb_api_t apiHandle,
return 0;
}
- if(dependenciesHandlingType == UID_CORRESPONDING_DEPENDENCIES &&
+ if(dependencySelectionType == UID_CORRESPONDING_DEPENDENCIES &&
! uid) {
AFB_API_ERROR(apiHandle, "Invalid uid");
return -2;
@@ -1181,7 +572,7 @@ int InternalHalHandleHalDependencies(afb_api_t apiHandle,
cds_list_for_each_entry(halCurrentDeviceToProbe, halDevicesToProbeListHead, node) {
validatedDepedency = 0;
- switch(dependenciesHandlingType) {
+ switch(dependencySelectionType) {
case ALL_DEPENDENCIES:
validatedDepedency = 1;
break;
@@ -1197,7 +588,7 @@ int InternalHalHandleHalDependencies(afb_api_t apiHandle,
}
if(validatedDepedency) {
- ret = InternalHalHandleOneHalDependencies(apiHandle, &halCurrentDeviceToProbe);
+ ret = InternalHalHandleOneHalDependencies(apiHandle, halCurrentDeviceToProbe);
if(ret < 0) {
AFB_API_ERROR(apiHandle,
"Error %i happened when tried to handle device to probe with uid:'%s' and request:'%s'",
@@ -1271,25 +662,765 @@ int InternalHalHalDependenciesConfig(afb_api_t apiHandle, CtlSectionT *section,
}
/*******************************************************************************
- * Internals HAL verbs functions *
+ * Internals HAL - 'halmixer' section parsing/handling functions *
******************************************************************************/
-void InternalHalInfo(afb_req_t request)
+int InternalHalHalMixerConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *MixerJ)
{
- char *apiToCall, *returnedError = NULL, *returnedInfo = NULL;
+ int err = 0, wrapRet;
+
+ char *mixerApiName, *prefix = NULL;
- afb_api_t apiHandle;
CtlConfigT *ctrlConfig;
+ struct HalData *currentHalData;
+ struct InternalHalProbedDevice *currentProbedDevice;
+
+ if(! apiHandle || ! section)
+ return -1;
+
+ ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
+ if(! ctrlConfig)
+ return -2;
+
+ currentHalData = (struct HalData *) getExternalData(ctrlConfig);
+ if(! currentHalData)
+ return -3;
+
+ if(MixerJ) {
+ if(json_object_is_type(MixerJ, json_type_object))
+ currentHalData->internalHalData->halMixerJ = MixerJ;
+ else
+ return -4;
+
+ wrapRet = wrap_json_unpack(MixerJ, "{s:s s?:s}", "mixerapi", &mixerApiName, "prefix", &prefix);
+ if(wrapRet)
+ return -5;
+
+ currentHalData->internalHalData->mixerApiName = strdup(mixerApiName);
+ if(! currentHalData->internalHalData->mixerApiName)
+ return -6;
+ if(prefix) {
+ currentHalData->internalHalData->prefix = strdup(prefix);
+ if(! currentHalData->internalHalData->prefix)
+ return -7;
+ }
+ }
+ else if(currentHalData->status == HAL_STATUS_AVAILABLE) {
+ cds_list_for_each_entry(currentProbedDevice, &currentHalData->internalHalData->probedDevicesListHead, node) {
+ if(! currentProbedDevice->deviceData) {
+ currentProbedDevice->mixerLinkStatus = DEPENDENCY_MIXER_LINK_USELESS;
+ continue;
+ }
+
+ if(currentProbedDevice->mixerLinkStatus == DEPENDENCY_MIXER_ATTACH_SUCCEED) {
+ AFB_API_WARNING(apiHandle, "Mixer status is already initialized, moving to next one");
+ continue;
+ }
+
+ err = InternalHalAttachDependencyToMixer(apiHandle, currentProbedDevice);
+ if(err) {
+ AFB_API_ERROR(apiHandle, "Error %i while attaching to mixer", err);
+ return -8;
+ }
+ }
+
+ currentHalData->status = HAL_STATUS_READY;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Internals HAL - 'halmap' section parsing/handling functions *
+ ******************************************************************************/
+
+int InternalHalProcessOneHalMapControl(afb_api_t apiHandle,
+ struct InternalHalAlsaMap *halMapData,
+ json_object *halMapControlJ)
+{
+ char *uid, *info = NULL, *action = NULL, *name = NULL, *typename = NULL;
+
+ json_object *alsaJ = NULL, *createAlsaCtlJ = NULL;
+
+ if(! apiHandle || ! halMapData || ! halMapControlJ) {
+ AFB_API_ERROR(apiHandle, "Invalid argument(s)");
+ return -1;
+ }
+
+ if(wrap_json_unpack(halMapControlJ,
+ "{s:s s?:s s:o s?:s !}",
+ "uid", &uid,
+ "info", &info,
+ "alsa", &alsaJ,
+ "action", &action)) {
+ AFB_API_ERROR(apiHandle,
+ "Parsing error, control json should only contains "
+ "[uid]|[info]|[alsa] in : '%s'",
+ json_object_get_string(halMapControlJ));
+ return -2;
+ }
+
+ halMapData->uid = strdup(uid);
+ if(! halMapData->uid) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'uid' string");
+ return -3;
+ }
+
+ if(info) {
+ halMapData->info = strdup(info);
+ if(! halMapData->info) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'info' string");
+ return -4;
+ }
+ }
+
+ if(wrap_json_unpack(alsaJ,
+ "{s?:s s?:i s?:i s?:o !}",
+ "name", &name,
+ "numid", &halMapData->ctl.numid,
+ "value", &halMapData->ctl.value,
+ "create", &createAlsaCtlJ)) {
+ AFB_API_ERROR(apiHandle,
+ "Parsing error, alsa json should only contains "
+ "[name]|[numid]||[value]|[create] in : '%s'",
+ json_object_get_string(alsaJ));
+ return -5;
+ }
+
+ if(name) {
+ halMapData->ctl.name = strdup(name);
+ if(! halMapData->ctl.name) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'info' string");
+ return -6;
+ }
+ }
+
+ if(createAlsaCtlJ) {
+ halMapData->ctl.alsaCtlCreation = calloc(1, sizeof(struct InternalHalAlsaCtlProperties));
+ if(! halMapData->ctl.alsaCtlCreation) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to allocate alsa properties data structure for control to create");
+ return -7;
+ }
+
+ if(wrap_json_unpack(createAlsaCtlJ,
+ "{s:s s:i s:i s:i s:i !}",
+ "type", &typename,
+ "count", &halMapData->ctl.alsaCtlCreation->count,
+ "minval", &halMapData->ctl.alsaCtlCreation->minval,
+ "maxval", &halMapData->ctl.alsaCtlCreation->maxval,
+ "step", &halMapData->ctl.alsaCtlCreation->step)) {
+ AFB_API_ERROR(apiHandle,
+ "Parsing error, alsa creation json should only contains "
+ "[type]|[count]|[minval]|[maxval]|[step] in : '%s'",
+ json_object_get_string(alsaJ));
+ return -8;
+ }
+
+ if(typename) {
+ halMapData->ctl.alsaCtlCreation->type = InternalHalMapsAlsaTypeToEnum(typename);
+ if(halMapData->ctl.alsaCtlCreation->type == SND_CTL_ELEM_TYPE_NONE) {
+ AFB_API_ERROR(apiHandle,
+ "Couldn't get alsa type from string %s in : '%s'",
+ typename,
+ json_object_get_string(alsaJ));
+ return -9;
+ }
+ }
+
+ if(! halMapData->ctl.name)
+ halMapData->ctl.name = halMapData->uid;
+ }
+ else if(halMapData->ctl.name && halMapData->ctl.numid > 0) {
+ AFB_API_ERROR(apiHandle,
+ "Can't have both a control name (%s) and a control uid (%i) in alsa object : '%s'",
+ halMapData->ctl.name,
+ halMapData->ctl.numid,
+ json_object_get_string(alsaJ));
+ return -10;
+ }
+ else if(! halMapData->ctl.name && halMapData->ctl.numid <= 0) {
+ AFB_API_ERROR(apiHandle,
+ "Need at least a control name or a control uid in alsa object : '%s'",
+ json_object_get_string(alsaJ));
+ return -11;
+ }
+
+ if(action)
+ halMapData->actionJ = json_object_get(halMapControlJ);
+
+ return 0;
+}
+
+int InternalHalProcessOneHalMapObject(afb_api_t apiHandle,
+ json_object *halMapForTargetJ,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead)
+{
+ int idx, controlsCount, err = 0, halMapControlsJsonIsAnArray = 0;
+
+ char *uid, *info = NULL, *target;
+
+ struct InternalHalAlsaMap *currentHalMapData;
+
+ json_object *controlsJ, *currentHalMapControlJ;
+ json_type halMapControlsType;
+
+ AFB_API_DEBUG(apiHandle, "halMapForTargetJ='%s'", json_object_get_string(halMapForTargetJ));
+
+ if(wrap_json_unpack(halMapForTargetJ,
+ "{s:s s?:s s:s s:o !}",
+ "uid", &uid,
+ "info", &info,
+ "target", &target,
+ "controls", &controlsJ)) {
+ AFB_API_ERROR(apiHandle,
+ "Parsing error, map should only contains "
+ "[uid]|[info]|[target]|[controls] in : '%s'",
+ json_object_get_string(halMapForTargetJ));
+ return -1;
+ }
+
+ if(! HalUtlSearchProbedDeviceDataById(halDevicesToProbeListHead, target)) {
+ AFB_API_ERROR(apiHandle,
+ "Content of 'halmap' section is not valid because targeted dependency ('%s') is not present "
+ "in 'haldependencies' section, json configuration file correction is needed",
+ target);
+ return -2;
+ }
+
+ halMapControlsType = json_object_get_type(controlsJ);
+ switch(halMapControlsType) {
+ case json_type_array:
+ controlsCount = (int) json_object_array_length(controlsJ);
+ halMapControlsJsonIsAnArray = 1;
+ break;
+
+ case json_type_object:
+ controlsCount = 1;
+ break;
+
+ default:
+ AFB_API_ERROR(apiHandle,
+ "Content of 'halmap' controls section is not valid ('%s')",
+ json_object_get_string(controlsJ));
+ return -3;
+ }
+
+ for(idx = 0; idx < controlsCount; idx++) {
+ currentHalMapControlJ = halMapControlsJsonIsAnArray ? json_object_array_get_idx(controlsJ, idx) : controlsJ;
+
+ currentHalMapData = HalUtlAddHalMapDataToHalMapDataList(halMapListHead);
+
+ currentHalMapData->targetUid = strdup(uid);
+ if(! currentHalMapData->targetUid) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'targetUid' string");
+ return -4;
+ }
+
+ if(info) {
+ currentHalMapData->targetInfo = strdup(info);
+ if(! currentHalMapData->targetInfo) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'targetInfo' string");
+ return -5;
+ }
+ }
+
+ currentHalMapData->targetedDependency = strdup(target);
+ if(! currentHalMapData->targetedDependency) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'targetedDependency' string");
+ return -6;
+ }
+
+ err = InternalHalProcessOneHalMapControl(apiHandle,
+ currentHalMapData,
+ currentHalMapControlJ);
+ if(err) {
+ AFB_API_ERROR(apiHandle,
+ "Error %i was returned when tried to proccess halmap control %i ('%s')",
+ err,
+ idx,
+ json_object_get_string(currentHalMapControlJ));
+ HalUtlRemoveSelectedHalMapData(halMapListHead, currentHalMapData);
+ return -7;
+ }
+ }
+
+ return 0;
+}
+
+int InternalHalProcessAllHalMap(afb_api_t apiHandle,
+ json_object *halMapJ,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead)
+{
+ int idx, targetCount, err = 0, halMapJsonIsAnArray = 0;
+
+ json_object *currentHalMapTargetJ;
+ json_type alsaMapType;
+
+ AFB_API_DEBUG(apiHandle, "halMapJ='%s'", json_object_get_string(halMapJ));
+
+ alsaMapType = json_object_get_type(halMapJ);
+ switch(alsaMapType) {
+ case json_type_array:
+ targetCount = (int) json_object_array_length(halMapJ);
+ halMapJsonIsAnArray = 1;
+ break;
+
+ case json_type_object:
+ targetCount = 1;
+ break;
+
+ default:
+ AFB_API_ERROR(apiHandle,
+ "Content of 'halmap' section is not valid ('%s')",
+ json_object_get_string(halMapJ));
+ return -1;
+ }
+
+ for(idx = 0; idx < targetCount; idx++) {
+ currentHalMapTargetJ = halMapJsonIsAnArray ? json_object_array_get_idx(halMapJ, idx) : halMapJ;
+
+ err = InternalHalProcessOneHalMapObject(apiHandle,
+ currentHalMapTargetJ,
+ halMapListHead,
+ halDevicesToProbeListHead);
+ if(err) {
+ AFB_API_ERROR(apiHandle,
+ "Error %i was returned when tried to proccess halmap target %i ('%s')",
+ err,
+ idx,
+ json_object_get_string(currentHalMapTargetJ));
+ HalUtlRemoveAllHalMapData(halMapListHead);
+ return -2;
+ }
+ }
+
+ return 0;
+}
+
+int InternalHalHandleOneHalMapObject(afb_api_t apiHandle, struct InternalHalAlsaMap *halMapData)
+{
+ int err;
+
+ char cardNbString[6];
+
+ json_object *valueJ, *convertedValueJ = NULL;
+
+ CtlActionT *toLoadAction;
+
+ halMapData->alsaControlEvent = afb_api_make_event(apiHandle, halMapData->uid);
+ if(! halMapData->alsaControlEvent) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to create event for alsa control with uid %s",
+ halMapData->uid);
+ return -1;
+ }
+
+ snprintf(cardNbString, sizeof(cardNbString), "hw:%i", halMapData->cardNb);
+
+ if(halMapData->ctl.alsaCtlCreation) {
+ if(InternalHalCreateAlsaCtl(apiHandle, cardNbString, &halMapData->ctl)) {
+ AFB_API_ERROR(apiHandle, "An error happened when trying to create a new alsa control");
+ return -2;
+ }
+ halMapData->ctl.alsaCtlProperties = halMapData->ctl.alsaCtlCreation;
+ }
+ else {
+ halMapData->ctl.alsaCtlProperties = calloc(1, sizeof(struct InternalHalAlsaCtlProperties));
+ if(! halMapData->ctl.alsaCtlProperties) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to allocate alsa properties data structure for control");
+ return -3;
+ }
+
+ if(InternalHalUpdateAlsaCtlProperties(apiHandle, cardNbString, &halMapData->ctl)) {
+ AFB_API_ERROR(apiHandle, "An error happened when trying to get existing alsa control info");
+ free(halMapData->ctl.alsaCtlProperties);
+ halMapData->ctl.alsaCtlProperties = NULL;
+ return -4;
+ }
+ }
+
+ if(halMapData->actionJ) {
+ toLoadAction = malloc(sizeof(CtlActionT));
+ if(! toLoadAction) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to allocate structure used to store action to perform "
+ "when the corresponding ALSA control is detected");
+ return -5;
+ }
+
+ if(ActionLoadOne(apiHandle, toLoadAction, halMapData->actionJ, 0)) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to load action using alsa object : '%s'",
+ json_object_get_string(halMapData->actionJ));
+ free(toLoadAction);
+ return -6;
+ }
+
+ halMapData->action = toLoadAction;
+ }
+
+ if(InternalHalSubscribeToAlsacoreCardEvent(apiHandle, cardNbString)) {
+ AFB_API_ERROR(apiHandle, "Error when trying to subscribe to alsacore event for audio card '%s'", cardNbString);
+ return -7;
+ }
+
+ if(halMapData->ctl.value) {
+ // TBD JAI : handle alsa controls type
+ valueJ = json_object_new_int(halMapData->ctl.value);
+ if(! valueJ) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to allocate ALSA control value json string");
+ return -8;
+ }
+
+ err = 0;
+
+ if(InternalHalConvertJsonValues(apiHandle,
+ halMapData->ctl.alsaCtlProperties,
+ valueJ,
+ &convertedValueJ,
+ CONVERSION_NORMALIZED_TO_ALSACORE)) {
+ AFB_API_ERROR(apiHandle, "Error when trying to convert initiate value json '%s'", json_object_get_string(valueJ));
+ err = -9;
+ }
+ else if(InternalHalSetAlsaCtlValue(apiHandle, cardNbString, halMapData->ctl.numid, convertedValueJ)) {
+ AFB_API_ERROR(apiHandle,
+ "Error while trying to set initial value on alsa control %i, device '%s', value '%s'",
+ halMapData->ctl.numid,
+ cardNbString,
+ json_object_get_string(valueJ));
+ err = -10;
+ }
+
+ json_object_put(valueJ);
+
+ if(convertedValueJ)
+ json_object_put(convertedValueJ);
+
+ if(err)
+ return err;
+ }
+
+ if(afb_api_add_verb(apiHandle, halMapData->uid, NULL, InternalHalActionOnAlsaCtl, (void *) halMapData, NULL, 0, 0)) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to create verb %s for alsa control named %s on card %i",
+ halMapData->uid,
+ halMapData->ctl.name ? halMapData->ctl.name : "'N/A'",
+ halMapData->cardNb);
+ return -11;
+ }
+
+ return 0;
+}
+
+int InternalHalUnmanageOneHalMapObject(afb_api_t apiHandle, struct InternalHalAlsaMap *halMapData)
+{
+ int err;
+
+ char cardNbString[6];
+
+ if(! apiHandle || ! halMapData) {
+ AFB_API_ERROR(apiHandle, "Invalid argument(s)");
+ return -1;
+ }
+
+ snprintf(cardNbString, sizeof(cardNbString), "hw:%i", halMapData->cardNb);
+
+ err = afb_api_del_verb(apiHandle, halMapData->uid, NULL);
+ if(err)
+ AFB_API_WARNING(apiHandle,
+ "Error %i returned when tried to remove halmap verb %s, "
+ "verb may have not been added before",
+ err,
+ halMapData->uid);
+
+ free(halMapData->action);
+ halMapData->action = NULL;
+
+ if(halMapData->ctl.alsaCtlCreation) {
+ err = InternalHalDeleteAlsaCtl(apiHandle, cardNbString, &halMapData->ctl);
+ if(err)
+ AFB_API_WARNING(apiHandle,
+ "Error %i returned when tried to custom ALSA control '%s', "
+ "custom control may have not been added before",
+ err,
+ halMapData->ctl.name);
+ }
+ else {
+ free(halMapData->ctl.alsaCtlProperties);
+ halMapData->ctl.alsaCtlProperties = NULL;
+ }
+
+ if(afb_event_is_valid(halMapData->alsaControlEvent)) {
+ afb_event_unref(halMapData->alsaControlEvent);
+ halMapData->alsaControlEvent = NULL;
+ }
+
+ halMapData->cardNb = HAL_UNKNOWN_DEVICE;
+
+ return 0;
+}
+
+int InternalHalProcessDependencyRelatedHalmap(afb_api_t apiHandle,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead,
+ char *targetedDependency,
+ enum DependencySelectionType halMapSelectionType,
+ enum HalMapProcessingType halMapProcessingType)
+{
+ int err = 0, validatedHalMap;
+
+ struct InternalHalAlsaMap *currentHalMapData;
+
+ if(cds_list_empty(halMapListHead)) {
+ AFB_API_ERROR(apiHandle, "HalMap list is empty, nothing to process");
+ return 0;
+ }
+
+ if(halMapSelectionType == UID_CORRESPONDING_DEPENDENCIES &&
+ ! targetedDependency) {
+ AFB_API_ERROR(apiHandle, "Invalid targeted dependency");
+ return -1;
+ }
+
+ cds_list_for_each_entry(currentHalMapData, halMapListHead, node) {
+ validatedHalMap = 0;
+ switch(halMapSelectionType) {
+ case ALL_DEPENDENCIES:
+ validatedHalMap = 1;
+ break;
+
+ case UID_CORRESPONDING_DEPENDENCIES:
+ if(! strcmp(targetedDependency, currentHalMapData->targetedDependency))
+ validatedHalMap = 1;
+ break;
+
+ default:
+ AFB_API_ERROR(apiHandle, "Invalid dependencies enum type");
+ return -2;
+ }
+
+ if(validatedHalMap) {
+ currentHalMapData->cardNb = HalUtlGetProbedDeviceCardNbUsingUid(halDevicesToProbeListHead,
+ currentHalMapData->targetedDependency);
+ if(currentHalMapData->cardNb == HAL_UNKNOWN_DEVICE) {
+ AFB_API_WARNING(apiHandle,
+ "Current halmap control %s can't be %s because corresponding "
+ "dependency ('%s') card is not available at the moment",
+ currentHalMapData->uid,
+ (halMapProcessingType == HANDLE_SELECTED_HALMAP) ? "handled" : "unmanaged",
+ currentHalMapData->targetedDependency);
+ continue;
+ }
+
+ if(halMapProcessingType == HANDLE_SELECTED_HALMAP)
+ err = InternalHalHandleOneHalMapObject(apiHandle, currentHalMapData);
+ else
+ err = InternalHalUnmanageOneHalMapObject(apiHandle, currentHalMapData);
+
+ if(err) {
+ AFB_API_ERROR(apiHandle,
+ "Error %i was returned when tried to %s halmap control with uid %s",
+ err,
+ (halMapProcessingType == HANDLE_SELECTED_HALMAP) ? "handle" : "unmanage",
+ currentHalMapData->uid);
+ return -3;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int InternalHalHandleDependencyRelatedHalmap(afb_api_t apiHandle,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead,
+ char *targetedDependency)
+{
+ return InternalHalProcessDependencyRelatedHalmap(apiHandle,
+ halMapListHead,
+ halDevicesToProbeListHead,
+ targetedDependency,
+ UID_CORRESPONDING_DEPENDENCIES,
+ HANDLE_SELECTED_HALMAP);
+}
+
+int InternalHalUnmanageDependencyRelatedHalmap(afb_api_t apiHandle,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead,
+ char *targetedDependency)
+{
+ return InternalHalProcessDependencyRelatedHalmap(apiHandle,
+ halMapListHead,
+ halDevicesToProbeListHead,
+ targetedDependency,
+ UID_CORRESPONDING_DEPENDENCIES,
+ UNMANAGE_SELECTED_HALMAP);
+}
+
+int InternalHalHandleAllHalMap(afb_api_t apiHandle,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead)
+{
+ return InternalHalProcessDependencyRelatedHalmap(apiHandle,
+ halMapListHead,
+ halDevicesToProbeListHead,
+ NULL,
+ ALL_DEPENDENCIES,
+ HANDLE_SELECTED_HALMAP);
+}
+
+int InternalHalUnmanageAllHalMap(afb_api_t apiHandle,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead)
+{
+ return InternalHalProcessDependencyRelatedHalmap(apiHandle,
+ halMapListHead,
+ halDevicesToProbeListHead,
+ NULL,
+ ALL_DEPENDENCIES,
+ UNMANAGE_SELECTED_HALMAP);
+}
+
+int InternalHalHalMapConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *AlsaMapJ)
+{
+ CtlConfigT *ctrlConfig;
struct HalData *currentHalData;
- json_object *requestJson,
+ ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
+ if(! ctrlConfig)
+ return -1;
+
+ currentHalData = (struct HalData *) getExternalData(ctrlConfig);
+ if(! currentHalData)
+ return -2;
+
+ if(AlsaMapJ) {
+ if(InternalHalProcessAllHalMap(apiHandle,
+ AlsaMapJ,
+ &currentHalData->internalHalData->halMapListHead,
+ &currentHalData->internalHalData->probedDevicesListHead)) {
+ AFB_API_ERROR(apiHandle, "Failed to process 'halmap' section");
+ HalUtlRemoveAllHalMapData(&currentHalData->internalHalData->halMapListHead);
+ return -4;
+ }
+ }
+ else if(cds_list_empty(&currentHalData->internalHalData->halMapListHead)) {
+ AFB_API_WARNING(apiHandle, "No alsa controls defined in 'halmap' section");
+ return 1;
+ }
+ else if(InternalHalHandleAllHalMap(apiHandle,
+ &currentHalData->internalHalData->halMapListHead,
+ &currentHalData->internalHalData->probedDevicesListHead)) {
+ AFB_API_ERROR(apiHandle, "Failed to handle 'halmap' section");
+ return -5;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Internals HAL verbs functions *
+ ******************************************************************************/
+
+int GenerateInternalHalInfoJson(afb_api_t apiHandle,
+ struct HalData *currentHalData,
+ json_object *requestJ,
+ json_object **returnedJ)
+{
+ int wrapRet, verboseLevel = 2;
+
+ char *apiToCall, *returnedError = NULL, *returnedInfo = NULL;
+
+ json_object *mixerRequestJ = NULL,
*toReturnJ = NULL,
*requestAnswer,
*streamsArray,
*controlsArray,
*dependenciesArray;
+ if(! apiHandle || ! currentHalData || ! returnedJ)
+ return -1;
+
+ *returnedJ = NULL;
+
+ if(requestJ) {
+ wrapRet = wrap_json_unpack(requestJ,
+ "{s?:i, s?:o !}",
+ "verbose", &verboseLevel,
+ "mixer", &mixerRequestJ);
+ if(wrapRet)
+ return -2;
+ }
+
+ if(mixerRequestJ &&
+ json_object_is_type(mixerRequestJ, json_type_object) &&
+ json_object_get_object(mixerRequestJ)->count > 0) {
+ apiToCall = currentHalData->internalHalData->mixerApiName;
+ if(! apiToCall)
+ return-3;
+
+ if(InternalHalGetInfoFromMixer(apiHandle,
+ apiToCall,
+ mixerRequestJ,
+ &toReturnJ,
+ &returnedError,
+ &returnedInfo))
+ return -4;
+
+ *returnedJ = toReturnJ;
+ return 0;
+ }
+
+ requestAnswer = json_object_new_object();
+
+ if(verboseLevel >= 0) {
+ dependenciesArray = HalUtlGetJsonArrayForAllDependencies(apiHandle,
+ &currentHalData->internalHalData->probedDevicesListHead,
+ DEPENDENCY_FULL_JSON);
+ if(dependenciesArray)
+ json_object_object_add(requestAnswer, "dependencies", dependenciesArray);
+ }
+
+ if(verboseLevel >= 1) {
+ controlsArray = HalUtGetJsonArrayForAllHalMapControls(apiHandle,
+ &currentHalData->internalHalData->halMapListHead);
+ if(controlsArray)
+ json_object_object_add(requestAnswer, "controls", controlsArray);
+ }
+
+ if(verboseLevel >= 2) {
+ streamsArray = HalUtlGetJsonArrayForAllMixersData(apiHandle,
+ &currentHalData->internalHalData->streamsDataListHead);
+ if(! streamsArray)
+ streamsArray = json_object_new_array(); // Always return an array for 4a-hl-api (to prevent segfault)
+ json_object_object_add(requestAnswer, "streams", streamsArray);
+ }
+
+ if(! json_object_get_object(requestAnswer)->count) {
+ json_object_put(requestAnswer);
+ requestAnswer = NULL;
+ }
+
+ *returnedJ = requestAnswer;
+ return 0;
+}
+
+void InternalHalInfoVerb(afb_req_t request)
+{
+ int err;
+
+ afb_api_t apiHandle;
+ CtlConfigT *ctrlConfig;
+
+ struct HalData *currentHalData;
+
+ json_object *requestJ, *toReturnJ;
+
apiHandle = afb_req_get_api(request);
if(! apiHandle) {
afb_req_fail(request, "api_handle", "Can't get current internal hal api handle");
@@ -1308,55 +1439,19 @@ void InternalHalInfo(afb_req_t request)
return;
}
- requestJson = afb_req_json(request);
- if(! requestJson) {
- AFB_REQ_NOTICE(request, "Can't get request json");
- }
- else if(json_object_is_type(requestJson, json_type_object) && json_object_get_object(requestJson)->count > 0) {
- apiToCall = currentHalData->internalHalData->mixerApiName;
- if(! apiToCall) {
- afb_req_fail(request, "mixer_api", "Can't get mixer api");
- return;
- }
-
- if(InternalHalGetInfoFromMixer(apiHandle, apiToCall, requestJson, &toReturnJ, &returnedError, &returnedInfo)) {
- afb_req_fail_f(request,
- "mixer_info",
- "Call to mixer info verb didn't succeed with status '%s' and info '%s'",
- returnedError ? returnedError : "not returned",
- returnedInfo ? returnedInfo : "not returned");
- return;
- }
+ requestJ = afb_req_json(request);
- afb_req_success(request, toReturnJ, "Mixer requested data");
+ err = GenerateInternalHalInfoJson(apiHandle, currentHalData, requestJ, &toReturnJ);
+ if(err) {
+ afb_req_fail_f(request,
+ "get_info_fail",
+ "Error %i happened when tried to get json info for request json '%s'",
+ err,
+ json_object_get_string(requestJ));
return;
}
- requestAnswer = json_object_new_object();
-
- dependenciesArray = HalUtlGetJsonArrayForAllDependencies(apiHandle,
- &currentHalData->internalHalData->probedDevicesListHead,
- DEPENDENCY_FULL_JSON);
- if(dependenciesArray)
- json_object_object_add(requestAnswer, "dependencies", dependenciesArray);
-
- streamsArray = HalUtlGetJsonArrayForAllMixersData(apiHandle,
- &currentHalData->internalHalData->streamsDataListHead);
- if(! streamsArray)
- streamsArray = json_object_new_array(); // Always return an array for 4a-hl-api (to prevent segfault)
- json_object_object_add(requestAnswer, "streams", streamsArray);
-
- controlsArray = HalUtGetJsonArrayForAllHalMapControls(apiHandle,
- &currentHalData->internalHalData->halMapListHead);
- if(controlsArray)
- json_object_object_add(requestAnswer, "controls", controlsArray);
-
- if(! json_object_get_object(requestAnswer)->count) {
- json_object_put(requestAnswer);
- requestAnswer = NULL;
- }
-
- afb_req_success(request, requestAnswer, "Requested data");
+ afb_req_success(request, toReturnJ, "Requested data");
}
void InternalHalSubscribeUnsubscribe(afb_req_t request, enum SubscribeUnsubscribeType subscribeUnsubscribeType)
diff --git a/src/4a-internals-hal/4a-internals-hal-cb.h b/src/4a-internals-hal/4a-internals-hal-cb.h
index 4864d46..2224046 100644
--- a/src/4a-internals-hal/4a-internals-hal-cb.h
+++ b/src/4a-internals-hal/4a-internals-hal-cb.h
@@ -24,12 +24,18 @@
#include <ctl-config.h>
-// Enum for the type of dependencies handling
-enum DependenciesHandlingType {
+// Enum for to define which type of dependency selection we want to use
+enum DependencySelectionType {
ALL_DEPENDENCIES = 0,
UID_CORRESPONDING_DEPENDENCIES = 1
};
+// Enum to define if to to handle or to unmanage a selected halmap
+enum HalMapProcessingType {
+ HANDLE_SELECTED_HALMAP = 0,
+ UNMANAGE_SELECTED_HALMAP = 1
+};
+
// Enum for the type of subscription
enum SubscribeUnsubscribeType {
SUBSCRIPTION = 0,
@@ -39,22 +45,40 @@ enum SubscribeUnsubscribeType {
// Internals HAL event handler function
void InternalHalDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json_object *eventJ);
-// Internals HAL - 'halmixer' section parsing/handling functions
-int InternalHalHalMixerConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *MixerJ);
-
-// Internals HAL - 'halmap' section parsing/handling functions
-int InternalHalHalMapConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *halMapJ);
-
// Internals HAL - 'haldependencies' section parsing/handling functions
int InternalHalHandleHalDependencies(afb_api_t apiHandle,
struct HalData *currentHalData,
struct cds_list_head *halDevicesToProbeListHead,
- enum DependenciesHandlingType dependenciesHandlingType,
+ enum DependencySelectionType dependenciesSelectionType,
char *uid);
int InternalHalHalDependenciesConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *DependenciesJ);
+// Internals HAL - 'halmixer' section parsing/handling functions
+int InternalHalHalMixerConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *MixerJ);
+
+// Internals HAL - 'halmap' section parsing/handling functions
+int InternalHalHandleDependencyRelatedHalmap(afb_api_t apiHandle,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead,
+ char *targetedDependency);
+int InternalHalUnmanageDependencyRelatedHalmap(afb_api_t apiHandle,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead,
+ char *targetedDependency);
+int InternalHalHandleAllHalMap(afb_api_t apiHandle,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead);
+int InternalHalUnmanageAllHalMap(afb_api_t apiHandle,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead);
+int InternalHalHalMapConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *halMapJ);
+
// Internals HAL verbs functions
-void InternalHalInfo(afb_req_t request);
+int GenerateInternalHalInfoJson(afb_api_t apiHandle,
+ struct HalData *currentHalData,
+ json_object *requestJ,
+ json_object **returnedJ);
+void InternalHalInfoVerb(afb_req_t request);
void InternalHalSubscribe(afb_req_t request);
void InternalHalUnsubscribe(afb_req_t request);
diff --git a/src/4a-internals-hal/4a-internals-hal-mixer-link.c b/src/4a-internals-hal/4a-internals-hal-mixer-link.c
index 56dc840..19fb3a0 100644
--- a/src/4a-internals-hal/4a-internals-hal-mixer-link.c
+++ b/src/4a-internals-hal/4a-internals-hal-mixer-link.c
@@ -142,7 +142,7 @@ int InternalHalHandleMixerAttachResponse(afb_api_t apiHandle, struct InternalHal
return 0;
}
-int InternalHalAttachToMixer(afb_api_t apiHandle)
+int InternalHalAttachDependencyToMixer(afb_api_t apiHandle, struct InternalHalProbedDevice *probedDeviceToAttach)
{
int err = 0, mixerError;
@@ -194,9 +194,10 @@ int InternalHalAttachToMixer(afb_api_t apiHandle)
return -6;
}
- dependencyJ = HalUtlGetJsonArrayForAllDependencies(apiHandle,
- &currentHalData->internalHalData->probedDevicesListHead,
- DEPENDENCY_COMPACT_JSON);
+ dependencyJ = HalUtlGetJsonArrayForAllDependenciesInfoWithHandledDependency(apiHandle,
+ &currentHalData->internalHalData->probedDevicesListHead,
+ DEPENDENCY_COMPACT_JSON,
+ probedDeviceToAttach->uid);
if(! dependencyJ) {
AFB_API_ERROR(apiHandle, "Didn't succeed to generate available dependencies compact json array");
return -7;
@@ -251,10 +252,14 @@ int InternalHalAttachToMixer(afb_api_t apiHandle)
MIXER_ATTACH_VERB,
apiToCall,
json_object_get_string(responseJ));
- currentHalData->status = HAL_STATUS_READY;
}
}
+ if(err)
+ probedDeviceToAttach->mixerLinkStatus = DEPENDENCY_MIXER_ATTACH_FAILED;
+ else
+ probedDeviceToAttach->mixerLinkStatus = DEPENDENCY_MIXER_ATTACH_SUCCEED;
+
if(responseJ)
json_object_put(responseJ);
@@ -264,6 +269,87 @@ int InternalHalAttachToMixer(afb_api_t apiHandle)
return err;
}
+int InternalHalDetachDependencyToMixer(afb_api_t apiHandle, struct InternalHalProbedDevice *probedDeviceToDetach)
+{
+ int err, toReturn = 0;
+
+ char *apiToCall, *returnedError = NULL, *returnedInfo = NULL;
+
+ CtlConfigT *ctrlConfig;
+
+ struct HalData *currentHalData;
+
+ json_object *requestJ, *dependencyJ, *responseJ = NULL;
+
+ if(! apiHandle) {
+ AFB_API_ERROR(apiHandle, "Can't get current internal hal api handle");
+ return -1;
+ }
+
+ ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
+ if(! ctrlConfig) {
+ AFB_API_ERROR(apiHandle, "Can't get current internal hal controller config");
+ return -2;
+ }
+
+ currentHalData = (struct HalData *) getExternalData(ctrlConfig);
+ if(! currentHalData) {
+ AFB_API_ERROR(apiHandle, "Can't get current internal hal controller data");
+ return -3;
+ }
+
+ apiToCall = currentHalData->internalHalData->mixerApiName;
+ if(! apiToCall) {
+ AFB_API_ERROR(apiHandle, "Can't get mixer api");
+ return -4;
+ }
+
+ dependencyJ = HalUtlGetJsonForSpecificDependenciesUsingUid(apiHandle,
+ &currentHalData->internalHalData->probedDevicesListHead,
+ probedDeviceToDetach->uid,
+ DEPENDENCY_COMPACT_JSON);
+ if(! dependencyJ) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to get dependency %s compact json array", probedDeviceToDetach->uid);
+ return -5;
+ }
+
+ err = wrap_json_pack(&requestJ, "{s:o}", "dependencies", dependencyJ);
+ if(err) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to allocate detach dependency %s request json", probedDeviceToDetach->uid);
+ return -6;
+ }
+
+ if(afb_api_call_sync(apiHandle,
+ apiToCall,
+ MIXER_DETACH_VERB,
+ requestJ,
+ &responseJ,
+ &returnedError,
+ &returnedInfo)) {
+ AFB_API_ERROR(apiHandle,
+ "Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s'",
+ MIXER_DETACH_VERB,
+ apiToCall,
+ returnedError ? returnedError : "not returned",
+ returnedInfo ? returnedInfo : "not returned");
+ toReturn = -7;
+ }
+
+ if(toReturn)
+ probedDeviceToDetach->mixerLinkStatus = DEPENDENCY_MIXER_DETACH_FAILED;
+ else
+ probedDeviceToDetach->mixerLinkStatus = DEPENDENCY_MIXER_DETACH_SUCCEED;
+
+ if(responseJ)
+ json_object_put(responseJ);
+
+ free(returnedError);
+ free(returnedInfo);
+
+ return toReturn;
+}
+
int InternalHalGetInfoFromMixer(afb_api_t apiHandle,
char *apiToCall,
json_object *requestJson,
diff --git a/src/4a-internals-hal/4a-internals-hal-mixer-link.h b/src/4a-internals-hal/4a-internals-hal-mixer-link.h
index 7132aca..af80844 100644
--- a/src/4a-internals-hal/4a-internals-hal-mixer-link.h
+++ b/src/4a-internals-hal/4a-internals-hal-mixer-link.h
@@ -29,12 +29,14 @@
#include "4a-hal-utilities-data.h"
#define MIXER_ATTACH_VERB "attach"
+#define MIXER_DETACH_VERB "detach"
#define MIXER_INFO_VERB "info"
#define HAL_ALL_STREAMS_VERB "all-streams"
// Internals HAL handle mixer calls functions
-int InternalHalAttachToMixer(afb_api_t apiHandle);
+int InternalHalAttachDependencyToMixer(afb_api_t apiHandle, struct InternalHalProbedDevice *probedDeviceToAttach);
+int InternalHalDetachDependencyToMixer(afb_api_t apiHandle, struct InternalHalProbedDevice *probedDeviceToDetach);
int InternalHalGetInfoFromMixer(afb_api_t apiHandle,
char *apiToCall,
json_object *requestJson,