Snap for 6379934 from d32f5fd92bc28ca83caf1ec9414e84474c2357af to r-keystone-qcom-release

Change-Id: Id79853abc81ee5941435be6adb2f409771e4d846
diff --git a/Android.bp b/Android.bp
index 137aa65..090d91c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -7,12 +7,7 @@
     },
     srcs: [
         "mixer.c",
-        "mixer_hw.c",
-        "mixer_plugin.c",
         "pcm.c",
-        "pcm_hw.c",
-        "pcm_plugin.c",
-        "snd_utils.c",
     ],
     cflags: ["-Werror", "-Wno-macro-redefined"],
     export_include_dirs: ["include"],
@@ -23,8 +18,6 @@
             enabled: false,
         },
     },
-
-    system_shared_libs: ["libc","libdl"],
 }
 
 cc_binary {
diff --git a/include/tinyalsa/asoundlib.h b/include/tinyalsa/asoundlib.h
index 364e385..935c8d0 100644
--- a/include/tinyalsa/asoundlib.h
+++ b/include/tinyalsa/asoundlib.h
@@ -31,7 +31,6 @@
 
 #include <sys/time.h>
 #include <stddef.h>
-#include <sound/asound.h>
 
 #if defined(__cplusplus)
 extern "C" {
@@ -318,7 +317,6 @@
 int mixer_subscribe_events(struct mixer *mixer, int subscribe);
 int mixer_wait_event(struct mixer *mixer, int timeout);
 int mixer_consume_event(struct mixer *mixer);
-int mixer_read_event(struct mixer *mixer, struct snd_ctl_event *ev);
 
 #if defined(__cplusplus)
 }  /* extern "C" */
diff --git a/include/tinyalsa/mixer_plugin.h b/include/tinyalsa/mixer_plugin.h
deleted file mode 100644
index 144c9a7..0000000
--- a/include/tinyalsa/mixer_plugin.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
-** Copyright (c) 2019, The Linux Foundation. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-**   * Redistributions of source code must retain the above copyright
-**     notice, this list of conditions and the following disclaimer.
-**   * Redistributions in binary form must reproduce the above
-**     copyright notice, this list of conditions and the following
-**     disclaimer in the documentation and/or other materials provided
-**     with the distribution.
-**   * Neither the name of The Linux Foundation nor the names of its
-**     contributors may be used to endorse or promote products derived
-**     from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-** ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**/
-
-
-#ifndef __MIXER_PLUGIN_H__
-#define __MIXER_PLUGIN_H__
-
-#define MIXER_PLUGIN_OPEN_FN(name)                             \
-    int name##_open(struct mixer_plugin **plugin,              \
-                    unsigned int card)
-
-#define MIXER_PLUGIN_OPEN_FN_PTR()                              \
-    int (*mixer_plugin_open_fn) (struct mixer_plugin **plugin,  \
-                                 unsigned int card)             \
-
-struct mixer_plugin;
-
-typedef void (*event_callback)(struct mixer_plugin *);
-
-struct mixer_plugin_ops {
-    void (*close) (struct mixer_plugin **plugin);
-    int (*subscribe_events) (struct mixer_plugin *plugin,
-                             event_callback event_cb);
-    ssize_t (*read_event) (struct mixer_plugin *plugin,
-                           struct snd_ctl_event *ev, size_t size);
-};
-
-struct snd_control {
-    snd_ctl_elem_iface_t iface;
-    unsigned int access;
-    const char *name;
-    snd_ctl_elem_type_t type;
-    void *value;
-    int (*get) (struct mixer_plugin *plugin,
-                struct snd_control *control,
-                struct snd_ctl_elem_value *ev);
-    int (*put) (struct mixer_plugin *plugin,
-                struct snd_control *control,
-                struct snd_ctl_elem_value *ev);
-    uint32_t private_value;
-    void *private_data;
-};
-
-struct mixer_plugin {
-    unsigned int card;
-    struct mixer_plugin_ops *ops;
-    void *priv;
-
-    int eventfd;
-    int subscribed;
-    int event_cnt;
-
-    struct snd_control *controls;
-    unsigned int num_controls;
-};
-
-struct snd_value_enum {
-    unsigned int items;
-    char **texts;
-};
-
-struct snd_value_bytes {
-    unsigned int size;
-};
-
-struct snd_value_tlv_bytes {
-    unsigned int size;
-    int (*get) (struct mixer_plugin *plugin,
-                struct snd_control *control,
-                struct snd_ctl_tlv *tlv);
-    int (*put) (struct mixer_plugin *plugin,
-                struct snd_control *control,
-                struct snd_ctl_tlv *tlv);
-};
-
-struct snd_value_int {
-    unsigned int count;
-    int min;
-    int max;
-    int step;
-};
-
-/* static initializers */
-
-#define SND_VALUE_ENUM(etexts, eitems)    \
-    {.texts = etexts, .items = eitems}
-
-#define SND_VALUE_BYTES(csize)    \
-    {.size = csize }
-
-#define SND_VALUE_INTEGER(icount, imin, imax, istep) \
-    {.count = icount, .min = imin, .max = imax, .step = istep }
-
-#define SND_VALUE_TLV_BYTES(csize, cget, cput)       \
-    {.size = csize, .get = cget, .put = cput }
-
-#define SND_CONTROL_ENUM(cname, cget, cput, cenum, priv_val, priv_data)   \
-    {    .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                             \
-        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,                        \
-        .type = SNDRV_CTL_ELEM_TYPE_ENUMERATED,                           \
-        .name = cname, .value = &cenum, .get = cget, .put = cput,         \
-        .private_value = priv_val, .private_data = priv_data,             \
-    }
-
-#define SND_CONTROL_BYTES(cname, cget, cput, cbytes, priv_val, priv_data) \
-    {                                                                     \
-        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                              \
-        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,                        \
-        .type = SNDRV_CTL_ELEM_TYPE_BYTES,                                \
-        .name = cname, .value = &cbytes, .get = cget, .put = cput,        \
-        .private_value = priv_val, .private_data = priv_data,             \
-    }
-
-#define SND_CONTROL_INTEGER(cname, cget, cput, cint, priv_val, priv_data) \
-    {                                                                        \
-        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                                 \
-        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,                           \
-        .type = SNDRV_CTL_ELEM_TYPE_INTEGER,                                 \
-        .name = cname, .value = &cint, .get = cget, .put = cput,             \
-        .private_value = priv_val, .private_data = priv_data,                \
-    }
-
-#define SND_CONTROL_TLV_BYTES(cname, cbytes, priv_val, priv_data)  \
-    {                                                                        \
-        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                                 \
-        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE,                       \
-        .type = SNDRV_CTL_ELEM_TYPE_BYTES,                                   \
-        .name = cname, .value = &cbytes,                                     \
-        .private_value = priv_val, .private_data = priv_data,                \
-    }
-
-/* pointer based initializers */
-#define INIT_SND_CONTROL_INTEGER(c, cname, cget, cput, cint, pval, pdata)   \
-    {                                                                       \
-        c->iface = SNDRV_CTL_ELEM_IFACE_MIXER;                              \
-        c->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;                        \
-        c->type = SNDRV_CTL_ELEM_TYPE_INTEGER;                              \
-        c->name = cname; c->value = &cint; c->get = cget; c->put = cput;    \
-        c->private_value = pval; c->private_data = pdata;                   \
-    }
-
-#define INIT_SND_CONTROL_BYTES(c, cname, cget, cput, cint, pval, pdata)     \
-    {                                                                       \
-        c->iface = SNDRV_CTL_ELEM_IFACE_MIXER;                              \
-        c->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;                        \
-        c->type = SNDRV_CTL_ELEM_TYPE_BYTES;                                \
-        c->name = cname; c->value = &cint; c->get = cget; c->put = cput;    \
-        c->private_value = pval; c->private_data = pdata;                   \
-    }
-
-#define INIT_SND_CONTROL_ENUM(c, cname, cget, cput, cenum, pval, pdata)     \
-    {                                                                       \
-        c->iface = SNDRV_CTL_ELEM_IFACE_MIXER;                              \
-        c->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;                        \
-        c->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;                           \
-        c->name = cname; c->value = cenum; c->get = cget; c->put = cput;    \
-        c->private_value = pval; c->private_data = pdata;                   \
-    }
-#define INIT_SND_CONTROL_TLV_BYTES(c, cname, cbytes, priv_val, priv_data)  \
-    {                                                                      \
-        c->iface = SNDRV_CTL_ELEM_IFACE_MIXER;                             \
-        c->access = SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE;                   \
-        c->type = SNDRV_CTL_ELEM_TYPE_BYTES;                               \
-        c->name = cname; c->value = &cbytes;                               \
-        c->private_value = priv_val; c->private_data = priv_data;          \
-    }
-#endif /* end of __MIXER_PLUGIN_H__ */
diff --git a/include/tinyalsa/pcm_plugin.h b/include/tinyalsa/pcm_plugin.h
deleted file mode 100644
index 5d6f503..0000000
--- a/include/tinyalsa/pcm_plugin.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* pcm_plugin.h
-** Copyright (c) 2019, The Linux Foundation. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-**   * Redistributions of source code must retain the above copyright
-**     notice, this list of conditions and the following disclaimer.
-**   * Redistributions in binary form must reproduce the above
-**     copyright notice, this list of conditions and the following
-**     disclaimer in the documentation and/or other materials provided
-**     with the distribution.
-**   * Neither the name of The Linux Foundation nor the names of its
-**     contributors may be used to endorse or promote products derived
-**     from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-** ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**/
-
-#ifndef __PCM_PLUGIN_H__
-#define __PCM_PLUGIN_H__
-
-#define PCM_PLUGIN_OPEN_FN(name)                    \
-    int name##_open(struct pcm_plugin **plugin,     \
-                    unsigned int card,              \
-                    unsigned int device,            \
-                    int mode)
-
-#define PCM_PLUGIN_OPEN_FN_PTR()                        \
-    int (*plugin_open_fn) (struct pcm_plugin **plugin,  \
-                           unsigned int card,           \
-                           unsigned int device,         \
-                           int mode);
-
-struct pcm_plugin;
-
-struct pcm_plugin_ops {
-    int (*close) (struct pcm_plugin *plugin);
-    int (*hw_params) (struct pcm_plugin *plugin,
-                      struct snd_pcm_hw_params *params);
-    int (*sw_params) (struct pcm_plugin *plugin,
-                      struct snd_pcm_sw_params *params);
-    int (*sync_ptr) (struct pcm_plugin *plugin,
-                     struct snd_pcm_sync_ptr *sync_ptr);
-    int (*writei_frames) (struct pcm_plugin *plugin,
-                          struct snd_xferi *x);
-    int (*readi_frames) (struct pcm_plugin *plugin,
-                         struct snd_xferi *x);
-    int (*ttstamp) (struct pcm_plugin *plugin,
-                    int *tstamp);
-    int (*prepare) (struct pcm_plugin *plugin);
-    int (*start) (struct pcm_plugin *plugin);
-    int (*drop) (struct pcm_plugin *plugin);
-    int (*ioctl) (struct pcm_plugin *plugin,
-                  int cmd, void *arg);
-};
-
-struct pcm_plugin_min_max {
-    unsigned int min;
-    unsigned int max;
-};
-
-struct pcm_plugin_hw_constraints {
-    uint64_t access;
-    /* As of this implementation ALSA supports 52 formats */
-    uint64_t format;
-    struct pcm_plugin_min_max bit_width;
-    struct pcm_plugin_min_max channels;
-    struct pcm_plugin_min_max rate;
-    struct pcm_plugin_min_max periods;
-    struct pcm_plugin_min_max period_bytes;
-};
-
-struct pcm_plugin {
-    unsigned int card;
-
-    struct pcm_plugin_ops *ops;
-    struct pcm_plugin_hw_constraints *constraints;
-
-    void *node;
-    int mode;
-    void *priv;
-
-    unsigned int state;
-};
-
-#endif /* end of __PCM_PLUGIN_H__ */
diff --git a/mixer.c b/mixer.c
index f26f43f..f3fdb62 100644
--- a/mixer.c
+++ b/mixer.c
@@ -40,7 +40,6 @@
 #include <sys/ioctl.h>
 
 #include <linux/ioctl.h>
