diff options
-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 * ******************************************************************************/ |