From 070ccac33d65c651c972dfab9c6148e43d8d5d8e Mon Sep 17 00:00:00 2001 From: fulup Date: Thu, 3 Aug 2017 12:00:41 +0200 Subject: Initial Working Version on Alsa Policy-Policy-Hook --- HAL-afb/HAL-interface/hal-interface.c | 619 ++++++++++++++++------------------ 1 file changed, 300 insertions(+), 319 deletions(-) (limited to 'HAL-afb/HAL-interface/hal-interface.c') diff --git a/HAL-afb/HAL-interface/hal-interface.c b/HAL-afb/HAL-interface/hal-interface.c index cba10d7..4d86504 100644 --- a/HAL-afb/HAL-interface/hal-interface.c +++ b/HAL-afb/HAL-interface/hal-interface.c @@ -25,40 +25,12 @@ alsaHalSndCardT *halSndCard; -STATIC const char *halCtlsLabels[] = { - - [Master_Playback_Volume] = "Master_Playback_Volume", - [Master_OnOff_Switch] = "Master_OnOff_Switch", - [Master_Playback_Ramp]= "Master_Playback_Ramp", - [PCM_Playback_Volume] = "PCM_Playback_Volume", - [PCM_Playback_Switch] = "PCM_Playback_Switch", - [Capture_Volume] = "Capture_Volume", - - [Vol_Ramp] = "Volume_Ramp", - [Vol_Ramp_Set_Mode] = "Volume_Ramp_Mode", - [Vol_Ramp_Set_Delay] = "Volume_Ramp_Delay", - [Vol_Ramp_Set_Down] = "Volume_Ramp_Down", - [Vol_Ramp_Set_Up] = "Volume_Ramp_Up", - [Vol_Ramp_Set_Slave] = "Volume_Ramp_Slave", - - [EndHalCrlTag] = NULL -}; - -PUBLIC char *halVolRampModes[] = { - - [RAMP_VOL_NONE] = "None", - [RAMP_VOL_NORMAL] = "Normal", - [RAMP_VOL_SMOOTH] = "Smooth", - [RAMP_VOL_EMERGENCY] = "Emergency", - - [EndHalVolMod] = NULL, - -}; // Force specific HAL to depend on ShareHalLib -PUBLIC char* SharedHalLibVersion="1.0"; - +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) { @@ -67,194 +39,200 @@ STATIC void halSubscribe(afb_req request) { } // 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 && !strcmp (halCtls[idx].label, label)) return idx; +STATIC int halCtlStringToIndex(const char* label) { + alsaHalMapT *halCtls = halSndCard->ctls; + + for (int idx = 0; halCtls[idx].tag != EndHalCrlTag; idx++) { + if (halCtls[idx].label && !strcmp(halCtls[idx].label, label)) return idx; } - + // not found return -1; } -STATIC int halCtlTagToIndex (halCtlsEnumT tag) { - alsaHalMapT *halCtls= halSndCard->ctls; +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; + 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; + 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(); - - json_object_object_add(ctlHalJ, "label", json_object_new_string(halCtls[idx].label)); - json_object_object_add(ctlHalJ, "tag" , json_object_new_int(halCtls[idx].tag)); + + 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); + + json_object_array_add(ctlsHalJ, ctlHalJ); } - - afb_req_success (request, ctlsHalJ, NULL); + + afb_req_success(request, ctlsHalJ, NULL); } -STATIC int halGetCtlIndex (afb_req request, json_object*ctlInJ) { +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); + enum json_type jtype = json_object_get_type(ctlInJ); switch (jtype) { - case json_type_array: - tmpJ = json_object_array_get_idx (ctlInJ, 0); + case json_type_array: + tmpJ = json_object_array_get_idx(ctlInJ, 0); tag = json_object_get_int(tmpJ); - index = halCtlTagToIndex(tag); + index = halCtlTagToIndex(tag); break; - - case json_type_int: + + case json_type_int: tag = json_object_get_int(ctlInJ); - index = halCtlTagToIndex(tag); + index = halCtlTagToIndex(tag); break; - + case json_type_object: - done = json_object_object_get_ex (ctlInJ, "tag" , &tmpJ); + done = json_object_object_get_ex(ctlInJ, "tag", &tmpJ); if (done) { tag = json_object_get_int(tmpJ); - index = halCtlTagToIndex(tag); + index = halCtlTagToIndex(tag); } else { const char *label; - done = json_object_object_get_ex (ctlInJ, "label" , &tmpJ); + done = json_object_object_get_ex(ctlInJ, "label", &tmpJ); if (!done) goto OnErrorExit; label = json_object_get_string(tmpJ); index = halCtlStringToIndex(label); } break; - - default: + + 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; -} +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) { +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, "devid", json_object_new_string(halSndCard->devid)); json_object_object_add(queryJ, "ctl", ctlsOutJ); - - err= afb_service_call_sync("alsacore", "setctl", queryJ, &responseJ); - json_object_put (responseJ); // let's ignore response - + + err = afb_service_call_sync("alsacore", "setctl", 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) { + +PUBLIC int halSetCtlByTag(halRampEnumT tag, int value) { json_object *ctlJ = json_object_new_array(); - alsaHalMapT *halCtls= halSndCard->ctls; + alsaHalMapT *halCtls = halSndCard->ctls; int err, index; - - index = halCtlTagToIndex(tag); + + 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))); - + json_object_array_add(ctlJ, volumeNormalise(ACTION_SET, &halCtls[index].ctl, json_object_new_int(value))); + err = halCallAlsaSetCtls(ctlJ); - + return err; - - OnErrorExit: - return -1; + +OnErrorExit: + return -1; } // Translate high level control to low level and call lower layer + PUBLIC void halSetCtls(afb_req request) { - alsaHalMapT *halCtls= halSndCard->ctls; + 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: { + case json_type_object: + { ctlsOutJ = json_object_new_object(); - + // control is in literal form {tag=xxx, label=xxx, value=xxxx} - index = halGetCtlIndex (request, ctlsInJ); + index = halGetCtlIndex(request, ctlsInJ); if (index < 0) goto OnErrorExit; - - done= json_object_object_get_ex (ctlsInJ, "val" , &valuesJ); + + 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; + 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)); + + 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: { + + 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); + + 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); + 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; + 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); + 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; + goto OnErrorExit; } - err = halCallAlsaSetCtls (ctlsOutJ); + err = halCallAlsaSetCtls(ctlsOutJ); if (err) { afb_req_fail_f(request, "subcall:alsacore/setctl", "%s", json_object_get_string(ctlsOutJ)); - goto OnErrorExit; + goto OnErrorExit; } - - afb_req_success (request, NULL, NULL); + + afb_req_success(request, NULL, NULL); return; OnErrorExit: @@ -262,8 +240,9 @@ OnErrorExit: }; // Remap low level controls into HAL hight level ones + STATIC json_object *HalGetPrepareResponse(afb_req request, json_object *ctlsJ) { - alsaHalMapT *halCtls= halSndCard->ctls; + alsaHalMapT *halCtls = halSndCard->ctls; json_object *halResponseJ; int length; @@ -274,14 +253,14 @@ STATIC json_object *HalGetPrepareResponse(afb_req request, json_object *ctlsJ) { length = json_object_array_length(ctlsJ); break; case json_type_object: - halResponseJ=NULL; + 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; @@ -289,356 +268,358 @@ STATIC json_object *HalGetPrepareResponse(afb_req request, json_object *ctlsJ) { // 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)) { + 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= (halCtlsEnumT) json_object_get_int(numidJ); + numid = (halCtlsTagT) json_object_get_int(numidJ); for (int idx = 0; halCtls[idx].ctl.numid; idx++) { - if (halCtls[idx].ctl.numid == numid) { + 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)); - + 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; - + else halResponseJ = halCtlJ; + break; - } + } } - if ( halCtls[idx].ctl.numid == 0) { + 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; -} - +OnErrorExit: + return NULL; +} -STATIC json_object *halCallAlsaGetCtls (json_object *ctlsOutJ) { +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, "devid", json_object_new_string(halSndCard->devid)); json_object_object_add(queryJ, "ctl", ctlsOutJ); - err= afb_service_call_sync("alsacore", "getctl", queryJ, &responseJ); + err = afb_service_call_sync("alsacore", "getctl", 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); + done = json_object_object_get_ex(responseJ, "response", &responseJ); if (!done) goto OnErrorExit; - + return responseJ; - - OnErrorExit: - return NULL; + +OnErrorExit: + return NULL; } // retrieve a single HAL control from its tag. -PUBLIC json_object *halGetCtlByTag (halRampEnumT tag) { + +PUBLIC json_object *halGetCtlByTag(halRampEnumT tag) { json_object *responseJ, *valJ; - alsaHalMapT *halCtls= halSndCard->ctls; + alsaHalMapT *halCtls = halSndCard->ctls; int done, index; - - index = halCtlTagToIndex(tag); + + 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; + +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; + 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: { + case json_type_object: + { - index = halGetCtlIndex (request, ctlsInJ); + index = halGetCtlIndex(request, ctlsInJ); if (index < 0) goto OnErrorExit; - json_object_array_add (ctlsOutJ, json_object_new_int(halCtls[index].ctl.numid)); + 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); + + 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)); + 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; + goto OnErrorExit; } // Call now level CTL - responseJ = halCallAlsaGetCtls (ctlsOutJ); + responseJ = halCallAlsaGetCtls(ctlsOutJ); if (!responseJ) { afb_req_fail_f(request, "subcall:alsacore/getctl", "%s", json_object_get_string(responseJ)); - goto OnErrorExit; + goto OnErrorExit; } - + // map back low level response to HAL ctl with normalised values - json_object *halResponse = HalGetPrepareResponse(request, responseJ); + json_object *halResponse = HalGetPrepareResponse(request, responseJ); if (!halResponse) goto OnErrorExit; - - afb_req_success (request, halResponse, NULL); + + afb_req_success(request, halResponse, NULL); return; OnErrorExit: return; }; - -STATIC int UpdateOneSndCtl (alsaHalCtlMapT *ctl, json_object *sndCtlJ) { +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); - + 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); - + 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)) { + if (json_object_object_get_ex(sndCtlJ, "tlv", &tmpJ)) { json_object *dbscaleJ; - - if (!json_object_object_get_ex (tmpJ, "dbscale" , &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); + 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; + +OnErrorExit: + return -1; } // this is call when after all bindings are loaded -PUBLIC int halServiceInit (const char *apiPrefix, alsaHalSndCardT *alsaHalSndCard) { + +PUBLIC int halServiceInit(const char *apiPrefix, alsaHalSndCardT *alsaHalSndCard) { int err; json_object *queryurl, *responseJ, *devidJ, *ctlsJ, *tmpJ; - alsaHalMapT *halCtls= alsaHalSndCard->ctls; - + 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 (!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; + 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); + + 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)); + 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)); + 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)); - + 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++) { + ctlsJ = json_object_new_array(); + for (int idx = 0; (halCtls[idx].ctl.name || halCtls[idx].ctl.numid); idx++) { json_object *ctlJ; - - // map HAL ctlTad with halCrlLabel to simplify set/get ctl operations using Labels - halCtls[idx].label = halCtlsLabels[halCtls[idx].tag]; - - if (halCtls[idx].cb.callback != NULL) { - ctlJ = json_object_new_object(); - 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, "value", 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); + + // Try to find best equivalent label for tag + if (halCtls[idx].tag >StartHalCrlTag && halCtls[idx].tag < EndHalCrlTag && halCtls[idx].label != 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; + } + + 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, "value", 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_array_add(ctlsJ, ctlJ); - } else { - 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)); - json_object_array_add(ctlsJ, ctlJ); - } + 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) { + 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); + 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)); + 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); + 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; + 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) ; + 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; + 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); + 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"); + AFB_ERROR("Fail subscribing to ALSA lowlevel events"); goto OnErrorExit; } - - return (0); - - 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; + 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); + + 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); - + 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++) { + 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); + 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 = "ctl-list", .callback = halListCtls , .info="List AGL normalised Sound Controls"}, - { .verb = "ctl-get", .callback = halGetCtls , .info="Get one/many sound controls"}, - { .verb = "ctl-set", .callback = halSetCtls , .info="Set one/many sound controls"}, - { .verb = "evt-sub", .callback = halSubscribe, .info="Subscribe to HAL events"}, + { .verb = "ping", .callback = pingtest, .info = "ping test for API"}, + { .verb = "ctl-list", .callback = halListCtls, .info = "List AGL normalised Sound Controls"}, + { .verb = "ctl-get", .callback = halGetCtls, .info = "Get one/many sound controls"}, + { .verb = "ctl-set", .callback = halSetCtls, .info = "Set one/many sound controls"}, + { .verb = "evt-sub", .callback = halSubscribe, .info = "Subscribe to HAL events"}, { .verb = NULL} /* marker for end of the array */ }; -- cgit 1.2.3-korg