Fix the byte control set/get method
am: b4e8d0d03f

Change-Id: I8a395e83ecfddb030feb3ef1bbe6b77b14361f36
diff --git a/include/tinyalsa/asoundlib.h b/include/tinyalsa/asoundlib.h
index f021682..08ace7a 100644
--- a/include/tinyalsa/asoundlib.h
+++ b/include/tinyalsa/asoundlib.h
@@ -68,6 +68,9 @@
 #define	PCM_STATE_SUSPENDED	7
 #define	PCM_STATE_DISCONNECTED	8
 
+/* TLV header size*/
+#define TLV_HEADER_SIZE (2 * sizeof(unsigned int))
+
 /* Bit formats */
 enum pcm_format {
     PCM_FORMAT_INVALID = -1,
diff --git a/mixer.c b/mixer.c
index c4e6765..3792159 100644
--- a/mixer.c
+++ b/mixer.c
@@ -338,8 +338,20 @@
     int ret = 0;
     size_t size;
     void *source;
+    size_t total_count;
 
-    if (!ctl || (count > ctl->info->count) || !count || !array)
+    if ((!ctl) || !count || !array)
+        return -EINVAL;
+
+    total_count = ctl->info->count;
+
+    if ((ctl->info->type == SNDRV_CTL_ELEM_TYPE_BYTES) &&
+        (ctl->info->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)) {
+            /* Additional two words is for the TLV header */
+            total_count += TLV_HEADER_SIZE;
+    }
+
+    if (count > total_count)
         return -EINVAL;
 
     memset(&ev, 0, sizeof(ev));
@@ -442,8 +454,20 @@
     struct snd_ctl_elem_value ev;
     size_t size;
     void *dest;
+    size_t total_count;
 
-    if (!ctl || (count > ctl->info->count) || !count || !array)
+    if ((!ctl) || !count || !array)
+        return -EINVAL;
+
+    total_count = ctl->info->count;
+
+    if ((ctl->info->type == SNDRV_CTL_ELEM_TYPE_BYTES) &&
+        (ctl->info->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)) {
+            /* Additional two words is for the TLV header */
+            total_count += TLV_HEADER_SIZE;
+    }
+
+    if (count > total_count)
         return -EINVAL;
 
     memset(&ev, 0, sizeof(ev));
diff --git a/tinymix.c b/tinymix.c
index a3c41a2..74ba28d 100644
--- a/tinymix.c
+++ b/tinymix.c
@@ -131,6 +131,7 @@
     int ret;
     char *buf = NULL;
     size_t len;
+    unsigned int tlv_header_size = 0;
 
     if (isdigit(control[0]))
         ctl = mixer_get_ctl(mixer, atoi(control));
@@ -146,15 +147,17 @@
     num_values = mixer_ctl_get_num_values(ctl);
 
     if (type == MIXER_CTL_TYPE_BYTE) {
-
-        buf = calloc(1, num_values);
+        if (ctl->info->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
+            tlv_header_size = TLV_HEADER_SIZE;
+        }
+        buf = calloc(1, num_values + tlv_header_size);
         if (buf == NULL) {
             fprintf(stderr, "Failed to alloc mem for bytes %d\n", num_values);
             return;
         }
 
         len = num_values;
-        ret = mixer_ctl_get_array(ctl, buf, len);
+        ret = mixer_ctl_get_array(ctl, buf, len + tlv_header_size);
         if (ret < 0) {
             fprintf(stderr, "Failed to mixer_ctl_get_array\n");
             free(buf);
@@ -178,7 +181,8 @@
             tinymix_print_enum(ctl, print_all);
             break;
         case MIXER_CTL_TYPE_BYTE:
-            printf("%02x", buf[i]);
+            /* skip printing TLV header if exists */
+            printf(" %02x", buf[i + tlv_header_size]);
             break;
         default:
             printf(" unknown");
@@ -207,13 +211,25 @@
     char *end;
     unsigned int i;
     long n;
+    unsigned int *tlv, tlv_size;
+    unsigned int tlv_header_size = 0;
 
-    buf = calloc(1, num_values);
+    if (ctl->info->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
+        tlv_header_size = TLV_HEADER_SIZE;
+    }
+
+    tlv_size = num_values + tlv_header_size;
+
+    buf = calloc(1, tlv_size);
     if (buf == NULL) {
         fprintf(stderr, "set_byte_ctl: Failed to alloc mem for bytes %d\n", num_values);
         exit(EXIT_FAILURE);
     }
 
+    tlv = (unsigned int *)buf;
+    tlv[0] = 0;
+    tlv[1] = num_values;
+
     for (i = 0; i < num_values; i++) {
         errno = 0;
         n = strtol(values[i], &end, 0);
@@ -231,10 +247,11 @@
                 values[i]);
             goto fail;
         }
-        buf[i] = n;
+        /* start filling after the TLV header */
+        buf[i + tlv_header_size] = n;
     }
 
-    ret = mixer_ctl_set_array(ctl, buf, num_values);
+    ret = mixer_ctl_set_array(ctl, buf, tlv_size);
     if (ret < 0) {
         fprintf(stderr, "Failed to set binary control\n");
         goto fail;