-
 #define __force
 #define __bitwise
 #define __user
@@ -51,266 +50,122 @@
 #endif
 
 #include <tinyalsa/asoundlib.h>
-#include "mixer_io.h"
 
 struct mixer_ctl {
     struct mixer *mixer;
-    struct mixer_ctl_group *grp;
     struct snd_ctl_elem_info *info;
     char **ename;
     bool info_retrieved;
 };
 
-struct mixer_ctl_group {
-    struct snd_ctl_elem_info *elem_info;
-    struct mixer_ctl *ctl;
-    unsigned int count;
-    int event_cnt;
-
-    struct mixer_ops *ops;
-    void *data;
-};
-
 struct mixer {
     int fd;
     struct snd_ctl_card_info card_info;
-
-    /* hardware/physical mixer control group */
-    struct mixer_ctl_group *hw_grp;
-
-    /*
-     * Virutal mixer control group.
-     * Currently supports one virtual mixer (.so)
-     * per card. Could be extended to multiple
-     */
-    struct mixer_ctl_group *virt_grp;
-
-    unsigned int total_ctl_count;
+    struct snd_ctl_elem_info *elem_info;
+    struct mixer_ctl *ctl;
+    unsigned int count;
 };
 
-static void mixer_grp_close(struct mixer_ctl_group *grp)
-{
-    unsigned int n, m;
-
-    if (!grp)
-        return;
-
-    if (grp->ctl) {
-        for (n = 0; n < grp->count; n++) {
-            if (grp->ctl[n].ename) {
-                unsigned int max = grp->ctl[n].info->value.enumerated.items;
-                for (m = 0; m < max; m++)
-                    free(grp->ctl[n].ename[m]);
-                free(grp->ctl[n].ename);
-            }
-        }
-        free(grp->ctl);
-    }
-
-    if (grp->elem_info)
-        free(grp->elem_info);
-
-    free(grp);
-}
-
 void mixer_close(struct mixer *mixer)
 {
+    unsigned int n,m;
+
     if (!mixer)
         return;
 
-    if (mixer->fd >= 0 && mixer->hw_grp)
-        mixer->hw_grp->ops->close(mixer->hw_grp->data);
-    mixer_grp_close(mixer->hw_grp);
+    if (mixer->fd >= 0)
+        close(mixer->fd);
 
-    if (mixer->virt_grp)
-        mixer->virt_grp->ops->close(mixer->virt_grp->data);
-    mixer_grp_close(mixer->virt_grp);
+    if (mixer->ctl) {
+        for (n = 0; n < mixer->count; n++) {
+            if (mixer->ctl[n].ename) {
+                unsigned int max = mixer->ctl[n].info->value.enumerated.items;
+                for (m = 0; m < max; m++)
+                    free(mixer->ctl[n].ename[m]);
+                free(mixer->ctl[n].ename);
+            }
+        }
+        free(mixer->ctl);
+    }
+
+    if (mixer->elem_info)
+        free(mixer->elem_info);
 
     free(mixer);
 
     /* TODO: verify frees */
 }
 
-static int mixer_grp_open(struct mixer *mixer,
-                struct mixer_ctl_group **ctl_grp,
-                struct mixer_ops *ops,
-                void *data, int *num_ctls_in_grp)
+struct mixer *mixer_open(unsigned int card)
 {
-    struct mixer_ctl_group *grp;
     struct snd_ctl_elem_list elist;
     struct snd_ctl_elem_id *eid = NULL;
+    struct mixer *mixer = NULL;
     unsigned int n;
-    int ret;
+    int fd;
+    char fn[256];
 
-    grp = calloc(1, sizeof(*grp));
-    if (!grp)
-        return -ENOMEM;
+    snprintf(fn, sizeof(fn), "/dev/snd/controlC%u", card);
+    fd = open(fn, O_RDWR);
+    if (fd < 0)
+        return 0;
 
     memset(&elist, 0, sizeof(elist));
-    ret = ops->ioctl(data, SNDRV_CTL_IOCTL_ELEM_LIST, &elist);
-    if (ret < 0)
-        goto err_get_elem_list;
+    if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
+        goto fail;
 
-    grp->ctl = calloc(elist.count, sizeof(struct mixer_ctl));
-    grp->elem_info = calloc(elist.count, sizeof(struct snd_ctl_elem_info));
-    if (!grp->ctl || !grp->elem_info) {
-        ret = -ENOMEM;
-        goto err_ctl_alloc;
-    }
+    mixer = calloc(1, sizeof(*mixer));
+    if (!mixer)
+        goto fail;
 
-    eid = calloc(elist.count, sizeof(*eid));
-    if (!eid) {
-        ret = -ENOMEM;
-        goto err_ctl_alloc;
-    }
+    mixer->ctl = calloc(elist.count, sizeof(struct mixer_ctl));
+    mixer->elem_info = calloc(elist.count, sizeof(struct snd_ctl_elem_info));
+    if (!mixer->ctl || !mixer->elem_info)
+        goto fail;
 
-    grp->count = elist.count;
-    elist.space = grp->count;
+    if (ioctl(fd, SNDRV_CTL_IOCTL_CARD_INFO, &mixer->card_info) < 0)
+        goto fail;
+
+    eid = calloc(elist.count, sizeof(struct snd_ctl_elem_id));
+    if (!eid)
+        goto fail;
+
+    mixer->count = elist.count;
+    mixer->fd = fd;
+    elist.space = mixer->count;
     elist.pids = eid;
-    ret = ops->ioctl(data, SNDRV_CTL_IOCTL_ELEM_LIST, &elist);
-    if (ret < 0)
-        goto err_ctl_alloc;
+    if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
+        goto fail;
 
-    for (n = 0; n < grp->count; n++) {
-        struct mixer_ctl *ctl = grp->ctl + n;
+    for (n = 0; n < mixer->count; n++) {
+        struct mixer_ctl *ctl = mixer->ctl + n;
 
-        ctl->grp = grp;
         ctl->mixer = mixer;
-        ctl->info = grp->elem_info + n;
+        ctl->info = mixer->elem_info + n;
         ctl->info->id.numid = eid[n].numid;
         strncpy((char *)ctl->info->id.name, (char *)eid[n].name,
                 SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
         ctl->info->id.name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN - 1] = 0;
     }
 
-    grp->data = data;
-    grp->ops = ops;
-    *ctl_grp = grp;
-    *num_ctls_in_grp = grp->count;
-
     free(eid);
-    return 0;
-
-err_ctl_alloc:
-
-    if (eid)
-        free(eid);
-
-    if (grp->elem_info)
-        free(grp->elem_info);
-
-    if (grp->ctl)
-        free(grp->ctl);
-
-err_get_elem_list:
-
-    free(grp);
-    return ret;
-
-}
-
-static int mixer_do_hw_open(struct mixer *mixer, unsigned int card)
-{
-    struct mixer_ops *ops;
-    void *data;
-    int fd, ret, num_grp_ctls = 0;
-
-    mixer->fd = -1;
-    fd = mixer_hw_open(card, &data, &ops);
-    if (fd < 0)
-        return fd;
-
-    ret = ops->ioctl(data, SNDRV_CTL_IOCTL_CARD_INFO, &mixer->card_info);
-    if (ret < 0)
-        goto err_card_info;
-
-    ret = mixer_grp_open(mixer, &mixer->hw_grp, ops, data, &num_grp_ctls);
-    if (ret < 0)
-        goto err_card_info;
-
-    mixer->total_ctl_count += num_grp_ctls;
-
-    mixer->fd = fd;
-    return 0;
-
-err_card_info:
-    ops->close(data);
-    return ret;
-
-}
-
-static int mixer_do_plugin_open(struct mixer *mixer, unsigned int card,
-                int is_hw_open_failed)
-{
-    struct mixer_ops *ops;
-    void *data;
-    int ret, num_grp_ctls = 0;
-
-    ret = mixer_plugin_open(card, &data, &ops);
-    if (ret < 0)
-        return ret;
-
-    /* Get card_info if hw_open failed */
-    if (is_hw_open_failed) {
-        ret = ops->ioctl(data, SNDRV_CTL_IOCTL_CARD_INFO, &mixer->card_info);
-        if (ret < 0)
-            goto err_card_info;
-    }
-
-    ret = mixer_grp_open(mixer, &mixer->virt_grp, ops, data, &num_grp_ctls);
-    if (ret < 0)
-        goto err_card_info;
-
-    mixer->total_ctl_count += num_grp_ctls;
-    return 0;
-
-err_card_info:
-    ops->close(data);
-    return ret;
-
-}
-
-struct mixer *mixer_open(unsigned int card)
-{
-    struct mixer *mixer = NULL;
-    int h_status, v_status;
-
-    mixer = calloc(1, sizeof(*mixer));
-    if (!mixer)
-        goto fail;
-
-    /* open hardware node first */
-    h_status = mixer_do_hw_open(mixer, card);
-
-    /*
-     * open the virtual node even if hw_open fails
-     * since hw_open is expected to fail for virtual cards
-     * for which kernel does not register mixer node
-     */
-    //TODO: open virtual node only if mixer is defined under snd-card-def
-    v_status = mixer_do_plugin_open(mixer, card, h_status);
-
-    /* Fail mixer_open if both hw and plugin nodes cannot be opened */
-    if (h_status < 0 && v_status < 0)
-        goto fail;
-
     return mixer;
 
 fail:
+    /* TODO: verify frees in failure case */
+    if (eid)
+        free(eid);
     if (mixer)
         mixer_close(mixer);
-
+    else if (fd >= 0)
+        close(fd);
     return 0;
 }
 
 static bool mixer_ctl_get_elem_info(struct mixer_ctl* ctl)
 {
-    struct mixer_ctl_group *grp = ctl->grp;
-    unsigned int i;
-
     if (!ctl->info_retrieved) {
-        if (grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_ELEM_INFO,
-                                                  ctl->info) < 0)
+        if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, ctl->info) < 0)
             return false;
         ctl->info_retrieved = true;
     }
@@ -323,11 +178,11 @@
     if (!enames)
         return false;
 
-    for (i = 0; i < ctl->info->value.enumerated.items; i++) {
+    for (unsigned int i = 0; i < ctl->info->value.enumerated.items; i++) {
         memset(&tmp, 0, sizeof(tmp));
         tmp.id.numid = ctl->info->id.numid;
         tmp.value.enumerated.item = i;
-        if (grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)
+        if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)
             goto fail;
         enames[i] = strdup(tmp.value.enumerated.name);
         if (!enames[i])
@@ -351,35 +206,17 @@
     if (!mixer)
         return 0;
 
-    return mixer->total_ctl_count;
-}
-
-static int mixer_grp_get_count(struct mixer_ctl_group *grp)
-{
-    if (!grp)
-        return 0;
-
-    return grp->count;
+    return mixer->count;
 }
 
 struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id)
 {
     struct mixer_ctl *ctl;
-    unsigned int hw_ctl_count, virt_ctl_count;
 
-    if (!mixer || (id >= mixer->total_ctl_count))
+    if (!mixer || (id >= mixer->count))
         return NULL;
 
-    hw_ctl_count = mixer_grp_get_count(mixer->hw_grp);
-    virt_ctl_count = mixer_grp_get_count(mixer->virt_grp);
-
-    if (id < hw_ctl_count)
-        ctl = mixer->hw_grp->ctl + id;
-    else if ((id - hw_ctl_count) < virt_ctl_count)
-        ctl = mixer->virt_grp->ctl + (id - hw_ctl_count);
-    else
-        return NULL;
-
+    ctl = mixer->ctl + id;
     if (!mixer_ctl_get_elem_info(ctl))
         return NULL;
 
@@ -388,37 +225,21 @@
 
 struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name)
 {
-    struct mixer_ctl_group *grp;
     unsigned int n;
-    int hw_ctl_count = mixer_grp_get_count(mixer->hw_grp);
 
     if (!mixer)
         return NULL;
 
-    if (mixer->hw_grp) {
-        grp = mixer->hw_grp;
-
-        for (n = 0; n < grp->count; n++)
-        if (!strcmp(name, (char*) grp->elem_info[n].id.name))
+    for (n = 0; n < mixer->count; n++)
+        if (!strcmp(name, (char*) mixer->elem_info[n].id.name))
             return mixer_get_ctl(mixer, n);
-    }
-
-    if (mixer->virt_grp) {
-        grp = mixer->virt_grp;
-
-        for (n = 0; n < grp->count; n++)
-        if (!strcmp(name, (char*) grp->elem_info[n].id.name))
-            return mixer_get_ctl(mixer, n + hw_ctl_count);
-    }
 
     return NULL;
 }
 
 void mixer_ctl_update(struct mixer_ctl *ctl)
 {
-    struct mixer_ctl_group *grp = ctl->grp;
-
-    grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_ELEM_INFO, ctl->info);
+    ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, ctl->info);
 }
 
 const char *mixer_ctl_get_name(struct mixer_ctl *ctl)
