diff options
author | Jonathan Aillet <jonathan.aillet@iot.bzh> | 2019-04-18 11:51:51 +0200 |
---|---|---|
committer | Jonathan Aillet <jonathan.aillet@iot.bzh> | 2019-05-24 16:35:06 +0200 |
commit | 907e2005ef3c7dcb5cf39c2f157d59fdf8685708 (patch) | |
tree | ac1ac3fa464c1a17bf99fab588fe75ed7b2315ff | |
parent | 95a00389d224939e809f651cb095c3ecbf594c56 (diff) |
Add functions to process 'haldependencies'
Add functions to process new 'haldependencies' section.
This new section will be used to probe for multiple audio device
using only one hal. Each probed device could be 'mandatory',
'dynamic' (optional but periodically probed),
or 'static' (optional and probed only at startup).
The result of handling this section will be used by softmixer and
in 'halmap' section.
BUG-AGL: SPEC-2329
Change-Id: Id4ea2a9c5d87158f0cfa9a88bc5c9296770a6a9b
Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-cb.c | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/src/4a-internals-hal/4a-internals-hal-cb.c b/src/4a-internals-hal/4a-internals-hal-cb.c index 10ed6c0..d0e4909 100644 --- a/src/4a-internals-hal/4a-internals-hal-cb.c +++ b/src/4a-internals-hal/4a-internals-hal-cb.c @@ -457,6 +457,323 @@ int InternalHalHalMapConfig(afb_api_t apiHandle, CtlSectionT *section, json_obje } /******************************************************************************* + * Internals HAL - 'haldependencies' section parsing/handling functions * + ******************************************************************************/ + +json_type InternalHalDependencyGetExpectedContentTypeFromKey(char *key) +{ + if(! key) + return json_type_null; + + if(! strcmp(key, "cardNb") || + ! strcmp(key, "playbackDeviceNb")) + return json_type_int; + + if(! strcmp(key, "cardPath") || + ! strcmp(key, "cardId") || + ! strcmp(key, "cardShortName") || + ! strcmp(key, "cardLongName") || + ! strcmp(key, "cardDriver") || + ! strcmp(key, "cardMixerName") || + ! strcmp(key, "cardComponents") || + ! strcmp(key, "playbackDeviceId") || + ! strcmp(key, "playbackDeviceName")) + return json_type_string; + + if(! strcmp(key, "AnyOf")) + return json_type_object; + + return json_type_null; +} + +int InternalHalDependencyIsObjectToAddValid(json_object *objectToAddJ) +{ + struct json_object_iterator currentPropertyToAdd, lastPropertyToAdd; + json_type currentPropertyValueExpectedType; + + if(! objectToAddJ) + return -1; + + currentPropertyToAdd = json_object_iter_begin(objectToAddJ); + lastPropertyToAdd = json_object_iter_end(objectToAddJ); + + while(! json_object_iter_equal(¤tPropertyToAdd, &lastPropertyToAdd)) { + currentPropertyValueExpectedType = InternalHalDependencyGetExpectedContentTypeFromKey((char *) json_object_iter_peek_name(¤tPropertyToAdd)); + if(! json_object_is_type(json_object_iter_peek_value(¤tPropertyToAdd), + currentPropertyValueExpectedType)) + return -2; + + json_object_iter_next(¤tPropertyToAdd); + } + + return 0; +} + +int InternalHalProcessOneDependencyProperty(afb_api_t apiHandle, char *key, json_object *valueJ, json_object **deviceToProbeRequestGenerationJ) +{ + int valueIdx, previouslyGeneratedRequestIdx, valueCount, previouslyGeneratedRequestCount; + + json_object *previouslyGeneratedRequestJ, *updatedGeneratedRequestJ, *currentValueJ, *objectToBeefUpJ; + json_type expectedContentType, contentType; + + if(! key || ! valueJ || ! deviceToProbeRequestGenerationJ) { + AFB_API_ERROR(apiHandle, "Invalid argument(s)"); + return -1; + } + + previouslyGeneratedRequestJ = *deviceToProbeRequestGenerationJ; + if(! previouslyGeneratedRequestJ) { + previouslyGeneratedRequestCount = 0; + } + else if(! json_object_is_type(previouslyGeneratedRequestJ, json_type_array)) { + AFB_API_ERROR(apiHandle, + "Invalid previously generated request (not an array : '%s')", + json_object_get_string(previouslyGeneratedRequestJ)); + return -2; + } + else { + previouslyGeneratedRequestCount = (int) json_object_array_length(previouslyGeneratedRequestJ); + } + + expectedContentType = InternalHalDependencyGetExpectedContentTypeFromKey(key); + if(expectedContentType == json_type_null) { + AFB_API_ERROR(apiHandle, "Unrecognized key '%s'", key); + return -3; + } + + contentType = json_object_get_type(valueJ); + switch(contentType) { + case json_type_int: + case json_type_string: + valueCount = 1; + break; + + case json_type_array: + valueCount = (int) json_object_array_length(valueJ); + break; + + default: + AFB_API_ERROR(apiHandle, + "Value doesn't have the expected type (value: '%s')", + json_object_get_string(valueJ)); + return -4; + } + + updatedGeneratedRequestJ = json_object_new_array(); + if(! updatedGeneratedRequestJ) { + AFB_API_ERROR(apiHandle, "Didn't succeed to allocate updated request json array"); + return -5; + } + + for(valueIdx = 0; valueIdx < valueCount; valueIdx++) { + if(contentType == json_type_array) + currentValueJ = json_object_array_get_idx(valueJ, valueIdx); + else + currentValueJ = valueJ; + + if(! json_object_is_type(currentValueJ, expectedContentType)) { + AFB_API_ERROR(apiHandle, + "Current value '%s' (index %i in value array) does not have the expected type, " + "won't be able to process property (key '%s')", + json_object_get_string(currentValueJ), + valueIdx, + key); + json_object_put(updatedGeneratedRequestJ); + return -6; + } + + previouslyGeneratedRequestIdx = 0; + do { + if(! previouslyGeneratedRequestCount) + objectToBeefUpJ = json_object_new_object(); + else + objectToBeefUpJ = wrap_json_clone(json_object_array_get_idx(previouslyGeneratedRequestJ, previouslyGeneratedRequestIdx)); + + if(! objectToBeefUpJ) { + AFB_API_ERROR(apiHandle, "Didn't succeed to allocate/clone object to beef up json object"); + json_object_put(objectToBeefUpJ); + json_object_put(updatedGeneratedRequestJ); + return -7; + } + + if(! json_object_is_type(currentValueJ, json_type_object)) { + json_object_object_add(objectToBeefUpJ, key, wrap_json_clone(currentValueJ)); + } + else if(! InternalHalDependencyIsObjectToAddValid(currentValueJ)) { + wrap_json_object_add(objectToBeefUpJ, wrap_json_clone(currentValueJ)); + } + else { + AFB_API_ERROR(apiHandle, + "Object '%s' is not valid", + json_object_get_string(currentValueJ)); + json_object_put(objectToBeefUpJ); + json_object_put(updatedGeneratedRequestJ); + return -8; + } + + json_object_array_add(updatedGeneratedRequestJ, objectToBeefUpJ); + + previouslyGeneratedRequestIdx++; + } while(previouslyGeneratedRequestIdx < previouslyGeneratedRequestCount); + } + + *deviceToProbeRequestGenerationJ = updatedGeneratedRequestJ; + json_object_put(previouslyGeneratedRequestJ); + + return 0; +} + +int InternalHalProcessOneHalDependency(afb_api_t apiHandle, json_object *DependencyJ, struct InternalHalProbedDevice *halDeviceToProbe) +{ + int ret; + + json_object *dependencyUidJ, *dependencyClassJ; + struct json_object_iterator dependencyCurrentProperty, dependencyLastProperty; + + if(! apiHandle || ! DependencyJ || ! halDeviceToProbe) { + AFB_API_ERROR(apiHandle, "Invalid argument(s)"); + return -1; + } + + if(! json_object_object_get_ex(DependencyJ, "uid", &dependencyUidJ)) { + AFB_API_ERROR(apiHandle, + "No dependency 'uid' has been specified, won't be able to process it ('%s')", + json_object_get_string(DependencyJ)); + return -2; + } + else if(! json_object_is_type(dependencyUidJ, json_type_string)) { + AFB_API_ERROR(apiHandle, + "Specified dependency 'uid' is not a string ('%s')", + json_object_get_string(dependencyUidJ)); + return -3; + } + + halDeviceToProbe->uid = strdup(json_object_get_string(dependencyUidJ)); + if(! halDeviceToProbe->uid) { + AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) dependency 'uid' string"); + return -4; + } + + if(! json_object_object_get_ex(DependencyJ, "class", &dependencyClassJ)) { + AFB_API_NOTICE(apiHandle, + "No class has been specified for dependency with uid:'%s', will be considered as static", + halDeviceToProbe->uid); + halDeviceToProbe->deviceClass = STATIC_PROBED_DEVICE; + } + else if(! json_object_is_type(dependencyClassJ, json_type_string)) { + AFB_API_ERROR(apiHandle, + "Specified dependency class is not a string ('%s')", + json_object_get_string(dependencyClassJ)); + return -5; + } + else { + halDeviceToProbe->deviceClass = HalUtlGetProbedDeviceClassFromString((char *) json_object_get_string(dependencyClassJ)); + if(halDeviceToProbe->deviceClass == INVALID_PROBED_DEVICE) { + AFB_API_ERROR(apiHandle, + "Specified device class is unknown ('%s')", + json_object_get_string(dependencyClassJ)); + return -6; + } + } + + dependencyCurrentProperty = json_object_iter_begin(DependencyJ); + dependencyLastProperty = json_object_iter_end(DependencyJ); + + while(! json_object_iter_equal(&dependencyCurrentProperty, &dependencyLastProperty)) { + if(! strcmp("uid", json_object_iter_peek_name(&dependencyCurrentProperty)) || + ! strcmp("class", json_object_iter_peek_name(&dependencyCurrentProperty))) { + json_object_iter_next(&dependencyCurrentProperty); + continue; + } + + ret = InternalHalProcessOneDependencyProperty(apiHandle, + (char *) json_object_iter_peek_name(&dependencyCurrentProperty), + json_object_iter_peek_value(&dependencyCurrentProperty), + &halDeviceToProbe->requestedDeviceJ); + if(ret) { + AFB_API_ERROR(apiHandle, + "Error %i while processing property with key '%s' and value '%s' in dependency '%s'", + ret, + json_object_iter_peek_name(&dependencyCurrentProperty), + json_object_get_string(json_object_iter_peek_value(&dependencyCurrentProperty)), + json_object_get_string(DependencyJ)); + return -7; + } + + json_object_iter_next(&dependencyCurrentProperty); + } + + return 0; +} + +int InternalHalProcessAllHalDependencies(afb_api_t apiHandle, json_object *DependenciesJ, struct InternalHalProbedDevice **halDevicesToProbeList) +{ + int idx, dependenciesCount, ret; + + struct InternalHalProbedDevice *currentDeviceToProbe; + + json_type dependenciesJType; + json_object *currentDependencyJ; + + if(! apiHandle || ! DependenciesJ || ! halDevicesToProbeList) { + AFB_API_ERROR(apiHandle, "Invalid argument(s)"); + return -1; + } + + dependenciesJType = json_object_get_type(DependenciesJ); + switch(dependenciesJType) { + case json_type_object: + dependenciesCount = 1; + break; + + case json_type_array: + dependenciesCount = (int) json_object_array_length(DependenciesJ); + break; + + default: + AFB_API_ERROR(apiHandle, + "'haldependencies' section is malformed, won't be able to handle it ('haldependencies' : '%s')", + json_object_get_string(DependenciesJ)); + return -2; + } + + for(idx = 0; idx < dependenciesCount; idx++) { + if(dependenciesJType == json_type_array) + currentDependencyJ = json_object_array_get_idx(DependenciesJ, idx); + else + currentDependencyJ = DependenciesJ; + + if(! json_object_is_type(currentDependencyJ, json_type_object)) { + AFB_API_ERROR(apiHandle, + "Dependency ('%s') is not an object, section is malformed, won't be able to handle it ('haldependencies' : '%s')", + json_object_get_string(currentDependencyJ), + json_object_get_string(DependenciesJ)); + HalUtlRemoveAllProbedDevicesFromList(halDevicesToProbeList); + return -3; + } + + currentDeviceToProbe = HalUtlAddProbedDeviceToProbedDeviceList(halDevicesToProbeList); + if(! currentDeviceToProbe) { + AFB_API_ERROR(apiHandle, "Error when tried to add a device to probe into device to probe list"); + HalUtlRemoveAllProbedDevicesFromList(halDevicesToProbeList); + return -4; + } + + ret = InternalHalProcessOneHalDependency(apiHandle, currentDependencyJ, currentDeviceToProbe); + if(ret) { + AFB_API_ERROR(apiHandle, + "Error %i returned when tried to process '%s' dependency", + ret, + json_object_get_string(currentDependencyJ)); + HalUtlRemoveAllProbedDevicesFromList(halDevicesToProbeList); + return -5; + } + } + + return 0; +} + +/******************************************************************************* * Internals HAL verbs functions * ******************************************************************************/ |