/* * Copyright (C) 2018 "IoT.bzh" * Author Jonathan Aillet * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _GNU_SOURCE #include #include #include #include #include "4a-hal-utilities-data.h" #include "4a-hal-utilities-alsa-data.h" /******************************************************************************* * Internal Hal - Linked list cleaning function declaration * ******************************************************************************/ void HalUtlFreeSelectedProbedDeviceAllocation(struct InternalHalProbedDevice *probedDeviceToFree); /******************************************************************************* * Internal Hal - Generic function for linked list * ******************************************************************************/ void *HalUtlAddNodeInList(struct cds_list_head *listHead, enum LinkedListType listType) { void *returned = NULL; struct cds_list_head *nodeToAdd; if(! listHead) return NULL; switch(listType) { case LINKED_LIST_FOR_DEPENDENCIES_DATA: returned = calloc(1, sizeof(struct InternalHalProbedDevice)); if(! returned) return NULL; nodeToAdd = &((struct InternalHalProbedDevice *) returned)->node; break; default: return NULL; } cds_list_add_tail(nodeToAdd, listHead); return returned; } int HalUtlRemoveNodeFromList(struct cds_list_head *listHead, void *dataToRemove, enum LinkedListType listType) { if(! listHead || cds_list_empty(listHead) || ! dataToRemove) return -1; switch(listType) { case LINKED_LIST_FOR_DEPENDENCIES_DATA: cds_list_del(&((struct InternalHalProbedDevice *) dataToRemove)->node); HalUtlFreeSelectedProbedDeviceAllocation((struct InternalHalProbedDevice *) dataToRemove); break; default: return -2; } return 0; } int HalUtlRemoveAllNodeFromList(struct cds_list_head *listHead, enum LinkedListType listType) { int nodesRemoved = 0; struct cds_list_head *nodeToRemove, *savedNode; if(! listHead) return -1; if(cds_list_empty(listHead)) return 0; cds_list_for_each_safe(nodeToRemove, savedNode, listHead) { switch(listType) { case LINKED_LIST_FOR_DEPENDENCIES_DATA: if(HalUtlRemoveSelectedProbedDeviceFromList(listHead, cds_list_entry(nodeToRemove, struct InternalHalProbedDevice, node))) return -2; break; default: return -3; } nodesRemoved++; } return nodesRemoved; } int HalUtlGetNumberOfNodesInList(struct cds_list_head *listHead) { int numberOfNodes = 0; struct cds_list_head *listNode; if(! listHead) return -1; if(cds_list_empty(listHead)) return 0; cds_list_for_each(listNode, listHead) numberOfNodes++; return numberOfNodes; } /******************************************************************************* * Internal Hal - Probed devices structure handling functions * ******************************************************************************/ enum ProbedDeviceClasses HalUtlGetProbedDeviceClassFromString(char *probedDeviceString) { if(! probedDeviceString) return INVALID_PROBED_DEVICE; if(! strcasecmp("static", probedDeviceString)) return STATIC_PROBED_DEVICE; if(! strcasecmp("dynamic", probedDeviceString)) return DYNAMIC_PROBED_DEVICE; if(! strcasecmp("mandatory", probedDeviceString)) return MANDATORY_PROBED_DEVICE; return INVALID_PROBED_DEVICE; } char *HalUtlGetProbedDeviceClassString(enum ProbedDeviceClasses deviceClass) { switch(deviceClass) { case STATIC_PROBED_DEVICE: return "static"; case DYNAMIC_PROBED_DEVICE: return "dynamic"; case MANDATORY_PROBED_DEVICE: return "mandatory"; case INVALID_PROBED_DEVICE: return "invalid"; default: return "unknown"; } return NULL; } int HalUtlIsDependencySelected(struct InternalHalProbedDevice *probedDevice, enum DependencyStatus requestedStatus) { if(! probedDevice) { return 0; } switch(requestedStatus) { case UNAVAILABLE_DEPENDENCY: if(! probedDevice->deviceData) return 1; else return 0; case AVAILABLE_DEPENDENCY: if(probedDevice->deviceData) return 1; else return 0; case ALL_DEPENDENCY: return 1; default: return 0; } } void HalUtlFreeSelectedProbedDeviceAllocation(struct InternalHalProbedDevice *probedDeviceToFree) { if(! probedDeviceToFree) return; free(probedDeviceToFree->uid); if(probedDeviceToFree->deviceData) { free(probedDeviceToFree->deviceData->extendedCardNb); free(probedDeviceToFree->deviceData->cardId); free(probedDeviceToFree->deviceData->cardShortName); free(probedDeviceToFree->deviceData->cardLongName); free(probedDeviceToFree->deviceData->cardDriver); free(probedDeviceToFree->deviceData->cardMixerName); free(probedDeviceToFree->deviceData->cardComponents); free(probedDeviceToFree->deviceData->playbackDeviceId); free(probedDeviceToFree->deviceData->playbackDeviceName); free(probedDeviceToFree->deviceData); } if(probedDeviceToFree->requestedDeviceJ) json_object_put(probedDeviceToFree->requestedDeviceJ); free(probedDeviceToFree); } struct InternalHalProbedDevice *HalUtlAddProbedDeviceToProbedDeviceList(struct cds_list_head *probedDevicesListHead) { return (struct InternalHalProbedDevice *) HalUtlAddNodeInList(probedDevicesListHead, LINKED_LIST_FOR_DEPENDENCIES_DATA); } int HalUtlRemoveSelectedProbedDeviceFromList(struct cds_list_head *probedDevicesListHead, struct InternalHalProbedDevice *probedDeviceToRemove) { return HalUtlRemoveNodeFromList(probedDevicesListHead, (void *) probedDeviceToRemove, LINKED_LIST_FOR_DEPENDENCIES_DATA); } int HalUtlRemoveAllProbedDevicesFromList(struct cds_list_head *probedDevicesListHead) { return HalUtlRemoveAllNodeFromList(probedDevicesListHead, LINKED_LIST_FOR_DEPENDENCIES_DATA); } int HalUtlGetNumberOfProbedDevicesInList(struct cds_list_head *probedDevicesListHead) { return HalUtlGetNumberOfNodesInList(probedDevicesListHead); } struct InternalHalProbedDevice *HalUtlSearchProbedDeviceDataById(struct cds_list_head *probedDevicesListHead, char *uid) { struct InternalHalProbedDevice *currentProbedDevice; if(! probedDevicesListHead || cds_list_empty(probedDevicesListHead) || ! uid) return NULL; cds_list_for_each_entry(currentProbedDevice, probedDevicesListHead, node) { if(! strcmp(uid, currentProbedDevice->uid)) return currentProbedDevice; } return NULL; } struct InternalHalDeviceData *HalUtlAllocateAndFillProbedDeviceDataUsingInfoGetResponse(json_object *responseJ) { struct InternalHalDeviceData *currentProbedDeviceData; if(! responseJ) return NULL; currentProbedDeviceData = calloc(1, sizeof(struct InternalHalDeviceData)); if(! currentProbedDeviceData) return NULL; currentProbedDeviceData->cardNb = HAL_UNKNOWN_DEVICE; currentProbedDeviceData->playbackDeviceNb = HAL_UNKNOWN_DEVICE; if(wrap_json_unpack(responseJ, "{s:i, s:s, s:s, s:s, s:s, s:s, s:s, s?:i, s?:s, s?:s !}", "cardNb", ¤tProbedDeviceData->cardNb, "cardId", ¤tProbedDeviceData->cardId, "cardShortName", ¤tProbedDeviceData->cardShortName, "cardLongName", ¤tProbedDeviceData->cardLongName, "cardDriver", ¤tProbedDeviceData->cardDriver, "cardMixerName", ¤tProbedDeviceData->cardMixerName, "cardComponents", ¤tProbedDeviceData->cardComponents, "playbackDeviceNb", ¤tProbedDeviceData->playbackDeviceNb, "playbackDeviceId", ¤tProbedDeviceData->playbackDeviceId, "playbackDeviceName", ¤tProbedDeviceData->playbackDeviceName) || currentProbedDeviceData->cardNb == HAL_UNKNOWN_DEVICE || (currentProbedDeviceData->playbackDeviceNb == HAL_UNKNOWN_DEVICE && asprintf(¤tProbedDeviceData->extendedCardNb, "hw:%i", currentProbedDeviceData->cardNb) < 0) || (currentProbedDeviceData->playbackDeviceNb != HAL_UNKNOWN_DEVICE && asprintf(¤tProbedDeviceData->extendedCardNb, "hw:%i,%i", currentProbedDeviceData->cardNb, currentProbedDeviceData->playbackDeviceNb) < 0)) { free(currentProbedDeviceData); return NULL; } return currentProbedDeviceData; } json_object *HalUtlGetCompactJsonForSpecificDependencies(afb_api_t apiHandle, struct InternalHalProbedDevice *requestedProbedDevice) { int wrapRet; char *cardNb; json_object *requestedProbedDeviceJ; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle is not valid"); return NULL; } if(! requestedProbedDevice) { AFB_API_ERROR(apiHandle, "Requested dependency is not valid"); return NULL; } if(! requestedProbedDevice->deviceData || requestedProbedDevice->deviceData->cardNb == HAL_UNKNOWN_DEVICE) cardNb = NULL; else cardNb = requestedProbedDevice->deviceData->extendedCardNb; wrapRet = wrap_json_pack(&requestedProbedDeviceJ, "{s:s s:s}", "uid", requestedProbedDevice->uid, "cardNb", cardNb ? cardNb : "none"); if(wrapRet) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate (uid: '%s') dependency compact json object", requestedProbedDevice->uid); return NULL; } return requestedProbedDeviceJ; } json_object *HalUtlGetFullJsonForSpecificDependencies(afb_api_t apiHandle, struct InternalHalProbedDevice *requestedProbedDevice) { int wrapRet; json_object *requestedProbedDeviceJ, *additionalInfoJ; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle is not valid"); return NULL; } if(! requestedProbedDevice) { AFB_API_ERROR(apiHandle, "Requested dependency is not valid"); return NULL; } wrapRet = wrap_json_pack(&requestedProbedDeviceJ, "{s:s s:s s:b}", "uid", requestedProbedDevice->uid, "class", HalUtlGetProbedDeviceClassString(requestedProbedDevice->deviceClass), "available", requestedProbedDevice->deviceData ? 1 : 0); if(wrapRet) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate first part of requested (uid: '%s') dependency full json object", requestedProbedDevice->uid); return NULL; } if(! requestedProbedDevice->deviceData || requestedProbedDevice->deviceData->cardNb == HAL_UNKNOWN_DEVICE) return requestedProbedDeviceJ; wrapRet = wrap_json_pack(&additionalInfoJ, "{s:i s:s s:s s:s s:s s:s s:s s:s}", "cardNb", requestedProbedDevice->deviceData->cardNb, "cardId", requestedProbedDevice->deviceData->cardId, "cardShortName", requestedProbedDevice->deviceData->cardShortName, "cardLongName", requestedProbedDevice->deviceData->cardLongName, "cardDriver", requestedProbedDevice->deviceData->cardDriver, "cardMixerName", requestedProbedDevice->deviceData->cardMixerName, "cardComponents", requestedProbedDevice->deviceData->cardComponents, "extendedCardNb", requestedProbedDevice->deviceData->extendedCardNb); if(wrapRet) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate second part of requested (uid: '%s') dependency full json object", requestedProbedDevice->uid); json_object_put(requestedProbedDeviceJ); return NULL; } wrap_json_object_add(requestedProbedDeviceJ, additionalInfoJ); if(requestedProbedDevice->deviceData->playbackDeviceNb == HAL_UNKNOWN_DEVICE) return requestedProbedDeviceJ; wrapRet = wrap_json_pack(&additionalInfoJ, "{s:i s:s s:s}", "playbackDeviceNb", requestedProbedDevice->deviceData->playbackDeviceNb, "playbackDeviceId", requestedProbedDevice->deviceData->playbackDeviceId, "playbackDeviceName", requestedProbedDevice->deviceData->playbackDeviceName); if(wrapRet) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate third part of requested (uid: '%s') dependency full json object", requestedProbedDevice->uid); json_object_put(requestedProbedDeviceJ); return NULL; } wrap_json_object_add(requestedProbedDeviceJ, additionalInfoJ); return requestedProbedDeviceJ; } json_object *HalUtlGetJsonForSpecificDependencies(afb_api_t apiHandle, struct InternalHalProbedDevice *requestedProbedDevice, enum DependencyInfoJsonFormat jsonFormat) { json_object *requestedProbedDeviceJ; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle is not valid"); return NULL; } if(! requestedProbedDevice) { AFB_API_ERROR(apiHandle, "Requested dependency is not valid"); return NULL; } switch(jsonFormat) { case DEPENDENCY_COMPACT_JSON: requestedProbedDeviceJ = HalUtlGetCompactJsonForSpecificDependencies(apiHandle,requestedProbedDevice); if(! requestedProbedDeviceJ) { AFB_API_ERROR(apiHandle, "An error happened when generating compact json for selected dependency (uid: '%s')", requestedProbedDevice->uid); return NULL; } return requestedProbedDeviceJ; case DEPENDENCY_FULL_JSON: requestedProbedDeviceJ = HalUtlGetFullJsonForSpecificDependencies(apiHandle,requestedProbedDevice); if(! requestedProbedDeviceJ) { AFB_API_ERROR(apiHandle, "An error happened when generating full json for selected dependency (uid: '%s')", requestedProbedDevice->uid); return NULL; } return requestedProbedDeviceJ; default: AFB_API_ERROR(apiHandle, "Unrecognized requested json format"); return NULL; } } json_object *HalUtlGetJsonForSpecificDependenciesUsingUid(afb_api_t apiHandle, struct cds_list_head *probedDevicesListHead, char *uid, enum DependencyInfoJsonFormat jsonFormat) { json_object *requestedProbedDeviceJ; struct InternalHalProbedDevice *requestedProbedDevice; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle is not valid"); return NULL; } if(! probedDevicesListHead || cds_list_empty(probedDevicesListHead)) { AFB_API_ERROR(apiHandle, "Probed device list is empty"); return NULL; } if(! uid) { AFB_API_ERROR(apiHandle, "Requested dependency uid is not valid"); return NULL; } requestedProbedDevice = HalUtlSearchProbedDeviceDataById(probedDevicesListHead, uid); if(! requestedProbedDevice) { AFB_API_ERROR(apiHandle, "Requested dependency uid ('%s) was not found in probed device list", uid); return NULL; } requestedProbedDeviceJ = HalUtlGetJsonForSpecificDependencies(apiHandle, requestedProbedDevice, jsonFormat); if(! requestedProbedDeviceJ) { AFB_API_ERROR(apiHandle, "An error happened when generating json for selected dependency (uid: '%s')", requestedProbedDevice->uid); return NULL; } return requestedProbedDeviceJ; } json_object *HalUtlGetJsonArrayForSelectedDependencies(afb_api_t apiHandle, struct cds_list_head *probedDevicesListHead, enum DependencyInfoJsonFormat jsonFormat, enum DependencyStatus requestedStatus) { json_object *requestedProbedDeviceJ, *requestedDependenciesInfoJ; struct InternalHalProbedDevice *currentProbedDevice; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle is not valid"); return NULL; } if(! probedDevicesListHead || cds_list_empty(probedDevicesListHead)) { AFB_API_ERROR(apiHandle, "Probed device list is empty"); return NULL; } requestedDependenciesInfoJ = json_object_new_array(); if(! requestedDependenciesInfoJ) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate probed devices (dependencies) json array"); return NULL; } cds_list_for_each_entry(currentProbedDevice, probedDevicesListHead, node) { requestedProbedDeviceJ = NULL; if(HalUtlIsDependencySelected(currentProbedDevice, requestedStatus)) { requestedProbedDeviceJ = HalUtlGetJsonForSpecificDependencies(apiHandle, currentProbedDevice, jsonFormat); if(! requestedProbedDeviceJ) { AFB_API_ERROR(apiHandle, "Didn't succeed to get json for probed devices (dependencies) with uid : '%s'", currentProbedDevice->uid); json_object_put(requestedDependenciesInfoJ); return NULL; } } if(requestedProbedDeviceJ) json_object_array_add(requestedDependenciesInfoJ, requestedProbedDeviceJ); } return requestedDependenciesInfoJ; } json_object *HalUtlGetJsonArrayForAvailableDependencies(afb_api_t apiHandle, struct cds_list_head *probedDevicesListHead, enum DependencyInfoJsonFormat jsonFormat) { json_object *requestedDependenciesInfoJ; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle is not valid"); return NULL; } if(! probedDevicesListHead || cds_list_empty(probedDevicesListHead)) { AFB_API_ERROR(apiHandle, "Probed device list is empty"); return NULL; } requestedDependenciesInfoJ = HalUtlGetJsonArrayForSelectedDependencies(apiHandle, probedDevicesListHead, jsonFormat, AVAILABLE_DEPENDENCY); if(! requestedDependenciesInfoJ) { AFB_API_ERROR(apiHandle, "Didn't succeed get available devices (dependencies) info"); return NULL; } return requestedDependenciesInfoJ; } json_object *HalUtlGetJsonArrayForAllDependencies(afb_api_t apiHandle, struct cds_list_head *probedDevicesListHead, enum DependencyInfoJsonFormat jsonFormat) { json_object *requestedDependenciesInfoJ; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle is not valid"); return NULL; } if(! probedDevicesListHead || cds_list_empty(probedDevicesListHead)) { AFB_API_ERROR(apiHandle, "Probed device list is empty"); return NULL; } requestedDependenciesInfoJ = HalUtlGetJsonArrayForSelectedDependencies(apiHandle, probedDevicesListHead, jsonFormat, ALL_DEPENDENCY); if(! requestedDependenciesInfoJ) { AFB_API_ERROR(apiHandle, "Didn't succeed get available devices (dependencies) info"); return NULL; } return requestedDependenciesInfoJ; } /******************************************************************************* * Internal Hal - Streams data handling functions * ******************************************************************************/ struct InternalHalMixerData *HalUtlAddMixerDataToMixerDataList(struct InternalHalMixerData **mixerDataList) { struct InternalHalMixerData *currentMixerData; if(! mixerDataList) return NULL; currentMixerData = *mixerDataList; if(! currentMixerData) { currentMixerData = (struct InternalHalMixerData *) calloc(1, sizeof(struct InternalHalMixerData)); if(! currentMixerData) return NULL; *mixerDataList = currentMixerData; } else { while(currentMixerData->next) currentMixerData = currentMixerData->next; currentMixerData->next = calloc(1, sizeof(struct InternalHalMixerData)); if(! currentMixerData->next) return NULL; currentMixerData = currentMixerData->next; } return currentMixerData; } int HalUtlRemoveSelectedMixerData(struct InternalHalMixerData **mixerDataList, struct InternalHalMixerData *mixerDataToRemove) { struct InternalHalMixerData *currentMixerData, *matchingMixerData; if(! mixerDataList || ! *mixerDataList || ! mixerDataToRemove) return -1; currentMixerData = *mixerDataList; if(currentMixerData == mixerDataToRemove) { *mixerDataList = currentMixerData->next; matchingMixerData = currentMixerData; } else { while(currentMixerData && currentMixerData->next != mixerDataToRemove) currentMixerData = currentMixerData->next; if(currentMixerData) { matchingMixerData = currentMixerData->next; currentMixerData->next = currentMixerData->next->next; } else { return -2; } } free(matchingMixerData->verb); free(matchingMixerData->verbToCall); free(matchingMixerData->streamCardId); free(matchingMixerData); return 0; } int HalUtlRemoveAllMixerData(struct InternalHalMixerData **mixerDataList) { int mixerDataRemoved = 0; if(! mixerDataList) return -1; while(*mixerDataList) { if(HalUtlRemoveSelectedMixerData(mixerDataList, *mixerDataList)) return -2; mixerDataRemoved++; } return mixerDataRemoved; } int HalUtlGetNumberOfMixerDataInList(struct InternalHalMixerData **mixerDataList) { int numberOfMixerData = 0; struct InternalHalMixerData *currentMixerData; if(! mixerDataList) return -1; currentMixerData = *mixerDataList; while(currentMixerData) { currentMixerData = currentMixerData->next; numberOfMixerData++; } return numberOfMixerData; } struct InternalHalMixerData *HalUtlSearchMixerDataByProperties(struct InternalHalMixerData **mixerDataList, char *verb, char *verbToCall, char *streamCardId) { struct InternalHalMixerData *currentMixerData; if(! mixerDataList || ! *mixerDataList || ! verb || ! verbToCall) return NULL; currentMixerData = *mixerDataList; while(currentMixerData) { if(! strcmp(verb, currentMixerData->verb) && ! strcmp(verbToCall, currentMixerData->verbToCall) && ((! streamCardId && ! currentMixerData->streamCardId) || (streamCardId && currentMixerData->streamCardId && ! strcmp(streamCardId, currentMixerData->streamCardId)))) return currentMixerData; currentMixerData = currentMixerData->next; } return NULL; } json_object *HalUtlGetJsonArrayForSpecificMixerData(afb_api_t apiHandle, struct InternalHalMixerData *mixerData) { int wrapRet; json_object *currentMixerDataJ; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle is not valid"); return NULL; } if(! mixerData) { AFB_API_ERROR(apiHandle, "Mixer data to use to generate json object are empty"); return NULL; } wrapRet = wrap_json_pack(¤tMixerDataJ, "{s:s s:s}", "name", mixerData->verb, "cardId", mixerData->streamCardId); if(wrapRet) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate current mixer json object"); return NULL; } return currentMixerDataJ; } json_object *HalUtlGetJsonArrayForAllMixersData(afb_api_t apiHandle, struct InternalHalMixerData **mixerDataList) { json_object *mixerDataArrayJ, *currentMixerDataJ; struct InternalHalMixerData *currentMixerData; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle is not valid"); return NULL; } mixerDataArrayJ = json_object_new_array(); if(! mixerDataArrayJ) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate requested mixer data json array"); return NULL; } currentMixerData = *mixerDataList; while(currentMixerData) { currentMixerDataJ = HalUtlGetJsonArrayForSpecificMixerData(apiHandle, currentMixerData); if(! currentMixerDataJ) { AFB_API_ERROR(apiHandle, "Didn't succeed to generate current mixer data json object"); json_object_put(mixerDataArrayJ); return NULL; } json_object_array_add(mixerDataArrayJ, currentMixerDataJ); currentMixerData = currentMixerData->next; } return mixerDataArrayJ; } /******************************************************************************* * Hal data handling functions * ******************************************************************************/ struct HalData *HalUtlAddHalToHalList(struct HalData **halDataList) { struct HalData *currentHalData; if(! halDataList) return NULL; currentHalData = *halDataList; if(! currentHalData) { currentHalData = (struct HalData *) calloc(1, sizeof(struct HalData)); if(! currentHalData) return NULL; *halDataList = currentHalData; } else { while(currentHalData->next) currentHalData = currentHalData->next; currentHalData->next = calloc(1, sizeof(struct HalData)); if(! currentHalData->next) return NULL; currentHalData = currentHalData->next; } return currentHalData; } int HalUtlRemoveSelectedHalFromList(struct HalData **halDataList, struct HalData *halToRemove) { struct HalData *currentHalData, *matchingHal; if(! halDataList || ! *halDataList || ! halToRemove) return -1; currentHalData = *halDataList; if(currentHalData == halToRemove) { *halDataList = currentHalData->next; matchingHal = currentHalData; } else { while(currentHalData && currentHalData->next != halToRemove) currentHalData = currentHalData->next; if(currentHalData) { matchingHal = currentHalData->next; currentHalData->next = currentHalData->next->next; } else { return -2; } } free(matchingHal->apiName); free(matchingHal->sndCardPath); free(matchingHal->info); free(matchingHal->author); free(matchingHal->version); free(matchingHal->date); if(matchingHal->internal) { free(matchingHal->internalHalData->mixerApiName); free(matchingHal->internalHalData->prefix); HalUtlRemoveAllProbedDevicesFromList(&matchingHal->internalHalData->probedDevicesListHead); HalUtlRemoveAllMixerData(&matchingHal->internalHalData->streamsData); HalUtlFreeAlsaCtlsMap(matchingHal->internalHalData->alsaMapT); free(matchingHal->internalHalData); } free(matchingHal); return 0; } int HalUtlRemoveAllHalFromList(struct HalData **halDataList) { int halRemoved = 0; if(! halDataList) return -1; while(*halDataList) { if(HalUtlRemoveSelectedHalFromList(halDataList, *halDataList)) return -2; halRemoved++; } return halRemoved; } int HalUtlGetNumberOfHalInList(struct HalData **halDataList) { int numberOfHal = 0; struct HalData *currentHalData; if(! halDataList) return -1; currentHalData = *halDataList; while(currentHalData) { currentHalData = currentHalData->next; numberOfHal++; } return numberOfHal; } struct HalData *HalUtlSearchHalDataByApiName(struct HalData **halDataList, char *apiName) { struct HalData *currentHalData; if(! halDataList || ! *halDataList || ! apiName) return NULL; currentHalData = *halDataList; while(currentHalData) { if(! strcmp(apiName, currentHalData->apiName)) return currentHalData; currentHalData = currentHalData->next; } return NULL; } struct HalData *HalUtlSearchReadyHalDataByCardId(struct HalData **halDataList, int cardId) { struct HalData *currentHalData; if(! halDataList || ! *halDataList) return NULL; currentHalData = *halDataList; while(currentHalData) { if(currentHalData->status == HAL_STATUS_READY && currentHalData->sndCardId == cardId) return currentHalData; currentHalData = currentHalData->next; } return NULL; } /******************************************************************************* * Hal Manager data handling functions * ******************************************************************************/ int HalUtlInitializeHalMgrData(afb_api_t apiHandle, struct HalMgrData *halMgrData, char *apiName, char *info) { if(! apiHandle || ! halMgrData || ! apiName || ! info) return -1; // Allocate and fill apiName and info strings halMgrData->apiName = strdup(apiName); if(! halMgrData->apiName) return -2; halMgrData->info = strdup(info); if(! halMgrData->info) return -3; halMgrData->apiHandle = apiHandle; return 0; } void HalUtlRemoveHalMgrData(struct HalMgrData *halMgrData) { if(! halMgrData) return; if(halMgrData->halDataList) HalUtlRemoveAllHalFromList(&halMgrData->halDataList); free(halMgrData->apiName); free(halMgrData->info); free(halMgrData); }