@@ -511,7 +332,6 @@
 
 int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id)
 {
-    struct mixer_ctl_group *grp = ctl->grp;
     struct snd_ctl_elem_value ev;
     int ret;
 
@@ -520,7 +340,7 @@
 
     memset(&ev, 0, sizeof(ev));
     ev.id.numid = ctl->info->id.numid;
-    ret = grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
+    ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
     if (ret < 0)
         return ret;
 
@@ -551,7 +371,6 @@
 
 int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count)
 {
-    struct mixer_ctl_group *grp = ctl->grp;
     struct snd_ctl_elem_value ev;
     int ret = 0;
     size_t size;
@@ -578,7 +397,7 @@
     switch (ctl->info->type) {
     case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
     case SNDRV_CTL_ELEM_TYPE_INTEGER:
-        ret = grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
+        ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
         if (ret < 0)
             return ret;
         size = sizeof(ev.value.integer.value[0]);
@@ -598,7 +417,7 @@
                 return -ENOMEM;
             tlv->numid = ctl->info->id.numid;
             tlv->length = count;
-            ret = grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_TLV_READ, tlv);
+            ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_TLV_READ, tlv);
 
             source = tlv->tlv;
             memcpy(array, source, count);
@@ -607,7 +426,7 @@
 
             return ret;
         } else {
-            ret = grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
+            ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
             if (ret < 0)
                 return ret;
             size = sizeof(ev.value.bytes.data[0]);
@@ -631,8 +450,6 @@
 
 int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value)
 {
-    struct mixer_ctl_group *grp = ctl->grp;
-
     struct snd_ctl_elem_value ev;
     int ret;
 
@@ -641,7 +458,7 @@
 
     memset(&ev, 0, sizeof(ev));
     ev.id.numid = ctl->info->id.numid;
-    ret = grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
+    ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
     if (ret < 0)
         return ret;
 
@@ -666,12 +483,11 @@
         return -EINVAL;
     }
 
-    return grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
+    return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
 }
 
 int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count)
 {
-    struct mixer_ctl_group *grp = ctl->grp;
     struct snd_ctl_elem_value ev;
     size_t size;
     void *dest;
@@ -715,7 +531,7 @@
             tlv->length = count;
             memcpy(tlv->tlv, array, count);
 
-            ret = grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_TLV_WRITE, tlv);
+            ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_TLV_WRITE, tlv);
             free(tlv);
 
             return ret;
@@ -736,7 +552,7 @@
 
     memcpy(dest, array, size * count);
 
-    return grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
+    return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
 }
 
 int mixer_ctl_get_range_min(struct mixer_ctl *ctl)
@@ -775,7 +591,6 @@
 
 int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string)
 {
-    struct mixer_ctl_group *grp = ctl->grp;
     unsigned int i, num_enums;
     struct snd_ctl_elem_value ev;
     int ret;
@@ -789,7 +604,7 @@
             memset(&ev, 0, sizeof(ev));
             ev.value.enumerated.item[0] = i;
             ev.id.numid = ctl->info->id.numid;
-            ret = grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
+            ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
             if (ret < 0)
                 return ret;
             return 0;
@@ -808,26 +623,8 @@
  */
 int mixer_subscribe_events(struct mixer *mixer, int subscribe)
 {
-    struct mixer_ctl_group *grp;
-
-    if (mixer->hw_grp) {
-        grp = mixer->hw_grp;
-        if (!subscribe)
-            grp->event_cnt = 0;
-
-    if (grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS,
-                                                    &subscribe) < 0)
-            return -1;
-    }
-
-    if (mixer->virt_grp) {
-        grp = mixer->virt_grp;
-        if (!subscribe)
-            grp->event_cnt = 0;
-
-        if (grp->ops->ioctl(grp->data, SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS,
-                                                        &subscribe) < 0)
-            return -1;
+    if (ioctl(mixer->fd, SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS, &subscribe) < 0) {
+        return -1;
     }
     return 0;
 }
@@ -842,59 +639,22 @@
  */
 int mixer_wait_event(struct mixer *mixer, int timeout)
 {
-    struct pollfd *pfd;
-    struct mixer_ctl_group *grp;
-    int count = 0, num_fds = 0, i;
+    struct pollfd pfd;
 
-    if (mixer->fd >= 0)
-        num_fds++;
-
-    if (mixer->virt_grp)
-        num_fds++;
-
-    pfd = (struct pollfd *)calloc(sizeof(struct pollfd), num_fds);
-    if (!pfd)
-        return -ENOMEM;
-
-    /* TODO wait events for virt fd */
-    if (mixer->fd >= 0) {
-        pfd[count].fd = mixer->fd;
-        pfd[count].events = POLLIN | POLLOUT | POLLERR | POLLNVAL;
-        count++;
-    }
-
-    if (mixer->virt_grp) {
-        grp = mixer->virt_grp;
-        if (!grp->ops->get_poll_fd(grp->data, pfd, count)) {
-            pfd[count].events = POLLIN | POLLERR | POLLNVAL;
-            count++;
-        }
-    }
-
-    if (!count)
-        return 0;
+    pfd.fd = mixer->fd;
+    pfd.events = POLLIN | POLLOUT | POLLERR | POLLNVAL;
 
     for (;;) {
         int err;
-        err = poll(pfd, count, timeout);
+        err = poll(&pfd, 1, timeout);
         if (err < 0)
             return -errno;
         if (!err)
             return 0;
-        for (i = 0; i < count; i++) {
-            if (pfd[i].revents & (POLLERR | POLLNVAL))
-                return -EIO;
-            if (pfd[i].revents & (POLLIN | POLLOUT)) {
-                if ((i == 0) && mixer->fd >= 0) {
-                    grp = mixer->hw_grp;
-                    grp->event_cnt++;
-                } else {
-                    grp = mixer->virt_grp;
-                    grp->event_cnt++;
-                }
-                return 1;
-            }
-        }
+        if (pfd.revents & (POLLERR | POLLNVAL))
+            return -EIO;
+        if (pfd.revents & (POLLIN | POLLOUT))
+            return 1;
     }
 }
 
@@ -908,69 +668,13 @@
  * @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;
-    struct mixer_ctl_group *grp;
-    ssize_t count = 0;
-
+    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.
-    if (mixer->hw_grp) {
-        grp = mixer->hw_grp;
-        if (grp->event_cnt) {
-            grp->event_cnt--;
-            count = grp->ops->read_event(grp->data, &ev, sizeof(ev));
-            return (count >= 0) ? 0 : -errno;
-        }
-    }
-
-    if (mixer->virt_grp) {
-        grp = mixer->virt_grp;
-        if (grp->event_cnt) {
-            grp->event_cnt--;
-            count += grp->ops->read_event(grp->data, &ev, sizeof(ev));
-            return (count >= 0) ? 0 : -errno;
-        }
-    }
-    return (count >= 0) ? 0 : -errno;
-}
-
-/** Read a mixer event.
- * If mixer_subscribe_events has been called,
- * mixer_wait_event will identify when a control value has changed.
- * This function will read and clear a single event from the mixer
- * so that further events can be alerted.
- *
- * @param mixer A mixer handle.
- * @param ev snd_ctl_event pointer where event needs to be read
- * @returns 0 on success.  -errno on failure.
- * @ingroup libtinyalsa-mixer
- */
-int mixer_read_event(struct mixer *mixer, struct snd_ctl_event *ev)
-{
-    struct mixer_ctl_group *grp;
-    ssize_t count = 0;
-
-    if (mixer->hw_grp) {
-        grp = mixer->hw_grp;
-        if (grp->event_cnt) {
-            grp->event_cnt--;
-            count = grp->ops->read_event(grp->data, ev, sizeof(*ev));
-            return (count >= 0) ? 0 : -errno;
-        }
-    }
-
-    if (mixer->virt_grp) {
-        grp = mixer->virt_grp;
-        if (grp->event_cnt) {
-            grp->event_cnt--;
-            count = grp->ops->read_event(grp->data, ev, sizeof(*ev));
-            return (count >= 0) ? 0 : -errno;
-        }
-    }
     return (count >= 0) ? 0 : -errno;
 }
