summaryrefslogtreecommitdiffstats
path: root/HAL-afb/HAL-interface
diff options
context:
space:
mode:
Diffstat (limited to 'HAL-afb/HAL-interface')
-rw-r--r--HAL-afb/HAL-interface/CMakeLists.txt37
-rw-r--r--HAL-afb/HAL-interface/hal-interface.c626
-rw-r--r--HAL-afb/HAL-interface/hal-interface.h106
-rw-r--r--HAL-afb/HAL-interface/hal-volramp.c185
-rw-r--r--HAL-afb/HAL-interface/hal-volume.c150
5 files changed, 0 insertions, 1104 deletions
diff --git a/HAL-afb/HAL-interface/CMakeLists.txt b/HAL-afb/HAL-interface/CMakeLists.txt
deleted file mode 100644
index bbe2e94..0000000
--- a/HAL-afb/HAL-interface/CMakeLists.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-###########################################################################
-# Copyright 2015, 2016, 2017 IoT.bzh
-#
-# author: Fulup Ar Foll <fulup@iot.bzh>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-###########################################################################
-
-
-# Add target to project dependency list
-PROJECT_TARGET_ADD(hal-interface)
-
- # Define targets
- ADD_LIBRARY(${TARGET_NAME} STATIC hal-volume.c hal-volramp.c hal-interface.c)
-
- # Library properties
- SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES OUTPUT_NAME halinterface)
-
- # Library dependencies (include updates automatically)
- TARGET_LINK_LIBRARIES(${TARGET_NAME}
- audio-common
- )
-
- # Define target includes
- TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME}
- PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
- )
diff --git a/HAL-afb/HAL-interface/hal-interface.c b/HAL-afb/HAL-interface/hal-interface.c
deleted file mode 100644
index 4a32d72..0000000
--- a/HAL-afb/HAL-interface/hal-interface.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author Fulup Ar Foll <fulup@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * reference:
- * amixer contents; amixer controls;
- * http://www.tldp.org/HOWTO/Alsa-sound-6.html
- */
-#define _GNU_SOURCE // needed for vasprintf
-#include <string.h>
-#include "hal-interface.h"
-#include <systemd/sd-event.h>
-
-alsaHalSndCardT *halSndCard;
-
-
-// Force specific HAL to depend on ShareHalLib
-PUBLIC char* SharedHalLibVersion = "1.0";
-
-// Subscribe to AudioBinding events
-
-STATIC void halSubscribe(afb_req request) {
- const char *devidJ = afb_req_value(request, "devid");
- if (devidJ == NULL) {
- afb_req_fail_f(request, "devidJ-missing", "devidJ=hw:xxx missing");
- }
-}
-
-// Map HAL ctlName to ctlLabel
-
-STATIC int halCtlStringToIndex(const char* label) {
- alsaHalMapT *halCtls = halSndCard->ctls;
-
- for (int idx = 0; halCtls[idx].tag != EndHalCrlTag; idx++) {
- if (halCtls[idx].label && !strcasecmp(halCtls[idx].label, label)) return idx;
- }
-
- // not found
- return -1;
-}
-
-STATIC int halCtlTagToIndex(halCtlsTagT tag) {
- alsaHalMapT *halCtls = halSndCard->ctls;
-
- for (int idx = 0; halCtls[idx].tag != EndHalCrlTag; idx++) {
- if (halCtls[idx].tag == tag) return idx;
- }
-
- // not found
- return -1;
-}
-
-
-// Return ALL HAL snd controls
-
-PUBLIC void halListCtls(afb_req request) {
- alsaHalMapT *halCtls = halSndCard->ctls;
- json_object *ctlsHalJ = json_object_new_array();
-
- for (int idx = 0; halCtls[idx].ctl.numid; idx++) {
- json_object *ctlHalJ = json_object_new_object();
-
- if (halCtls[idx].label) json_object_object_add(ctlHalJ, "label", json_object_new_string(halCtls[idx].label));
- else json_object_object_add(ctlHalJ, "label", json_object_new_string("HAL Label Not Set "));
- json_object_object_add(ctlHalJ, "tag", json_object_new_int(halCtls[idx].tag));
- json_object_object_add(ctlHalJ, "count", json_object_new_int(halCtls[idx].ctl.count));
-
- json_object_array_add(ctlsHalJ, ctlHalJ);
- }
-
- afb_req_success(request, ctlsHalJ, NULL);
-}
-
-STATIC int halGetCtlIndex(afb_req request, json_object*ctlInJ) {
- json_object *tmpJ;
- int tag, index, done;
-
- // check 1st short command mode [tag1, tag2, ...]
- enum json_type jtype = json_object_get_type(ctlInJ);
- switch (jtype) {
- case json_type_array:
- tmpJ = json_object_array_get_idx(ctlInJ, 0);
- tag = json_object_get_int(tmpJ);
- index = halCtlTagToIndex(tag);
- break;
-
- case json_type_int:
- tag = json_object_get_int(ctlInJ);
- index = halCtlTagToIndex(tag);
- break;
-
- case json_type_object:
- done = json_object_object_get_ex(ctlInJ, "tag", &tmpJ);
- if (done) {
- tag = json_object_get_int(tmpJ);
- index = halCtlTagToIndex(tag);
- } else {
- const char *label;
- done = json_object_object_get_ex(ctlInJ, "label", &tmpJ);
- if (!done) goto OnErrorExit;
- label = json_object_get_string(tmpJ);
- index = halCtlStringToIndex(label);
- }
- break;
-
- default:
- goto OnErrorExit;
- }
-
- if (index < 0) goto OnErrorExit;
-
- // return corresponding lowlevel numid to querylist
- return index;
-
-OnErrorExit:
- afb_req_fail_f(request, "ctl-invalid", "No Label/Tag given ctl='%s'", json_object_get_string(ctlInJ));
- return -1;
-}
-
-STATIC int halCallAlsaSetCtls(json_object *ctlsOutJ) {
- json_object *responseJ, *queryJ;
- int err;
-
- // Call now level CTL
- queryJ = json_object_new_object();
- json_object_object_add(queryJ, "devid", json_object_new_string(halSndCard->devid));
- json_object_object_add(queryJ, "ctl", ctlsOutJ);
-
- err = afb_service_call_sync("alsacore", "ctlset", queryJ, &responseJ);
- json_object_put(responseJ); // let's ignore response
-
- return err;
-}
-
-
-// retrieve a single HAL control from its tag.
-
-PUBLIC int halSetCtlByTag(halRampEnumT tag, int value) {
- json_object *ctlJ = json_object_new_array();
- alsaHalMapT *halCtls = halSndCard->ctls;
- int err, index;
-
- index = halCtlTagToIndex(tag);
- if (index < 0) goto OnErrorExit;
-
- json_object_array_add(ctlJ, json_object_new_int(halCtls[index].ctl.numid));
- json_object_array_add(ctlJ, volumeNormalise(ACTION_SET, &halCtls[index].ctl, json_object_new_int(value)));
-
- err = halCallAlsaSetCtls(ctlJ);
-
- return err;
-
-OnErrorExit:
- return -1;
-}
-
-
-// Translate high level control to low level and call lower layer
-
-PUBLIC void halSetCtls(afb_req request) {
- alsaHalMapT *halCtls = halSndCard->ctls;
- int err, done, index;
- json_object *ctlsInJ, *ctlsOutJ, *valuesJ;
-
- // get query from request
- ctlsInJ = afb_req_json(request);
-
- switch (json_object_get_type(ctlsInJ)) {
- case json_type_object:
- {
- ctlsOutJ = json_object_new_object();
-
- // control is in literal form {tag=xxx, label=xxx, value=xxxx}
- index = halGetCtlIndex(request, ctlsInJ);
- if (index < 0) goto OnErrorExit;
-
- done = json_object_object_get_ex(ctlsInJ, "val", &valuesJ);
- if (!done) {
- afb_req_fail_f(request, "ctl-invalid", "No val=[val1, ...] ctl='%s'", json_object_get_string(ctlsInJ));
- goto OnErrorExit;
- }
-
- json_object_object_add(ctlsOutJ, "id", json_object_new_int(halCtls[index].ctl.numid));
- json_object_object_add(ctlsOutJ, "val", volumeNormalise(ACTION_SET, &halCtls[index].ctl, valuesJ));
- break;
- }
-
- case json_type_array:
- {
- ctlsOutJ = json_object_new_array();
-
- for (int idx = 0; idx < json_object_array_length(ctlsInJ); idx++) {
- json_object *ctlInJ = json_object_array_get_idx(ctlsInJ, idx);
- index = halGetCtlIndex(request, ctlInJ);
- if (index < 0) goto OnErrorExit;
-
- done = json_object_object_get_ex(ctlInJ, "val", &valuesJ);
- if (!done) {
- afb_req_fail_f(request, "ctl-invalid", "No val=[val1, ...] ctl='%s'", json_object_get_string(ctlsInJ));
- goto OnErrorExit;
- }
- // let's create alsa low level set control request
- json_object *ctlOutJ = json_object_new_object();
- json_object_object_add(ctlOutJ, "id", json_object_new_int(halCtls[index].ctl.numid));
- json_object_object_add(ctlOutJ, "val", volumeNormalise(ACTION_SET, &halCtls[index].ctl, valuesJ));
-
- json_object_array_add(ctlsOutJ, ctlOutJ);
- }
- break;
- }
-
- default:
- afb_req_fail_f(request, "ctl-invalid", "Not a valid JSON ctl='%s'", json_object_get_string(ctlsInJ));
- goto OnErrorExit;
- }
-
- err = halCallAlsaSetCtls(ctlsOutJ);
- if (err) {
- afb_req_fail_f(request, "subcall:alsacore/setctl", "%s", json_object_get_string(ctlsOutJ));
- goto OnErrorExit;
- }
-
- afb_req_success(request, NULL, NULL);
- return;
-
-OnErrorExit:
- return;
-};
-
-// Remap low level controls into HAL hight level ones
-
-STATIC json_object *HalGetPrepareResponse(afb_req request, json_object *ctlsJ) {
- alsaHalMapT *halCtls = halSndCard->ctls;
- json_object *halResponseJ;
- int length;
-
- switch (json_object_get_type(ctlsJ)) {
- case json_type_array:
- // responseJ is a JSON array
- halResponseJ = json_object_new_array();
- length = json_object_array_length(ctlsJ);
- break;
- case json_type_object:
- halResponseJ = NULL;
- length = 1;
- break;
- default:
- afb_req_fail_f(request, "ctls-notarray", "Invalid Controls return from alsa/getcontrol ctlsJ=%s", json_object_get_string(ctlsJ));
- goto OnErrorExit;
- }
-
- // loop on array and store values into client context
- for (int idx = 0; idx < length; idx++) {
- json_object *sndCtlJ, *valJ, *numidJ;
- int numid;
-
- // extract control from array if any
- if (halResponseJ) sndCtlJ = json_object_array_get_idx(ctlsJ, idx);
- else sndCtlJ = ctlsJ;
-
- if (!json_object_object_get_ex(sndCtlJ, "id", &numidJ) || !json_object_object_get_ex(sndCtlJ, "val", &valJ)) {
- afb_req_fail_f(request, "ctl-invalid", "Invalid Control return from alsa/getcontrol ctl=%s", json_object_get_string(sndCtlJ));
- goto OnErrorExit;
- }
-
- // HAL and Business logic use the same AlsaMixerHal.h direct conversion
- numid = (halCtlsTagT) json_object_get_int(numidJ);
-
- for (int idx = 0; halCtls[idx].ctl.numid; idx++) {
- if (halCtls[idx].ctl.numid == numid) {
- // translate low level numid to HAL one and normalise values
- json_object *halCtlJ = json_object_new_object();
- json_object_object_add(halCtlJ, "label", json_object_new_string(halCtls[idx].label)); // idx+1 == HAL/NUMID
- json_object_object_add(halCtlJ, "tag", json_object_new_int(halCtls[idx].tag)); // idx+1 == HAL/NUMID
- json_object_object_add(halCtlJ, "val", volumeNormalise(ACTION_GET, &halCtls[idx].ctl, valJ));
-
- if (halResponseJ) json_object_array_add(halResponseJ, halCtlJ);
- else halResponseJ = halCtlJ;
-
- break;
- }
- }
- if (halCtls[idx].ctl.numid == 0) {
- afb_req_fail_f(request, "ctl-invalid", "Invalid Control numid=%d from alsa/getcontrol ctlJ=%s", numid, json_object_get_string(sndCtlJ));
- goto OnErrorExit;
- }
- }
- return halResponseJ;
-
-OnErrorExit:
- return NULL;
-}
-
-STATIC json_object *halCallAlsaGetCtls(json_object *ctlsOutJ) {
- json_object *responseJ, *queryJ;
- int err, done;
-
- // Call now level CTL
- queryJ = json_object_new_object();
- json_object_object_add(queryJ, "devid", json_object_new_string(halSndCard->devid));
- json_object_object_add(queryJ, "ctl", ctlsOutJ);
-
- err = afb_service_call_sync("alsacore", "ctlget", queryJ, &responseJ);
- if (err) goto OnErrorExit;
-
- // Let ignore info data if any and keep on response
- done = json_object_object_get_ex(responseJ, "response", &responseJ);
- if (!done) goto OnErrorExit;
-
- return responseJ;
-
-OnErrorExit:
- return NULL;
-}
-
-// retrieve a single HAL control from its tag.
-
-PUBLIC json_object *halGetCtlByTag(halRampEnumT tag) {
- json_object *responseJ, *valJ;
- alsaHalMapT *halCtls = halSndCard->ctls;
- int done, index;
-
- index = halCtlTagToIndex(tag);
- if (index < 0) goto OnErrorExit;
- responseJ = halCallAlsaGetCtls(json_object_new_int(halCtls[index].ctl.numid));
-
- done = json_object_object_get_ex(responseJ, "val", &valJ);
- if (!done) goto OnErrorExit;
-
- return volumeNormalise(ACTION_GET, &halCtls[index].ctl, valJ);
-
-OnErrorExit:
- return NULL;
-}
-
-
-// Translate high level control to low level and call lower layer
-
-PUBLIC void halGetCtls(afb_req request) {
- int index;
- alsaHalMapT *halCtls = halSndCard->ctls;
- json_object *ctlsInJ, *ctlsOutJ, *responseJ;
-
- // get query from request
- ctlsInJ = afb_req_json(request);
- ctlsOutJ = json_object_new_array();
-
- switch (json_object_get_type(ctlsInJ)) {
- case json_type_object:
- {
-
- index = halGetCtlIndex(request, ctlsInJ);
- if (index < 0) goto OnErrorExit;
- json_object_array_add(ctlsOutJ, json_object_new_int(halCtls[index].ctl.numid));
- break;
- }
-
- case json_type_array:
- {
-
- for (int idx = 0; idx < json_object_array_length(ctlsInJ); idx++) {
- json_object *ctlInJ = json_object_array_get_idx(ctlsInJ, idx);
- index = halGetCtlIndex(request, ctlInJ);
- if (index < 0) goto OnErrorExit;
- json_object_array_add(ctlsOutJ, json_object_new_int(halCtls[index].ctl.numid));
- }
- break;
- }
-
- default:
- afb_req_fail_f(request, "ctl-invalid", "Not a valid JSON ctl='%s'", json_object_get_string(ctlsInJ));
- goto OnErrorExit;
- }
-
- // Call now level CTL
- responseJ = halCallAlsaGetCtls(ctlsOutJ);
- if (!responseJ) {
- afb_req_fail_f(request, "subcall:alsacore/getctl", "%s", json_object_get_string(responseJ));
- goto OnErrorExit;
- }
-
- // map back low level response to HAL ctl with normalised values
- json_object *halResponse = HalGetPrepareResponse(request, responseJ);
- if (!halResponse) goto OnErrorExit;
-
- afb_req_success(request, halResponse, NULL);
- return;
-
-OnErrorExit:
- return;
-};
-
-STATIC int UpdateOneSndCtl(alsaHalCtlMapT *ctl, json_object *sndCtlJ) {
- json_object *tmpJ, *ctlJ;
-
- json_object_object_get_ex(sndCtlJ, "name", &tmpJ);
- ctl->name = (char*) json_object_get_string(tmpJ);
-
- json_object_object_get_ex(sndCtlJ, "id", &tmpJ);
- ctl->numid = json_object_get_int(tmpJ);
-
- // make sure we face a valid Alsa Low level ctl
- if (!json_object_object_get_ex(sndCtlJ, "ctl", &ctlJ)) goto OnErrorExit;
-
- json_object_object_get_ex(ctlJ, "min", &tmpJ);
- ctl->minval = json_object_get_int(tmpJ);
-
- json_object_object_get_ex(ctlJ, "max", &tmpJ);
- ctl->maxval = json_object_get_int(tmpJ);
-
- json_object_object_get_ex(ctlJ, "step", &tmpJ);
- ctl->step = json_object_get_int(tmpJ);
-
- json_object_object_get_ex(ctlJ, "count", &tmpJ);
- ctl->count = json_object_get_int(tmpJ);
-
- json_object_object_get_ex(ctlJ, "type", &tmpJ);
- ctl->type = (snd_ctl_elem_type_t) json_object_get_int(tmpJ);
-
- // process dbscale TLV if any
- if (json_object_object_get_ex(sndCtlJ, "tlv", &tmpJ)) {
- json_object *dbscaleJ;
-
- if (!json_object_object_get_ex(tmpJ, "dbscale", &dbscaleJ)) {
- AFB_WARNING("TLV found but not DBscale attached ctl name=%s numid=%d", ctl->name, ctl->numid);
- } else {
- ctl->dbscale = malloc(sizeof (alsaHalDBscaleT));
-
- json_object_object_get_ex(dbscaleJ, "min", &tmpJ);
- ctl->dbscale->min = (snd_ctl_elem_type_t) json_object_get_int(tmpJ);
-
- json_object_object_get_ex(dbscaleJ, "max", &tmpJ);
- ctl->dbscale->max = (snd_ctl_elem_type_t) json_object_get_int(tmpJ);
-
- json_object_object_get_ex(dbscaleJ, "step", &tmpJ);
- ctl->dbscale->step = (snd_ctl_elem_type_t) json_object_get_int(tmpJ);
-
- json_object_object_get_ex(dbscaleJ, "mute", &tmpJ);
- ctl->dbscale->mute = (snd_ctl_elem_type_t) json_object_get_int(tmpJ);
- }
- }
-
- return 0;
-
-OnErrorExit:
- return -1;
-}
-
-// this is call when after all bindings are loaded
-
-PUBLIC int halServiceInit(const char *apiPrefix, alsaHalSndCardT *alsaHalSndCard) {
- int err;
- json_object *queryurl, *responseJ, *devidJ, *ctlsJ, *tmpJ;
- alsaHalMapT *halCtls = alsaHalSndCard->ctls;
-
- // if not volume normalisation CB provided use default one
- if (!alsaHalSndCard->volumeCB) alsaHalSndCard->volumeCB = volumeNormalise;
- halSndCard = alsaHalSndCard;
-
- err = afb_daemon_require_api("alsacore", 1);
- if (err) {
- AFB_ERROR("AlsaCore missing cannot use AlsaHAL");
- goto OnErrorExit;
- }
-
- // register HAL with Alsa Low Level Binder
- queryurl = json_object_new_object();
- json_object_object_add(queryurl, "prefix", json_object_new_string(apiPrefix));
- json_object_object_add(queryurl, "sndname", json_object_new_string(alsaHalSndCard->name));
-
- err = afb_service_call_sync("alsacore", "halregister", queryurl, &responseJ);
- json_object_put(queryurl);
- if (err) {
- AFB_NOTICE("Fail to register HAL to ALSA lowlevel binding Response='%s'", json_object_get_string(responseJ));
- goto OnErrorExit;
- }
-
- // extract sound devidJ from HAL registration
- if (!json_object_object_get_ex(responseJ, "response", &tmpJ) || !json_object_object_get_ex(tmpJ, "devid", &devidJ)) {
- AFB_ERROR("Ooops: Internal error no devidJ return from HAL registration Response='%s'", json_object_get_string(responseJ));
- goto OnErrorExit;
- }
-
- // save devid for future use
- halSndCard->devid = strdup(json_object_get_string(devidJ));
-
- // for each Non Alsa Control callback create a custom control
- ctlsJ = json_object_new_array();
- for (int idx = 0; (halCtls[idx].ctl.name || halCtls[idx].ctl.numid); idx++) {
- json_object *ctlJ;
-
- // Try to find best equivalent label for tag
- if (halCtls[idx].tag >StartHalCrlTag && halCtls[idx].tag < EndHalCrlTag && halCtlsLabels[halCtls[idx].tag] != NULL) {
- halCtls[idx].label = halCtlsLabels[halCtls[idx].tag];
- } else {
- if (halCtls[idx].ctl.name) halCtls[idx].label=halCtls[idx].ctl.name;
- else if (halCtls[idx].info) halCtls[idx].label=halCtls[idx].info;
- else halCtls[idx].label="NoHalCttNameSet";
- }
-
- ctlJ = json_object_new_object();
- if (halCtls[idx].ctl.numid) json_object_object_add(ctlJ, "ctl", json_object_new_int(halCtls[idx].ctl.numid));
- if (halCtls[idx].ctl.name) json_object_object_add(ctlJ, "name", json_object_new_string(halCtls[idx].ctl.name));
- if (halCtls[idx].ctl.minval) json_object_object_add(ctlJ, "min", json_object_new_int(halCtls[idx].ctl.minval));
- if (halCtls[idx].ctl.maxval) json_object_object_add(ctlJ, "max", json_object_new_int(halCtls[idx].ctl.maxval));
- if (halCtls[idx].ctl.step) json_object_object_add(ctlJ, "step", json_object_new_int(halCtls[idx].ctl.step));
- if (halCtls[idx].ctl.type) json_object_object_add(ctlJ, "type", json_object_new_int(halCtls[idx].ctl.type));
- if (halCtls[idx].ctl.count) json_object_object_add(ctlJ, "count", json_object_new_int(halCtls[idx].ctl.count));
- if (halCtls[idx].ctl.value) json_object_object_add(ctlJ, "val", json_object_new_int(halCtls[idx].ctl.value));
-
- if (halCtls[idx].ctl.dbscale) {
- json_object *dbscaleJ = json_object_new_object();
- if (halCtls[idx].ctl.dbscale->max) json_object_object_add(dbscaleJ, "max", json_object_new_int(halCtls[idx].ctl.dbscale->max));
- if (halCtls[idx].ctl.dbscale->min) json_object_object_add(dbscaleJ, "min", json_object_new_int(halCtls[idx].ctl.dbscale->min));
- if (halCtls[idx].ctl.dbscale->step) json_object_object_add(dbscaleJ, "step", json_object_new_int(halCtls[idx].ctl.dbscale->step));
- if (halCtls[idx].ctl.dbscale->mute) json_object_object_add(dbscaleJ, "mute", json_object_new_int(halCtls[idx].ctl.dbscale->mute));
- json_object_object_add(ctlJ, "dbscale", dbscaleJ);
- }
-
- if (halCtls[idx].ctl.enums) {
- json_object *enumsJ = json_object_new_array();
- for (int jdx = 0; halCtls[idx].ctl.enums[jdx]; jdx++) {
- json_object_array_add(enumsJ, json_object_new_string(halCtls[idx].ctl.enums[jdx]));
- }
- json_object_object_add(ctlJ, "enums", enumsJ);
- }
- json_object_array_add(ctlsJ, ctlJ);
- }
-
- // Build new queryJ to add HAL custom control if any
- if (json_object_array_length(ctlsJ) > 0) {
- queryurl = json_object_new_object();
- json_object_get(devidJ); // make sure devidJ does not get free by 1st call.
- json_object_object_add(queryurl, "devid", devidJ);
- json_object_object_add(queryurl, "ctl", ctlsJ);
- json_object_object_add(queryurl, "mode", json_object_new_int(QUERY_COMPACT));
- err = afb_service_call_sync("alsacore", "addcustomctl", queryurl, &responseJ);
- if (err) {
- AFB_ERROR("Fail creating HAL Custom ALSA ctls Response='%s'", json_object_get_string(responseJ));
- goto OnErrorExit;
- }
- }
-
- // Make sure response is valid
- json_object_object_get_ex(responseJ, "response", &ctlsJ);
- if (json_object_get_type(ctlsJ) != json_type_array) {
- AFB_ERROR("Response Invalid JSON array ctls Response='%s'", json_object_get_string(responseJ));
- goto OnErrorExit;
- }
-
- // update HAL data from JSON response
- for (int idx = 0; idx < json_object_array_length(ctlsJ); idx++) {
- json_object *ctlJ = json_object_array_get_idx(ctlsJ, idx);
- err = UpdateOneSndCtl(&halCtls[idx].ctl, ctlJ);
- if (err) {
- AFB_ERROR("Fail found MAP Alsa Low level=%s", json_object_get_string(ctlJ));
- goto OnErrorExit;
- }
- }
-
-
- // finally register for alsa lowlevel event
- queryurl = json_object_new_object();
- json_object_object_add(queryurl, "devid", devidJ);
- err = afb_service_call_sync("alsacore", "subscribe", queryurl, &responseJ);
- if (err) {
- AFB_ERROR("Fail subscribing to ALSA lowlevel events");
- goto OnErrorExit;
- }
-
- return (0);
-
-OnErrorExit:
- return (1);
-};
-
-
-// This receive all event this binding subscribe to
-
-PUBLIC void halServiceEvent(const char *evtname, json_object *eventJ) {
- int numid;
- alsaHalMapT *halCtls = halSndCard->ctls;
- json_object *numidJ, *valuesJ;
-
- AFB_DEBUG("halServiceEvent evtname=%s [msg=%s]", evtname, json_object_get_string(eventJ));
-
- json_object_object_get_ex(eventJ, "id", &numidJ);
- numid = json_object_get_int(numidJ);
- if (!numid) {
- AFB_ERROR("halServiceEvent noid: evtname=%s [msg=%s]", evtname, json_object_get_string(eventJ));
- return;
- }
- json_object_object_get_ex(eventJ, "val", &valuesJ);
-
- // search it corresponding numid in halCtls attach a callback
- if (numid) {
- for (int idx = 0; halCtls[idx].ctl.numid; idx++) {
- if (halCtls[idx].ctl.numid == numid && halCtls[idx].cb.callback != NULL) {
- halCtls[idx].cb.callback(halCtls[idx].tag, &halCtls[idx].ctl, halCtls[idx].cb.handle, valuesJ);
- }
- }
- }
-}
-
-// Every HAL export the same API & Interface Mapping from SndCard to AudioLogic is done through alsaHalSndCardT
-PUBLIC afb_verb_v2 halServiceApi[] = {
- /* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */
- { .verb = "ping", .callback = pingtest, .info = "ping test for API"},
- { .verb = "ctllist", .callback = halListCtls, .info = "List AGL normalised Sound Controls"},
- { .verb = "ctlget", .callback = halGetCtls, .info = "Get one/many sound controls"},
- { .verb = "ctlset", .callback = halSetCtls, .info = "Set one/many sound controls"},
- { .verb = "evtsub", .callback = halSubscribe, .info = "Subscribe to HAL events"},
- { .verb = NULL} /* marker for end of the array */
-};
diff --git a/HAL-afb/HAL-interface/hal-interface.h b/HAL-afb/HAL-interface/hal-interface.h
deleted file mode 100644
index c210f02..0000000
--- a/HAL-afb/HAL-interface/hal-interface.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * AlsaLibMapping -- provide low level interface with AUDIO lib (extracted from alsa-json-gateway code)
- * Copyright (C) 2015,2016,2017, Fulup Ar Foll fulup@iot.bzh
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SHAREHALLIB_H
-#define SHAREHALLIB_H
-
-#include <stdio.h>
-#include <alsa/asoundlib.h>
-
-#include "audio-common.h"
-#include <systemd/sd-event.h>
-
-typedef enum {
- ACTION_SET,
- ACTION_GET
-} ActionSetGetT;
-
-// VolRamp Handle Store current status for a given VolRam CB set
-
-typedef struct {
- halRampEnumT mode;
- halCtlsTagT slave;
- int delay; // delay between volset in us
- int stepDown; // linear %
- int stepUp; // linear %
- int current; // current volume for slave ctl
- int target; // target volume
- sd_event_source *evtsrc; // event loop timer source
-} halVolRampT;
-
-typedef struct {
- int min;
- int max;
- int step;
- int mute;
-} alsaHalDBscaleT;
-
-typedef struct {
- char* name;
- int numid;
- snd_ctl_elem_type_t type;
- int count;
- int minval;
- int maxval;
- int value;
- int step;
- const char **enums;
- alsaHalDBscaleT *dbscale;
-} alsaHalCtlMapT;
-
-
-// avoid compiler warning [Jose does not like typedef :) ]
-typedef struct afb_service alsaHalServiceT;
-
-typedef struct {
- void (*callback)(halCtlsTagT tag, alsaHalCtlMapT *control, void* handle, json_object *valuesJ);
- void* handle;
-} alsaHalCbMapT;
-
-typedef struct {
- halCtlsTagT tag;
- const char *label;
- alsaHalCtlMapT ctl;
- alsaHalCbMapT cb;
- char* info;
-} alsaHalMapT;
-
-typedef struct {
- const char *name;
- const char *info;
- alsaHalMapT *ctls;
- const char *devid;
- json_object* (*volumeCB)(ActionSetGetT action, const alsaHalCtlMapT *halCtls, json_object *valuesJ);
-} alsaHalSndCardT;
-
-// hal-interface.c
-extern afb_verb_v2 halServiceApi[];
-PUBLIC void halServiceEvent(const char *evtname, json_object *object);
-PUBLIC int halServiceInit(const char *apiPrefix, alsaHalSndCardT *alsaHalSndCard);
-PUBLIC json_object *halGetCtlByTag(halRampEnumT tag);
-PUBLIC int halSetCtlByTag(halRampEnumT tag, int value);
-
-
-// hal-volramp.c
-PUBLIC void volumeRamp(halCtlsTagT halTag, alsaHalCtlMapT *control, void* handle, json_object *valJ);
-
-// hal-volume.c
-PUBLIC json_object *volumeNormalise(ActionSetGetT action, const alsaHalCtlMapT *halCtls, json_object *valuesJ);
-
-
-#endif /* SHAREHALLIB_H */
-
diff --git a/HAL-afb/HAL-interface/hal-volramp.c b/HAL-afb/HAL-interface/hal-volramp.c
deleted file mode 100644
index 60e91d6..0000000
--- a/HAL-afb/HAL-interface/hal-volramp.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author Fulup Ar Foll <fulup@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#define _GNU_SOURCE // needed for vasprintf
-#include "hal-interface.h"
-
-STATIC int RampTimerCB(sd_event_source* source, uint64_t timer, void* handle) {
- halVolRampT *volRamp = (halVolRampT*) handle;
- int err;
- uint64_t usec;
-
- // RampDown
- if (volRamp->current > volRamp->target) {
- volRamp->current = volRamp->current - volRamp->stepDown;
- if (volRamp->current < volRamp->target) volRamp->current = volRamp->target;
- }
-
- // RampUp
- if (volRamp->current < volRamp->target) {
- volRamp->current = volRamp->current + volRamp->stepUp;
- if (volRamp->current > volRamp->target) volRamp->current = volRamp->target;
- }
-
- // request current Volume Level
- err = halSetCtlByTag(volRamp->slave, volRamp->current);
- if (err) goto OnErrorExit;
-
- // we reach target stop volram event
- if (volRamp->current == volRamp->target) sd_event_source_unref(source);
- else {
- // otherwise validate timer for a new run
- sd_event_now(afb_daemon_get_event_loop(), CLOCK_MONOTONIC, &usec);
- sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
- err = sd_event_source_set_time(source, usec + volRamp->delay);
- }
-
- return 0;
-
-OnErrorExit:
- AFB_WARNING("RampTimerCB Fail to set HAL ctl tag=%d vol=%d", Master_Playback_Volume, volRamp->current);
- sd_event_source_unref(source); // abandon VolRamp
- return -1;
-}
-
-STATIC void SetRampTimer(void *handle) {
- halVolRampT *volRamp = (halVolRampT*) handle;
- uint64_t usec;
-
- // set a timer with ~250us accuracy
- sd_event_now(afb_daemon_get_event_loop(), CLOCK_MONOTONIC, &usec);
- sd_event_add_time(afb_daemon_get_event_loop(), &volRamp->evtsrc, CLOCK_MONOTONIC, usec, 250, RampTimerCB, volRamp);
-}
-
-STATIC int volumeDoRamp(halVolRampT *volRamp, int numid, json_object *volumeJ) {
- json_object *responseJ;
-
- // request current Volume Level
- responseJ = halGetCtlByTag(volRamp->slave);
- if (!responseJ) {
- AFB_WARNING("volumeDoRamp Fail to get HAL ctl tag=%d", Master_Playback_Volume);
- goto OnErrorExit;
- }
-
- // use 1st volume value as target for ramping
- switch (json_object_get_type(volumeJ)) {
- case json_type_array:
- volRamp->target = json_object_get_int(json_object_array_get_idx(volumeJ, 0));
- break;
-
- case json_type_int:
- volRamp->target = json_object_get_int(volumeJ);
- break;
-
- default:
- AFB_WARNING("volumeDoRamp Invalid volumeJ=%s", json_object_get_string(volumeJ));
- goto OnErrorExit;
- }
-
- // use 1st volume value as current for ramping
- switch (json_object_get_type(responseJ)) {
- case json_type_array:
- volRamp->current = json_object_get_int(json_object_array_get_idx(responseJ, 0));
- break;
-
- case json_type_int:
- volRamp->current = json_object_get_int(responseJ);
- break;
-
- default:
- AFB_WARNING("volumeDoRamp Invalid reponseJ=%s", json_object_get_string(responseJ));
- goto OnErrorExit;
- }
-
- SetRampTimer(volRamp);
-
- return 0;
-
-OnErrorExit:
- return -1;
-}
-
-PUBLIC void volumeRamp(halCtlsTagT halTag, alsaHalCtlMapT *ctl, void* handle, json_object *valJ) {
- halVolRampT *volRamp = (halVolRampT*) handle;
- json_object *tmpJ;
-
- if (json_object_get_type(valJ) != json_type_array || volRamp == NULL) goto OnErrorExit;
-
- switch (halTag) {
-
- // Only config use wellknown tag. Default is DoVolRamp
- default:
- tmpJ = json_object_array_get_idx(valJ, 0);
- volumeDoRamp(volRamp, ctl->numid, tmpJ);
- break;
-
- case Vol_Ramp_Set_Mode:
- tmpJ = json_object_array_get_idx(valJ, 0);
- volRamp->mode = json_object_get_int(tmpJ);
- switch (volRamp->mode) {
-
- case RAMP_VOL_SMOOTH:
- volRamp->delay = 100 * 1000;
- volRamp->stepDown = 1;
- volRamp->stepUp = 1;
- break;
-
- case RAMP_VOL_NORMAL:
- volRamp->delay = 100 * 1000;
- volRamp->stepDown = 3;
- volRamp->stepUp = 2;
- break;
-
- case RAMP_VOL_EMERGENCY:
- volRamp->delay = 50 * 1000;
- volRamp->stepDown = 6;
- volRamp->stepUp = 2;
- break;
-
- default:
- goto OnErrorExit;
- }
- break;
-
- case Vol_Ramp_Set_Slave:
- tmpJ = json_object_array_get_idx(valJ, 0);
- volRamp->slave = json_object_get_int(tmpJ);
- break;
-
- case Vol_Ramp_Set_Delay:
- tmpJ = json_object_array_get_idx(valJ, 0);
- volRamp->delay = 1000 * json_object_get_int(tmpJ);
- break;
-
- case Vol_Ramp_Set_Down:
- tmpJ = json_object_array_get_idx(valJ, 0);
- volRamp->stepDown = json_object_get_int(tmpJ);
- break;
-
- case Vol_Ramp_Set_Up:
- tmpJ = json_object_array_get_idx(valJ, 0);
- volRamp->stepUp = json_object_get_int(tmpJ);
- break;
- }
-
- return;
-
-OnErrorExit:
- AFB_WARNING("volumeRamp: Invalid Ctrl Event halCtlsTagT=%d numid=%d name=%s value=%s", halTag, ctl->numid, ctl->name, json_object_get_string(valJ));
- return;
-}
diff --git a/HAL-afb/HAL-interface/hal-volume.c b/HAL-afb/HAL-interface/hal-volume.c
deleted file mode 100644
index 997ce98..0000000
--- a/HAL-afb/HAL-interface/hal-volume.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author Fulup Ar Foll <fulup@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * references:
- * alsa-util/amixer.c + alsa-lib/simple.c
- * snd_tlv_convert_from_dB
- * nt snd_tlv_convert_to_dB
- * snd_tlv_get_dB_range
- */
-
-#define _GNU_SOURCE // needed for vasprintf
-#include <math.h>
-#include "hal-interface.h"
-
-typedef enum {
- NORMALIZE_NONE = 0,
- NORMALIZE_DB_LINEAR,
- NORMALIZE_DB_MATH,
- NORMALIZE_LINEAR,
-} enumRandeModeDB_T;
-
-
-// Return Value express from 0-100%
-
-STATIC int dbNormalizeVal(enumRandeModeDB_T normaliseMode, const alsaHalDBscaleT *dbscale, int value) {
- double normalized, min_norm;
-
- // To get real DB from TLV DB values should be divided by 100
- switch (normaliseMode) {
- case NORMALIZE_DB_LINEAR:
- normalized = ((double) (value - dbscale->min) / (double) (dbscale->max - dbscale->min));
- break;
-
- case NORMALIZE_DB_MATH:
- normalized = exp10((double) (value - dbscale->max) / 6000.0);
- if (dbscale->min != SND_CTL_TLV_DB_GAIN_MUTE) {
- min_norm = exp10((double) (dbscale->min - dbscale->max) / 20);
- normalized = (normalized - min_norm) / (1 - min_norm);
- }
-
- break;
-
- default:
- normalized = 0;
- }
-
- return (int) round(normalized * 100);
-}
-
-// HAL normalise volume values to 0-100%
-
-PUBLIC json_object *volumeNormalise(ActionSetGetT action, const alsaHalCtlMapT *halCtls, json_object *valuesJ) {
- enumRandeModeDB_T useNormalizeDB;
- int length;
-
- // If Integer look for DBscale
- if (halCtls->type == SND_CTL_ELEM_TYPE_INTEGER) {
-
- // If not valid db_scale let's use raw_scale
- if (!halCtls->dbscale || (halCtls->dbscale->min >= halCtls->dbscale->max)) {
-
- // dbscale is invalid let's try raw range
- if (halCtls->minval >= halCtls->maxval) goto ExitOnError;
-
- // Use Raw Scale Model
- useNormalizeDB = NORMALIZE_LINEAR;
-
- } else { // db_scale looks OK let's use it
- if ((halCtls->dbscale->max - halCtls->dbscale->min) <= MAX_LINEAR_DB_SCALE * 100) useNormalizeDB = NORMALIZE_DB_LINEAR;
- else useNormalizeDB = NORMALIZE_LINEAR; // Fulup not sure how to handle this useNormalizeDB=NORMALIZE_DB_MATH;
- }
- } else useNormalizeDB = NORMALIZE_NONE;
-
-
- // loop on values to normalise
- enum json_type jtype = json_object_get_type(valuesJ);
- if (jtype == json_type_array) length = json_object_array_length(valuesJ);
- else length = 1;
-
- json_object *normalisedJ = json_object_new_array();
- for (int idx = 0; idx < length; idx++) {
- int value;
-
- if (jtype == json_type_array) {
- json_object *valueJ = json_object_array_get_idx(valuesJ, idx);
- value = json_object_get_int(valueJ);
- } else {
- value = json_object_get_int(valuesJ);
- }
-
- // If Integer scale to 0/100
- if (halCtls->type == SND_CTL_ELEM_TYPE_INTEGER) {
-
- switch (action) {
-
- case ACTION_GET:
- switch (useNormalizeDB) {
- case NORMALIZE_LINEAR:
- value = 100 * (value - halCtls->minval) / (halCtls->maxval - halCtls->minval);
- break;
- case NORMALIZE_DB_MATH: //ToBeDone
- value = dbNormalizeVal(useNormalizeDB, halCtls->dbscale, value);
- break;
- case NORMALIZE_NONE:
- default:
- value = value;
- }
- break;
-
- case ACTION_SET:
- switch (useNormalizeDB) {
- case NORMALIZE_LINEAR:
- value = (value * (halCtls->maxval - halCtls->minval)) / 100;
- break;
- case NORMALIZE_DB_MATH: //ToBeDone
- value = dbNormalizeVal(useNormalizeDB, halCtls->dbscale, value);
- break;
- case NORMALIZE_NONE:
- default:
- value = value;
- }
- break;
-
- default:
- AFB_NOTICE("volumeNormalise: invalid action value=%d", (int) action);
- goto ExitOnError;
- }
- }
-
- json_object_array_add(normalisedJ, json_object_new_int(value));
- }
-
- return (normalisedJ);
-
-ExitOnError:
- return NULL;
-}