From bdc1fcf5f04b1bc2f97e9d449ced1c516f70d4af Mon Sep 17 00:00:00 2001 From: Andrew Chant Date: Mon, 5 Feb 2018 15:16:41 -0800 Subject: tinyalsa: add mixer_consume_event mixer_consume_event consumes subscribed events from the mixer in order to allow monitoring of mixer control value changed. --- src/mixer.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src') diff --git a/src/mixer.c b/src/mixer.c index 1c9e63b..c8c6c2a 100644 --- a/src/mixer.c +++ b/src/mixer.c @@ -535,6 +535,27 @@ int mixer_wait_event(struct mixer *mixer, int timeout) } } +/** Consume a mixer event. + * If mixer_subscribe_events has been called, + * mixer_wait_event will identify when a control value has changed. + * This function will clear a single event from the mixer so that + * further events can be alerted. + * + * @param mixer A mixer handle. + * @returns 0 on success. -errno on failure. + * @ingroup libtinyalsa-mixer + */ +int mixer_consume_event(struct mixer *mixer) { + struct snd_ctl_event ev; + ssize_t count = read(mixer->fd, &ev, sizeof(ev)); + // Exporting the actual event would require exposing snd_ctl_event + // via the header file, and all associated structs. + // The events generally tell you exactly which value changed, + // but reading values you're interested isn't hard and simplifies + // the interface greatly. + return (count >= 0) ? 0 : -errno; +} + static unsigned int mixer_grp_get_count(struct mixer_ctl_group *grp) { if (!grp) -- cgit v1.2.3 From f38405c4fd804fc3482055f1345095343ef243c5 Mon Sep 17 00:00:00 2001 From: Rohit kumar Date: Tue, 2 Jun 2020 11:14:38 +0530 Subject: mixer: Add plugin support for mixer_consume/read_event snd_ctl_event is needed by client to get details of event received. Introduce mixer_read_event() with plugin support to support this. --- src/mixer.c | 38 ++++++++++++++++++++++++++++++-------- src/mixer_hw.c | 9 +++++++++ 2 files changed, 39 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/mixer.c b/src/mixer.c index c8c6c2a..582d8c1 100644 --- a/src/mixer.c +++ b/src/mixer.c @@ -545,15 +545,37 @@ int mixer_wait_event(struct mixer *mixer, int timeout) * @returns 0 on success. -errno on failure. * @ingroup libtinyalsa-mixer */ -int mixer_consume_event(struct mixer *mixer) { +int mixer_consume_event(struct mixer *mixer) +{ struct snd_ctl_event ev; - ssize_t count = read(mixer->fd, &ev, sizeof(ev)); - // Exporting the actual event would require exposing snd_ctl_event - // via the header file, and all associated structs. - // The events generally tell you exactly which value changed, - // but reading values you're interested isn't hard and simplifies - // the interface greatly. - return (count >= 0) ? 0 : -errno; + + return mixer_read_event(mixer, &ev); +} + +int mixer_read_event(struct mixer *mixer, struct snd_ctl_event *ev) +{ + struct mixer_ctl_group *grp; + ssize_t count = 0; + + if (mixer->h_grp) { + grp = mixer->h_grp; + if (grp->event_cnt) { + grp->event_cnt--; + count = grp->ops->read_event(grp->data, ev, sizeof(*ev)); + return (count >= 0) ? 0 : -errno; + } + } +#ifdef TINYALSA_USES_PLUGINS + if (mixer->v_grp) { + grp = mixer->v_grp; + if (grp->event_cnt) { + grp->event_cnt--; + count = grp->ops->read_event(grp->data, ev, sizeof(*ev)); + return (count >= 0) ? 0 : -errno; + } + } +#endif + return 0; } static unsigned int mixer_grp_get_count(struct mixer_ctl_group *grp) diff --git a/src/mixer_hw.c b/src/mixer_hw.c index 2e86dfa..da5a390 100644 --- a/src/mixer_hw.c +++ b/src/mixer_hw.c @@ -82,9 +82,18 @@ static int mixer_hw_ioctl(void *data, unsigned int cmd, ...) return ioctl(hw_data->fd, cmd, arg); } +static ssize_t mixer_hw_read_event(void *data, struct snd_ctl_event *ev, + size_t size) +{ + struct mixer_hw_data *hw_data = data; + + return read(hw_data->fd, ev, size); +} + static const struct mixer_ops mixer_hw_ops = { .close = mixer_hw_close, .ioctl = mixer_hw_ioctl, + .read_event = mixer_hw_read_event, }; int mixer_hw_open(unsigned int card, void **data, -- cgit v1.2.3 From df855e804886f2846d0bdb6d8b1aad506452f051 Mon Sep 17 00:00:00 2001 From: Rohit kumar Date: Tue, 2 Jun 2020 11:41:13 +0530 Subject: mixer: Fix memory leak and other issues in mixer event Fix memory leak in mixer_wait_event(). Also, poll should be unblocked after increasing event_cnt in mixer_plugin, otherwise event_cnt can become negative during read_event. Fix the same. --- src/mixer.c | 29 +++++++++++++++++++---------- src/mixer_plugin.c | 2 +- 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/mixer.c b/src/mixer.c index 582d8c1..c8480d7 100644 --- a/src/mixer.c +++ b/src/mixer.c @@ -475,7 +475,7 @@ int mixer_wait_event(struct mixer *mixer, int timeout) { struct pollfd *pfd; struct mixer_ctl_group *grp; - int count = 0, num_fds = 0, i; + int count = 0, num_fds = 0, i, ret = 0; if (mixer->fd >= 0) num_fds++; @@ -485,7 +485,7 @@ int mixer_wait_event(struct mixer *mixer, int timeout) num_fds++; #endif - pfd = (struct pollfd *)calloc(sizeof(struct pollfd), num_fds); + pfd = (struct pollfd *)calloc(num_fds, sizeof(struct pollfd)); if (!pfd) return -ENOMEM; @@ -506,33 +506,42 @@ int mixer_wait_event(struct mixer *mixer, int timeout) #endif if (!count) - return 0; + goto exit; for (;;) { int err; err = poll(pfd, count, timeout); - if (err < 0) - return -errno; + if (err < 0) { + ret = -errno; + goto exit; + } if (!err) - return 0; + goto exit; + for (i = 0; i < count; i++) { - if (pfd[i].revents & (POLLERR | POLLNVAL)) - return -EIO; + if (pfd[i].revents & (POLLERR | POLLNVAL)) { + ret = -EIO; + goto exit; + } if (pfd[i].revents & (POLLIN | POLLOUT)) { if ((i == 0) && mixer->fd >= 0) { grp = mixer->h_grp; grp->event_cnt++; } #ifdef TINYALSA_USES_PLUGINS - else { + else { grp = mixer->v_grp; grp->event_cnt++; } #endif - return 1; + ret = 1; + goto exit; } } } +exit: + free(pfd); + return ret; } /** Consume a mixer event. diff --git a/src/mixer_plugin.c b/src/mixer_plugin.c index 389003e..9f22b7e 100644 --- a/src/mixer_plugin.c +++ b/src/mixer_plugin.c @@ -137,8 +137,8 @@ static int mixer_plug_info_integer(struct snd_control *ctl, void mixer_plug_notifier_cb(struct mixer_plugin *plugin) { - eventfd_write(plugin->eventfd, 1); plugin->event_cnt++; + eventfd_write(plugin->eventfd, 1); } /* In consume_event/read, do not call eventfd_read until all events are read from list. -- cgit v1.2.3