diff --git a/mixer_hw.c b/mixer_hw.c
deleted file mode 100644
index a051d3a..0000000
--- a/mixer_hw.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/* mixer_hw.c
-**
-** Copyright (c) 2019, The Linux Foundation. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-**   * Redistributions of source code must retain the above copyright
-**     notice, this list of conditions and the following disclaimer.
-**   * Redistributions in binary form must reproduce the above
-**     copyright notice, this list of conditions and the following
-**     disclaimer in the documentation and/or other materials provided
-**     with the distribution.
-**   * Neither the name of The Linux Foundation nor the names of its
-**     contributors may be used to endorse or promote products derived
-**     from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-** ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <ctype.h>
-#include <poll.h>
-
-#include <sys/ioctl.h>
-
-#include <linux/ioctl.h>
-#include <sound/asound.h>
-
-#include "mixer_io.h"
-
-struct mixer_hw_data {
-    unsigned int card;
-    int fd;
-};
-
-static void mixer_hw_close(void *data)
-{
-    struct mixer_hw_data *hw_data = data;
-
-    if (!hw_data)
-        return;
-
-    if (hw_data->fd >= 0)
-        close(hw_data->fd);
-
-    hw_data->fd = -1;
-    free(hw_data);
-    hw_data = NULL;
-}
-
-static int mixer_hw_ioctl(void *data, unsigned int cmd, ...)
-{
-    struct mixer_hw_data *hw_data = data;
-    va_list ap;
-    void *arg;
-
-    va_start(ap, cmd);
-    arg = va_arg(ap, void *);
-    va_end(ap);
-
-    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 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,
-                  struct mixer_ops **ops)
-{
-    struct mixer_hw_data *hw_data;
-    int fd;
-    char fn[256];
-
-    snprintf(fn, sizeof(fn), "/dev/snd/controlC%u", card);
-    fd = open(fn, O_RDWR);
-    if (fd < 0)
-        return fd;
-
-    hw_data = calloc(1, sizeof(*hw_data));
-    if (!hw_data)
-        return -1;
-
-    hw_data->card = card;
-    hw_data->fd = fd;
-    *data = hw_data;
-    *ops = &mixer_hw_ops;
-
-    return fd;
-}
diff --git a/mixer_io.h b/mixer_io.h
deleted file mode 100644
index 77daae0..0000000
--- a/mixer_io.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* mixer_io.h
-**
-** Copyright (c) 2019, The Linux Foundation. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-**   * Redistributions of source code must retain the above copyright
-**     notice, this list of conditions and the following disclaimer.
-**   * Redistributions in binary form must reproduce the above
-**     copyright notice, this list of conditions and the following
-**     disclaimer in the documentation and/or other materials provided
-**     with the distribution.
-**   * Neither the name of The Linux Foundation nor the names of its
-**     contributors may be used to endorse or promote products derived
-**     from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-** ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**/
-
-#ifndef __MIXER_H__
-#define __MIXER_H__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sound/asound.h>
-
-struct mixer_ops;
-
-int mixer_hw_open(unsigned int card, void **data,
-                  struct mixer_ops **ops);
-int mixer_plugin_open(unsigned int card, void **data,
-                      struct mixer_ops **ops);
-
-struct mixer_ops {
-    void (*close) (void *data);
-    int (*get_poll_fd) (void *data, struct pollfd *pfd, int count);
-    ssize_t (*read_event) (void *data, struct snd_ctl_event *ev, size_t size);
-    int (*ioctl) (void *data, unsigned int cmd, ...);
-};
-
-#endif /* end of __MIXER_H__ */
diff --git a/mixer_plugin.c b/mixer_plugin.c
deleted file mode 100644
index b3f1ccf..0000000
--- a/mixer_plugin.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/* mixer_plugin.c
-**
-** Copyright (c) 2019, The Linux Foundation. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-**   * Redistributions of source code must retain the above copyright
-**     notice, this list of conditions and the following disclaimer.
-**   * Redistributions in binary form must reproduce the above
-**     copyright notice, this list of conditions and the following
-**     disclaimer in the documentation and/or other materials provided
-**     with the distribution.
-**   * Neither the name of The Linux Foundation nor the names of its
-**     contributors may be used to endorse or promote products derived
-**     from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-** ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <ctype.h>
-#include <poll.h>
-#include <dlfcn.h>
-#include <string.h>
-#include <sys/eventfd.h>
-#include <sys/ioctl.h>
-
-#include <linux/ioctl.h>
-#include <sound/asound.h>
-
-#include <tinyalsa/mixer_plugin.h>
-#include "snd_utils.h"
-
-#include "mixer_io.h"
-
-struct mixer_plug_data {
-    int card;
-    void *mixer_node;
-
-    struct mixer_plugin *plugin;
-    void *dl_hdl;
-    MIXER_PLUGIN_OPEN_FN_PTR();
-};
-
-static int mixer_plug_get_elem_id(struct mixer_plug_data *plug_data,
-                struct snd_ctl_elem_id *id, unsigned int offset)
-{
-    struct mixer_plugin *plugin = plug_data->plugin;
-    struct snd_control *ctl;
-
-    if (offset >= plugin->num_controls) {
-        printf("%s: invalid offset %u\n", __func__, offset);
-        return -EINVAL;
-    }
-
-    ctl = plugin->controls + offset;
-    id->numid = offset;
-    id->iface = ctl->iface;
-
-    strncpy((char *)id->name, (char *)ctl->name,
-            sizeof(id->name));
-
-    return 0;
-}
-
-static int mixer_plug_info_enum(struct snd_control *ctl,
-                struct snd_ctl_elem_info *einfo)
-{
-    struct snd_value_enum *val = ctl->value;
-
-    einfo->count = 1;
-    einfo->value.enumerated.items = val->items;
-
-    if (einfo->value.enumerated.item > val->items)
-        return -EINVAL;
-
-    strncpy(einfo->value.enumerated.name,
-            val->texts[einfo->value.enumerated.item],
-            sizeof(einfo->value.enumerated.name));
-
-    return 0;
-}
-
-static int mixer_plug_info_bytes(struct snd_control *ctl,
-                struct snd_ctl_elem_info *einfo)
-{
-    struct snd_value_bytes *val;
-    struct snd_value_tlv_bytes *val_tlv;
-
-    if (ctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
-        val_tlv = ctl->value;
-        einfo->count = val_tlv->size;
-    } else {
-        val = ctl->value;
-        einfo->count = val->size;
-    }
-
-    return 0;
-}
-
-static int mixer_plug_info_integer(struct snd_control *ctl,
-                struct snd_ctl_elem_info *einfo)
-{
-    struct snd_value_int *val = ctl->value;
-
-    einfo->count = val->count;
-    einfo->value.integer.min = val->min;
-    einfo->value.integer.max = val->max;
-    einfo->value.integer.step = val->step;
-
-    return 0;
-}
-
-void mixer_plug_notifier_cb(struct mixer_plugin *plugin)
-{
-    eventfd_write(plugin->eventfd, 1);
-    plugin->event_cnt++;
-}
-
-/* In consume_event/read, do not call eventfd_read until all events are read from list.
-   This will make poll getting unblocked until all events are read */
-static ssize_t mixer_plug_read_event(void *data, struct snd_ctl_event *ev, size_t size)
-{
-    struct mixer_plug_data *plug_data = data;
-    struct mixer_plugin *plugin = plug_data->plugin;
-    eventfd_t evfd;
-    ssize_t result = 0;
-
-    result = plugin->ops->read_event(plugin, ev, size);
-
-    if (result > 0) {
-        plugin->event_cnt -=  result / sizeof(struct snd_ctl_event);
-        if (plugin->event_cnt == 0)
-            eventfd_read(plugin->eventfd, &evfd);
-    }
-
-    return result;
-}
-
-static int mixer_plug_subscribe_events(struct mixer_plug_data *plug_data,
-                int *subscribe)
-{
-    struct mixer_plugin *plugin = plug_data->plugin;
-    eventfd_t evfd;
-
-    if (*subscribe < 0 || *subscribe > 1) {
-        *subscribe = plugin->subscribed;
-        return -EINVAL;
-    }
-
-    if (*subscribe && !plugin->subscribed) {
-        plugin->ops->subscribe_events(plugin, &mixer_plug_notifier_cb);
-    } else if (plugin->subscribed && !*subscribe) {
-        plugin->ops->subscribe_events(plugin, NULL);
-
-        if (plugin->event_cnt)
-            eventfd_read(plugin->eventfd, &evfd);
-
-        plugin->event_cnt = 0;
-    }
-
-    plugin->subscribed = *subscribe;
-    return 0;
-}
-
-static int mixer_plug_get_poll_fd(void *data, struct pollfd *pfd, int count)
-{
-    struct mixer_plug_data *plug_data = data;
-    struct mixer_plugin *plugin = plug_data->plugin;
-
-    if (plugin->eventfd != -1) {
-        pfd[count].fd = plugin->eventfd;
-        return 0;
-    }
-    return -ENODEV;
-}
-
-static int mixer_plug_tlv_write(struct mixer_plug_data *plug_data,
-                struct snd_ctl_tlv *tlv)
-{
-    struct mixer_plugin *plugin = plug_data->plugin;
-    struct snd_control *ctl;
-    struct snd_value_tlv_bytes *val_tlv;
-
-    ctl = plugin->controls + tlv->numid;
-    val_tlv = ctl->value;
-
-    return val_tlv->put(plugin, ctl, tlv);
-}
-
-static int mixer_plug_tlv_read(struct mixer_plug_data *plug_data,
-                struct snd_ctl_tlv *tlv)
-{
-    struct mixer_plugin *plugin = plug_data->plugin;
-    struct snd_control *ctl;
-    struct snd_value_tlv_bytes *val_tlv;
-
-    ctl = plugin->controls + tlv->numid;
-    val_tlv = ctl->value;
-
-    return val_tlv->get(plugin, ctl, tlv);
-}
-
-static int mixer_plug_elem_write(struct mixer_plug_data *plug_data,
-                struct snd_ctl_elem_value *ev)
-{
-    struct mixer_plugin *plugin = plug_data->plugin;
-    struct snd_control *ctl;
-    int ret;
-
-    ret = mixer_plug_get_elem_id(plug_data, &ev->id, ev->id.numid);
-    if (ret < 0)
-        return ret;
-
-    ctl = plugin->controls + ev->id.numid;
-
-    return ctl->put(plugin, ctl, ev);
-}
-
-static int mixer_plug_elem_read(struct mixer_plug_data *plug_data,
-                struct snd_ctl_elem_value *ev)
-{
-    struct mixer_plugin *plugin = plug_data->plugin;
-    struct snd_control *ctl;
-    int ret;
-
-    ret = mixer_plug_get_elem_id(plug_data, &ev->id, ev->id.numid);
-    if (ret < 0)
-        return ret;
-
-    ctl = plugin->controls + ev->id.numid;
-
-    return ctl->get(plugin, ctl, ev);
-
-}
-
-static int mixer_plug_get_elem_info(struct mixer_plug_data *plug_data,
-                struct snd_ctl_elem_info *einfo)
-{
-    struct mixer_plugin *plugin = plug_data->plugin;
-    struct snd_control *ctl;
-    int ret;
-
-    ret = mixer_plug_get_elem_id(plug_data, &einfo->id,
-                    einfo->id.numid);
-    if (ret < 0)
-        return ret;
-
-    ctl = plugin->controls + einfo->id.numid;
-    einfo->type = ctl->type;
-    einfo->access = ctl->access;
-
-    switch (einfo->type) {
-    case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
-        ret = mixer_plug_info_enum(ctl, einfo);
-        if (ret < 0)
-            return ret;
-        break;
-    case SNDRV_CTL_ELEM_TYPE_BYTES:
-        ret = mixer_plug_info_bytes(ctl, einfo);
-        if (ret < 0)
-            return ret;
-        break;
-    case SNDRV_CTL_ELEM_TYPE_INTEGER:
-        ret = mixer_plug_info_integer(ctl, einfo);
-        if (ret < 0)
-            return ret;
-        break;
-    default:
-        printf("%s: unknown type %d\n", __func__, einfo->type);
-        return -EINVAL;
-    }
-
-    return 0;
-}
-
-static int mixer_plug_get_elem_list(struct mixer_plug_data *plug_data,
-                struct snd_ctl_elem_list *elist)
-{
-    struct mixer_plugin *plugin = plug_data->plugin;
-    unsigned int avail;
-    struct snd_ctl_elem_id *id;
-    int ret;
-
-    elist->count = plugin->num_controls;
-    elist->used = 0;
-    avail = elist->space;
-
-    while (avail > 0) {
-        id = elist->pids + elist->used;
-        ret = mixer_plug_get_elem_id(plug_data, id, elist->used);
-        if (ret < 0)
-            return ret;
-
-        avail--;
-        elist->used++;
-    }
-
-    return 0;
-}
-
-static int mixer_plug_get_card_info(struct mixer_plug_data *plug_data,
-                struct snd_ctl_card_info *card_info)
-{
-    /*TODO: Fill card_info here from snd-card-def */
-    memset(card_info, 0, sizeof(*card_info));
-    card_info->card = plug_data->card;
-    memcpy(card_info->id, "card_id", sizeof(card_info->id));
-    memcpy(card_info->driver, "mymixer-so-name", sizeof(card_info->driver));
-    memcpy(card_info->name, "card-name", sizeof(card_info->name));
-    memcpy(card_info->longname, "card-name", sizeof(card_info->longname));
-    memcpy(card_info->mixername, "mixer-name", sizeof(card_info->mixername));
-
-    printf("%s: card = %d\n", __func__, plug_data->card);
-
-    return 0;
-}
-
-static void mixer_plug_close(void *data)
-{
-    struct mixer_plug_data *plug_data = data;
-    struct mixer_plugin *plugin = plug_data->plugin;
-    eventfd_t evfd;
-
-    if (plugin->event_cnt)
-        eventfd_read(plugin->eventfd, &evfd);
-
-    plugin->ops->close(&plugin);
-    dlclose(plug_data->dl_hdl);
-    snd_utils_put_dev_node(plug_data->mixer_node);
-    free(plug_data);
-    plug_data = NULL;
-}
-
-static int mixer_plug_ioctl(void *data, unsigned int cmd, ...)
-{
-    struct mixer_plug_data *plug_data = data;
-    int ret;
-    va_list ap;
-    void *arg;
-
-    va_start(ap, cmd);
-    arg = va_arg(ap, void *);
-    va_end(ap);
-
-    switch (cmd) {
-    case SNDRV_CTL_IOCTL_CARD_INFO:
-        ret = mixer_plug_get_card_info(plug_data, arg);
-        break;
-    case SNDRV_CTL_IOCTL_ELEM_LIST:
-        ret = mixer_plug_get_elem_list(plug_data, arg);
-        break;
-    case SNDRV_CTL_IOCTL_ELEM_INFO:
-        ret = mixer_plug_get_elem_info(plug_data, arg);
-        break;
-    case SNDRV_CTL_IOCTL_ELEM_READ:
-        ret = mixer_plug_elem_read(plug_data, arg);
-        break;
-    case SNDRV_CTL_IOCTL_ELEM_WRITE:
-        ret = mixer_plug_elem_write(plug_data, arg);
-        break;
-    case SNDRV_CTL_IOCTL_TLV_READ:
-        ret = mixer_plug_tlv_read(plug_data, arg);
-        break;
-    case SNDRV_CTL_IOCTL_TLV_WRITE:
-        ret = mixer_plug_tlv_write(plug_data, arg);
-        break;
-    case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
-        ret = mixer_plug_subscribe_events(plug_data, arg);
-        break;
-    default:
-        /* TODO: plugin should support ioctl */
-        ret = -EFAULT;
-        break;
-    }
-
-    return ret;
-}
-
-static struct mixer_ops mixer_plug_ops = {
-    .close = mixer_plug_close,
-    .read_event = mixer_plug_read_event,
-    .get_poll_fd = mixer_plug_get_poll_fd,
-    .ioctl = mixer_plug_ioctl,
-};
-
-int mixer_plugin_open(unsigned int card, void **data,
-                      struct mixer_ops **ops)
-{
-    struct mixer_plug_data *plug_data;
-    struct mixer_plugin *plugin = NULL;
-    const char *err = NULL;
-    void *dl_hdl;
-    char *name, *so_name;
-    char *open_fn_name, token[80];
-    int ret;
-
-    plug_data = calloc(1, sizeof(*plug_data));
-    if (!plug_data)
-        return -ENOMEM;
-
-    /* mixer id is fixed to 1 in snd-card-def xml */
-    plug_data->mixer_node = snd_utils_get_dev_node(card, 1, NODE_MIXER);
-    if (!plug_data->mixer_node) {
-        /* Do not print error here.
-         * It is valid for card to not have virtual mixer node
-         */
-        goto err_get_mixer_node;
-    }
-
-    ret = snd_utils_get_str(plug_data->mixer_node, "so-name",
-                               &so_name);
-    if(ret) {
-        fprintf(stderr, "%s: mixer so-name not found for card %u\n",
-                __func__, card);
-        goto err_get_mixer_node;
-
-    }
-
-    dl_hdl = dlopen(so_name, RTLD_NOW);
-    if (!dl_hdl) {
-        fprintf(stderr, "%s: unable to open %s\n",
-                __func__, so_name);
-        goto err_get_mixer_node;
-    }
-
-    sscanf(so_name, "lib%s", token);
-    name = strtok(token, ".");
-
-    open_fn_name = calloc(1, strlen(name) + strlen("_open") + 1);
-    if (!open_fn_name) {
-        ret = -ENOMEM;
-        goto err_get_mixer_node;
-    }
-
-    strncpy(open_fn_name, name, strlen(name) + 1);
-    strcat(open_fn_name, "_open");
-
-    printf("%s - %s\n", __func__, open_fn_name);
-
-    dlerror();
-    plug_data->mixer_plugin_open_fn = dlsym(dl_hdl, open_fn_name);
-    if (err) {
-        fprintf(stderr, "%s: dlsym open fn failed: %s\n",
-                __func__, err);
-        goto err_get_name;
-    }
-    ret = plug_data->mixer_plugin_open_fn(&plugin, card);
-    if (ret) {
-        fprintf(stderr, "%s: failed to open plugin, err: %d\n",
-                __func__, ret);
-        goto err_get_name;
-    }
-
-    plug_data->plugin = plugin;
-    plug_data->card = card;
-    plug_data->dl_hdl = dl_hdl;
-    plugin->eventfd = eventfd(0, 0);
-
-    *data = plug_data;
-    *ops = &mixer_plug_ops;
-
-    printf("%s: card = %d\n", __func__, plug_data->card);
-
-    return 0;
-
-err_get_name:
-    snd_utils_put_dev_node(plug_data->mixer_node);
-    dlclose(dl_hdl);
-
-err_get_mixer_node:
-
-    free(plug_data);
-    return -1;
-}
diff --git a/pcm.c b/pcm.c
index f64eb40..4ae321b 100644
--- a/pcm.c
+++ b/pcm.c
@@ -47,13 +47,6 @@
 #include <sound/asound.h>
 
 #include <tinyalsa/asoundlib.h>
