udev: use ID_MODEL_ENC instead of ID_MODEL if it is set
authorLennart Poettering <lennart@poettering.net>
Thu, 14 Jan 2010 19:31:00 +0000 (20:31 +0100)
committerColin Guthrie <cguthrie@mandriva.org>
Tue, 9 Feb 2010 22:44:00 +0000 (22:44 +0000)
That way we should be able to make use of the nicer USB strings the USB
hw provides.

Fixes the issues pointed out in:

https://tango.0pointer.de/pipermail/pulseaudio-discuss/2010-January/006248.html

src/modules/udev-util.c

index cc82446..eee5409 100644 (file)
@@ -58,6 +58,112 @@ static int read_id(struct udev_device *d, const char *n) {
     return u;
 }
 
+static int dehex(char x) {
+    if (x >= '0' && x <= '9')
+        return x - '0';
+
+    if (x >= 'A' && x <= 'F')
+        return x - 'A';
+
+    if (x >= 'a' && x <= 'f')
+        return x - 'a';
+
+    return -1;
+}
+
+static void proplist_sets_unescape(pa_proplist *p, const char *prop, const char *s) {
+    const char *f;
+    char *t, *r;
+    int c;
+
+    enum {
+        TEXT,
+        BACKSLASH,
+        EX,
+        FIRST
+    } state = TEXT;
+
+    /* The resulting string is definitely shorter than the source string */
+    r = pa_xnew(char, strlen(s)+1);
+
+    for (f = s, t = r; *f; f++) {
+
+        switch (state) {
+
+            case TEXT:
+                if (*f == '\\')
+                    state = BACKSLASH;
+                else
+                    *(t++) = *f;
+                break;
+
+            case BACKSLASH:
+                if (*f == 'x')
+                    state = EX;
+                else {
+                    *(t++) = '\\';
+                    *(t++) = *f;
+                    state = TEXT;
+                }
+                break;
+
+            case EX:
+                c = dehex(*f);
+
+                if (c < 0) {
+                    *(t++) = '\\';
+                    *(t++) = 'x';
+                    *(t++) = *f;
+                    state = TEXT;
+                } else
+                    state = FIRST;
+
+                break;
+
+            case FIRST: {
+                int d = dehex(*f);
+
+                if (d < 0) {
+                    *(t++) = '\\';
+                    *(t++) = 'x';
+                    *(t++) = *(f-1);
+                    *(t++) = *f;
+                } else
+                    *(t++) = (char) (c << 4) | d;
+
+                state = TEXT;
+                break;
+            }
+        }
+    }
+
+    switch (state) {
+
+        case TEXT:
+            break;
+
+        case BACKSLASH:
+            *(t++) = '\\';
+            break;
+
+        case EX:
+            *(t++) = '\\';
+            *(t++) = 'x';
+            break;
+
+        case FIRST:
+            *(t++) = '\\';
+            *(t++) = 'x';
+            *(t++) = *(f-1);
+            break;
+    }
+
+    *t = 0;
+
+    pa_proplist_sets(p, prop, r);
+    pa_xfree(r);
+}
+
 int pa_udev_get_info(int card_idx, pa_proplist *p) {
     int r = -1;
     struct udev *udev;
@@ -107,6 +213,8 @@ int pa_udev_get_info(int card_idx, pa_proplist *p) {
     if (!pa_proplist_contains(p, PA_PROP_DEVICE_VENDOR_NAME)) {
         if ((v = udev_device_get_property_value(card, "ID_VENDOR_FROM_DATABASE")) && *v)
             pa_proplist_sets(p, PA_PROP_DEVICE_VENDOR_NAME, v);
+        else if ((v = udev_device_get_property_value(card, "ID_VENDOR_ENC")) && *v)
+            proplist_sets_unescape(p, PA_PROP_DEVICE_VENDOR_NAME, v);
         else if ((v = udev_device_get_property_value(card, "ID_VENDOR")) && *v)
             pa_proplist_sets(p, PA_PROP_DEVICE_VENDOR_NAME, v);
     }
@@ -118,6 +226,8 @@ int pa_udev_get_info(int card_idx, pa_proplist *p) {
     if (!pa_proplist_contains(p, PA_PROP_DEVICE_PRODUCT_NAME)) {
         if ((v = udev_device_get_property_value(card, "ID_MODEL_FROM_DATABASE")) && *v)
             pa_proplist_sets(p, PA_PROP_DEVICE_PRODUCT_NAME, v);
+        else if ((v = udev_device_get_property_value(card, "ID_MODEL_ENC")) && *v)
+            proplist_sets_unescape(p, PA_PROP_DEVICE_PRODUCT_NAME, v);
         else if ((v = udev_device_get_property_value(card, "ID_MODEL")) && *v)
             pa_proplist_sets(p, PA_PROP_DEVICE_PRODUCT_NAME, v);
     }