[libvirt] [PATCH V2 3/4] Add convertion domxml USB config to/from xl.cfg

Chunyan Liu cyliu at suse.com
Thu May 19 08:14:35 UTC 2016


xl.cfg:
usbdev = [ "hostbus=1,hostaddr=3" ]

usb.xml:
  <hostdev mode='subsystem' type='usb' managed='no'>
    <source>
      <address bus='1' device='3'/>
    </source>
  </hostdev>

Signed-off-by: Chunyan Liu <cyliu at suse.com>
---
 src/xenconfig/xen_xl.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 151 insertions(+)

diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c
index 15350f9..11e90b6 100644
--- a/src/xenconfig/xen_xl.c
+++ b/src/xenconfig/xen_xl.c
@@ -485,6 +485,85 @@ xenParseXLInputDevs(virConfPtr conf, virDomainDefPtr def)
     return 0;
 }
 
+static int
+xenParseXLUSB(virConfPtr conf, virDomainDefPtr def)
+{
+    virConfValuePtr list = virConfGetValue(conf, "usbdev");
+    virDomainHostdevDefPtr hostdev = NULL;
+
+    if (list && list->type == VIR_CONF_LIST) {
+        list = list->list;
+        while (list) {
+            char bus[3];
+            char device[3];
+            char *key;
+            int busNum;
+            int devNum;
+
+            bus[0] = device[0] = '\0';
+
+            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
+                goto skipusb;
+            /* usbdev=['hostbus=1,hostaddr=3'] */
+            key = list->str;
+            while (key) {
+                char *data;
+                char *nextkey = strchr(key, ',');
+
+                if (!(data = strchr(key, '=')))
+                    goto skipusb;
+                data++;
+
+                if (STRPREFIX(key, "hostbus=")) {
+                    int len = nextkey ? (nextkey - data) : sizeof(bus) - 1;
+                    if (virStrncpy(bus, data, len, sizeof(bus)) == NULL) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("bus %s too big for destination"),
+                                       data);
+                        goto skipusb;
+                    }
+                } else if (STRPREFIX(key, "hostaddr=")) {
+                    int len = nextkey ? (nextkey - data) : sizeof(device) - 1;
+                    if (virStrncpy(device, data, len, sizeof(device)) == NULL) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("device %s too big for destination"),
+                                       data);
+                        goto skipusb;
+                    }
+                }
+
+                while (nextkey && (nextkey[0] == ',' ||
+                                   nextkey[0] == ' ' ||
+                                   nextkey[0] == '\t'))
+                    nextkey++;
+                key = nextkey;
+            }
+
+            if (virStrToLong_i(bus, NULL, 16, &busNum) < 0)
+                goto skipusb;
+            if (virStrToLong_i(device, NULL, 16, &devNum) < 0)
+                goto skipusb;
+            if (!(hostdev = virDomainHostdevDefAlloc(NULL)))
+               return -1;
+
+            hostdev->managed = false;
+            hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB;
+            hostdev->source.subsys.u.usb.bus = busNum;
+            hostdev->source.subsys.u.usb.device = devNum;
+
+            if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev) < 0) {
+                virDomainHostdevDefFree(hostdev);
+                return -1;
+            }
+
+        skipusb:
+            list = list->next;
+        }
+    }
+
+    return 0;
+}
+
 virDomainDefPtr
 xenParseXL(virConfPtr conf,
            virCapsPtr caps,
@@ -513,6 +592,9 @@ xenParseXL(virConfPtr conf,
     if (xenParseXLInputDevs(conf, def) < 0)
         goto cleanup;
 
+    if (xenParseXLUSB(conf, def) < 0)
+        goto cleanup;
+
     if (virDomainDefPostParse(def, caps, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE,
                               xmlopt) < 0)
         goto cleanup;
@@ -984,6 +1066,72 @@ xenFormatXLInputDevs(virConfPtr conf, virDomainDefPtr def)
     return -1;
 }
 
+static int
+xenFormatXLUSB(virConfPtr conf,
+               virDomainDefPtr def)
+{
+    virConfValuePtr usbVal = NULL;
+    int hasUSB = 0;
+    size_t i;
+
+    for (i = 0; i < def->nhostdevs; i++) {
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
+            hasUSB = 1;
+            break;
+        }
+    }
+
+    if (!hasUSB)
+        return 0;
+
+    if (VIR_ALLOC(usbVal) < 0)
+        return -1;
+
+    usbVal->type = VIR_CONF_LIST;
+    usbVal->list = NULL;
+
+    for (i = 0; i < def->nhostdevs; i++) {
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
+            virConfValuePtr val, tmp;
+            char *buf;
+
+            if (virAsprintf(&buf, "hostbus=%x,hostaddr=%x",
+                            def->hostdevs[i]->source.subsys.u.usb.bus,
+                            def->hostdevs[i]->source.subsys.u.usb.device) < 0)
+                goto error;
+
+            if (VIR_ALLOC(val) < 0) {
+                VIR_FREE(buf);
+                goto error;
+            }
+            val->type = VIR_CONF_STRING;
+            val->str = buf;
+            tmp = usbVal->list;
+            while (tmp && tmp->next)
+                tmp = tmp->next;
+            if (tmp)
+                tmp->next = val;
+            else
+                usbVal->list = val;
+        }
+    }
+
+    if (usbVal->list != NULL) {
+        int ret = virConfSetValue(conf, "usbdev", usbVal);
+        usbVal = NULL;
+        if (ret < 0)
+            return -1;
+    }
+    VIR_FREE(usbVal);
+
+    return 0;
+
+ error:
+    virConfFreeValue(usbVal);
+    return -1;
+}
 
 virConfPtr
 xenFormatXL(virDomainDefPtr def, virConnectPtr conn)
@@ -1008,6 +1156,9 @@ xenFormatXL(virDomainDefPtr def, virConnectPtr conn)
     if (xenFormatXLInputDevs(conf, def) < 0)
         goto cleanup;
 
+    if (xenFormatXLUSB(conf, def) < 0)
+        goto cleanup;
+
     return conf;
 
  cleanup:
-- 
2.1.4




More information about the libvir-list mailing list