All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 2/2] xl: Add hvm-host-usb-add and hvm-host-usb-del commands
  2013-03-20 16:41 [PATCH v2 1/2] libxl: Introduce functions to add and remove host USB devices to an HVM guest George Dunlap
@ 2013-03-20 16:41 ` George Dunlap
  0 siblings, 0 replies; 2+ messages in thread
From: George Dunlap @ 2013-03-20 16:41 UTC (permalink / raw)
  To: xen-devel; +Cc: George Dunlap, Ian Jackson, Ian Campbell, Roger Pau Monne

Add commands to add and remove host USB to HVM guests.

v2:
 - Ported to suggested libxl interface
 - Allow user to specify either host-device-spec or devname on remove
 - Options specified with -d, -v, and -i, rather than implicit ordering

Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
---
 docs/man/xl.pod.1         |   51 +++++++++
 tools/libxl/xl.h          |    2 +
 tools/libxl/xl_cmdimpl.c  |  267 +++++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/xl_cmdtable.c |   10 ++
 4 files changed, 330 insertions(+)

diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1
index a0e298e..2b5e6d7 100644
--- a/docs/man/xl.pod.1
+++ b/docs/man/xl.pod.1
@@ -1110,6 +1110,57 @@ List virtual network interfaces for a domain.
 
 =back
 
+=head2 HVM DEVICES
+
+=over 4
+
+=item B<hvm-host-usb-add> I<-d domain-id> I<-v host-device-spec> [I<-i devname>]  
+
+Passes through the host USB device specified by I<host-device-spec> to the 
+HVM domain I<domain-id>.  Host-device-spec can be one of the following:
+
+=over 4
+
+=item <hostbus>.<hostaddr>
+
+=item <vendorid>:<productid>
+
+=item <hostbus>.<hostaddr>:<vendorid>:<productid>
+
+=back
+
+The best way to find out the information for the device is typically using
+lsusb.
+
+Using the I<-i> option, you can specify a I<devname> for the
+device. This is an arbitrary string that can be used by
+I<hvm-host-usb-del> to remove the device later.  If no name is
+specified, then one will be chosen automatically.  In any case the
+devname will be printed to stdout if the device is successfully added.
+
+If the I<-i> option is used, then it must be used on device removal;
+I<host-device-spec> cannot be used.
+
+This command is only available for domains using qemu-xen, not
+qemu-traditional.
+
+=item B<hvm-host-usb-del> I<-d domain-id> (I<-i devname> | I<-v host-device-spec>)
+
+Remove the host USB device from I<domain-id> which is specified either
+by I<devname> or I<host-device-spec>.  Exactly one of the two must be
+specified.  I<devname> is a string that was specified when the device
+was inserted by B<hvm-host-usb-add>.  I<host-device-spec> can only be
+used if no name I<devname> was specified when the device was added,
+and it must match exactly the specification given at that time.
+
+Devices specified in the config file do not have an associated
+devname, and thus cannot be removed using this command.
+
+This command is only available for domains using qemu-xen, not
+qemu-traditional.
+
+=back
+
 =head2 VTPM DEVICES
 
 =over 4
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index b881f92..8eb368c 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -35,6 +35,8 @@ int main_info(int argc, char **argv);
 int main_sharing(int argc, char **argv);
 int main_cd_eject(int argc, char **argv);
 int main_cd_insert(int argc, char **argv);
+int main_hvm_host_usb_add(int argc, char **argv);
+int main_hvm_host_usb_del(int argc, char **argv);
 int main_console(int argc, char **argv);
 int main_vncviewer(int argc, char **argv);
 int main_pcilist(int argc, char **argv);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 2d40f8f..721343b 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -2584,6 +2584,273 @@ int main_cd_insert(int argc, char **argv)
     return 0;
 }
 
+
+
+static int parse_usb_specifier_hbhavipi(libxl_device_host_usb *dev, const char *s)
+{
+    const char * vid, *pid, *p;
+    const char * hostbus, *hostaddr;
+
+    hostbus = s;
+    hostaddr = vid = pid = NULL;
+
+#define is_dec(_c) ((_c) >= '0' && (_c) <= '9')
+#define is_hex(_c) (is_dec(_c) || ((_c) >= 'a' && (_c) <= 'f'))
+
+    /* Match [0-9]+\.[0-9]:[0-9a-f]+:[0-9a-f] */
+
+    /* First look for [0-9]+\.[0-9]:*/
+    if ( !is_dec(*hostbus) )
+        return -1;
+
+    for(p=s; *p; p++) {
+        if(*p == '.') {
+            if ( !hostaddr )
+                hostaddr = p+1;
+            else {
+                return -1;
+            }
+        } else if (*p == ':') {
+            break;
+        } else if (!is_dec(*p)) {
+            return -1;
+        }
+    }
+    if ( !hostaddr || !is_dec(*hostaddr) )
+        return -1;
+    if ( *p != ':' )
+        return -1;
+
+    p++;
+    /* Now match [0-9a-f]+:[0-9a-f] */
+    vid = p;
+    if ( !is_hex(*vid) )
+        return -1;
+
+    for(; *p; p++) {
+        if(*p == ':') {
+            if ( !pid )
+                pid = p+1;
+            else
+                return -1;
+        } else if (!is_hex(*p)) {
+            return -1;
+        }
+    }
+    if (!pid || !is_hex(*pid))
+        return -1;
+
+    dev->hostbus  = strtoul(hostbus,  NULL, 10);
+    dev->hostaddr = strtoul(hostaddr, NULL, 10);
+    dev->vendorid  = strtoul(vid, NULL, 16);
+    dev->productid = strtoul(pid, NULL, 16);
+
+    return 0;
+}
+
+static int parse_usb_specifier_vipi(libxl_device_host_usb *dev, const char *s)
+{
+    const char * vid, *pid, *p;
+
+    vid = s;
+    pid = NULL;
+
+    /* Match [0-9a-f]+:[0-9a-f] */
+    if ( !is_hex(*vid) )
+        return -1;
+
+    for(p=s; *p; p++) {
+        if(*p == ':') {
+            if ( !pid )
+                pid = p+1;
+            else
+                return -1;
+        } else if (!is_hex(*p)) {
+            return -1;
+        }
+    }
+    if (!pid || !is_hex(*pid))
+        return -1;
+    dev->vendorid  = strtoul(vid, NULL, 16);
+    dev->productid = strtoul(pid, NULL, 16);
+
+    return 0;
+}
+
+static int parse_usb_specifier_hbha(libxl_device_host_usb *dev, const char *s)
+{
+    const char * hostbus, *hostaddr, *p;
+
+    hostbus = s;
+    hostaddr=NULL;
+
+    /* Match [0-9]+\.[0-9] */
+    if (!is_dec(*hostbus))
+        return -1;
+
+    for(p=s; *p; p++) {
+        if(*p == '.') {
+            if ( !hostaddr )
+                hostaddr = p+1;
+            else {
+                return -1;
+            }
+        } else if (!is_dec(*p)) {
+            return -1;
+        }
+    }
+    if (!hostaddr || !is_dec(*hostaddr))
+        return -1;
+    dev->hostbus  = strtoul(hostbus,  NULL, 10);
+    dev->hostaddr = strtoul(hostaddr, NULL, 10);
+
+    return 0;
+}
+
+static int parse_usb_specifier(libxl_device_host_usb *dev, const char *s)
+{
+    /*
+     * Acceptable formats:
+     * - hostbus.hostaddr
+     * - vendorid:productid
+     * - hostbus.hostaddr:vendorid:productid
+     */
+    if ( !parse_usb_specifier_hbha(dev, s) )
+        return 0;
+    if ( !parse_usb_specifier_vipi(dev, s) )
+        return 0;
+    if ( !parse_usb_specifier_hbhavipi(dev, s) )
+        return 0;
+
+    return -1;
+}
+
+#undef is_dec
+#undef is_hex
+
+static int hvm_host_usb_add(uint32_t domid, const char * device,
+                            const char * id)
+{
+    libxl_device_host_usb usbdev;
+    int rc;
+
+    libxl_device_host_usb_init(&usbdev);
+
+    if ( id )
+        usbdev.id = strdup(id);
+
+    if ( parse_usb_specifier(&usbdev, device) < 0 )
+        return -1;
+
+    if ( (rc = libxl_hvm_host_usb_add(ctx, domid, &usbdev, NULL)) >= 0 )
+        printf("Added device with name %s\n", usbdev.id);
+
+    libxl_device_host_usb_dispose(&usbdev);
+
+    return rc;
+}
+
+int main_hvm_host_usb_add(int argc, char **argv)
+{
+    uint32_t domid = -1;
+    int opt = 0, rc;
+    const char *id = NULL, *device = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "d:v:i:", NULL, "hvm-host-usb-add", 0) {
+    case 'd':
+        domid = find_domain(optarg);
+        break;
+    case 'v':
+        device = optarg;
+        break;
+    case 'i':
+        id = optarg;
+        break;
+    }
+
+    if ( domid == -1 ) {
+        fprintf(stderr, "Must specify domid\n\n");
+        help("hvm-host-usb-add");
+        return 2;
+    }
+
+    if ( !device ) {
+        fprintf(stderr, "Must specify a device\n\n");
+        help("hvm-host-usb-add");
+        return 2;
+    }
+
+    rc = hvm_host_usb_add(domid, device, id);
+    if ( rc < 0 )
+        return 1;
+    else
+        return 0;
+}
+
+static int hvm_host_usb_del(uint32_t domid, const char * device,
+                            const char * id)
+{
+    libxl_device_host_usb usbdev;
+    int rc;
+
+    libxl_device_host_usb_init(&usbdev);
+
+    if ( id ) {
+        usbdev.id = strdup(id);
+    } else if ( device && (parse_usb_specifier(&usbdev, device) < 0) ) { 
+            return -1;
+    }
+
+    rc = libxl_hvm_host_usb_del(ctx, domid, &usbdev, NULL);
+
+    libxl_device_host_usb_dispose(&usbdev);
+
+    return rc;
+}
+
+int main_hvm_host_usb_del(int argc, char **argv)
+{
+    uint32_t domid = -1;
+    int opt = 0, rc;
+    const char *id = NULL, *device = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "d:v:i:", NULL, "hvm-host-usb-add", 0) {
+    case 'd':
+        domid = find_domain(optarg);
+        break;
+    case 'v':
+        device = optarg;
+        break;
+    case 'i':
+        id = optarg;
+        break;
+    }
+
+    if ( domid == -1 ) {
+        fprintf(stderr, "Must specify domid\n\n");
+        help("hvm-host-usb-del");
+        return 2;
+    }
+
+    if ( device && id ) {
+        fprintf(stderr, "Cannot specify both device and device-id\n\n");
+        help("hvm-host-usb-del");
+        return 2;
+    }
+
+    if ( !device && !id ) {
+        help("hvm-host-usb-del");
+        fprintf(stderr, "Must specify either device or device-id\n\n");
+        return 2;
+    }
+
+    rc = hvm_host_usb_del(domid, device, id);
+    if ( rc < 0 )
+        return 1;
+    else
+        return 0;
+}
+
 int main_console(int argc, char **argv)
 {
     uint32_t domid;
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index b4a87ca..62ba4f2 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -187,6 +187,16 @@ struct cmd_spec cmd_table[] = {
       "Eject a cdrom from a guest's cd drive",
       "<Domain> <VirtualDevice>",
     },
+    { "hvm-host-usb-add",
+      &main_hvm_host_usb_add, 1, 1,
+      "Hot-plug a host usb device to an HVM domain.",
+      "-d <Domain> -v <host-device-spec> [-i <devname>] ",
+    },
+    { "hvm-host-usb-del",
+      &main_hvm_host_usb_del, 1, 1,
+      "Hot-unplug the named host device from an HVM domain.",
+      "-d <Domain> (-i <devname> | -v <host-device-spec>)",
+    },
     { "mem-max",
       &main_memmax, 0, 1,
       "Set the maximum amount reservation for a domain",
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH v2 2/2] xl: Add hvm-host-usb-add and hvm-host-usb-del commands
@ 2013-04-04 19:37 Stefan
  0 siblings, 0 replies; 2+ messages in thread
From: Stefan @ 2013-04-04 19:37 UTC (permalink / raw)
  To: xen-devel

Where was that code pushed? I wasn't able to find that submission' right 
git url / branch.

Stefan.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-04-04 19:37 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-04 19:37 [PATCH v2 2/2] xl: Add hvm-host-usb-add and hvm-host-usb-del commands Stefan
  -- strict thread matches above, loose matches on Subject: below --
2013-03-20 16:41 [PATCH v2 1/2] libxl: Introduce functions to add and remove host USB devices to an HVM guest George Dunlap
2013-03-20 16:41 ` [PATCH v2 2/2] xl: Add hvm-host-usb-add and hvm-host-usb-del commands George Dunlap

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.