summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Aillet <jonathan.aillet@iot.bzh>2019-09-20 12:08:25 +0200
committerJonathan Aillet <jonathan.aillet@iot.bzh>2019-10-01 10:57:28 +0200
commitf51db7cc6a8aed530ca24adda4be279b5b4d6a84 (patch)
tree3261273a94bd8b31dd6f9812eb0cc3f1fb79df20
parent2be5e4462b36b9ccc7562a83047de81dffe7e899 (diff)
Add verb to remove custom ALSA control
Add verb to remove previously added custom ALSA control. It can be done using 'removecustomctl' verb. BUG-AGL: SPEC-2836 Change-Id: I07b842e3425f6c176423473afcd8b3d18dcaa79b Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
-rw-r--r--alsa-binding/Alsa-AddCtl.c193
-rw-r--r--alsa-binding/Alsa-ApiHat.c1
-rw-r--r--alsa-binding/Alsa-ApiHat.h9
3 files changed, 147 insertions, 56 deletions
diff --git a/alsa-binding/Alsa-AddCtl.c b/alsa-binding/Alsa-AddCtl.c
index a40112c..ecb2a05 100644
--- a/alsa-binding/Alsa-AddCtl.c
+++ b/alsa-binding/Alsa-AddCtl.c
@@ -27,6 +27,8 @@
#include <sys/ioctl.h>
#include <math.h>
+#include <wrap-json.h>
+
#include "Alsa-ApiHat.h"
// Performs like a toggle switch for attenuation, because they're bool (ref:user-ctl-element-set.c)
@@ -79,61 +81,46 @@ static const unsigned int *allocate_int_dbscale_tlv(int min_dB, int max_dB, int
}
STATIC json_object * addOneSndCtl(afb_req_t request, snd_ctl_t *ctlDev, json_object *ctlJ, queryModeE queryMode) {
- int err, done, ctlNumid, ctlValue=0, shouldCreate;
- json_object *tmpJ;
- const char *ctlName;
- ctlRequestT ctlRequest;
- int ctlMax=100, ctlMin=0, ctlStep=1, ctlCount=1, ctlSubDev=0, ctlSndDev=0;
- snd_ctl_elem_type_t ctlType=SND_CTL_ELEM_TYPE_NONE;
+ int err, ctlNumid = CTL_UNKNOWN, shouldCreate;
+ int ctlValue = 0, ctlMax = 100, ctlMin = 0, ctlStep = 1, ctlCount = 1, ctlSubDev = 0, ctlSndDev = 0;
+ const unsigned int *elemTlv = NULL;
+
+ char *ctlName = NULL;
+
+ snd_ctl_elem_type_t ctlType = SND_CTL_ELEM_TYPE_NONE;
snd_ctl_elem_info_t *elemInfo;
snd_ctl_elem_id_t *elemId;
snd_ctl_elem_value_t *elemValue;
- const unsigned int *elemTlv = NULL;
- // parse json ctl object
- json_object_object_get_ex(ctlJ, "name", &tmpJ);
- ctlName = json_object_get_string(tmpJ);
+ json_object *tmpJ;
- json_object_object_get_ex(ctlJ, "ctl", &tmpJ);
- ctlNumid = json_object_get_int(tmpJ);
+ ctlRequestT ctlRequest;
- if (!ctlNumid && !ctlName) {
+ // parse json ctl object
+ if(wrap_json_unpack(ctlJ, "{s?:s, s?:i}", "name", &ctlName, "ctl", &ctlNumid) ||
+ ((ctlNumid == CTL_UNKNOWN) && ! ctlName)) {
afb_req_fail_f(request, "ctl-invalid", "crl=%s name or numid missing", json_object_get_string(ctlJ));
goto OnErrorExit;
}
// We are facing a software ctl
if (ctlNumid == CTL_AUTO) {
- done = json_object_object_get_ex(ctlJ, "type", &tmpJ);
- if (done) ctlType = json_object_get_int(tmpJ);
- else ctlType = SND_CTL_ELEM_TYPE_INTEGER;
-
- done = json_object_object_get_ex(ctlJ, "count", &tmpJ);
- if (!done) ctlCount = 1;
- else ctlCount = json_object_get_int(tmpJ);
-
- json_object_object_get_ex(ctlJ, "val", &tmpJ);
- ctlValue = json_object_get_int(tmpJ);
-
- json_object_object_get_ex(ctlJ, "snddev", &tmpJ);
- ctlSndDev = json_object_get_int(tmpJ);
-
- json_object_object_get_ex(ctlJ, "subdev", &tmpJ);
- ctlSubDev = json_object_get_int(tmpJ);
+ wrap_json_unpack(ctlJ,
+ "{s?:i, s?:i, s?:i, s?:i, s?:i}",
+ "type", &ctlType,
+ "count", &ctlCount,
+ "val", &ctlValue,
+ "snddev", &ctlSndDev,
+ "subdev", &ctlSubDev);
switch(ctlType) {
case SND_CTL_ELEM_TYPE_INTEGER:
// default for json_object_get_int is zero
- json_object_object_get_ex(ctlJ, "min", &tmpJ);
- ctlMin = json_object_get_int(tmpJ);
-
- done = json_object_object_get_ex(ctlJ, "max", &tmpJ);
- if (done) ctlMax = json_object_get_int(tmpJ);
- else ctlMax = 100;
-
- done = json_object_object_get_ex(ctlJ, "step", &tmpJ);
- if (!done) ctlStep = 1;
- else ctlStep = json_object_get_int(tmpJ);
+ wrap_json_unpack(ctlJ,
+ "{s?:i, s?:i, s?:i}",
+ "min", &ctlMin,
+ "max", &ctlMax,
+ "step", &ctlStep);
break;
case SND_CTL_ELEM_TYPE_BOOLEAN:
@@ -208,9 +195,15 @@ STATIC json_object * addOneSndCtl(afb_req_t request, snd_ctl_t *ctlDev, json_obj
}
if(shouldCreate) {
+ if(! snd_ctl_elem_info_is_user(elemInfo)) {
+ afb_req_fail_f(request, "ctl-invalid", "ctrl=%s is not a user created control, impossible to modify it", json_object_get_string(ctlJ));
+ goto OnErrorExit;
+ }
+
err = snd_ctl_elem_remove(ctlDev, elemId);
if (err < 0) {
- AFB_ERROR("addOneSndCtl: ctlName=%s numid=%d fail to reset", snd_ctl_elem_info_get_name(elemInfo), snd_ctl_elem_info_get_numid(elemInfo));
+ AFB_ERROR("addOneSndCtl: ctlName=%s ctlNumid=%d fail to reset", snd_ctl_elem_info_get_name(elemInfo), snd_ctl_elem_info_get_numid(elemInfo));
+ afb_req_fail_f(request, "ctl-reset-fail", "ctlName=%s ctlNumid=%d fail to reset", snd_ctl_elem_info_get_name(elemInfo), snd_ctl_elem_info_get_numid(elemInfo));
goto DoNotUpdate;
};
@@ -362,22 +355,102 @@ DoNotUpdate:
if (ctlRequest.used < 0) {
AFB_WARNING("addOneSndCtl: crl=%s numid=%d Fail to get value", json_object_get_string(ctlJ), snd_ctl_elem_info_get_numid(elemInfo));
}
+
return ctlRequest.valuesJ;
OnErrorExit:
return NULL;
}
-PUBLIC void alsaAddCustomCtls(afb_req_t request) {
+STATIC json_object * removeOneSndCtl(afb_req_t request, snd_ctl_t *ctlDev, json_object *ctlJ, queryModeE queryMode) {
+ int err, ctlNumid = CTL_UNKNOWN;
+
+ const char *ctlName = NULL;
+
+ snd_ctl_elem_info_t *elemInfo;
+ snd_ctl_elem_id_t *elemId;
+
+ json_object *responseJ;
+
+ if(wrap_json_unpack(ctlJ, "{s?:s, s?:i}", "name", &ctlName, "ctl", &ctlNumid) ||
+ ((ctlNumid == CTL_UNKNOWN) && ! ctlName)) {
+ afb_req_fail_f(request, "ctl-invalid", "crl=%s name or numid missing", json_object_get_string(ctlJ));
+ goto OnErrorExit;
+ }
+
+ snd_ctl_elem_info_alloca(&elemInfo);
+
+ if(ctlName)
+ snd_ctl_elem_info_set_name(elemInfo, ctlName);
+ if(ctlNumid > 0)
+ snd_ctl_elem_info_set_numid(elemInfo, ctlNumid);
+
+ snd_ctl_elem_info_set_interface(elemInfo, SND_CTL_ELEM_IFACE_MIXER);
+
+ if(snd_ctl_elem_info(ctlDev, elemInfo)) {
+ afb_req_fail_f(request, "ctl-invalid", "ctrl=%s does not exist", json_object_get_string(ctlJ));
+ goto OnErrorExit;
+ }
+
+ if(! snd_ctl_elem_info_is_user(elemInfo)) {
+ afb_req_fail_f(request, "ctl-invalid", "ctrl=%s is not a user created control, impossible to delete it", json_object_get_string(ctlJ));
+ goto OnErrorExit;
+ }
+
+ if(! ctlName)
+ ctlName = snd_ctl_elem_info_get_name(elemInfo);
+
+ if(ctlNumid == CTL_UNKNOWN)
+ ctlNumid = snd_ctl_elem_info_get_numid(elemInfo);
+
+ snd_ctl_elem_id_alloca(&elemId);
+ snd_ctl_elem_info_get_id(elemInfo, elemId);
+
+ if(snd_ctl_elem_remove(ctlDev, elemId) < 0) {
+ afb_req_fail_f(request,
+ "ctl-remove-fail",
+ "ctlName=%s ctlNumid=%d fail to remove",
+ ctlName,
+ ctlNumid);
+ goto OnErrorExit;
+ }
+
+ err = wrap_json_pack(&responseJ,
+ "{s:{s:s, s:i}}",
+ "removed",
+ "ctlName", ctlName,
+ "ctlId", ctlNumid);
+ if(err) {
+ afb_req_fail_f(request,
+ "ctl-remove-json",
+ "Did nor succeed to allocate response json for removed control with name=%s id=%d",
+ ctlName,
+ ctlNumid);
+ goto OnErrorExit;
+ }
+
+ return responseJ;
+
+OnErrorExit:
+ return NULL;
+}
+
+STATIC void alsaAddRemoveCustomCtls(afb_req_t request, ControlAddRemoveT controlAction) {
int err;
- json_object *ctlsJ, *ctlsValues, *ctlValues;
- enum json_type;
+
+ queryModeE queryMode;
+
+ const char *devid;
+
snd_ctl_t *ctlDev = NULL;
- const char *devid, *mode;
- devid = afb_req_value(request, "devid");
- if (devid == NULL) {
- afb_req_fail_f(request, "devid-missing", "devid MUST be defined for alsaAddCustomCtls");
+ json_object *queryJ, *ctlsJ, *ctlsValues = NULL, *ctlValues = NULL;
+
+ queryJ = afb_req_json(request);
+
+ devid = alsaGetDevIdFromQuery(queryJ);
+ if (!devid) {
+ afb_req_fail_f(request, "devid-missing", "devid MUST be defined for alsaAddRemoveCustomCtls");
goto OnErrorExit;
}
@@ -389,22 +462,21 @@ PUBLIC void alsaAddCustomCtls(afb_req_t request) {
}
// get verbosity level
- queryModeE queryMode = QUERY_QUIET;
- mode = afb_req_value(request, "mode");
- if (mode != NULL) {
- sscanf(mode, "%i", (int*) &queryMode);
- }
+ queryMode = alsaGetModeFromQuery(queryJ);
// extract sound controls and parse json
ctlsJ = json_tokener_parse(afb_req_value(request, "ctl"));
if (!ctlsJ) {
- afb_req_fail_f(request, "ctls-missing", "ctls MUST be defined as a JSON array for alsaAddCustomCtls");
+ afb_req_fail_f(request, "ctls-missing", "ctls MUST be defined as a JSON array for alsaAddRemoveCustomCtls");
goto OnErrorExit;
}
switch (json_object_get_type(ctlsJ)) {
case json_type_object:
- ctlsValues = addOneSndCtl(request, ctlDev, ctlsJ, queryMode);
+ if(controlAction == CONTROL_ADD)
+ ctlsValues = addOneSndCtl(request, ctlDev, ctlsJ, queryMode);
+ else if(controlAction == CONTROL_REMOVE)
+ ctlsValues = removeOneSndCtl(request, ctlDev, ctlsJ, queryMode);
if (!ctlsValues) goto OnErrorExit;
break;
@@ -412,7 +484,10 @@ PUBLIC void alsaAddCustomCtls(afb_req_t request) {
ctlsValues = json_object_new_array();
for (int idx = 0; idx < json_object_array_length(ctlsJ); idx++) {
json_object *ctlJ = json_object_array_get_idx(ctlsJ, idx);
- ctlValues = addOneSndCtl(request, ctlDev, ctlJ, queryMode);
+ if(controlAction == CONTROL_ADD)
+ ctlsValues = addOneSndCtl(request, ctlDev, ctlJ, queryMode);
+ else if(controlAction == CONTROL_REMOVE)
+ ctlsValues = removeOneSndCtl(request, ctlDev, ctlJ, queryMode);
if (ctlValues) json_object_array_add(ctlsValues, ctlValues);
else goto OnErrorExit;
}
@@ -430,3 +505,11 @@ OnErrorExit:
if (ctlDev) snd_ctl_close(ctlDev);
return;
}
+
+PUBLIC void alsaAddCustomCtls(afb_req_t request) {
+ alsaAddRemoveCustomCtls(request, CONTROL_ADD);
+}
+
+PUBLIC void alsaRemoveCustomCtls(afb_req_t request) {
+ alsaAddRemoveCustomCtls(request, CONTROL_REMOVE);
+} \ No newline at end of file
diff --git a/alsa-binding/Alsa-ApiHat.c b/alsa-binding/Alsa-ApiHat.c
index f43e421..470467b 100644
--- a/alsa-binding/Alsa-ApiHat.c
+++ b/alsa-binding/Alsa-ApiHat.c
@@ -55,6 +55,7 @@ static const afb_verb_t api_verbs[] = {
{ .verb = "ucmreset", .callback = alsaUseCaseReset, .info="Use Case Manager Reset"},
{ .verb = "ucmclose", .callback = alsaUseCaseClose, .info="Use Case Manager Close"},
{ .verb = "addcustomctl", .callback = alsaAddCustomCtls, .info="Add Software Alsa Custom Control"},
+ { .verb = "removecustomctl", .callback = alsaRemoveCustomCtls, .info="Remove Software Alsa Custom Control"},
{ .verb = NULL} /* marker for end of the array */
};
diff --git a/alsa-binding/Alsa-ApiHat.h b/alsa-binding/Alsa-ApiHat.h
index ba0d054..209c65b 100644
--- a/alsa-binding/Alsa-ApiHat.h
+++ b/alsa-binding/Alsa-ApiHat.h
@@ -27,7 +27,8 @@
#include <json-c/json.h>
// Soft control have dynamically allocated numid
-#define CTL_AUTO -1
+#define CTL_AUTO -1
+#define CTL_UNKNOWN -2
#ifndef PUBLIC
#define PUBLIC
@@ -54,6 +55,11 @@ typedef enum {
ACTION_GET
} ActionSetGetT;
+typedef enum {
+ CONTROL_ADD,
+ CONTROL_REMOVE
+} ControlAddRemoveT;
+
// structure to store card
typedef struct {
int cardNb;
@@ -105,6 +111,7 @@ PUBLIC void alsaUseCaseGet(afb_req_t request);
PUBLIC void alsaUseCaseClose(afb_req_t request);
PUBLIC void alsaUseCaseReset(afb_req_t request);
PUBLIC void alsaAddCustomCtls(afb_req_t request);
+PUBLIC void alsaRemoveCustomCtls(afb_req_t request);
// AlsaRegEvt
PUBLIC void alsaEvtSubcribe (afb_req_t request);