-#include "pcm_io.h"
-#include "snd_utils.h"
-
-enum {
-    PCM_NODE_TYPE_HW = 0,
-    PCM_NODE_TYPE_PLUGIN,
-};
 
 #define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL
 
@@ -130,9 +123,6 @@
 #endif
 };
 
-extern struct pcm_ops hw_ops;
-extern struct pcm_ops plug_ops;
-
 /* refer to SNDRV_PCM_SUBFORMAT_##index in sound/asound.h. */
 static const char * const subformat_lookup[] = {
         "STD",
@@ -267,10 +257,6 @@
     unsigned int noirq_frames_per_msec;
     int wait_for_avail_min;
     unsigned int subdevice;
-
-    struct pcm_ops *ops;
-    void *data;
-    void *snd_node;
 };
 
 unsigned int pcm_get_buffer_size(struct pcm *pcm)
@@ -350,8 +336,7 @@
 static int pcm_sync_ptr(struct pcm *pcm, int flags) {
     if (pcm->sync_ptr) {
         pcm->sync_ptr->flags = flags;
-        if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_SYNC_PTR,
-                            pcm->sync_ptr) < 0)
+        if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SYNC_PTR, pcm->sync_ptr) < 0)
             return -1;
     }
     return 0;
@@ -547,12 +532,12 @@
             int prepare_error = pcm_prepare(pcm);
             if (prepare_error)
                 return prepare_error;
-            if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))
+            if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))
                 return oops(pcm, errno, "cannot write initial data");
             pcm->running = 1;
             return 0;
         }
-        if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) {
+        if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) {
             pcm->prepared = 0;
             pcm->running = 0;
             if (errno == EPIPE) {
@@ -588,7 +573,7 @@
                 return -errno;
             }
         }
-        if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {
+        if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {
             pcm->prepared = 0;
             pcm->running = 0;
             if (errno == EPIPE) {
@@ -610,22 +595,15 @@
                                   unsigned int flags)
 {
     struct snd_pcm_hw_params *params;
-    enum snd_node_type pcm_type;
-    struct pcm_ops *ops;
-    void *snd_node, *data;
+    char fn[256];
     int fd;
 
-    snd_node = snd_utils_get_dev_node(card, device, NODE_PCM);
-    pcm_type = snd_utils_get_node_type(snd_node);
-    if (pcm_type == SND_NODE_TYPE_PLUGIN)
-        ops = &plug_ops;
-    else
-        ops = &hw_ops;
+    snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
+             flags & PCM_IN ? 'c' : 'p');
 
-    fd = ops->open(card, device, flags, &data, snd_node);
+    fd = open(fn, O_RDWR);
     if (fd < 0) {
-        fprintf(stderr, "cannot open device %u for card %u\n",
-                device, card);
+        fprintf(stderr, "cannot open device '%s'\n", fn);
         goto err_open;
     }
 
@@ -634,22 +612,20 @@
         goto err_calloc;
 
     param_init(params);
-    if (ops->ioctl(data, SNDRV_PCM_IOCTL_HW_REFINE, params)) {
+    if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, params)) {
         fprintf(stderr, "SNDRV_PCM_IOCTL_HW_REFINE error (%d)\n", errno);
         goto err_hw_refine;
     }
 
-    snd_utils_put_dev_node(snd_node);
-    ops->close(data);
+    close(fd);
 
     return (struct pcm_params *)params;
 
 err_hw_refine:
     free(params);
 err_calloc:
-    ops->close(data);
+    close(fd);
 err_open:
-    snd_utils_put_dev_node(snd_node);
     return NULL;
 }
 
@@ -886,9 +862,8 @@
         munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size));
     }
 
-    pcm->ops->close(pcm->data);
-    snd_utils_put_dev_node(pcm->snd_node);
-
+    if (pcm->fd >= 0)
+        close(pcm->fd);
     pcm->prepared = 0;
     pcm->running = 0;
     pcm->buffer_size = 0;
@@ -904,7 +879,8 @@
     struct snd_pcm_info info;
     struct snd_pcm_hw_params params;
     struct snd_pcm_sw_params sparams;
-    int rc, pcm_type;
+    char fn[256];
+    int rc;
 
     if (!config) {
         return &bad_pcm; /* TODO: could support default config here */
@@ -914,23 +890,24 @@
         return &bad_pcm; /* TODO: could support default config here */
 
     pcm->config = *config;
+
+    snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
+             flags & PCM_IN ? 'c' : 'p');
+
     pcm->flags = flags;
-
-    pcm->snd_node = snd_utils_get_dev_node(card, device, NODE_PCM);
-    pcm_type = snd_utils_get_node_type(pcm->snd_node);
-    if (pcm_type == SND_NODE_TYPE_PLUGIN)
-        pcm->ops = &plug_ops;
-    else
-        pcm->ops = &hw_ops;
-
-    pcm->fd = pcm->ops->open(card, device, flags, &pcm->data, pcm->snd_node);
+    pcm->fd = open(fn, O_RDWR|O_NONBLOCK);
     if (pcm->fd < 0) {
-        oops(pcm, errno, "cannot open device %u for card %u",
-             device, card);
-        goto fail_open;
+        oops(pcm, errno, "cannot open device '%s'", fn);
+        return pcm;
     }
 
-    if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_INFO, &info)) {
+    if (fcntl(pcm->fd, F_SETFL, fcntl(pcm->fd, F_GETFL) &
+              ~O_NONBLOCK) < 0) {
+        oops(pcm, errno, "failed to reset blocking mode '%s'", fn);
+        goto fail_close;
+    }
+
+    if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) {
         oops(pcm, errno, "cannot get info");
         goto fail_close;
     }
@@ -968,7 +945,7 @@
         param_set_mask(&params, SNDRV_PCM_HW_PARAM_ACCESS,
                        SNDRV_PCM_ACCESS_RW_INTERLEAVED);
 
-    if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_HW_PARAMS, &params)) {
+    if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, &params)) {
         oops(pcm, errno, "cannot set hw params");
         goto fail_close;
     }
@@ -1029,7 +1006,7 @@
     while (pcm->boundary * 2 <= INT_MAX - pcm->buffer_size)
         pcm->boundary *= 2;
 
-    if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) {
+    if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) {
         oops(pcm, errno, "cannot set sw params");
         goto fail;
     }
@@ -1043,7 +1020,7 @@
 #ifdef SNDRV_PCM_IOCTL_TTSTAMP
     if (pcm->flags & PCM_MONOTONIC) {
         int arg = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
-        rc = pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_TTSTAMP, &arg);
+        rc = ioctl(pcm->fd, SNDRV_PCM_IOCTL_TTSTAMP, &arg);
         if (rc < 0) {
             oops(pcm, errno, "cannot set timestamp type");
             goto fail;
@@ -1058,11 +1035,8 @@
     if (flags & PCM_MMAP)
         munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size));
 fail_close:
-    pcm->ops->close(pcm->data);
+    close(pcm->fd);
     pcm->fd = -1;
-
-fail_open:
-    snd_utils_put_dev_node(pcm->snd_node);
     return pcm;
 }
 
