summaryrefslogtreecommitdiffstats
path: root/ALSA-afb
diff options
context:
space:
mode:
Diffstat (limited to 'ALSA-afb')
-rw-r--r--ALSA-afb/Alsa-AddCtl.c54
-rw-r--r--ALSA-afb/Alsa-ApiHat.c8
-rw-r--r--ALSA-afb/Alsa-ApiHat.h23
-rw-r--r--ALSA-afb/Alsa-RegEvt.c309
-rw-r--r--ALSA-afb/Alsa-SetGet.c318
-rw-r--r--ALSA-afb/Alsa-Ucm.c12
-rw-r--r--ALSA-afb/CMakeLists.txt2
7 files changed, 399 insertions, 327 deletions
diff --git a/ALSA-afb/Alsa-AddCtl.c b/ALSA-afb/Alsa-AddCtl.c
index 7593f2d..2edec5f 100644
--- a/ALSA-afb/Alsa-AddCtl.c
+++ b/ALSA-afb/Alsa-AddCtl.c
@@ -67,7 +67,7 @@ STATIC int addOneSndCtl(afb_req request, snd_ctl_t *ctlDev, json_object *ctlJ)
// set info event ID and get value
snd_ctl_elem_info_alloca(&elemInfo);
snd_ctl_elem_info_set_name (elemInfo, ctlName); // map ctlInfo to ctlId elemInfo is updated !!!
- snd_ctl_elem_info_set_numid(elemInfo, ctlNumid); // map ctlInfo to ctlId elemInfo is updated !!!
+ snd_ctl_elem_info_set_numid(elemInfo, ctlNumid); // map ctlInfo to ctlId elemInfo is updated !!!
if (snd_ctl_elem_info(ctlDev, elemInfo) >= 0) {
afb_req_fail_f (request, "ctl-already-exist", "crl=%s name/numid not unique", json_object_to_json_string(ctlJ));
@@ -101,10 +101,58 @@ STATIC int addOneSndCtl(afb_req request, snd_ctl_t *ctlDev, json_object *ctlJ)
afb_req_fail_f (request, "ctl-invalid-type", "crl=%s invalid/unknown type", json_object_to_json_string(ctlJ));
goto OnErrorExit;
}
-
-
+
return 0;
OnErrorExit:
return -1;
}
+
+PUBLIC void alsaAddCustomCtls(afb_req request) {
+ int err;
+ json_object *ctlsJ;
+ enum json_type;
+ snd_ctl_t *ctlDev=NULL;
+ const char *devid;
+
+ devid = afb_req_value(request, "devid");
+ if (devid == NULL) {
+ afb_req_fail_f (request, "devid-missing", "devid MUST be defined for alsaAddCustomCtls");
+ goto OnErrorExit;
+ }
+
+ // open control interface for devid
+ err = snd_ctl_open(&ctlDev, devid, SND_CTL_READONLY);
+ if (err < 0) {
+ afb_req_fail_f (request, "devid-unknown", "SndCard devid=[%s] Not Found err=%s", devid, snd_strerror(err));
+ goto OnErrorExit;
+ }
+
+ // extract sound controls and parse json
+ ctlsJ = json_tokener_parse (afb_req_value(request, "ctls"));
+ if (!ctlsJ) {
+ afb_req_fail_f (request, "ctls-missing", "ctls MUST be defined as a JSON array for alsaAddCustomCtls");
+ goto OnErrorExit;
+ }
+
+ switch (json_object_get_type(ctlsJ)) {
+ case json_type_object:
+ addOneSndCtl(request, ctlDev, ctlsJ);
+ break;
+
+ case json_type_array:
+ for (int idx= 1; idx < json_object_array_length (ctlsJ); idx++) {
+ json_object *ctlJ = json_object_array_get_idx (ctlsJ, idx);
+ addOneSndCtl(request, ctlDev, ctlJ) ;
+ }
+ break;
+
+ default:
+ afb_req_fail_f (request, "ctls-invalid","ctls=%s not valid JSON array", json_object_to_json_string(ctlsJ));
+ goto OnErrorExit;
+ }
+
+ OnErrorExit:
+ if (ctlDev) snd_ctl_close(ctlDev);
+ return;
+} \ No newline at end of file
diff --git a/ALSA-afb/Alsa-ApiHat.c b/ALSA-afb/Alsa-ApiHat.c
index ced5d50..588e91b 100644
--- a/ALSA-afb/Alsa-ApiHat.c
+++ b/ALSA-afb/Alsa-ApiHat.c
@@ -31,13 +31,13 @@
/*
* array of the verbs exported to afb-daemon
*/
-static const struct afb_verb_v2 binding_verbs[] = {
+static const struct afb_verb_v2 api_verbs[] = {
/* VERB'S NAME FUNCTION TO CALL */
{ .verb= "ping" , .callback= pingtest },
{ .verb= "getinfo", .callback= alsaGetInfo},
{ .verb= "getctls", .callback= alsaGetCtls},
{ .verb= "setctls", .callback= alsaSetCtls},
- { .verb= "subscribe", .callback= alsaSubcribe},
+ { .verb= "subscribe", .callback= alsaEvtSubcribe},
{ .verb= "getcardid", .callback= alsaGetCardId},
{ .verb= "registerHal", .callback= alsaRegisterHal},
{ .verb= "ucmquery", .callback= alsaUseCaseQuery},
@@ -45,7 +45,7 @@ static const struct afb_verb_v2 binding_verbs[] = {
{ .verb= "ucmget", .callback= alsaUseCaseGet},
{ .verb= "ucmreset", .callback= alsaUseCaseReset},
{ .verb= "ucmclose", .callback= alsaUseCaseClose},
- { .verb= "addctl", .callback= alsaAddCustomCtl},
+ { .verb= "addcustomctl",.callback= alsaAddCustomCtls},
{ .verb= NULL } /* marker for end of the array */
};
@@ -54,5 +54,5 @@ static const struct afb_verb_v2 binding_verbs[] = {
*/
const struct afb_binding_v2 afbBindingV2 = {
.api = "alsacore",
- .verbs = binding_verbs,
+ .verbs = api_verbs,
};
diff --git a/ALSA-afb/Alsa-ApiHat.h b/ALSA-afb/Alsa-ApiHat.h
index c33f92e..bd8518f 100644
--- a/ALSA-afb/Alsa-ApiHat.h
+++ b/ALSA-afb/Alsa-ApiHat.h
@@ -19,6 +19,9 @@
#ifndef ALSALIBMAPPING_H
#define ALSALIBMAPPING_H
+
+#include <alsa/asoundlib.h>
+#include <systemd/sd-event.h>
#include "audio-interface.h"
typedef enum {
@@ -34,17 +37,24 @@ typedef struct {
int count;
} queryValuesT;
+// use to store crl numid user request
+typedef struct {
+ unsigned int numId;
+ json_object *jToken;
+ json_object *jValues;
+ int used;
+} ctlRequestT;
+
// import from AlsaAfbBinding
extern const struct afb_binding_interface *afbIface;
PUBLIC int alsaCheckQuery (struct afb_req request, queryValuesT *queryValues);
// AlseCoreSetGet exports
+PUBLIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest, int quiet);
PUBLIC void alsaGetInfo (struct afb_req request);
PUBLIC void alsaGetCtls(struct afb_req request);
PUBLIC void alsaSetCtls(struct afb_req request);
-PUBLIC void alsaSubcribe (struct afb_req request);
-PUBLIC void alsaGetCardId (struct afb_req request);
-PUBLIC void alsaRegisterHal (struct afb_req request);
+
// AlsaUseCase exports
PUBLIC void alsaUseCaseQuery(struct afb_req request);
@@ -52,9 +62,12 @@ PUBLIC void alsaUseCaseSet(struct afb_req request);
PUBLIC void alsaUseCaseGet(struct afb_req request);
PUBLIC void alsaUseCaseClose(struct afb_req request);
PUBLIC void alsaUseCaseReset(struct afb_req request);
-PUBLIC void alsaAddCustomCtl(struct afb_req request);
-
+PUBLIC void alsaAddCustomCtls(struct afb_req request);
+// AlsaRegEvt
+PUBLIC void alsaEvtSubcribe (struct afb_req request);
+PUBLIC void alsaGetCardId (struct afb_req request);
+PUBLIC void alsaRegisterHal (struct afb_req request);
#endif /* ALSALIBMAPPING_H */
diff --git a/ALSA-afb/Alsa-RegEvt.c b/ALSA-afb/Alsa-RegEvt.c
new file mode 100644
index 0000000..e06cf87
--- /dev/null
+++ b/ALSA-afb/Alsa-RegEvt.c
@@ -0,0 +1,309 @@
+/*
+ * AlsaLibMapping -- provide low level interface with ALSA 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.
+
+*/
+
+#define _GNU_SOURCE // needed for vasprintf
+
+#include "Alsa-ApiHat.h"
+
+// generic sndctrl event handle hook to event callback when pooling
+typedef struct {
+ struct pollfd pfds;
+ sd_event_source *src;
+ snd_ctl_t *ctlDev;
+ int quiet;
+ struct afb_event afbevt;
+} evtHandleT;
+
+typedef struct {
+ int ucount;
+ int cardId;
+ evtHandleT *evtHandle;
+} sndHandleT;
+
+typedef struct {
+ char *apiprefix;
+ char *shortname;
+}cardRegistryT;
+
+cardRegistryT *cardRegistry[MAX_SND_CARD+1];
+
+// This routine is called when ALSA event are fired
+STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void* userData) {
+ int err;
+ evtHandleT *evtHandle = (evtHandleT*)userData;
+ snd_ctl_event_t *eventId;
+ json_object *ctlEventJ;
+ unsigned int mask;
+ int iface;
+ int device;
+ int subdev;
+ const char*devname;
+ ctlRequestT ctlRequest;
+ snd_ctl_elem_id_t *elemId;
+
+ if ((revents & EPOLLHUP) != 0) {
+ AFB_NOTICE( "SndCtl hanghup [car disconnected]");
+ goto ExitOnSucess;
+ }
+
+ if ((revents & EPOLLIN) != 0) {
+
+ // initialise event structure on stack
+ snd_ctl_event_alloca(&eventId);
+ snd_ctl_elem_id_alloca(&elemId);
+
+ err = snd_ctl_read(evtHandle->ctlDev, eventId);
+ if (err < 0) goto OnErrorExit;
+
+ // we only process sndctrl element
+ if (snd_ctl_event_get_type(eventId) != SND_CTL_EVENT_ELEM) goto ExitOnSucess;
+
+ // we only process value changed events
+ mask = snd_ctl_event_elem_get_mask(eventId);
+ if (!(mask & SND_CTL_EVENT_MASK_VALUE)) goto ExitOnSucess;
+
+ snd_ctl_event_elem_get_id (eventId, elemId);
+
+ err = alsaGetSingleCtl (evtHandle->ctlDev, elemId, &ctlRequest, evtHandle->quiet);
+ if (err) goto OnErrorExit;
+
+ iface = snd_ctl_event_elem_get_interface(eventId);
+ device = snd_ctl_event_elem_get_device(eventId);
+ subdev = snd_ctl_event_elem_get_subdevice(eventId);
+ devname= snd_ctl_event_elem_get_name(eventId);
+
+ // proxy ctlevent as a binder event
+ ctlEventJ = json_object_new_object();
+ json_object_object_add(ctlEventJ, "device" ,json_object_new_int (device));
+ json_object_object_add(ctlEventJ, "subdev" ,json_object_new_int (subdev));
+ if (evtHandle->quiet < 2) {
+ json_object_object_add(ctlEventJ, "iface" ,json_object_new_int (iface));
+ json_object_object_add(ctlEventJ, "devname",json_object_new_string (devname));
+ }
+ if (ctlRequest.jValues) (json_object_object_add(ctlEventJ, "values" ,ctlRequest.jValues));
+ AFB_DEBUG( "sndCtlEventCB=%s", json_object_get_string(ctlEventJ));
+ afb_event_push(evtHandle->afbevt, ctlEventJ);
+ }
+
+ ExitOnSucess:
+ return 0;
+
+ OnErrorExit:
+ WARNING ("sndCtlEventCB: ignored unsupported event type");
+ return (0);
+}
+
+// Subscribe to every Alsa CtlEvent send by a given board
+PUBLIC void alsaEvtSubcribe (afb_req request) {
+ static sndHandleT sndHandles[MAX_SND_CARD];
+ evtHandleT *evtHandle;
+ snd_ctl_t *ctlDev;
+ int err, idx, cardId, idxFree=-1;
+ snd_ctl_card_info_t *cardinfo;
+ queryValuesT queryValues;
+
+
+ err = alsaCheckQuery (request, &queryValues);
+ if (err) goto OnErrorExit;
+
+
+ // open control interface for devid
+ err = snd_ctl_open(&ctlDev, queryValues.devid, SND_CTL_READONLY);
+ if (err < 0) {
+ ctlDev=NULL;
+ afb_req_fail_f (request, "devid-unknown", "SndCard devid=%s Not Found err=%s", queryValues.devid, snd_strerror(err));
+ goto OnErrorExit;
+ }
+
+ snd_ctl_card_info_alloca(&cardinfo);
+ if ((err = snd_ctl_card_info(ctlDev, cardinfo)) < 0) {
+ afb_req_fail_f (request, "devid-invalid", "SndCard devid=%s Not Found err=%s", queryValues.devid, snd_strerror(err));
+ goto OnErrorExit;
+ }
+
+ cardId=snd_ctl_card_info_get_card(cardinfo);
+
+ // search for an existing subscription and mark 1st free slot
+ for (idx= 0; idx < MAX_SND_CARD; idx ++) {
+ if (sndHandles[idx].ucount > 0 && cardId == sndHandles[idx].cardId) {
+ evtHandle= sndHandles[idx].evtHandle;
+ break;
+ } else if (idxFree == -1) idxFree= idx;
+ };
+
+ // if not subscription exist for the event let's create one
+ if (idx == MAX_SND_CARD) {
+
+ // reach MAX_SND_CARD event registration
+ if (idxFree == -1) {
+ afb_req_fail_f (request, "register-toomany", "Cannot register new event Maxcard==%d", idx);
+ goto OnErrorExit;
+ }
+
+ evtHandle = malloc (sizeof(evtHandleT));
+ evtHandle->ctlDev = ctlDev;
+ evtHandle->quiet = queryValues.quiet;
+ sndHandles[idxFree].ucount = 0;
+ sndHandles[idxFree].cardId = cardId;
+ sndHandles[idxFree].evtHandle = evtHandle;
+
+ // subscribe for sndctl events attached to devid
+ err = snd_ctl_subscribe_events(evtHandle->ctlDev, 1);
+ if (err < 0) {
+ afb_req_fail_f (request, "subscribe-fail", "Cannot subscribe events from devid=%s err=%d", queryValues.devid, err);
+ goto OnErrorExit;
+ }
+
+ // get pollfd attach to this sound board
+ snd_ctl_poll_descriptors(evtHandle->ctlDev, &evtHandle->pfds, 1);
+
+ // register sound event to binder main loop
+ err = sd_event_add_io(afb_daemon_get_event_loop(), &evtHandle->src, evtHandle->pfds.fd, EPOLLIN, sndCtlEventCB, evtHandle);
+ if (err < 0) {
+ afb_req_fail_f (request, "register-mainloop", "Cannot hook events to mainloop devid=%s err=%d", queryValues.devid, err);
+ goto OnErrorExit;
+ }
+
+ // create binder event attached to devid name
+ evtHandle->afbevt = afb_daemon_make_event (queryValues.devid);
+ if (!afb_event_is_valid (evtHandle->afbevt)) {
+ afb_req_fail_f (request, "register-event", "Cannot register new binder event name=%s", queryValues.devid);
+ goto OnErrorExit;
+ }
+
+ // everything looks OK let's move forward
+ idx=idxFree;
+ }
+
+ // subscribe to binder event
+ err = afb_req_subscribe(request, evtHandle->afbevt);
+ if (err != 0) {
+ afb_req_fail_f (request, "register-eventname", "Cannot subscribe binder event name=%s [invalid channel]", queryValues.devid);
+ goto OnErrorExit;
+ }
+
+ // increase usage count and return success
+ sndHandles[idx].ucount ++;
+ afb_req_success(request, NULL, NULL);
+ return;
+
+ OnErrorExit:
+ if (ctlDev) snd_ctl_close(ctlDev);
+ return;
+}
+
+// Subscribe to every Alsa CtlEvent send by a given board
+PUBLIC void alsaGetCardId (afb_req request) {
+ char devid [10];
+ const char *devname, *shortname, *longname;
+ int card, err, index, idx;
+ json_object *respJson;
+ snd_ctl_t *ctlDev;
+ snd_ctl_card_info_t *cardinfo;
+
+ const char *sndname = afb_req_value(request, "sndname");
+ if (sndname == NULL) {
+ afb_req_fail_f (request, "argument-missing", "sndname=SndCardName missing");
+ goto OnErrorExit;
+ }
+
+ // loop on potential card number
+ snd_ctl_card_info_alloca(&cardinfo);
+ for (card =0; card < MAX_SND_CARD; card++) {
+
+ // build card devid and probe it
+ snprintf (devid, sizeof(devid), "hw:%i", card);
+
+ // open control interface for devid
+ err = snd_ctl_open(&ctlDev, devid, SND_CTL_READONLY);
+ if (err < 0) continue;
+
+ // extract sound card information
+ snd_ctl_card_info(ctlDev, cardinfo);
+ index = snd_ctl_card_info_get_card(cardinfo);
+ devname = snd_ctl_card_info_get_id(cardinfo);
+ shortname= snd_ctl_card_info_get_name(cardinfo);
+ longname = snd_ctl_card_info_get_longname(cardinfo);
+
+ // check if short|long name match
+ if (!strcmp (sndname, devname)) break;
+ if (!strcmp (sndname, shortname)) break;
+ if (!strcmp (sndname, longname)) break;
+ }
+
+ if (card == MAX_SND_CARD) {
+ afb_req_fail_f (request, "ctlDev-notfound", "Fail to find card with name=%s", sndname);
+ goto OnErrorExit;
+ }
+
+ // proxy ctlevent as a binder event
+ respJson = json_object_new_object();
+ json_object_object_add(respJson, "index" ,json_object_new_int (index));
+ json_object_object_add(respJson, "devid" ,json_object_new_string (devid));
+ json_object_object_add(respJson, "shortname" ,json_object_new_string (shortname));
+ json_object_object_add(respJson, "longname" ,json_object_new_string (longname));
+
+ // search for a HAL binder card mapping name to api prefix
+ for (idx=0; idx < MAX_SND_CARD; idx++) {
+ if (!strcmp (cardRegistry[idx]->shortname, shortname)) break;
+ }
+ // if a match if found, then we have an HAL for this board let's return its value
+ if (idx < MAX_SND_CARD) json_object_object_add(respJson, "halapi",json_object_new_string (cardRegistry[idx]->apiprefix));
+
+ afb_req_success(request, respJson, NULL);
+ return;
+
+ OnErrorExit:
+ return;
+}
+
+// Register loaded HAL with board Name and API prefix
+PUBLIC void alsaRegisterHal (afb_req request) {
+ static int index=0;
+ const char *shortname, *apiPrefix;
+
+ apiPrefix = afb_req_value(request, "prefix");
+ if (apiPrefix == NULL) {
+ afb_req_fail_f (request, "argument-missing", "prefix=BindingApiPrefix missing");
+ goto OnErrorExit;
+ }
+
+ shortname = afb_req_value(request, "sndname");
+ if (shortname == NULL) {
+ afb_req_fail_f (request, "argument-missing", "sndname=SndCardName missing");
+ goto OnErrorExit;
+ }
+
+ if (index == MAX_SND_CARD) {
+ afb_req_fail_f (request, "alsahal-toomany", "Fail to register sndname=[%s]", shortname);
+ goto OnErrorExit;
+ }
+
+ cardRegistry[index]= malloc (sizeof(cardRegistry));
+ cardRegistry[index]->apiprefix=strdup(apiPrefix);
+ cardRegistry[index]->shortname=strdup(shortname);
+ index++;cardRegistry[index]=NULL;
+
+ // If OK return sound card Alsa ID+Info
+ alsaGetCardId(request);
+ return;
+
+ OnErrorExit:
+ return;
+}
+
diff --git a/ALSA-afb/Alsa-SetGet.c b/ALSA-afb/Alsa-SetGet.c
index d6cf50d..280078c 100644
--- a/ALSA-afb/Alsa-SetGet.c
+++ b/ALSA-afb/Alsa-SetGet.c
@@ -26,41 +26,8 @@
#define _GNU_SOURCE // needed for vasprintf
-#include <alsa/asoundlib.h>
-#include <systemd/sd-event.h>
-
#include "Alsa-ApiHat.h"
-// use to store crl numid user request
-typedef struct {
- unsigned int numId;
- json_object *jToken;
- json_object *jValues;
- int used;
-} ctlRequestT;
-
-// generic sndctrl event handle hook to event callback when pooling
-typedef struct {
- struct pollfd pfds;
- sd_event_source *src;
- snd_ctl_t *ctlDev;
- int quiet;
- struct afb_event afbevt;
-} evtHandleT;
-
-typedef struct {
- int ucount;
- int cardId;
- evtHandleT *evtHandle;
-} sndHandleT;
-
-typedef struct {
- char *apiprefix;
- char *shortname;
-}cardRegistryT;
-
-cardRegistryT *cardRegistry[MAX_SND_CARD+1];
-
PUBLIC void NumidsListParse (queryValuesT *queryValues, ctlRequestT *ctlRequest) {
json_object *jValues;
int length;
@@ -103,7 +70,7 @@ PUBLIC void NumidsListParse (queryValuesT *queryValues, ctlRequestT *ctlRequest)
case json_type_object:
// numid+values formated as {id:xxx, val:[aa,bb...,nn]}
if (!json_object_object_get_ex (ctlRequest[idx].jToken,"id", &jId) || !json_object_object_get_ex (ctlRequest[idx].jToken,"val",&jVal)) {
- NOTICE("Invalid Json=%s missing 'id'|'val'", json_object_get_string(ctlRequest[idx].jToken));
+ AFB_NOTICE("Invalid Json=%s missing 'id'|'val'", json_object_get_string(ctlRequest[idx].jToken));
ctlRequest[idx].used=-1;
} else {
ctlRequest[idx].numId =json_object_get_int(jId);
@@ -478,7 +445,7 @@ STATIC json_object *getControlAcl (snd_ctl_elem_info_t *info) {
}
// process ALSA control and store resulting value into ctlRequest
-STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest) {
+PUBLIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest) {
snd_ctl_elem_value_t *elemData;
snd_ctl_elem_info_t *elemInfo;
int count, length, err, valueIsArray;
@@ -490,13 +457,13 @@ STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe
snd_ctl_elem_info_alloca(&elemInfo);
snd_ctl_elem_info_set_id(elemInfo, elemId); // map ctlInfo to ctlId elemInfo is updated !!!
if (snd_ctl_elem_info(ctlDev, elemInfo) < 0) {
- NOTICE( "Fail to load ALSA NUMID=%d Values=[%s]", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues));
+ AFB_NOTICE( "Fail to load ALSA NUMID=%d Values=[%s]", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues));
goto OnErrorExit;
}
snd_ctl_elem_info_get_id(elemInfo, elemId); // map ctlInfo to ctlId elemInfo is updated !!!
if (!snd_ctl_elem_info_is_writable(elemInfo)) {
- NOTICE( "Not Writable ALSA NUMID=%d Values=[%s]", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues));
+ AFB_NOTICE( "Not Writable ALSA NUMID=%d Values=[%s]", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues));
goto OnErrorExit;
}
@@ -515,12 +482,13 @@ STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe
break;
default:
count =0;
+ length = 0;
break;
}
if (count == 0 || count < length) {
- NOTICE( "Invalid values NUMID='%d' Values='%s' count='%d' wanted='%d'", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues), length, count);
+ AFB_NOTICE( "Invalid values NUMID='%d' Values='%s' count='%d' wanted='%d'", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues), length, count);
goto OnErrorExit;
}
@@ -542,7 +510,7 @@ STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe
err = snd_ctl_elem_write(ctlDev, elemData);
if (err < 0) {
- NOTICE( "Fail to write ALSA NUMID=%d Values=[%s] Error=%s", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues), snd_strerror(err));
+ AFB_NOTICE( "Fail to write ALSA NUMID=%d Values=[%s] Error=%s", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues), snd_strerror(err));
goto OnErrorExit;
}
@@ -555,7 +523,7 @@ STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe
}
// process ALSA control and store then into ctlRequest
-STATIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest, int quiet) {
+PUBLIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest, int quiet) {
snd_ctl_elem_type_t elemType;
snd_ctl_elem_value_t *elemData;
snd_ctl_elem_info_t *elemInfo;
@@ -681,7 +649,7 @@ STATIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe
}
// assign multiple control to the same value
-PUBLIC void alsaSetGetCtls (afb_req request, ActionSetGetT action) {
+STATIC void alsaSetGetCtls (afb_req request, ActionSetGetT action) {
ctlRequestT *ctlRequest;
const char *warmsg=NULL;
int err=0, status=0;
@@ -736,7 +704,7 @@ PUBLIC void alsaSetGetCtls (afb_req request, ActionSetGetT action) {
} else {
int numid = snd_ctl_elem_list_get_numid(ctlList, ctlIndex);
if (numid < 0) {
- NOTICE("snd_ctl_elem_list_get_numid index=%d fail", ctlIndex);
+ AFB_NOTICE("snd_ctl_elem_list_get_numid index=%d fail", ctlIndex);
continue;
}
// check if current control was requested in query numids list
@@ -814,269 +782,3 @@ PUBLIC void alsaSetCtls (afb_req request) {
}
-// This routine is called when ALSA event are fired
-STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void* userData) {
- int err;
- evtHandleT *evtHandle = (evtHandleT*)userData;
- snd_ctl_event_t *eventId;
- json_object *ctlEventJ;
- unsigned int mask;
- int iface;
- int device;
- int subdev;
- const char*devname;
- ctlRequestT ctlRequest;
- snd_ctl_elem_id_t *elemId;
-
- if ((revents & EPOLLHUP) != 0) {
- NOTICE( "SndCtl hanghup [car disconnected]");
- goto ExitOnSucess;
- }
-
- if ((revents & EPOLLIN) != 0) {
-
- // initialise event structure on stack
- snd_ctl_event_alloca(&eventId);
- snd_ctl_elem_id_alloca(&elemId);
-
- err = snd_ctl_read(evtHandle->ctlDev, eventId);
- if (err < 0) goto OnErrorExit;
-
- // we only process sndctrl element
- if (snd_ctl_event_get_type(eventId) != SND_CTL_EVENT_ELEM) goto ExitOnSucess;
-
- // we only process value changed events
- mask = snd_ctl_event_elem_get_mask(eventId);
- if (!(mask & SND_CTL_EVENT_MASK_VALUE)) goto ExitOnSucess;
-
- snd_ctl_event_elem_get_id (eventId, elemId);
-
- err = alsaGetSingleCtl (evtHandle->ctlDev, elemId, &ctlRequest, evtHandle->quiet);
- if (err) goto OnErrorExit;
-
- iface = snd_ctl_event_elem_get_interface(eventId);
- device = snd_ctl_event_elem_get_device(eventId);
- subdev = snd_ctl_event_elem_get_subdevice(eventId);
- devname= snd_ctl_event_elem_get_name(eventId);
-
- // proxy ctlevent as a binder event
- ctlEventJ = json_object_new_object();
- json_object_object_add(ctlEventJ, "device" ,json_object_new_int (device));
- json_object_object_add(ctlEventJ, "subdev" ,json_object_new_int (subdev));
- if (evtHandle->quiet < 2) {
- json_object_object_add(ctlEventJ, "iface" ,json_object_new_int (iface));
- json_object_object_add(ctlEventJ, "devname",json_object_new_string (devname));
- }
- if (ctlRequest.jValues) (json_object_object_add(ctlEventJ, "values" ,ctlRequest.jValues));
- DEBUG( "sndCtlEventCB=%s", json_object_get_string(ctlEventJ));
- afb_event_push(evtHandle->afbevt, ctlEventJ);
-
- }
-
- ExitOnSucess:
- return 0;
-
- OnErrorExit:
- WARNING ("sndCtlEventCB: ignored unsupported event type");
- return (0);
-}
-
-// Subscribe to every Alsa CtlEvent send by a given board
-PUBLIC void alsaSubcribe (afb_req request) {
- static sndHandleT sndHandles[MAX_SND_CARD];
- evtHandleT *evtHandle;
- snd_ctl_t *ctlDev;
- int err, idx, cardId, idxFree=-1;
- snd_ctl_card_info_t *cardinfo;
- queryValuesT queryValues;
-
-
- err = alsaCheckQuery (request, &queryValues);
- if (err) goto OnErrorExit;
-
-
- // open control interface for devid
- err = snd_ctl_open(&ctlDev, queryValues.devid, SND_CTL_READONLY);
- if (err < 0) {
- ctlDev=NULL;
- afb_req_fail_f (request, "devid-unknown", "SndCard devid=%s Not Found err=%s", queryValues.devid, snd_strerror(err));
- goto OnErrorExit;
- }
-
- snd_ctl_card_info_alloca(&cardinfo);
- if ((err = snd_ctl_card_info(ctlDev, cardinfo)) < 0) {
- afb_req_fail_f (request, "devid-invalid", "SndCard devid=%s Not Found err=%s", queryValues.devid, snd_strerror(err));
- goto OnErrorExit;
- }
-
- cardId=snd_ctl_card_info_get_card(cardinfo);
-
- // search for an existing subscription and mark 1st free slot
- for (idx= 0; idx < MAX_SND_CARD; idx ++) {
- if (sndHandles[idx].ucount > 0 && cardId == sndHandles[idx].cardId) {
- evtHandle= sndHandles[idx].evtHandle;
- break;
- } else if (idxFree == -1) idxFree= idx;
- };
-
- // if not subscription exist for the event let's create one
- if (idx == MAX_SND_CARD) {
-
- // reach MAX_SND_CARD event registration
- if (idxFree == -1) {
- afb_req_fail_f (request, "register-toomany", "Cannot register new event Maxcard==%d", idx);
- goto OnErrorExit;
- }
-
- evtHandle = malloc (sizeof(evtHandleT));
- evtHandle->ctlDev = ctlDev;
- evtHandle->quiet = queryValues.quiet;
- sndHandles[idxFree].ucount = 0;
- sndHandles[idxFree].cardId = cardId;
- sndHandles[idxFree].evtHandle = evtHandle;
-
- // subscribe for sndctl events attached to devid
- err = snd_ctl_subscribe_events(evtHandle->ctlDev, 1);
- if (err < 0) {
- afb_req_fail_f (request, "subscribe-fail", "Cannot subscribe events from devid=%s err=%d", queryValues.devid, err);
- goto OnErrorExit;
- }
-
- // get pollfd attach to this sound board
- snd_ctl_poll_descriptors(evtHandle->ctlDev, &evtHandle->pfds, 1);
-
- // register sound event to binder main loop
- err = sd_event_add_io(afb_daemon_get_event_loop(), &evtHandle->src, evtHandle->pfds.fd, EPOLLIN, sndCtlEventCB, evtHandle);
- if (err < 0) {
- afb_req_fail_f (request, "register-mainloop", "Cannot hook events to mainloop devid=%s err=%d", queryValues.devid, err);
- goto OnErrorExit;
- }
-
- // create binder event attached to devid name
- evtHandle->afbevt = afb_daemon_make_event (queryValues.devid);
- if (!afb_event_is_valid (evtHandle->afbevt)) {
- afb_req_fail_f (request, "register-event", "Cannot register new binder event name=%s", queryValues.devid);
- goto OnErrorExit;
- }
-
- // everything looks OK let's move forward
- idx=idxFree;
- }
-
- // subscribe to binder event
- err = afb_req_subscribe(request, evtHandle->afbevt);
- if (err != 0) {
- afb_req_fail_f (request, "register-eventname", "Cannot subscribe binder event name=%s [invalid channel]", queryValues.devid);
- goto OnErrorExit;
- }
-
- // increase usage count and return success
- sndHandles[idx].ucount ++;
- afb_req_success(request, NULL, NULL);
- return;
-
- OnErrorExit:
- if (ctlDev) snd_ctl_close(ctlDev);
- return;
-}
-
-// Subscribe to every Alsa CtlEvent send by a given board
-PUBLIC void alsaGetCardId (afb_req request) {
- char devid [10];
- const char *devname, *shortname, *longname;
- int card, err, index, idx;
- json_object *respJson;
- snd_ctl_t *ctlDev;
- snd_ctl_card_info_t *cardinfo;
-
- const char *sndname = afb_req_value(request, "sndname");
- if (sndname == NULL) {
- afb_req_fail_f (request, "argument-missing", "sndname=SndCardName missing");
- goto OnErrorExit;
- }
-
- // loop on potential card number
- snd_ctl_card_info_alloca(&cardinfo);
- for (card =0; card < MAX_SND_CARD; card++) {
-
- // build card devid and probe it
- snprintf (devid, sizeof(devid), "hw:%i", card);
-
- // open control interface for devid
- err = snd_ctl_open(&ctlDev, devid, SND_CTL_READONLY);
- if (err < 0) continue;
-
- // extract sound card information
- snd_ctl_card_info(ctlDev, cardinfo);
- index = snd_ctl_card_info_get_card(cardinfo);
- devname = snd_ctl_card_info_get_id(cardinfo);
- shortname= snd_ctl_card_info_get_name(cardinfo);
- longname = snd_ctl_card_info_get_longname(cardinfo);
-
- // check if short|long name match
- if (!strcmp (sndname, devname)) break;
- if (!strcmp (sndname, shortname)) break;
- if (!strcmp (sndname, longname)) break;
- }
-
- if (card == MAX_SND_CARD) {
- afb_req_fail_f (request, "ctlDev-notfound", "Fail to find card with name=%s", sndname);
- goto OnErrorExit;
- }
-
- // proxy ctlevent as a binder event
- respJson = json_object_new_object();
- json_object_object_add(respJson, "index" ,json_object_new_int (index));
- json_object_object_add(respJson, "devid" ,json_object_new_string (devid));
- json_object_object_add(respJson, "shortname" ,json_object_new_string (shortname));
- json_object_object_add(respJson, "longname" ,json_object_new_string (longname));
-
- // search for a HAL binder card mapping name to api prefix
- for (idx=0; idx < MAX_SND_CARD; idx++) {
- if (!strcmp (cardRegistry[idx]->shortname, shortname)) break;
- }
- // if a match if found, then we have an HAL for this board let's return its value
- if (idx < MAX_SND_CARD) json_object_object_add(respJson, "halapi",json_object_new_string (cardRegistry[idx]->apiprefix));
-
- afb_req_success(request, respJson, NULL);
- return;
-
- OnErrorExit:
- return;
-}
-
-// Register loaded HAL with board Name and API prefix
-PUBLIC void alsaRegisterHal (afb_req request) {
- static int index=0;
- const char *shortname, *apiPrefix;
-
- apiPrefix = afb_req_value(request, "prefix");
- if (apiPrefix == NULL) {
- afb_req_fail_f (request, "argument-missing", "prefix=BindingApiPrefix missing");
- goto OnErrorExit;
- }
-
- shortname = afb_req_value(request, "name");
- if (shortname == NULL) {
- afb_req_fail_f (request, "argument-missing", "sndname=SndCardName missing");
- goto OnErrorExit;
- }
-
- if (index == MAX_SND_CARD) {
- afb_req_fail_f (request, "alsahal-toomany", "Fail to register sndname=[%s]", shortname);
- goto OnErrorExit;
- }
-
- cardRegistry[index]= malloc (sizeof(cardRegistry));
- cardRegistry[index]->apiprefix=strdup(apiPrefix);
- cardRegistry[index]->shortname=strdup(shortname);
- index++;cardRegistry[index]=NULL;
-
- // when OK nothing to return
- afb_req_success(request, NULL, NULL);
- return;
-
- OnErrorExit:
- return;
-}
-
diff --git a/ALSA-afb/Alsa-Ucm.c b/ALSA-afb/Alsa-Ucm.c
index 78a80ad..c9ee4f9 100644
--- a/ALSA-afb/Alsa-Ucm.c
+++ b/ALSA-afb/Alsa-Ucm.c
@@ -143,7 +143,7 @@ PUBLIC void alsaUseCaseQuery(struct afb_req request) {
json_object_object_add (ucmJ, "verb", json_object_new_string(verbList[idx]));
if (verbList[idx+1]) json_object_object_add (ucmJ, "info", json_object_new_string(verbList[idx+1]));
- DEBUG (afbIface, "Verb[%d] Action=%s Info=%s", idx, verbList[idx], verbList[idx+1]);
+ AFB_DEBUG ("Verb[%d] Action=%s Info=%s", idx, verbList[idx], verbList[idx+1]);
snprintf (identifier, sizeof(identifier), "_devices/%s", verbList[idx]);
devCount = snd_use_case_get_list (ucmHandle, identifier, &devList);
@@ -152,7 +152,7 @@ PUBLIC void alsaUseCaseQuery(struct afb_req request) {
for (int jdx=0; jdx < devCount; jdx+=2) {
json_object *devJ = json_object_new_object();
- DEBUG (afbIface, "device[%d] Action=%s Info=%s", jdx, devList[jdx], devList[jdx+1]);
+ AFB_DEBUG ("device[%d] Action=%s Info=%s", jdx, devList[jdx], devList[jdx+1]);
json_object_object_add (devJ, "dev", json_object_new_string(devList[jdx]));
if (devList[jdx+1]) json_object_object_add (devJ, "info", json_object_new_string(devList[jdx+1]));
json_object_array_add (devsJ, devJ);
@@ -168,7 +168,7 @@ PUBLIC void alsaUseCaseQuery(struct afb_req request) {
for (int jdx=0; jdx < modCount; jdx+=2) {
json_object *modJ = json_object_new_object();
- DEBUG (afbIface, "modifier[%d] Action=%s Info=%s", jdx, modList[jdx], modList[jdx+1]);
+ AFB_DEBUG ("modifier[%d] Action=%s Info=%s", jdx, modList[jdx], modList[jdx+1]);
json_object_object_add (modJ, "mod", json_object_new_string(modList[jdx]));
if (modList[jdx+1]) json_object_object_add (modJ, "info", json_object_new_string(modList[jdx+1]));
json_object_array_add (modsJ, modJ);
@@ -184,7 +184,7 @@ PUBLIC void alsaUseCaseQuery(struct afb_req request) {
for (int jdx=0; jdx < tqCount; jdx+=2) {
json_object *tqJ = json_object_new_object();
- DEBUG (afbIface, "toneqa[%d] Action=%s Info=%s", jdx, tqList[jdx], tqList[jdx+1]);
+ AFB_DEBUG ("toneqa[%d] Action=%s Info=%s", jdx, tqList[jdx], tqList[jdx+1]);
json_object_object_add (tqJ, "tq", json_object_new_string(tqList[jdx]));
if (tqList[jdx+1]) json_object_object_add (tqJ, "info", json_object_new_string(tqList[jdx+1]));
json_object_array_add (tqsJ, tqJ);
@@ -214,14 +214,14 @@ STATIC json_object *ucmGetValue (ucmHandleT *ucmHandle, const char *verb, const
if (!verb) verb="";
if (!label) {
- NOTICE (afbIface, "ucmGetValue cardname=[%s] value label missing", ucmHandle->cardName);
+ AFB_NOTICE ("ucmGetValue cardname=[%s] value label missing", ucmHandle->cardName);
goto OnErrorExit;
}
snprintf (identifier, sizeof(identifier), "%s/%s/%s", label, mod, verb);
err = snd_use_case_get (ucmHandle->ucm, identifier, (const char**)&value); // Note: value casting is a known "FEATURE" of AlsaUCM API
if (err) {
- DEBUG (afbIface, "ucmGetValue cardname=[%s] identifier=[%s] error=%s", ucmHandle->cardName, identifier, snd_strerror (err));
+ AFB_DEBUG ("ucmGetValue cardname=[%s] identifier=[%s] error=%s", ucmHandle->cardName, identifier, snd_strerror (err));
goto OnErrorExit;
}
diff --git a/ALSA-afb/CMakeLists.txt b/ALSA-afb/CMakeLists.txt
index 5c62149..4ca7158 100644
--- a/ALSA-afb/CMakeLists.txt
+++ b/ALSA-afb/CMakeLists.txt
@@ -20,7 +20,7 @@
PROJECT_TARGET_ADD(alsa-lowlevel)
# Define project Targets
- ADD_LIBRARY(alsa-lowlevel MODULE Alsa-ApiHat.c Alsa-SetGet.c Alsa-Ucm.c Alsa-AddCtl.c)
+ ADD_LIBRARY(alsa-lowlevel MODULE Alsa-ApiHat.c Alsa-SetGet.c Alsa-Ucm.c Alsa-AddCtl.c Alsa-RegEvt.c)
# Binder exposes a unique public entry point
SET_TARGET_PROPERTIES(alsa-lowlevel PROPERTIES