From 5e0ef17e8049722d70a76b93a0dc177016ac5f1c Mon Sep 17 00:00:00 2001 From: Jonathan Aillet Date: Mon, 19 Aug 2019 11:35:28 +0200 Subject: Rework ALSA card control events functions Rework ALSA card control events subscription and handling to: - Clean unnecessary part of codes. - Increase reliability of ALSA control events polling callback. Bug-AGL: SPEC-2749 Change-Id: I75dc90483254b1befdf83968c9032ec877c1d895 Signed-off-by: Jonathan Aillet --- alsa-binding/Alsa-RegEvt.c | 150 +++++++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 66 deletions(-) diff --git a/alsa-binding/Alsa-RegEvt.c b/alsa-binding/Alsa-RegEvt.c index 36bb590..c9ac5f1 100644 --- a/alsa-binding/Alsa-RegEvt.c +++ b/alsa-binding/Alsa-RegEvt.c @@ -32,14 +32,16 @@ typedef struct { snd_ctl_t *ctlDev; int mode; afb_event_t afbevt; -} evtHandleT; +} ctrlEvtHandleT; typedef struct { - int ucount; - int cardId; - evtHandleT *evtHandle; + ctrlEvtHandleT *evtHandle; } sndHandleT; +typedef struct { + sndHandleT sndHandles[MAX_SND_CARD]; +} sndCardsT; + typedef struct { int cardid; char *devid; @@ -86,11 +88,12 @@ OnErrorExit: return NULL; } -// This routine is called when ALSA event are fired +// This routine is called when ALSA control events are fired STATIC int sndCtlEventCB(sd_event_source* src, int fd, uint32_t revents, void* userData) { int err, ctlNumid; - evtHandleT *evtHandle = (evtHandleT*) userData; + sndHandleT *sndHandle = (sndHandleT *) userData; + ctrlEvtHandleT *evtHandle = (ctrlEvtHandleT*) sndHandle->evtHandle; snd_ctl_event_t *eventId; json_object *ctlEventJ; unsigned int mask; @@ -104,7 +107,11 @@ STATIC int sndCtlEventCB(sd_event_source* src, int fd, uint32_t revents, void* u if ((revents & EPOLLERR) != 0) { AFB_ERROR("An error has been send by event loop polling, prevent new errors to be fired by deleting event src"); sd_event_source_unref(src); - return -1; + afb_event_unref(sndHandle->evtHandle->afbevt); + snd_ctl_close(sndHandle->evtHandle->ctlDev); + free(sndHandle->evtHandle); + sndHandle->evtHandle = NULL; + goto OnErrorExit; } if ((revents & EPOLLHUP) != 0) { @@ -113,7 +120,6 @@ STATIC int sndCtlEventCB(sd_event_source* src, int fd, uint32_t revents, void* u } if ((revents & EPOLLIN) != 0) { - // initialise event structure on stack snd_ctl_event_alloca(&eventId); snd_ctl_elem_id_alloca(&elemId); @@ -155,7 +161,6 @@ STATIC int sndCtlEventCB(sd_event_source* src, int fd, uint32_t revents, void* u json_object_object_add(ctlEventJ, "sub", json_object_new_int(subdev)); } - AFB_DEBUG("sndCtlEventCB=%s", json_object_get_string(ctlEventJ)); afb_event_push(evtHandle->afbevt, ctlEventJ); } @@ -164,105 +169,118 @@ ExitOnSucess: return 0; OnErrorExit: - AFB_WARNING("sndCtlEventCB: ignored unsupported event type"); - return (0); + AFB_WARNING("sndCtlEventCB: Error detected"); + return -1; } -// Subscribe to every Alsa CtlEvent send by a given board -PUBLIC void alsaEvtSubcribe(afb_req_t request) { - static sndHandleT sndHandles[MAX_SND_CARD]; - evtHandleT *evtHandle = NULL; +// Subscribe to every Alsa CtlEvent send by a given board +STATIC afb_event_t alsaEvtSubscribeAlsaControlEvent(afb_req_t request, sndCardsT *sndCards, queryValuesT *queryValues) { + sndHandleT *currentSndHandle = NULL; snd_ctl_t *ctlDev = NULL; - int err, idx, cardId, idxFree = -1; + int err, cardId; snd_ctl_card_info_t *cardinfo; - queryValuesT 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); + 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)); + err = snd_ctl_card_info(ctlDev, cardinfo); + if (err < 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) { + if(cardId < 0 || cardId >= MAX_SND_CARD) { + afb_req_fail_f(request, "devid-invalid", "SndCard cardId=%i invalid", cardId); + goto OnErrorExit; + } - // 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; - } + currentSndHandle = &sndCards->sndHandles[cardId]; - evtHandle = malloc(sizeof (evtHandleT)); - evtHandle->ctlDev = ctlDev; - evtHandle->mode = queryValues.mode; - sndHandles[idxFree].ucount = 0; - sndHandles[idxFree].cardId = cardId; - sndHandles[idxFree].evtHandle = evtHandle; + // if not subscription exist for the event let's create one + if (! currentSndHandle->evtHandle) { + currentSndHandle->evtHandle = malloc(sizeof (ctrlEvtHandleT)); + currentSndHandle->evtHandle->ctlDev = ctlDev; + currentSndHandle->evtHandle->mode = queryValues->mode; // subscribe for sndctl events attached to devid - err = snd_ctl_subscribe_events(evtHandle->ctlDev, 1); + err = snd_ctl_subscribe_events(currentSndHandle->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); + snd_ctl_poll_descriptors(currentSndHandle->evtHandle->ctlDev, ¤tSndHandle->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); + err = sd_event_add_io(afb_daemon_get_event_loop(), + ¤tSndHandle->evtHandle->src, + currentSndHandle->evtHandle->pfds.fd, + EPOLLIN, + sndCtlEventCB, + currentSndHandle); 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); + currentSndHandle->evtHandle->afbevt = afb_daemon_make_event(queryValues->devid); + if (!afb_event_is_valid(currentSndHandle->evtHandle->afbevt)) { + afb_req_fail_f(request, "register-event", "Cannot register new binder event name=%s", queryValues->devid); goto OnErrorExit; } + } + else if (ctlDev) { + snd_ctl_close(ctlDev); + } + + return currentSndHandle->evtHandle->afbevt; + +OnErrorExit: + if (ctlDev) + snd_ctl_close(ctlDev); - // everything looks OK let's move forward - idx = idxFree; + return NULL; +} + +// Subscribe to alsacore event +PUBLIC void alsaEvtSubcribe(afb_req_t request) { + static sndCardsT *sndCards = NULL; + afb_event_t eventToSubscribe; + int err; + queryValuesT queryValues; + + json_object *queryJ; + + if(! sndCards) { + sndCards = calloc(1, sizeof(sndCardsT)); } + queryJ = alsaCheckQuery(request, &queryValues); + if (!queryJ) return; + + eventToSubscribe = alsaEvtSubscribeAlsaControlEvent(request, sndCards, &queryValues); + + if(! eventToSubscribe) + return; + // 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; + err = afb_req_subscribe(request, eventToSubscribe); + if (err) { + afb_req_fail_f(request, "register-eventname", "Cannot subscribe binder event"); + return; } - // 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 -- cgit 1.2.3-korg