@@ -1076,7 +1050,7 @@
     if (pcm->prepared)
         return 0;
 
-    if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_PREPARE) < 0)
+    if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE) < 0)
         return oops(pcm, errno, "cannot prepare channel");
 
     pcm->prepared = 1;
@@ -1090,9 +1064,9 @@
         return prepare_error;
 
     if (pcm->flags & PCM_MMAP)
-        pcm_sync_ptr(pcm, 0);
+	    pcm_sync_ptr(pcm, 0);
 
-    if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_START) < 0)
+    if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START) < 0)
         return oops(pcm, errno, "cannot start channel");
 
     pcm->running = 1;
@@ -1101,7 +1075,7 @@
 
 int pcm_stop(struct pcm *pcm)
 {
-    if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_DROP) < 0)
+    if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_DROP) < 0)
         return oops(pcm, errno, "cannot stop channel");
 
     pcm->prepared = 0;
@@ -1277,7 +1251,7 @@
         }
 
         /* start the audio if we reach the threshold */
-        if (!pcm->running &&
+	    if (!pcm->running &&
             (pcm->buffer_size - avail) >= pcm->config.start_threshold) {
             if (pcm_start(pcm) < 0) {
                fprintf(stderr, "start error: hw 0x%x app 0x%x avail 0x%x\n",
@@ -1373,5 +1347,5 @@
     arg = va_arg(ap, void *);
     va_end(ap);
 
-    return pcm->ops->ioctl(pcm->data, request, arg);
+    return ioctl(pcm->fd, request, arg);
 }
diff --git a/pcm_hw.c b/pcm_hw.c
deleted file mode 100644
index bcd076f..0000000
--- a/pcm_hw.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/* pcm_hw.c
-**
-** Copyright (c) 2019, The Linux Foundation. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-**   * Redistributions of source code must retain the above copyright
-**     notice, this list of conditions and the following disclaimer.
-**   * Redistributions in binary form must reproduce the above
-**     copyright notice, this list of conditions and the following
-**     disclaimer in the documentation and/or other materials provided
-**     with the distribution.
-**   * Neither the name of The Linux Foundation nor the names of its
-**     contributors may be used to endorse or promote products derived
-**     from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-** ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <poll.h>
-
-#include <sys/ioctl.h>
-#include <linux/ioctl.h>
-#include <sound/asound.h>
-#include <tinyalsa/asoundlib.h>
-
-#include "pcm_io.h"
-
-struct pcm_hw_data {
-    unsigned int card;
-    unsigned int device;
-    unsigned int fd;
-    void *snd_node;
-};
-
-static void pcm_hw_close(void *data)
-{
-    struct pcm_hw_data *hw_data = data;
-
-    if (hw_data->fd > 0)
-        close(hw_data->fd);
-
-    free(hw_data);
-}
-
-static int pcm_hw_ioctl(void *data, unsigned int cmd, ...)
-{
-    struct pcm_hw_data *hw_data = data;
-    va_list ap;
-    void *arg;
-
-    va_start(ap, cmd);
-    arg = va_arg(ap, void *);
-    va_end(ap);
-
-    return ioctl(hw_data->fd, cmd, arg);
-}
-
-static int pcm_hw_open(unsigned int card, unsigned int device,
-                unsigned int flags, void **data,
-                __attribute__((unused)) void *node)
-{
-    struct pcm_hw_data *hw_data;
-    char fn[256];
-    int fd;
-
-    hw_data = calloc(1, sizeof(*hw_data));
-    if (!hw_data) {
-        return -ENOMEM;
-    }
-
-    snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
-             flags & PCM_IN ? 'c' : 'p');
-    fd = open(fn, O_RDWR|O_NONBLOCK);
-    if (fd < 0) {
-        printf("%s: cannot open device '%s'", __func__, fn);
-        return fd;
-    }
-
-    if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK) < 0) {
-        printf("%s: failed to reset blocking mode '%s'",
-                __func__, fn);
-        goto err_close;
-    }
-
-    hw_data->snd_node = node;
-    hw_data->card = card;
-    hw_data->device = device;
-    hw_data->fd = fd;
-
-    *data = hw_data;
-
-    return fd;
-
-err_close:
-    close(fd);
-    free(hw_data);
-    return -ENODEV;
-}
-
-struct pcm_ops hw_ops = {
-    .open = pcm_hw_open,
-    .close = pcm_hw_close,
-    .ioctl = pcm_hw_ioctl,
-};
-
diff --git a/pcm_io.h b/pcm_io.h
deleted file mode 100644
index c4e1315..0000000
--- a/pcm_io.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* pcm.h
-**
-** Copyright (c) 2019, The Linux Foundation. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-**   * Redistributions of source code must retain the above copyright
-**     notice, this list of conditions and the following disclaimer.
-**   * Redistributions in binary form must reproduce the above
-**     copyright notice, this list of conditions and the following
-**     disclaimer in the documentation and/or other materials provided
-**     with the distribution.
-**   * Neither the name of The Linux Foundation nor the names of its
-**     contributors may be used to endorse or promote products derived
-**     from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-** ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**/
-
-#ifndef __PCM_H__
-#define __PCM_H__
-
-#include <sound/asound.h>
-
-struct pcm_ops {
-    int (*open) (unsigned int card, unsigned int device,
-                 unsigned int flags, void **data, void *node);
-    void (*close) (void *data);
-    int (*ioctl) (void *data, unsigned int cmd, ...);
-};
-
-#endif /* end of __PCM_H__ */
diff --git a/pcm_plugin.c b/pcm_plugin.c
deleted file mode 100644
index 8ffe6ae..0000000
--- a/pcm_plugin.c
+++ /dev/null
@@ -1,740 +0,0 @@
-/* pcm_plugin.c
-**
-** Copyright (c) 2019, The Linux Foundation. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-**   * Redistributions of source code must retain the above copyright
-**     notice, this list of conditions and the following disclaimer.
-**   * Redistributions in binary form must reproduce the above
-**     copyright notice, this list of conditions and the following
-**     disclaimer in the documentation and/or other materials provided
-**     with the distribution.
-**   * Neither the name of The Linux Foundation nor the names of its
-**     contributors may be used to endorse or promote products derived
-**     from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-** ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <poll.h>
-#include <dlfcn.h>
-
-#include <sys/ioctl.h>
-#include <linux/ioctl.h>
-#include <sound/asound.h>
-#include <tinyalsa/asoundlib.h>
-#include <tinyalsa/pcm_plugin.h>
-
-#include "pcm_io.h"
-#include "snd_utils.h"
-
-/* 2 words of uint32_t = 64 bits of mask */
-#define PCM_MASK_SIZE (2)
-#define ARRAY_SIZE(a)         \
-    (sizeof(a) / sizeof(a[0]))
-
-#define PCM_PARAM_GET_MASK(p, n)    \
-    &p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK];
-
-enum {
-    PCM_PLUG_HW_PARAM_SELECT_MIN,
-    PCM_PLUG_HW_PARAM_SELECT_MAX,
-    PCM_PLUG_HW_PARAM_SELECT_VAL,
-};
-
-enum {
-    PCM_PLUG_STATE_OPEN,
-    PCM_PLUG_STATE_SETUP,
-    PCM_PLUG_STATE_PREPARED,
-    PCM_PLUG_STATE_RUNNING,
-};
-
-struct pcm_plug_data {
-    unsigned int card;
-    unsigned int device;
-    unsigned int fd;
-    unsigned int flags;
-
-    void *dl_hdl;
-    PCM_PLUGIN_OPEN_FN_PTR();
-
-    struct pcm_plugin *plugin;
-    void *dev_node;
-};
-
-static unsigned int my_params[] = {
-    SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
-    SNDRV_PCM_HW_PARAM_CHANNELS,
-    SNDRV_PCM_HW_PARAM_RATE,
-    SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
-    SNDRV_PCM_HW_PARAM_PERIODS,
-};
-
-static void pcm_plug_close(void *data)
-{
-    struct pcm_plug_data *plug_data = data;
-    struct pcm_plugin *plugin = plug_data->plugin;
-
-    plugin->ops->close(plugin);
-    dlclose(plug_data->dl_hdl);
-
-    free(plug_data);
-}
-
-static int pcm_plug_info(struct pcm_plug_data *plug_data,
-                struct snd_pcm_info *info)
-{
-    int stream = SNDRV_PCM_STREAM_PLAYBACK;
-    int ret = 0, val = -1;
-    char *name;
-
-    memset(info, 0, sizeof(*info));
-
-    if (plug_data->flags & PCM_IN) {
-        stream = SNDRV_PCM_STREAM_CAPTURE;
-        ret = snd_utils_get_int(plug_data->dev_node, "capture", &val);
-        if (ret || !val) {
-            fprintf(stderr, "%s: not a capture device\n", __func__);
-            return -EINVAL;
-        }
-    } else {
-        stream = SNDRV_PCM_STREAM_PLAYBACK;
-        ret = snd_utils_get_int(plug_data->dev_node, "playback", &val);
-        if (ret || !val) {
-            fprintf(stderr, "%s: not a playback device\n", __func__);
-            return -EINVAL;
-        }
-    }
-
-    info->stream = stream;
-    info->card = plug_data->card;
-    info->device = plug_data->device;
-
-    ret = snd_utils_get_str(plug_data->dev_node, "name", &name);
-    if (ret) {
-        fprintf(stderr, "%s: failed to get pcm device name\n", __func__);
-        return ret;
-    }
-
-    strncpy((char *)info->id, name, sizeof(info->id));
-    strncpy((char *)info->name, name, sizeof(info->name));
-    strncpy((char *)info->subname, name, sizeof(info->subname));
-
-    info->subdevices_count = 1;
-
-    return ret;
-}
-
-static void pcm_plug_set_mask(struct snd_pcm_hw_params *p, int n, uint64_t v)
-{
-    struct snd_mask *mask;
-
-    mask = PCM_PARAM_GET_MASK(p, n);
-
-    mask->bits[0] |= (v & 0xFFFFFFFF);
-    mask->bits[1] |= ((v >> 32) & 0xFFFFFFFF);
-    /*
-     * currently only supporting 64 bits, may need to update to support
-     * more than 64 bits
-     */
-}
-
-static void pcm_plug_set_interval(struct snd_pcm_hw_params *params,
-                    int p, struct pcm_plugin_min_max *v, int is_integer)
-{
-    struct snd_interval *i;
-
-    i = &params->intervals[p - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
-
-    i->min = v->min;
-    i->max = v->max;
-
-    if (is_integer)
-        i->integer = 1;
-}
-
-static int pcm_plug_frames_to_bytes(unsigned int frames,
-                                    unsigned int frame_bits)
-{
-    return (frames * (frame_bits / 8));
-}
-
-static int pcm_plug_bytes_to_frames(unsigned int size,
-                                    unsigned int frame_bits)
-{
-    return (size * 8)  / frame_bits;
-}
-
-static int pcm_plug_get_params(struct pcm_plugin *plugin,
-                struct snd_pcm_hw_params *params)
-{
-    struct pcm_plugin_min_max bw, ch, pb, periods;
-    struct pcm_plugin_min_max val;
-    struct pcm_plugin_min_max frame_bits, buffer_bytes;
-
-    /*
-     * populate the struct snd_pcm_hw_params structure
-     * using the hw_param constraints provided by plugin
-     * via the plugin->constraints
-     */
-
-    /* Set the mask params */
-    pcm_plug_set_mask(params, SNDRV_PCM_HW_PARAM_ACCESS,
-                      plugin->constraints->access);
-    pcm_plug_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
-                      plugin->constraints->format);
-    pcm_plug_set_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
-                      SNDRV_PCM_SUBFORMAT_STD);
-
-    /* Set the standard interval params */
-    pcm_plug_set_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
-                          &plugin->constraints->bit_width, 1);
-    pcm_plug_set_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS,
-                          &plugin->constraints->channels, 1);
-    pcm_plug_set_interval(params, SNDRV_PCM_HW_PARAM_RATE,
-                          &plugin->constraints->rate, 1);
-    pcm_plug_set_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
-                          &plugin->constraints->period_bytes, 0);
-    pcm_plug_set_interval(params, SNDRV_PCM_HW_PARAM_PERIODS,
-                          &plugin->constraints->periods, 1);
-
-    /* set the calculated interval params */
-
-    bw.min = plugin->constraints->bit_width.min;
-    bw.max = plugin->constraints->bit_width.max;
-
-    ch.min = plugin->constraints->channels.min;
-    ch.max = plugin->constraints->channels.max;
-
-    pb.min = plugin->constraints->period_bytes.min;
-    pb.max = plugin->constraints->period_bytes.max;
-
-    periods.min = plugin->constraints->periods.min;
-    periods.max = plugin->constraints->periods.max;
-
-    /* Calculate and set frame bits */
-    frame_bits.min = bw.min * ch.min;
-    frame_bits.max = bw.max * ch.max;
-    pcm_plug_set_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
-                          &frame_bits, 1);
-
-
-    /* Calculate and set period_size in frames */
-    val.min = pcm_plug_bytes_to_frames(pb.min, frame_bits.min);
-    val.max = pcm_plug_bytes_to_frames(pb.max, frame_bits.min);
-    pcm_plug_set_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
-                          &val, 1);
-
-    /* Calculate and set buffer_bytes */
-    buffer_bytes.min = pb.min * periods.min;
-    buffer_bytes.max = pb.max * periods.max;
-    pcm_plug_set_interval(params, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-                          &buffer_bytes, 1);
-
-    /* Calculate and set buffer_size in frames */
-    val.min = pcm_plug_bytes_to_frames(buffer_bytes.min, frame_bits.min);
-    val.max = pcm_plug_bytes_to_frames(buffer_bytes.max, frame_bits.min);
-    pcm_plug_set_interval(params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
-                          &val, 1);
-    return 0;
-}
-
-static int pcm_plug_masks_refine(struct snd_pcm_hw_params *p,
-                struct snd_pcm_hw_params *c)
-{
-    struct snd_mask *req_mask;
-    struct snd_mask *con_mask;
-    unsigned int idx, i, masks;
-
-    masks = SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK;
-
-    for (idx = 0; idx <= masks; idx++) {
-
-        if (!(p->rmask & (1 << (idx + SNDRV_PCM_HW_PARAM_FIRST_MASK))))
-            continue;
-
-        req_mask = PCM_PARAM_GET_MASK(p, idx);
-        con_mask = PCM_PARAM_GET_MASK(c, idx);
-
-        /*
-         * set the changed mask if requested mask value is not the same as
-         * constrained mask value
-         */
-        if (memcmp(req_mask, con_mask, PCM_MASK_SIZE * sizeof(uint32_t)))
-            p->cmask |= 1 << (idx + SNDRV_PCM_HW_PARAM_FIRST_MASK);
-
-        /* Actually change the requested mask to constrained mask */
-        for (i = 0; i < PCM_MASK_SIZE; i++)
-            req_mask->bits[i] &= con_mask->bits[i];
-    }
-
-    return 0;
-}
-
-static int pcm_plug_interval_refine(struct snd_pcm_hw_params *p,
-                struct snd_pcm_hw_params *c)
-{
-    struct snd_interval *ri;
-    struct snd_interval *ci;
-    unsigned int idx;
-    unsigned int intervals;
-    int changed = 0;
-
-    intervals = SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
-                SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
-
-    for (idx = 0; idx <= intervals; idx++) {
-        ri = &p->intervals[idx];
-        ci = &c->intervals[idx];
-
-        if (!(p->rmask & (1 << (idx + SNDRV_PCM_HW_PARAM_FIRST_INTERVAL)) ))
-            continue;
-
-        if (ri->min < ci->min) {
-            ri->min = ci->min;
-            ri->openmin = ci->openmin;
-            changed = 1;
-        } else if (ri->min == ci->min && !ri->openmin && ci->openmin) {
-            ri->openmin = 1;
-            changed = 1;
-        }
-
-        if (ri->max > ci->max) {
-            ri->max = ci->max;
-            ri->openmax = ci->openmax;
-            changed = 1;
-        } else if (ri->max == ci->max && !ri->openmax && ci->openmax) {
-            ri->openmax = 1;
-            changed = 1;
-        };
-
-        if (!ri->integer && ci->integer) {
-            ri->integer = 1;
-            changed = 1;
-        }
-
-        if (ri->integer) {
-            if (ri->openmin) {
-                ri->min++;
-                ri->openmin = 0;
-            }
-            if (ri->openmax) {
-                ri->max--;
-                ri->openmax = 0;
-            }
-        } else if (!ri->openmin && !ri->openmax && ri->min == ri->max) {
-            ri->integer = 1;
-        }
-
-        /* Set the changed mask */
-        if (changed)
-            p->cmask |= (1 << (idx + SNDRV_PCM_HW_PARAM_FIRST_INTERVAL));
-    }
-
-    return 0;
-}
-
-
-static int pcm_plug_hw_params_refine(struct snd_pcm_hw_params *p,
-                struct snd_pcm_hw_params *c)
-{
-    int rc;
-
-    rc = pcm_plug_masks_refine(p, c);
-    if (rc) {
-        fprintf(stderr, "%s: masks refine failed %d\n", __func__, rc);
-        return rc;
-    }
-
-    rc = pcm_plug_interval_refine(p, c);
-    if (rc) {
-        fprintf(stderr, "%s: interval refine failed %d\n", __func__, rc);
-        return rc;
-    }
-
-    /* clear the requested params */
-    p->rmask = 0;
-
-    return rc;
-}
-
-static int __pcm_plug_hrefine(struct pcm_plug_data *plug_data,
-                struct snd_pcm_hw_params *params)
-{
-    struct pcm_plugin *plugin = plug_data->plugin;
-    struct snd_pcm_hw_params plug_params;
-    int rc;
-
-    memset(&plug_params, 0, sizeof(plug_params));
-    rc = pcm_plug_get_params(plugin, &plug_params);
-    if (rc) {
-        fprintf(stderr, "%s: pcm_plug_get_params failed %d\n",
-               __func__, rc);
-        return -EINVAL;
-    }
-
-    return pcm_plug_hw_params_refine(params, &plug_params);
-
-}
-
-static int pcm_plug_hrefine(struct pcm_plug_data *plug_data,
-                struct snd_pcm_hw_params *params)
-{
-    return __pcm_plug_hrefine(plug_data, params);
-}
-
-static int pcm_plug_interval_select(struct snd_pcm_hw_params *p,
-        unsigned int param, unsigned int select, unsigned int val)
-{
-    struct snd_interval *i;
-
-    if (param < SNDRV_PCM_HW_PARAM_FIRST_INTERVAL ||
-        param > SNDRV_PCM_HW_PARAM_LAST_INTERVAL)
-        return -EINVAL;
-
-    i = &p->intervals[param - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
-
-    if (!i->min)
-        return -EINVAL;
-
-    switch (select) {
-
-    case PCM_PLUG_HW_PARAM_SELECT_MIN:
-        i->max = i->min;
-        break;
-
-    case PCM_PLUG_HW_PARAM_SELECT_MAX:
-        i->min = i->max;
-        break;
-
-    case PCM_PLUG_HW_PARAM_SELECT_VAL:
-        i->min = i->max = val;
-        break;
-
-    default:
-        return -EINVAL;
-    }
-
-    return 0;
-}
-
-static void pcm_plug_hw_params_set(struct snd_pcm_hw_params *p)
-{
-    unsigned int i, select;
-    unsigned int bw, ch, period_sz, periods;
-    unsigned int val1, val2, offset;
-
-    offset = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
-
-    /* Select the min values first */
-    select = PCM_PLUG_HW_PARAM_SELECT_MIN;
-    for (i = 0; i < ARRAY_SIZE(my_params); i++)
-        pcm_plug_interval_select(p, my_params[i], select, 0);
-
-    /* Select calculated values */
-    select = PCM_PLUG_HW_PARAM_SELECT_VAL;
-    bw = (p->intervals[SNDRV_PCM_HW_PARAM_SAMPLE_BITS - offset]).min;
-    ch = (p->intervals[SNDRV_PCM_HW_PARAM_CHANNELS - offset]).min;
-    period_sz = (p->intervals[SNDRV_PCM_HW_PARAM_PERIOD_SIZE - offset]).min;
-    periods = (p->intervals[SNDRV_PCM_HW_PARAM_PERIODS - offset]).min;
-
-    val1 = bw * ch;        // frame_bits;
-    pcm_plug_interval_select(p, SNDRV_PCM_HW_PARAM_FRAME_BITS, select, val1);
-
-    val2 = pcm_plug_frames_to_bytes(period_sz, val1); // period_bytes;
-    pcm_plug_interval_select(p, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, select,
-                             val2);
-
-    val2 = period_sz * periods; //buffer_size;
-    pcm_plug_interval_select(p, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, select, val2);
-
-    val2 = pcm_plug_frames_to_bytes(period_sz * periods, val1); //buffer_bytes;
-    pcm_plug_interval_select(p, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, select, val2);
-}
-
-static int pcm_plug_hparams(struct pcm_plug_data *plug_data,
-                struct snd_pcm_hw_params *params)
-{
-    struct pcm_plugin *plugin = plug_data->plugin;
-    int rc;
-
-    if (plugin->state != PCM_PLUG_STATE_OPEN)
-            return -EBADFD;
-
-    params->rmask = ~0U;
-
-    rc = __pcm_plug_hrefine(plug_data, params);
-    if (rc) {
-        fprintf(stderr, "%s: __pcm_plug_hrefine failed %d\n",
-               __func__, rc);
-        return rc;
-    }
-
-    pcm_plug_hw_params_set(params);
-
-    rc = plugin->ops->hw_params(plugin, params);
-    if (!rc)
-        plugin->state = PCM_PLUG_STATE_SETUP;
-
-    return rc;
-}
-
-static int pcm_plug_sparams(struct pcm_plug_data *plug_data,
-                struct snd_pcm_sw_params *params)
-{
-    struct pcm_plugin *plugin = plug_data->plugin;
-
-    if (plugin->state != PCM_PLUG_STATE_SETUP)
-        return -EBADFD;
-
-    return plugin->ops->sw_params(plugin, params);
-}
-
-static int pcm_plug_sync_ptr(struct pcm_plug_data *plug_data,
-                struct snd_pcm_sync_ptr *sync_ptr)
-{
-    struct pcm_plugin *plugin = plug_data->plugin;
-
-    return plugin->ops->sync_ptr(plugin, sync_ptr);
-}
-
-static int pcm_plug_writei_frames(struct pcm_plug_data *plug_data,
-                struct snd_xferi *x)
-{
-    struct pcm_plugin *plugin = plug_data->plugin;
-
-    if (plugin->state != PCM_PLUG_STATE_PREPARED &&
-        plugin->state != PCM_PLUG_STATE_RUNNING)
-        return -EBADFD;
-
-    return plugin->ops->writei_frames(plugin, x);
-}
-
-static int pcm_plug_readi_frames(struct pcm_plug_data *plug_data,
-                struct snd_xferi *x)
-{
-    struct pcm_plugin *plugin = plug_data->plugin;
-
-    if (plugin->state != PCM_PLUG_STATE_RUNNING)
-        return -EBADFD;
-
-    return plugin->ops->readi_frames(plugin, x);
-}
-
-static int pcm_plug_ttstamp(struct pcm_plug_data *plug_data,
-                int *tstamp)
-{
-    struct pcm_plugin *plugin = plug_data->plugin;
-
-    if (plugin->state != PCM_PLUG_STATE_RUNNING)
-        return -EBADFD;
-
-    return plugin->ops->ttstamp(plugin, tstamp);
-}
-
-static int pcm_plug_prepare(struct pcm_plug_data *plug_data)
-{
-    struct pcm_plugin *plugin = plug_data->plugin;
-    int rc;
-
-    if (plugin->state != PCM_PLUG_STATE_SETUP)
-        return -EBADFD;
-
-    rc = plugin->ops->prepare(plugin);
-    if (!rc)
-        plugin->state = PCM_PLUG_STATE_PREPARED;
-
-    return rc;
-}
-
-static int pcm_plug_start(struct pcm_plug_data *plug_data)
-{
-    struct pcm_plugin *plugin = plug_data->plugin;
-    int rc;
-
-    if (plugin->state != PCM_PLUG_STATE_PREPARED)
-        return -EBADFD;
-
-    rc = plugin->ops->start(plugin);
-    if (!rc)
-        plugin->state = PCM_PLUG_STATE_RUNNING;
-
-    return rc;
-}
-
-static int pcm_plug_drop(struct pcm_plug_data *plug_data)
-{
-    struct pcm_plugin *plugin = plug_data->plugin;
-    int rc = 0;
-
-    rc = plugin->ops->drop(plugin);
-    if (!rc)
-        plugin->state = PCM_PLUG_STATE_SETUP;
-
-    return rc;
-}
-
-static int pcm_plug_ioctl(void *data, unsigned int cmd, ...)
-{
-    struct pcm_plug_data *plug_data = data;
-    struct pcm_plugin *plugin = plug_data->plugin;
-    int ret;
-    va_list ap;
-    void *arg;
-
-    va_start(ap, cmd);
-    arg = va_arg(ap, void *);
-    va_end(ap);
-
-    switch (cmd) {
-    case SNDRV_PCM_IOCTL_INFO:
-        ret = pcm_plug_info(plug_data, arg); 
-        break;
-    case SNDRV_PCM_IOCTL_TTSTAMP:
-        ret = pcm_plug_ttstamp(plug_data, arg);
-        break;
-    case SNDRV_PCM_IOCTL_HW_REFINE:
-        ret = pcm_plug_hrefine(plug_data, arg);
-        break;
-    case SNDRV_PCM_IOCTL_HW_PARAMS:
-        ret = pcm_plug_hparams(plug_data, arg);
-        break;
-    case SNDRV_PCM_IOCTL_SW_PARAMS:
-        ret = pcm_plug_sparams(plug_data, arg);
-        break;
-    case SNDRV_PCM_IOCTL_SYNC_PTR:
-        ret = pcm_plug_sync_ptr(plug_data, arg);
-        break;
-    case SNDRV_PCM_IOCTL_PREPARE:
-        ret = pcm_plug_prepare(plug_data);
-        break;
-    case SNDRV_PCM_IOCTL_START:
-        ret = pcm_plug_start(plug_data);
-        break;
-    case SNDRV_PCM_IOCTL_DROP:
-        ret = pcm_plug_drop(plug_data);
-        break;
-    case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
-        ret = pcm_plug_writei_frames(plug_data, arg);
-        break;
-    case SNDRV_PCM_IOCTL_READI_FRAMES:
-        ret = pcm_plug_readi_frames(plug_data, arg);
-        break;
-    default:
-        ret = plugin->ops->ioctl(plugin, cmd, arg);
-        break;
-    }
-
-    return ret;
-}
-
-static int pcm_plug_open(unsigned int card, unsigned int device,
-                  unsigned int flags, void **data, void *pcm_node)
-{
-    struct pcm_plug_data *plug_data;
-    const char *err = NULL;
-    void *dl_hdl;
-    int rc = 0;
-    char *so_name, token[80], *name, *open_fn;
-
-    plug_data = calloc(1, sizeof(*plug_data));
-    if (!plug_data) {
-        return -ENOMEM;
-    }
-
-    rc = snd_utils_get_str(pcm_node, "so-name", &so_name);
-    if (rc) {
-        fprintf(stderr, "%s: failed to get plugin lib name\n", __func__);
-        goto err_get_lib;
-    }
-
-    dl_hdl = dlopen(so_name, RTLD_NOW);
-    if (!dl_hdl) {
-        fprintf(stderr, "%s: unable to open %s\n", __func__, so_name);
-        goto err_dl_open;
-    } else {
-        fprintf(stderr, "%s: dlopen successful for %s\n", __func__, so_name);
-    }
-
-    dlerror();
-
-    sscanf(so_name, "lib%s", token);
-    name = strtok(token, ".");
-
-    open_fn = calloc(1, strlen(name) + strlen("_open") + 1);
-    if (!open_fn) {
-        rc = -ENOMEM;
-        goto err_open_fn;
-    }
-
-    strncpy(open_fn, name, strlen(name) + 1);
-    strcat(open_fn, "_open");
-
-    printf("%s - %s\n", __func__, open_fn);
-    plug_data->plugin_open_fn = dlsym(dl_hdl, open_fn);
-    err = dlerror();
-
-    if (err) {
-        fprintf(stderr, "%s: dlsym to open fn failed, err = '%s'\n",
-                __func__, err);
-        goto err_dlsym;
-    }
-
-    rc = plug_data->plugin_open_fn(&plug_data->plugin,
-                    card, device, flags);
-    if (rc) {
-        fprintf(stderr, "%s: failed to open plugin\n", __func__);
-        goto err_dlsym;
-    }
-
-    /* Call snd-card-def to get card and pcm nodes */
-    /* Check how to manage fd for plugin */
-
-    plug_data->dl_hdl = dl_hdl;
-    plug_data->card = card;
-    plug_data->device = device;
-    plug_data->dev_node = pcm_node;
-    plug_data->flags = flags;
-
-    *data = plug_data;
-
-    plug_data->plugin->state = PCM_PLUG_STATE_OPEN;
-
-    return 0;
-
-err_dlsym:
-    free(open_fn);
-err_open_fn:
-    dlclose(dl_hdl);
-err_get_lib:
-err_dl_open:
-    free(plug_data);
-
-    return rc;
-}
-
-struct pcm_ops plug_ops = {
-    .open = pcm_plug_open,
-    .close = pcm_plug_close,
-    .ioctl = pcm_plug_ioctl,
-};
diff --git a/snd_utils.c b/snd_utils.c
deleted file mode 100644
index ac3ddf9..0000000
--- a/snd_utils.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/* snd_utils.c
-**
-** Copyright (c) 2019, The Linux Foundation. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-**   * Redistributions of source code must retain the above copyright
-**     notice, this list of conditions and the following disclaimer.
-**   * Redistributions in binary form must reproduce the above
-**     copyright notice, this list of conditions and the following
-**     disclaimer in the documentation and/or other materials provided
-**     with the distribution.
-**   * Neither the name of The Linux Foundation nor the names of its
-**     contributors may be used to endorse or promote products derived
-**     from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-** ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include "snd_utils.h"
-
-#define SND_DLSYM(h, p, s, err) \
-do {                            \
-    err = 0;                    \
-    p = dlsym(h, s);            \
-    if (!p)                        \
-        err = -ENODEV;            \
-} while(0)
-
-int snd_utils_get_int(struct snd_node *node, const char *prop, int *val)
-{
-    if (!node || !node->card_node || !node->dev_node)
-        return SND_NODE_TYPE_HW;
-
-    return node->get_int(node->dev_node, prop, val);
-}
-
-int snd_utils_get_str(struct snd_node *node, const char *prop, char **val)
-{
-    if (!node || !node->card_node || !node->dev_node)
-        return SND_NODE_TYPE_HW;
-
-    return node->get_str(node->dev_node, prop, val);
-}
-
-void snd_utils_put_dev_node(struct snd_node *node)
-{
-    if (!node)
-        return;
-
-    if (node->card_node)
-        node->put_card(node->card_node);
-
-    if (node->dl_hdl)
-        dlclose(node->dl_hdl);
-
-    free(node);
-}
-
-enum snd_node_type snd_utils_get_node_type(struct snd_node *node)
-{
-    int val = SND_NODE_TYPE_HW;
-
-    if (!node || !node->card_node || !node->dev_node)
-        return SND_NODE_TYPE_HW;
-
-    node->get_int(node->dev_node, "type", &val);
-
-    return val;
-};
-
-
-static int snd_utils_resolve_symbols(struct snd_node *node)
-{
-    void *dl = node->dl_hdl;
-    int err;
-
-    SND_DLSYM(dl, node->get_card, "snd_card_def_get_card", err);
-    if (err)
-        goto done;
-    SND_DLSYM(dl, node->put_card, "snd_card_def_put_card", err);
-    if (err)
-        goto done;
-    SND_DLSYM(dl, node->get_node, "snd_card_def_get_node", err);
-    if (err)
-        goto done;
-    SND_DLSYM(dl, node->get_int, "snd_card_def_get_int", err);
-    if (err)
-        goto done;
-    SND_DLSYM(dl, node->get_str, "snd_card_def_get_str", err);
-
-done:
-    return err;
-}
-
-struct snd_node *snd_utils_get_dev_node(unsigned int card,
-        unsigned int device, int dev_type)
-{
-    struct snd_node *node;
-    int rc = 0;
-
-    node = calloc(1, sizeof(*node));
-    if (!node)
-        return NULL;
-
-    node->dl_hdl = dlopen("libsndcardparser.so", RTLD_NOW);
-    if (!node->dl_hdl) {
-        goto err_dl_open;
-    }
-
-    rc = snd_utils_resolve_symbols(node);
-    if (rc < 0)
-        goto err_resolve_symbols;
-
-    node->card_node = node->get_card(card);
-    if (!node->card_node)
-        goto err_resolve_symbols;
-
-    node->dev_node = node->get_node(node->card_node,
-                                    device, dev_type);
-    if (!node->dev_node)
-        goto err_get_node;
-
-    return node;
-
-err_get_node:
-    node->put_card(node->card_node);
-
-err_resolve_symbols:
-    dlclose(node->dl_hdl);
-
-err_dl_open:
-    free(node);
-    return NULL;
-}
diff --git a/snd_utils.h b/snd_utils.h
deleted file mode 100644
index 64bfeb8..0000000
--- a/snd_utils.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* snd_utils.h
-**
-** Copyright (c) 2019, The Linux Foundation. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-**   * Redistributions of source code must retain the above copyright
-**     notice, this list of conditions and the following disclaimer.
-**   * Redistributions in binary form must reproduce the above
-**     copyright notice, this list of conditions and the following
-**     disclaimer in the documentation and/or other materials provided
-**     with the distribution.
-**   * Neither the name of The Linux Foundation nor the names of its
-**     contributors may be used to endorse or promote products derived
-**     from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-** ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**/
-
-#ifndef __SND_CARD_UTILS_H__
-#define __SND_CARD_UTILS_H__
-
-#include <dlfcn.h>
-
-struct snd_node {
-    void *card_node;
-    void *dev_node;
-    void *dl_hdl;
-
-    void* (*get_card) (unsigned int card);
-    void (*put_card) (void *card);
-    void* (*get_node) (void *card, unsigned int id,
-                      int type);
-    int (*get_int) (void *node, const char *prop, int *val);
-    int (*get_str) (void *node, const char *prop, char **val);
-};
-
-enum {
-    NODE_PCM,
-    NODE_MIXER,
-};
-
-enum snd_node_type {
-    SND_NODE_TYPE_HW = 0,
-    SND_NODE_TYPE_PLUGIN,
-    SND_NODE_TYPE_INVALID,
-};
-
-struct snd_node *snd_utils_get_dev_node(unsigned int card,
-        unsigned int device, int dev_type);
-
-void snd_utils_put_dev_node(struct snd_node *node);
-
-enum snd_node_type snd_utils_get_node_type(struct snd_node *node);
-
-int snd_utils_get_int(struct snd_node *node, const char *prop, int *val);
-
-int snd_utils_get_str(struct snd_node *node, const char *prop, char **val);
-
-#endif /* end of __SND_CARD_UTILS_H__ */