summaryrefslogtreecommitdiffstats
path: root/ALSA-afb/Alsa-RegEvt.c
diff options
context:
space:
mode:
authorfulup <fulup.arfoll@iot.bzh>2017-08-03 12:00:41 +0200
committerfulup <fulup.arfoll@iot.bzh>2017-08-03 12:00:41 +0200
commit070ccac33d65c651c972dfab9c6148e43d8d5d8e (patch)
tree07b79faec9bcaacf14dcc7f8ed08cacf35557e7d /ALSA-afb/Alsa-RegEvt.c
parent39384e722d9fd7d162012b682aed41b35d16d003 (diff)
Initial Working Version on Alsa Policy-Policy-Hook
Diffstat (limited to 'ALSA-afb/Alsa-RegEvt.c')
-rw-r--r--ALSA-afb/Alsa-RegEvt.c327
1 files changed, 167 insertions, 160 deletions
diff --git a/ALSA-afb/Alsa-RegEvt.c b/ALSA-afb/Alsa-RegEvt.c
index add3944..080b6cc 100644
--- a/ALSA-afb/Alsa-RegEvt.c
+++ b/ALSA-afb/Alsa-RegEvt.c
@@ -14,17 +14,18 @@
* 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;
+ snd_ctl_t *ctlDev;
int mode;
struct afb_event afbevt;
} evtHandleT;
@@ -40,29 +41,29 @@ typedef struct {
char *apiprefix;
char *shortname;
char *longname;
-}cardRegistryT;
+} cardRegistryT;
-cardRegistryT *cardRegistry[MAX_SND_CARD+1];
+cardRegistryT *cardRegistry[MAX_SND_CARD + 1];
-PUBLIC json_object *alsaCheckQuery (afb_req request, queryValuesT *queryValues) {
+PUBLIC json_object *alsaCheckQuery(afb_req request, queryValuesT *queryValues) {
json_object *tmpJ;
int done;
// get query from request
json_object *queryInJ = afb_req_json(request);
-
- done= json_object_object_get_ex (queryInJ, "devid" , &tmpJ);
+
+ done = json_object_object_get_ex(queryInJ, "devid", &tmpJ);
if (!done) {
afb_req_fail_f(request, "devid-missing", "Invalid query='%s'", json_object_get_string(queryInJ));
- goto OnErrorExit;
+ goto OnErrorExit;
}
queryValues->devid = json_object_get_string(tmpJ);
- done= json_object_object_get_ex (queryInJ, "mode" , &tmpJ);
- if (!done) queryValues->mode=QUERY_QUIET; // default quiet
- else queryValues->mode = json_object_get_int (tmpJ);
-
+ done = json_object_object_get_ex(queryInJ, "mode", &tmpJ);
+ if (!done) queryValues->mode = QUERY_QUIET; // default quiet
+ else queryValues->mode = json_object_get_int(tmpJ);
+
return queryInJ;
OnErrorExit:
@@ -70,9 +71,10 @@ OnErrorExit:
}
// This routine is called when ALSA event are fired
-STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void* userData) {
+
+STATIC int sndCtlEventCB(sd_event_source* src, int fd, uint32_t revents, void* userData) {
int err, ctlNumid;
- evtHandleT *evtHandle = (evtHandleT*)userData;
+ evtHandleT *evtHandle = (evtHandleT*) userData;
snd_ctl_event_t *eventId;
json_object *ctlEventJ;
unsigned int mask;
@@ -82,307 +84,312 @@ STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void*
const char*ctlName;
ctlRequestT ctlRequest;
snd_ctl_elem_id_t *elemId;
-
+
if ((revents & EPOLLHUP) != 0) {
AFB_NOTICE("SndCtl hanghup [car disconnected]");
goto ExitOnSucess;
}
-
- if ((revents & EPOLLIN) != 0) {
-
+
+ if ((revents & EPOLLIN) != 0) {
+
// initialise event structure on stack
- snd_ctl_event_alloca(&eventId);
+ 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->mode);
+
+ snd_ctl_event_elem_get_id(eventId, elemId);
+
+ err = alsaGetSingleCtl(evtHandle->ctlDev, elemId, &ctlRequest, evtHandle->mode);
if (err) goto OnErrorExit;
-
+
// If CTL as a value use it as container for response
- if (ctlRequest.valuesJ) ctlEventJ= ctlRequest.valuesJ;
+ if (ctlRequest.valuesJ) ctlEventJ = ctlRequest.valuesJ;
else {
ctlEventJ = json_object_new_object();
ctlNumid = snd_ctl_event_elem_get_numid(eventId);
- json_object_object_add(ctlEventJ, "id",json_object_new_int (ctlNumid));
+ json_object_object_add(ctlEventJ, "id", json_object_new_int(ctlNumid));
}
if (evtHandle->mode >= QUERY_COMPACT) {
ctlName = snd_ctl_event_elem_get_name(eventId);
- json_object_object_add(ctlEventJ, "name",json_object_new_string (ctlName));
+ json_object_object_add(ctlEventJ, "name", json_object_new_string(ctlName));
}
if (evtHandle->mode >= QUERY_VERBOSE) {
- iface = snd_ctl_event_elem_get_interface(eventId);
- device = snd_ctl_event_elem_get_device(eventId);
- subdev = snd_ctl_event_elem_get_subdevice(eventId);
- json_object_object_add(ctlEventJ, "ifc" ,json_object_new_int (iface));
- json_object_object_add(ctlEventJ, "dev" ,json_object_new_int (device));
- json_object_object_add(ctlEventJ, "sub" ,json_object_new_int (subdev));
+ iface = snd_ctl_event_elem_get_interface(eventId);
+ device = snd_ctl_event_elem_get_device(eventId);
+ subdev = snd_ctl_event_elem_get_subdevice(eventId);
+ json_object_object_add(ctlEventJ, "ifc", json_object_new_int(iface));
+ json_object_object_add(ctlEventJ, "dev", json_object_new_int(device));
+ json_object_object_add(ctlEventJ, "sub", json_object_new_int(subdev));
}
-
- AFB_DEBUG( "sndCtlEventCB=%s", json_object_get_string(ctlEventJ));
+
+ AFB_DEBUG("sndCtlEventCB=%s", json_object_get_string(ctlEventJ));
afb_event_push(evtHandle->afbevt, ctlEventJ);
}
- ExitOnSucess:
- return 0;
-
- OnErrorExit:
- AFB_WARNING ("sndCtlEventCB: ignored unsupported event type");
- return (0);
+ExitOnSucess:
+ return 0;
+
+OnErrorExit:
+ AFB_WARNING("sndCtlEventCB: ignored unsupported event type");
+ return (0);
}
// Subscribe to every Alsa CtlEvent send by a given board
-PUBLIC void alsaEvtSubcribe (afb_req request) {
+
+PUBLIC void alsaEvtSubcribe(afb_req request) {
static sndHandleT sndHandles[MAX_SND_CARD];
- evtHandleT *evtHandle=NULL;
- snd_ctl_t *ctlDev=NULL;
- int err, idx, cardId, idxFree=-1;
+ evtHandleT *evtHandle = NULL;
+ snd_ctl_t *ctlDev = NULL;
+ int err, idx, cardId, idxFree = -1;
snd_ctl_card_info_t *cardinfo;
queryValuesT queryValues;
- json_object *queryJ = alsaCheckQuery (request, &queryValues);
+ json_object *queryJ = alsaCheckQuery(request, &queryValues);
if (!queryJ) goto OnErrorExit;
// open control interface for devid
err = snd_ctl_open(&ctlDev, queryValues.devid, SND_CTL_READONLY);
if (err < 0) {
- afb_req_fail_f (request, "devid-unknown", "SndCard devid=%s Not Found err=%s", queryValues.devid, snd_strerror(err));
+ 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));
+
+ 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);
-
+
+ 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;
+ 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));
+ afb_req_fail_f(request, "register-toomany", "Cannot register new event Maxcard==%d", idx);
+ goto OnErrorExit;
+ }
+
+ evtHandle = malloc(sizeof (evtHandleT));
evtHandle->ctlDev = ctlDev;
- evtHandle->mode = queryValues.mode;
+ evtHandle->mode = queryValues.mode;
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);
+ 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);
+ 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;
+ 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;
+ 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);
+ 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 ++;
+ sndHandles[idx].ucount++;
afb_req_success(request, NULL, NULL);
return;
-
- OnErrorExit:
- if (ctlDev) snd_ctl_close(ctlDev);
- return;
+
+OnErrorExit:
+ if (ctlDev) snd_ctl_close(ctlDev);
+ return;
}
// Subscribe to every Alsa CtlEvent send by a given board
-STATIC json_object *alsaProbeCardId (afb_req request) {
+
+STATIC json_object *alsaProbeCardId(afb_req request) {
char devid [10];
const char *ctlName, *shortname, *longname;
int card, err, index, idx;
json_object *responseJ;
- snd_ctl_t *ctlDev;
+ 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");
+ 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++) {
+ 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);
-
+ 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;
-
+ if (err < 0) continue;
+
// extract sound card information
snd_ctl_card_info(ctlDev, cardinfo);
- index = snd_ctl_card_info_get_card(cardinfo);
- ctlName = snd_ctl_card_info_get_id(cardinfo);
- shortname= snd_ctl_card_info_get_name(cardinfo);
+ index = snd_ctl_card_info_get_card(cardinfo);
+ ctlName = 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, ctlName)) break;
- if (!strcmp (sndname, shortname)) break;
- if (!strcmp (sndname, longname)) break;
+ if (!strcmp(sndname, ctlName)) 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);
+ afb_req_fail_f(request, "ctlDev-notfound", "Fail to find card with name=%s", sndname);
goto OnErrorExit;
}
-
+
// proxy ctlevent as a binder event
responseJ = json_object_new_object();
- json_object_object_add(responseJ, "index" ,json_object_new_int (index));
- json_object_object_add(responseJ, "devid" ,json_object_new_string (devid));
- json_object_object_add(responseJ, "shortname" ,json_object_new_string (shortname));
- json_object_object_add(responseJ, "longname" ,json_object_new_string (longname));
-
+ json_object_object_add(responseJ, "index", json_object_new_int(index));
+ json_object_object_add(responseJ, "devid", json_object_new_string(devid));
+ json_object_object_add(responseJ, "shortname", json_object_new_string(shortname));
+ json_object_object_add(responseJ, "longname", json_object_new_string(longname));
+
// search for a HAL binder card mapping name to api prefix
- for (idx=0; (idx < MAX_SND_CARD && cardRegistry[idx]); idx++) {
- if (!strcmp (cardRegistry[idx]->shortname, shortname)) {
- json_object_object_add(responseJ, "halapi",json_object_new_string (cardRegistry[idx]->apiprefix));
+ for (idx = 0; (idx < MAX_SND_CARD && cardRegistry[idx]); idx++) {
+ if (!strcmp(cardRegistry[idx]->shortname, shortname)) {
+ json_object_object_add(responseJ, "halapi", json_object_new_string(cardRegistry[idx]->apiprefix));
break;
}
}
-
+
return responseJ;
-
- OnErrorExit:
- return NULL;
+
+OnErrorExit:
+ return NULL;
}
// Make alsaProbeCardId compatible with AFB request
-PUBLIC void alsaGetCardId (afb_req request) {
-
- json_object *responseJ = alsaProbeCardId (request);
+
+PUBLIC void alsaGetCardId(afb_req request) {
+
+ json_object *responseJ = alsaProbeCardId(request);
if (responseJ) afb_req_success(request, responseJ, NULL);
}
// Return list of active resgistrated HAL with corresponding sndcard
-PUBLIC void alsaActiveHal (afb_req request) {
+
+PUBLIC void alsaActiveHal(afb_req request) {
json_object *responseJ = json_object_new_array();
-
- for (int idx=0; idx < MAX_SND_CARD; idx++) {
+
+ for (int idx = 0; idx < MAX_SND_CARD; idx++) {
if (!cardRegistry[idx]) break;
-
+
json_object *haldevJ = json_object_new_object();
json_object_object_add(haldevJ, "api", json_object_new_string(cardRegistry[idx]->apiprefix));
- if (cardRegistry[idx]->devid) json_object_object_add(haldevJ, "devid", json_object_new_string(cardRegistry[idx]->devid));
+ if (cardRegistry[idx]->devid) json_object_object_add(haldevJ, "devid", json_object_new_string(cardRegistry[idx]->devid));
if (cardRegistry[idx]->shortname)json_object_object_add(haldevJ, "shortname", json_object_new_string(cardRegistry[idx]->shortname));
if (cardRegistry[idx]->longname) json_object_object_add(haldevJ, "longname", json_object_new_string(cardRegistry[idx]->longname));
- json_object_array_add (responseJ, haldevJ);
+ json_object_array_add(responseJ, haldevJ);
}
-
+
afb_req_success(request, responseJ, NULL);
}
// Register loaded HAL with board Name and API prefix
-PUBLIC void alsaRegisterHal (afb_req request) {
- static int index=0;
+
+PUBLIC void alsaRegisterHal(afb_req request) {
+ static int index = 0;
json_object *responseJ;
const char *shortname, *apiPrefix;
-
+
apiPrefix = afb_req_value(request, "prefix");
if (apiPrefix == NULL) {
- afb_req_fail_f (request, "argument-missing", "prefix=BindingApiPrefix missing");
+ 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");
+ 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;
+ afb_req_fail_f(request, "alsahal-toomany", "Fail to register sndname=[%s]", shortname);
+ goto OnErrorExit;
}
-
+
// alsaGetCardId should be check to register only valid card
- responseJ= alsaProbeCardId(request);
+ responseJ = alsaProbeCardId(request);
if (responseJ) {
json_object *tmpJ;
int done;
-
- cardRegistry[index]= malloc (sizeof(cardRegistry));
- cardRegistry[index]->apiprefix=strdup(apiPrefix);
- cardRegistry[index]->shortname=strdup(shortname);
-
- done= json_object_object_get_ex (responseJ, "devid" , &tmpJ);
- if (done) cardRegistry[index]->devid = strdup (json_object_get_string(tmpJ));
- else cardRegistry[index]->devid=NULL;
-
- done = json_object_object_get_ex (responseJ, "longname" , &tmpJ);
- if (done) cardRegistry[index]->longname = strdup (json_object_get_string(tmpJ));
- else cardRegistry[index]->longname=NULL;
-
+
+ cardRegistry[index] = malloc(sizeof (cardRegistry));
+ cardRegistry[index]->apiprefix = strdup(apiPrefix);
+ cardRegistry[index]->shortname = strdup(shortname);
+
+ done = json_object_object_get_ex(responseJ, "devid", &tmpJ);
+ if (done) cardRegistry[index]->devid = strdup(json_object_get_string(tmpJ));
+ else cardRegistry[index]->devid = NULL;
+
+ done = json_object_object_get_ex(responseJ, "longname", &tmpJ);
+ if (done) cardRegistry[index]->longname = strdup(json_object_get_string(tmpJ));
+ else cardRegistry[index]->longname = NULL;
+
// make sure register close with a null value
index++;
- cardRegistry[index]=NULL;
-
- afb_req_success(request, responseJ, NULL);
+ cardRegistry[index] = NULL;
+
+ afb_req_success(request, responseJ, NULL);
}
-
+
// If OK return sound card Alsa ID+Info
return;
-
- OnErrorExit:
- return;
+
+OnErrorExit:
+ return;
}