mixer: Add mixer_ctl_{set,get}_bytes()

For binary controls we don't want to go through
mixer_ctl_{set,get}_value() as that will trigger many calls to our
get()/put() callback in the kernel.  Set the entire payload at once
and trigger the get()/put() callback once.

Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
diff --git a/mixer.c b/mixer.c
index 58d4fb5..f52bca9 100644
--- a/mixer.c
+++ b/mixer.c
@@ -317,6 +317,27 @@
     return 0;
 }
 
+int mixer_ctl_get_bytes(struct mixer_ctl *ctl, void *data, size_t len)
+{
+    struct snd_ctl_elem_value ev;
+    int ret;
+
+    if (!ctl || (len > ctl->info->count) || !len || !data ||
+        (ctl->info->type != SNDRV_CTL_ELEM_TYPE_BYTES))
+        return -EINVAL;
+
+    memset(&ev, 0, sizeof(ev));
+    ev.id.numid = ctl->info->id.numid;
+
+    ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
+    if (ret < 0)
+        return ret;
+
+    memcpy(data, ev.value.bytes.data, len);
+
+    return 0;
+}
+
 int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value)
 {
     struct snd_ctl_elem_value ev;
@@ -351,6 +372,22 @@
     return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
 }
 
+int mixer_ctl_set_bytes(struct mixer_ctl *ctl, const void *data, size_t len)
+{
+    struct snd_ctl_elem_value ev;
+
+    if (!ctl || (len > ctl->info->count) || !len || !data ||
+        (ctl->info->type != SNDRV_CTL_ELEM_TYPE_BYTES))
+        return -EINVAL;
+
+    memset(&ev, 0, sizeof(ev));
+    ev.id.numid = ctl->info->id.numid;
+
+    memcpy(ev.value.bytes.data, data, len);
+
+    return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
+}
+
 int mixer_ctl_get_range_min(struct mixer_ctl *ctl)
 {
     if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))