OSDN Git Service

audio_route: Add support to set complete byte arrays
authorAndreas Schneider <asn@cryptomilk.org>
Wed, 8 Feb 2017 09:07:58 +0000 (10:07 +0100)
committerZhao Wei Liew <zhaoweiliew@lineageos.org>
Thu, 9 Feb 2017 13:52:38 +0000 (13:52 +0000)
This adds a new directive <param> and allows us to set several values in
a byte array.

    <param name="DSP4 XM f010:0" value="0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0" />

Change-Id: I9eda4cad414cd60e80b257c95858ff3e7fc2be07
(cherry picked from commit 57fc1b8289fbb2359f45ce4d156a74a4dc531709)

audio_route/audio_route.c

index 74912cd..58274dc 100644 (file)
 
 #define LOG_TAG "audio_route"
 /*#define LOG_NDEBUG 0*/
+/*#define VERY_VERY_VERBOSE_LOGGING*/
+#ifdef VERY_VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while(0)
+#endif
 
 #include <errno.h>
 #include <expat.h>
@@ -31,6 +37,7 @@
 #define BUF_SIZE 1024
 #define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
 #define INITIAL_MIXER_PATH_SIZE 8
+#define BYTE_ARRAY_MAX_SIZE 512
 
 union ctl_values {
     int *enumerated;
@@ -39,6 +46,11 @@ union ctl_values {
     unsigned char *bytes;
 };
 
+struct param_values {
+    unsigned int num_bytes;
+    unsigned char *bytes;
+};
+
 struct mixer_state {
     struct mixer_ctl *ctl;
     unsigned int num_values;
@@ -555,6 +567,96 @@ static void start_tag(void *data, const XML_Char *tag_name,
         }
     }
 
+    else if (strcmp(tag_name, "param") == 0) {
+        unsigned int vnum;
+        int count;
+        char *str;
+        char *p;
+
+        /* Obtain the mixer ctl and value */
+        ctl = mixer_get_ctl_by_name(ar->mixer, attr_name);
+        if (ctl == NULL) {
+            ALOGE("Control '%s' doesn't exist - skipping", attr_name);
+            goto done;
+        }
+
+        vnum = mixer_ctl_get_num_values(ctl);
+        if (vnum > BYTE_ARRAY_MAX_SIZE) {
+            ALOGE("Byte array control too big(%u)", vnum);
+            goto done;
+        }
+
+        switch (mixer_ctl_get_type(ctl)) {
+        case MIXER_CTL_TYPE_BYTE:
+            str = strdup(attr_value);
+            if (str == NULL) {
+                goto done;
+            }
+
+            p = strtok(str, " ");
+            for (count = 0; p != NULL; count++) {
+                p = strtok(NULL, " ");
+            }
+            free(str);
+
+            ALOGVV("param: %d values in byte array %s to set",
+                   count,
+                   attr_name);
+
+            if (count > BYTE_ARRAY_MAX_SIZE) {
+                count = BYTE_ARRAY_MAX_SIZE;
+            }
+
+            break;
+        default:
+            goto done;
+        }
+
+        /* locate the mixer ctl in the list */
+        for (ctl_index = 0; ctl_index < ar->num_mixer_ctls; ctl_index++) {
+            if (ar->mixer_state[ctl_index].ctl == ctl) {
+                break;
+            }
+        }
+
+        str = strdup(attr_value);
+        if (str == NULL) {
+            goto done;
+        }
+
+        for (p = strtok(str, " "), count = 0; p != NULL; count++) {
+            value = strtol(p, NULL, 0);
+            if (value < 0) {
+                break;
+            }
+            ALOGE_IF(value > 0xFF, "Byte out of range");
+
+            if (state->level == 1) {
+                /* top level param */
+                ALOGVV("param: Initialize %s byte[%d] with %ld",
+                      attr_name,
+                      count,
+                      value);
+                ar->mixer_state[ctl_index].new_value.bytes[count] = value;
+            } else {
+                /* param in a ctl */
+                mixer_value.ctl_index = ctl_index;
+                mixer_value.index = count;
+                mixer_value.value = value;
+
+                ALOGVV("param: Add %s to path %s and set byte[%d] to %ld",
+                       attr_name,
+                       state->path->name,
+                       count,
+                       value);
+                path_add_value(ar, state->path, &mixer_value);
+            }
+
+            p = strtok(NULL, " ");
+        }
+        free(str);
+    }
+
 done:
     state->level++;
 }