WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] PVUSB: xm/xend support

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] PVUSB: xm/xend support
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 11 Dec 2009 01:10:32 -0800
Delivery-date: Fri, 11 Dec 2009 01:18:52 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1260521537 0
# Node ID 2e5032921b077a4e89fc26343060c026547cca98
# Parent  1f5f36e11114d63c2a1c755106cb697666a92207
PVUSB: xm/xend support

You can see the following slides to understand the usage.
http://www.xen.org/files/xensummit_intel09/PVUSBStatusUpdate.pdf
Limitations:
"xm usb-hc-create" accepts up to 16 ports, but, current usbfront
can work with up to 15 ports. This may be bug and I'm preparing
to fix it.

This xm/xend support requires linux-2.6.18-xen.hg c/s 939 or above.
I recommend latest tip.

Signed-off-by: Noboru Iwamatsu <n_iwamatsu@xxxxxxxxxxxxxx>
---
 tools/hotplug/Linux/xend.rules            |    1 
 tools/python/xen/util/vusb_util.py        |  338 ++++++++++++++++++++++++++++++
 tools/python/xen/xend/XendConfig.py       |   82 +++++++
 tools/python/xen/xend/XendDevices.py      |    3 
 tools/python/xen/xend/XendDomainInfo.py   |   31 ++
 tools/python/xen/xend/XendNode.py         |   15 +
 tools/python/xen/xend/server/udevevent.py |   12 +
 tools/python/xen/xend/server/vusbif.py    |  126 +++++++++++
 tools/python/xen/xm/create.py             |   45 +++
 tools/python/xen/xm/main.py               |  151 +++++++++++++
 10 files changed, 803 insertions(+), 1 deletion(-)

diff -r 1f5f36e11114 -r 2e5032921b07 tools/hotplug/Linux/xend.rules
--- a/tools/hotplug/Linux/xend.rules    Fri Dec 11 08:51:21 2009 +0000
+++ b/tools/hotplug/Linux/xend.rules    Fri Dec 11 08:52:17 2009 +0000
@@ -1,3 +1,4 @@ SUBSYSTEM=="pci", RUN+="socket:/org/xen/
 SUBSYSTEM=="pci", RUN+="socket:/org/xen/xend/udev_event"
 SUBSYSTEM=="scsi", RUN+="socket:/org/xen/xend/udev_event"
+SUBSYSTEM=="usb", RUN+="socket:/org/xen/xend/udev_event"
 #SUBSYSTEM=="net", KERNEL!="vif[0-9]*.[0-9]*|tap[0-9]*.[0-9]*", 
RUN+="socket:/org/xen/xend/udev_event"
diff -r 1f5f36e11114 -r 2e5032921b07 tools/python/xen/util/vusb_util.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/util/vusb_util.py        Fri Dec 11 08:52:17 2009 +0000
@@ -0,0 +1,338 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
+# Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+#  Author: Noboru Iwamatsu <n_iwamatsu@xxxxxxxxxxxxxx>
+#============================================================================
+
+
+"""Support for VUSB Devices.
+"""
+import os
+import os.path
+import sys
+import re
+import string
+from xen.util import utils
+
+SYSFS_USB_DEVS_PATH = '/bus/usb/devices'
+SYSFS_USB_DEV_BDEVICECLASS_PATH = '/bDeviceClass'
+SYSFS_USB_DEV_BDEVICESUBCLASS_PATH = '/bDeviceSubClass'
+SYSFS_USB_DEV_DEVNUM_PATH = '/devnum'
+SYSFS_USB_DEV_IDVENDOR_PATH = '/idVendor'
+SYSFS_USB_DEV_IDPRODUCT_PATH = '/idProduct'
+SYSFS_USB_DEV_MANUFACTURER_PATH = '/manufacturer'
+SYSFS_USB_DEV_PRODUCT_PATH = '/product'
+SYSFS_USB_DEV_SERIAL_PATH = '/serial'
+SYSFS_USB_DEV_DRIVER_PATH = '/driver'
+SYSFS_USB_DRIVER_BIND_PATH = '/bind'
+SYSFS_USB_DRIVER_UNBIND_PATH = '/unbind'
+SYSFS_USBBACK_PATH = '/bus/usb/drivers/usbback'
+SYSFS_PORTIDS_PATH = '/port_ids'
+USBHUB_CLASS_CODE = '09'
+
+def get_usb_bDeviceClass(dev):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_usb_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
+        if os.path.exists(sysfs_usb_dev_path + 
SYSFS_USB_DEV_BDEVICECLASS_PATH):
+            usb_deviceclass = \
+                os.popen('cat ' + sysfs_usb_dev_path + \
+                              SYSFS_USB_DEV_BDEVICECLASS_PATH).readline()
+            return usb_deviceclass.splitlines()[0]
+        else:
+            return ""
+    except:
+        return None
+
+def get_usb_bDeviceSubClass(dev):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_usb_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
+        if os.path.exists(sysfs_usb_dev_path + 
SYSFS_USB_DEV_BDEVICESUBCLASS_PATH):
+            usb_devicesubclass = \
+                os.popen('cat ' + sysfs_usb_dev_path + \
+                              SYSFS_USB_DEV_BDEVICESUBCLASS_PATH).readline()
+            return usb_devicesubclass.splitlines()[0]
+        else:
+            return ""
+    except:
+        return None
+
+def get_usb_devnum(dev):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_usb_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
+        if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_DEVNUM_PATH):
+            usb_devicesubclass = \
+                os.popen('cat ' + sysfs_usb_dev_path + \
+                              SYSFS_USB_DEV_DEVNUM_PATH).readline()
+            return usb_devicesubclass.splitlines()[0]
+        else:
+            return ""
+    except:
+        return None
+
+def get_usb_idvendor(dev):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_usb_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
+        if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_IDVENDOR_PATH):
+            usb_idvendor = \
+                os.popen('cat ' + sysfs_usb_dev_path + \
+                              SYSFS_USB_DEV_IDVENDOR_PATH).readline()
+            return usb_idvendor.splitlines()[0]
+        else:
+            return ""
+    except:
+        return None
+
+def get_usb_idproduct(dev):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_usb_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
+        if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_IDPRODUCT_PATH):
+            usb_idproduct = \
+                os.popen('cat ' + sysfs_usb_dev_path + \
+                              SYSFS_USB_DEV_IDPRODUCT_PATH).readline()
+            return usb_idproduct.splitlines()[0]
+        else:
+            return ""
+    except:
+        return None
+
+def get_usb_manufacturer(dev):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_usb_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
+
+        if os.path.exists(sysfs_usb_dev_path + 
SYSFS_USB_DEV_MANUFACTURER_PATH):
+            usb_manufacturer = \
+                os.popen('cat ' + sysfs_usb_dev_path + \
+                              SYSFS_USB_DEV_MANUFACTURER_PATH).readline()
+            return usb_manufacturer.splitlines()[0]
+        else:
+            return ""
+    except:
+        return None
+
+def get_usb_product(dev):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_usb_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
+        if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_PRODUCT_PATH):
+            usb_product = \
+                os.popen('cat ' + sysfs_usb_dev_path + \
+                              SYSFS_USB_DEV_PRODUCT_PATH).readline()
+            return usb_product.splitlines()[0]
+        else:
+            return ""
+    except:
+        return None
+
+def get_usb_serial(dev):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_usb_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
+        if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_SERIAL_PATH):
+            usb_serial = \
+                os.popen('cat ' + sysfs_usb_dev_path + \
+                              SYSFS_USB_DEV_SERIAL_PATH).readline()
+            return usb_serial.splitlines()[0]
+        else:
+            return ""
+    except:
+        return None
+
+def get_usbdevice_info_by_lsusb(dev):
+    try:
+        vend = get_usb_idvendor(dev)
+        prod = get_usb_idproduct(dev)
+        output = os.popen('lsusb -d ' + vend + ':' + prod).readline().split()
+        text = ""
+        if len(output) > 6:
+            for str in output[6:]:
+                if text != "":
+                    text= text + ' '
+                text = text + str
+            return text
+        else:
+            return ""
+    except:
+        return None
+
+def get_usbdevice_info(dev):
+    try:
+        manuf = get_usb_manufacturer(dev)
+        prod = get_usb_product(dev)
+        if manuf == "" or prod == "":
+            return get_usbdevice_info_by_lsusb(dev)
+        else:
+            return manuf + ' ' + prod
+    except:
+        return None
+
+def usb_device_is_hub(dev):
+    usb_classcode = get_usb_bDeviceClass(dev)
+    if (usb_classcode == USBHUB_CLASS_CODE):
+        return True
+    else:
+        return False
+
+def get_all_usb_names():
+    usb_names = []
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        usb_names = os.popen('ls ' + sysfs_mnt + 
SYSFS_USB_DEVS_PATH).read().split()
+    except:
+        pass
+    return usb_names
+
+def get_usb_devices():
+    devs = []
+    for name in get_all_usb_names():
+        dev_match = re.match(r"(^(?P<bus>[0-9]{1,2})[-,])" + \
+                     r"(?P<root_port>[0-9]{1,2})" + \
+                     r"(?P<port>([\.,]{1}[0-9]{1,2}){0,5})$", name)
+        if dev_match is not None:
+            dev = dev_match.group('bus') + '-' \
+            + dev_match.group('root_port') \
+            + dev_match.group('port') 
+            if (usb_device_is_hub(dev)):
+                continue
+            else:
+                devs.append(dev)
+    return devs
+
+def get_usb_intfs(dev):
+    intfs = []
+    try:
+        search = re.compile(r'^' + dev + ':')
+    except:
+        raise UsbDeviceParseError("Invalid expression.")
+    for name in get_all_usb_names():
+        if search.match(name):
+            intfs.append(name)
+    return intfs
+
+def get_assigned_buses():
+    buses = []
+    try:
+        sysfs_mnt = utils.find_sysfs_mount()
+        if os.path.exists(sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH):
+            portids = \
+                os.popen('cat ' + sysfs_mnt + SYSFS_USBBACK_PATH + 
SYSFS_PORTIDS_PATH).read().splitlines()
+            for portid in portids:
+                buses.append(portid.split(':')[0])
+    except:
+        raise UsbDeviceParseError("Can't get assigned buses from port_ids.")
+    return buses
+
+def get_assigned_bus(domid, dev, port):
+    bus = ""
+    try:
+        sysfs_mnt = utils.find_sysfs_mount()
+        if os.path.exists(sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH):
+            portids = \
+                os.popen('cat ' + sysfs_mnt + SYSFS_USBBACK_PATH + 
SYSFS_PORTIDS_PATH).read().splitlines()
+        for portid in portids:
+            if portid.split(':')[1] == str(domid) and portid.split(':')[2] == 
str(dev) and portid.split(':')[3] == str(port):
+                bus = portid.split(':')[0]
+    except:
+        raise UsbDeviceParseError("Can't get assigned bus (%d:%d:%d)." % 
(domid, dev, port))
+    return bus
+
+def bus_is_assigned(bus):
+    assigned = False    
+    try:
+        sysfs_mnt = utils.find_sysfs_mount()
+        if os.path.exists(sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH):
+            portids = \
+                os.popen('cat ' + sysfs_mnt + SYSFS_USBBACK_PATH + 
SYSFS_PORTIDS_PATH).read().splitlines()
+        for portid in portids:
+            if portid.split(':')[0] == bus:
+                assigned = True
+    except:
+        raise UsbDeviceParseError("Can't get assignment status: (%s)." % bus)
+    return assigned
+
+def usb_intf_is_binded(intf):
+    if os.path.exists(SYSFS_USBBACK_PATH + '/' + intf):
+        return True
+    else:
+        return False
+
+def usb_device_is_connected(dev):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount()
+        sysfs_dev_path = \
+                os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
+        if os.path.exists(sysfs_dev_path):
+            return True
+        else:
+            return False
+    except:
+        raise UsbDeviceParseError("Can't get connection status (%s)." % dev)
+
+def unbind_usb_device(dev):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount()
+        for intf in get_usb_intfs(dev): 
+            sysfs_usb_intf_path = \
+                os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, intf)
+            if os.path.exists(sysfs_usb_intf_path + SYSFS_USB_DEV_DRIVER_PATH):
+                fd = os.open(sysfs_usb_intf_path + \
+                             SYSFS_USB_DEV_DRIVER_PATH + \
+                             SYSFS_USB_DRIVER_UNBIND_PATH, os.O_WRONLY)
+                os.write(fd, intf)
+                os.close(fd)
+    except:
+        raise UsbDeviceBindingError("can't unbind intf (%s). " % intf)
+
+def bind_usb_device(dev):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount()
+        for intf in get_usb_intfs(dev): 
+            sysfs_usb_intf_path = \
+                os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, intf)
+            if os.path.exists(sysfs_usb_intf_path + SYSFS_USB_DEV_DRIVER_PATH):
+                unbind_usb_device(dev)
+
+            fd = os.open(sysfs_mnt + SYSFS_USBBACK_PATH + \
+                         SYSFS_USB_DRIVER_BIND_PATH, os.O_WRONLY)
+            os.write(fd, intf)
+            os.close(fd)
+    except:
+        raise UsbDeviceBindingError("can't bind intf (%s). " % intf)
+
+class UsbDeviceParseError(Exception):
+    def __init__(self,msg):
+        self.message = msg
+    def __str__(self):
+        return 'vusb: Error parsing USB device info: '+self.message
+
+class UsbDeviceBindingError(Exception):
+    def __init__(self,msg):
+        self.message = msg
+    def __str__(self):
+        return 'vusb: Failed to bind/unbind USB device: ' + \
+            self.message
diff -r 1f5f36e11114 -r 2e5032921b07 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Fri Dec 11 08:51:21 2009 +0000
+++ b/tools/python/xen/xend/XendConfig.py       Fri Dec 11 08:52:17 2009 +0000
@@ -1400,6 +1400,14 @@ class XendConfig(dict):
                           (vscsi_devs, vscsi_mode))
                 return vscsi_devs_uuid
 
+            if dev_type == 'vusb':
+                vusb_devs_uuid = sxp.child_value(config, 'uuid',
+                                                uuid.createString())
+                vusb_dict = self.vusb_convert_sxp_to_dict(config)
+                vusb_dict['uuid'] = vusb_devs_uuid
+                target['devices'][vusb_devs_uuid] = (dev_type, vusb_dict)
+                return vusb_devs_uuid
+
             for opt_val in config[1:]:
                 try:
                     opt, val = opt_val
@@ -1776,6 +1784,68 @@ class XendConfig(dict):
 
         return dev_config
 
+    def vusb_convert_sxp_to_dict(self, dev_sxp):
+        """Convert vusb device sxp to dict
+        @param dev_sxp: device configuration
+        @type  dev_sxp: SXP object (parsed config)
+        @return: dev_config
+        @rtype: dictionary
+        """
+        # Parsing USB devices SXP. 
+        #
+        # USB device's SXP looks like this:
+        #
+        # [device,
+        #   [vusb,
+        #     [usb-ver, 2],
+        #     [num-ports, 8],
+        #     [port,
+        #          [1, 1-1],
+        #          [2, 1-2],
+        #          [3, ''],
+        #          [4, ''],
+        #          [5, ''],
+        #          [6, ''],
+        #          [7, 6-2.1],        
+        #          [8, '']
+        #     ]
+        #   ],
+        #   [vusb,
+        #     [usb-ver, 1],
+        #     [num-ports, 2],
+        #     [port,
+        #          [1, 4-1],
+        #          [2, 4-2]
+        #     ]
+        #   ]  
+        # ]
+        #
+        # The dict looks like this
+        #
+        # { usb-ver: 2,
+        #   num-ports: 8,
+        #   port-1: 1-1,
+        #   port-2: 1-2,
+        #   port-3: "",
+        #   port-4: "",
+        #   port-5: "",
+        #   port-6: "",
+        #   port-7: "",
+        #   port-8: "" }
+
+        dev_config = {}
+        dev_config['usb-ver'] = sxp.child(dev_sxp, 'usb-ver')[1]
+        dev_config['num-ports'] = sxp.child(dev_sxp, 'num-ports')[1]
+        ports = sxp.child(dev_sxp, 'port')
+        for port in ports[1:]:
+            try:
+                num, bus = port
+                dev_config['port-%i' % int(num)] = str(bus)
+            except TypeError:
+                pass
+
+        return dev_config
+
     def console_add(self, protocol, location, other_config = {}):
         dev_uuid = uuid.createString()
         if protocol == 'vt100':
@@ -2001,6 +2071,18 @@ class XendConfig(dict):
                         sxpr.append(['backend', dev_info['backend']])
                 for pci_dev_info in dev_info['devs']:
                     sxpr.append(dev_dict_to_sxp(pci_dev_info))
+                sxprs.append((dev_type, sxpr))
+            elif dev_type == 'vusb':
+                sxpr = ['vusb', ['uuid', dev_info['uuid']],
+                                ['usb-ver', dev_info['usb-ver']],
+                                ['num-ports', dev_info['num-ports']]]
+                port_sxpr = ['port']
+                for i in range(1, int(dev_info['num-ports']) + 1):
+                    if dev_info.has_key('port-%i' % i):
+                        port_sxpr.append([i, str(dev_info['port-%i' % i])])
+                    else:
+                        port_sxpr.append([i, ""])
+                sxpr.append(port_sxpr)
                 sxprs.append((dev_type, sxpr))
             else:
                 sxpr = self.device_sxpr(dev_type = dev_type,
diff -r 1f5f36e11114 -r 2e5032921b07 tools/python/xen/xend/XendDevices.py
--- a/tools/python/xen/xend/XendDevices.py      Fri Dec 11 08:51:21 2009 +0000
+++ b/tools/python/xen/xend/XendDevices.py      Fri Dec 11 08:52:17 2009 +0000
@@ -19,7 +19,7 @@
 # A collection of DevControllers 
 #
 
-from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, vfbif, 
vscsiif, netif2
+from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, vfbif, 
vscsiif, netif2, vusbif
 from xen.xend.server.BlktapController import BlktapController, 
Blktap2Controller
 from xen.xend.server.ConsoleController import ConsoleController
 
@@ -48,6 +48,7 @@ class XendDevices:
         'vkbd': vfbif.VkbdifController,
         'console': ConsoleController,
         'vscsi': vscsiif.VSCSIController,
+        'vusb': vusbif.VUSBController,
     }
 
     #@classmethod
diff -r 1f5f36e11114 -r 2e5032921b07 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Fri Dec 11 08:51:21 2009 +0000
+++ b/tools/python/xen/xend/XendDomainInfo.py   Fri Dec 11 08:52:17 2009 +0000
@@ -1102,6 +1102,27 @@ class XendDomainInfo:
 
         return True
 
+    def vusb_device_configure(self, dev_sxp, devid):
+        """Configure a virtual root port.
+        """
+        dev_class = sxp.name(dev_sxp)
+        if dev_class != 'vusb':
+            return False
+
+        dev_config = {}
+        ports = sxp.child(dev_sxp, 'port')
+        for port in ports[1:]:
+            try:
+                num, bus = port
+                dev_config['port-%i' % int(num)] = str(bus)
+            except TypeError:
+                pass
+
+        dev_control = self.getDeviceController(dev_class)
+        dev_control.reconfigureDevice(devid, dev_config)
+
+        return True
+
     def device_configure(self, dev_sxp, devid = None):
         """Configure an existing device.
         
@@ -1122,6 +1143,9 @@ class XendDomainInfo:
 
         if dev_class == 'vscsi':
             return self.vscsi_device_configure(dev_sxp)
+
+        if dev_class == 'vusb':
+            return self.vusb_device_configure(dev_sxp, devid)
 
         for opt_val in dev_sxp[1:]:
             try:
@@ -1376,6 +1400,13 @@ class XendDomainInfo:
             devs = sxp.children(dev_info, 'dev')
             if devid == int(sxp.child_value(devs[0], 'devid')):
                 return dev_info
+        return None
+
+    def _getDeviceInfo_vusb(self, devid):
+        for dev_type, dev_info in self.info.all_devices_sxpr():
+            if dev_type != 'vusb':
+                continue
+            return dev_info
         return None
 
     def _get_assigned_pci_devices(self, devid = 0):
diff -r 1f5f36e11114 -r 2e5032921b07 tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Fri Dec 11 08:51:21 2009 +0000
+++ b/tools/python/xen/xend/XendNode.py Fri Dec 11 08:52:17 2009 +0000
@@ -24,6 +24,7 @@ from xen.util import Brctl
 from xen.util import Brctl
 from xen.util import pci as PciUtil
 from xen.util import vscsi_util
+from xen.util import vusb_util
 from xen.xend import XendAPIStore
 from xen.xend import osdep
 from xen.xend.XendConstants import *
@@ -478,6 +479,20 @@ class XendNode:
 
                 return
 
+    def add_usbdev(self, busid):
+        # if the adding usb device should be owned by usbback
+        # and is probed by other usb drivers, seize it!
+        bus, intf = busid.split(':')
+        buses = vusb_util.get_assigned_buses()
+        if str(bus) in buses:
+            if not vusb_util.usb_intf_is_binded(busid):
+                log.debug("add_usb(): %s is binded to other driver" % busid)
+                vusb_util.unbind_usb_device(bus)
+                vusb_util.bind_usb_device(bus)
+        return
+
+    def remove_usbdev(self, busid):
+        log.debug("remove_usbdev(): Not implemented.")
 
 ##    def network_destroy(self, net_uuid):
  ##       del self.networks[net_uuid]
diff -r 1f5f36e11114 -r 2e5032921b07 tools/python/xen/xend/server/udevevent.py
--- a/tools/python/xen/xend/server/udevevent.py Fri Dec 11 08:51:21 2009 +0000
+++ b/tools/python/xen/xend/server/udevevent.py Fri Dec 11 08:52:17 2009 +0000
@@ -60,6 +60,18 @@ class UdevEventProtocol(protocol.Protoco
                     log.info("Removing scsi device %s", hctl)
                     XendNode.instance().remove_PSCSI(hctl)
 
+            elif (udev_event.get('SUBSYSTEM', None) == 'usb'):
+                busid = udev_event.get('KERNEL', None)
+                if busid:
+                    if len(busid.split(':')) != 2:
+                        return
+                if (udev_event['ACTION'] == 'add'):
+                    log.info("Adding usb device %s", busid)
+                    XendNode.instance().add_usbdev(busid)
+                elif (udev_event['ACTION'] == 'remove'):
+                    log.info("Removing usb device %s", busid)
+                    XendNode.instance().remove_usbdev(busid)
+
             elif (udev_event.get('SUBSYSTEM', None) == 'net'):
                 interface = udev_event.get('INTERFACE', None)
                 if (udev_event['ACTION'] == 'add'):
diff -r 1f5f36e11114 -r 2e5032921b07 tools/python/xen/xend/server/vusbif.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xend/server/vusbif.py    Fri Dec 11 08:52:17 2009 +0000
@@ -0,0 +1,126 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
+# Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+#  Author: Noboru Iwamatsu <n_iwamatsu@xxxxxxxxxxxxxx>
+#============================================================================
+
+"""Support for virtual USB host controllers.
+"""
+import re
+import string
+
+import types
+
+from xen.xend import sxp
+from xen.xend.XendError import VmError
+from xen.xend.XendLogging import log
+
+from xen.xend.server.DevController import DevController
+from xen.xend.server.DevConstants import xenbusState
+from xen.xend.xenstore.xstransact import xstransact
+
+from xen.util import vusb_util
+
+class VUSBController(DevController):
+    """VUSB Devices.
+    """
+    def __init__(self, vm):
+        """Create a VUSB Devices.
+        """
+        DevController.__init__(self, vm)
+
+    def sxprs(self):
+        """@see DevController.sxprs"""
+        devslist = []
+        for devid in self.deviceIDs():
+            vusb_config = []
+            backid = self.readFrontend(devid, 'backend-id')
+            vusb_config.append(['backend-id', backid])
+            state = self.readFrontend(devid, 'state')
+            vusb_config.append(['state', state])
+            backpath = self.readFrontend(devid, 'backend')
+            vusb_config.append(['backend', backpath]) 
+            usbver = self.readBackend(devid, 'usb-ver')
+            vusb_config.append(['usb-ver', usbver])
+            numports = self.readBackend(devid, 'num-ports') 
+            vusb_config.append(['num-ports', numports])             
+
+            portpath = "port/"
+            ports = ['port']
+            for i in range(1, int(numports) + 1):
+                bus = self.readBackend(devid, portpath + '%i' % i)
+                ports.append(['%i' % i, str(bus)])
+
+            vusb_config.append(ports)             
+            devslist.append([devid, vusb_config])
+
+        return devslist
+
+    def getDeviceDetails(self, config):
+        """@see DevController.getDeviceDetails"""
+        back = {}
+        devid = self.allocateDeviceID()
+        usbver = config.get('usb-ver', '')
+        numports = config.get('num-ports', '')
+        back['usb-ver'] = str(usbver)
+        back['num-ports'] = str(numports)
+        for i in range(1, int(numports) + 1):
+            back['port/%i' % i] = config['port-%i' % i]
+        return (devid, back, {})
+
+    def getDeviceConfiguration(self, devid, transaction = None):
+        """@see DevController.configuration"""
+        config = DevController.getDeviceConfiguration(self, devid, transaction)
+        if transaction is None:
+            hcinfo = self.readBackend(devid, 'usb-ver', 'num-ports')
+        else:
+            hcinfo = self.readBackendTxn(transaction, devid,
+                                          'usb-ver', 'num-ports')
+        (usbver, numports) = hcinfo
+        config['usb-ver'] = str(usbver)
+        config['num-ports'] = str(numports)
+        for i in range(1, int(numports) + 1):
+            if transaction is None:
+                config['port-%i' % i] = self.readBackend(devid, 'port/%i' % i)
+            else:
+                config['port-%i' % i] = self.readBackendTxn(transaction, devid,
+                                                             'port/%i' % i)
+        return config
+
+    def reconfigureDevice(self, devid, config):
+        """@see DevController.reconfigureDevice"""
+        cur_config = self.getDeviceConfiguration(devid)
+
+        numports = cur_config['num-ports']
+        for i in range(1, int(numports) + 1):
+            if config.has_key('port-%i' % i):
+                if not config['port-%i' % i] == cur_config['port-%i' % i]:
+                    if not cur_config['port-%i' % i] == "":
+                        vusb_util.unbind_usb_device(cur_config['port-%i' % i])
+                    self.writeBackend(devid, 'port/%i' % i, 
+                                      config['port-%i' % i])
+                    if not config['port-%i' % i] == "":
+                        vusb_util.bind_usb_device(config['port-%i' % i])
+
+        return self.readBackend(devid, 'uuid')
+
+    def waitForBackend(self, devid):
+        return (0, "ok - no hotplug")
+
+    def waitForBackend_destroy(self, backpath):
+        return 0
+
+    def migrate(self, deviceConfig, network, dst, step, domName):
+        raise VmError('Migration not permitted with assigned USB device.')
diff -r 1f5f36e11114 -r 2e5032921b07 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Fri Dec 11 08:51:21 2009 +0000
+++ b/tools/python/xen/xm/create.py     Fri Dec 11 08:52:17 2009 +0000
@@ -349,6 +349,18 @@ gopts.var('vscsi', val='PDEV,VDEV[,DOM]'
           fn=append_value, default=[],
           use="""Add a SCSI device to a domain. The physical device is PDEV,
           which is exported to the domain as VDEV(X:X:X:X).""")
+
+gopts.var('vusb', val="usbver=USBVER,numports=NUMPORTS," + \
+          "port_1=PORT1,port_2=PORT2,port_3=PORT3,port_4=PORT4" + \
+          "port_5=PORT5,port_6=PORT6,port_7=PORT7,port_8=PORT8" + \
+          "port_9=PORT9,port_10=PORT10,port_11=PORT11,port_12=PORT12" + \
+          "port_13=PORT13,port_14=PORT14,port_15=PORT15,port_16=PORT16",
+          fn=append_value, default=[],
+          use="""Add a Virtual USB Host Controller to a domain.
+          The USB Spec Version is usbver (1|2, default: 2).
+          usbver=1 means USB1.1, usbver=2 mens USB2.0.
+          The number of root ports is numports (1 to 16, default: 8).
+          This option may be repeated to add more than one host controller.""")
 
 gopts.var('ioports', val='FROM[-TO]',
           fn=append_value, default=[],
@@ -849,6 +861,38 @@ def configure_vscsis(config_devs, vals):
             device.append(['backend', config['backend']])
         config_devs.append(['device', device])
 
+def configure_vusbs(config_devs, vals):
+    """Create the config for virtual usb host controllers.
+    """
+    for f in vals.vusb:
+        d = comma_sep_kv_to_dict(f)
+        config = ['vusb']
+
+        usbver = 2
+        if d.has_key('usbver'):
+            usbver = int(d['usbver'])
+        if usbver == 1 or usbver == 2:
+            config.append(['usb-ver', str(usbver)])
+        else:
+            err('Invalid vusb option: ' + 'usbver')
+
+        numports = 8
+        if d.has_key('numports'):
+            numports = d['numports']
+        if int(numports) < 1 or int(numports) > 16:
+            err('Invalid vusb option: ' + 'numports')
+        config.append(['num-ports', str(numports)])
+
+        port_config = []
+        for i in range(1, int(numports) + 1):
+            if d.has_key('port_%i' % i):
+                port_config.append(['%i' % i, str(d['port_%i' % i])])
+            else:
+                port_config.append(['%i' % i, ""])
+        port_config.insert(0, 'port')
+        config.append(port_config)
+        config_devs.append(['device', config])        
+
 def configure_ioports(config_devs, vals):
     """Create the config for legacy i/o ranges.
     """
@@ -1103,6 +1147,7 @@ def make_config(vals):
     configure_disks(config_devs, vals)
     configure_pci(config_devs, vals)
     configure_vscsis(config_devs, vals)
+    configure_vusbs(config_devs, vals)
     configure_ioports(config_devs, vals)
     configure_irq(config_devs, vals)
     configure_vifs(config_devs, vals)
diff -r 1f5f36e11114 -r 2e5032921b07 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Fri Dec 11 08:51:21 2009 +0000
+++ b/tools/python/xen/xm/main.py       Fri Dec 11 08:52:17 2009 +0000
@@ -39,6 +39,7 @@ from xen.util.blkif import blkdev_name_t
 from xen.util.blkif import blkdev_name_to_number
 from xen.util import vscsi_util
 from xen.util.pci import *
+from xen.util import vusb_util
 
 import warnings
 warnings.filterwarnings('ignore', category=FutureWarning)
@@ -211,6 +212,17 @@ SUBCOMMAND_HELP = {
                         'Detach a specified SCSI device.'),
     'scsi-list'    :  ('<Domain> [--long]',
                         'List all SCSI devices currently attached.'),
+    'usb-attach'  :  ('<Domain> <DevId> <PortNumber> <BusId>',
+                        'Attach a new USB physical bus to domain\'s virtual 
port.'),
+    'usb-detach'  :  ('<Domain> <DevId> <PortNumber>',
+                        'Detach a USB physical bus from domain\'s virtual 
port.'),
+    'usb-list'    :  ('<Domain>',
+                        'List domain\'s attachment state of all virtual port 
.'),
+    'usb-list-assignable-devices' : ('', 'List all the assignable usb 
devices'),
+    'usb-hc-create'  :  ('<Domain> <USBSpecVer> <NumberOfPorts>',
+                        'Create a domain\'s new virtual USB host controller.'),
+    'usb-hc-destroy'  :  ('<Domain> <DevId>',
+                        'Destroy a domain\'s virtual USB host controller.'),
 
     # tmem
     'tmem-list'     :  ('[-l|--long] [<Domain>|-a|--all]', 'List tmem pools.'),
@@ -429,6 +441,12 @@ device_commands = [
     "scsi-attach",
     "scsi-detach",
     "scsi-list",
+    "usb-attach",
+    "usb-detach",
+    "usb-list",
+    "usb-list-assignable-devices",
+    "usb-hc-create",
+    "usb-hc-destroy",
     ]
 
 vnet_commands = [
@@ -2409,6 +2427,58 @@ def xm_scsi_list(args):
                 print "%(idx)-3d %(backend-id)-3d %(state)-5d 
%(feature-host)-4d " % ni,
                 print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s 
%(frontstate)-4s" % mi
 
+def xm_usb_list(args):
+    xenapi_unsupported()
+    arg_check(args, 'usb-list', 1)
+    dom = args[0]
+    devs = server.xend.domain.getDeviceSxprs(dom, 'vusb')
+    for x in devs:
+        print "%-3s %-3s %-5s %-7s  %-30s" \
+            % ('Idx', 'BE', 'state', 'usb-ver', 'BE-path')
+        ni = parse_dev_info(x[1])
+        ni['idx'] = int(x[0])
+        usbver = sxp.child_value(x[1], 'usb-ver')
+        if int(usbver) == 1:
+            ni['usb-ver'] = 'USB1.1'
+        else:
+            ni['usb-ver'] = 'USB2.0'
+        print "%(idx)-3d %(backend-id)-3d %(state)-5d %(usb-ver)-7s 
%(be-path)-30s  " % ni
+
+        ports = sxp.child(x[1], 'port')
+        for port in ports[1:]:
+            try:
+                num, bus = port
+                if bus != "" and vusb_util.usb_device_is_connected(bus):
+                        idvendor = vusb_util.get_usb_idvendor(bus)
+                        idproduct = vusb_util.get_usb_idproduct(bus)
+                        prodinfo = vusb_util.get_usbdevice_info(bus)
+                        print "port %i: %s [ID %-4s:%-4s %s]" \
+                            % (int(num), str(bus), idvendor, idproduct, 
prodinfo)
+                else:
+                    print "port %i: " % int(num) + str(bus)
+            except TypeError:
+                pass
+
+def xm_usb_list_assignable_devices(args):
+    xenapi_unsupported()
+    arg_check(args, 'usb-list-assignable-devices', 0)
+
+    usb_devs = vusb_util.get_usb_devices()
+    buses = vusb_util.get_assigned_buses()
+
+    for x in buses:
+        try:
+            usb_devs.remove(x)
+        except ValueError:
+            pass
+
+    for dev in usb_devs:
+        idvendor = vusb_util.get_usb_idvendor(dev)
+        idproduct = vusb_util.get_usb_idproduct(dev)
+        prodinfo = vusb_util.get_usbdevice_info(dev)
+        print "%-13s: ID %-4s:%-4s %s" \
+                % (dev, idvendor, idproduct, prodinfo)
+
 def parse_block_configuration(args):
     dom = args[0]
 
@@ -2757,6 +2827,64 @@ def xm_scsi_attach(args):
             scsi.append(['backend', args[3]])
         server.xend.domain.device_configure(dom, scsi)
 
+def xm_usb_attach(args):
+    xenapi_unsupported()
+    arg_check(args, 'usb-attach', 4)
+    dom = args[0]
+    dev = args[1]
+    port = args[2]
+    bus = args[3]
+
+    dev_exist = 0
+    num_ports = 0
+    devs = server.xend.domain.getDeviceSxprs(dom, 'vusb')
+    for x in devs:
+        if int(x[0]) == int(dev):
+            dev_exist = 1
+            num_ports = sxp.child_value(x[1], 'num-ports')
+
+    if dev_exist == 0:
+        print "Cannot find device '%s' in domain '%s'" % (dev,dom)
+        return False
+
+    if int(port) < 1 or int(port) > int(num_ports):
+        print "Invalid Port Number '%s'" % port
+        return False
+
+    bus_match = re.match(r"(^(?P<bus>[0-9]{1,2})[-,])" + \
+                         r"(?P<root_port>[0-9]{1,2})" + \
+                         r"(?P<port>([\.,]{1}[0-9]{1,2}){0,5})$", bus)
+    if bus_match is None:
+        print "Invalid Busid '%s'" % bus
+        return False
+
+    if vusb_util.bus_is_assigned(bus):
+        print "Cannot assign already attached bus '%s', detach first." % bus
+        return False
+
+    prev_bus = vusb_util.get_assigned_bus(domain_name_to_domid(dom), dev, port)
+    if not prev_bus == "": 
+        print "Cannot override already attached port '%s', detach first." % 
port
+        return False
+
+    usb = ['vusb', ['port', [port, str(bus)]]]
+    server.xend.domain.device_configure(dom, usb, dev)
+
+def xm_usb_hc_create(args):
+    xenapi_unsupported()
+    arg_check(args, 'usb-hc-create', 3)
+    dom = args[0]
+    ver = args[1]
+    num = args[2]
+    vusb_config = ['vusb']
+    vusb_config.append(['usb-ver', str(ver)])
+    vusb_config.append(['num-ports', str(num)])
+    port_config = ['port']
+    for i in range(1, int(num) + 1):
+        port_config.append(['%i' % i, ""])
+    vusb_config.append(port_config)
+    server.xend.domain.device_create(dom, vusb_config)
+
 def detach(args, deviceClass):
     rm_cfg = True
     dom = args[0]
@@ -2941,6 +3069,22 @@ def xm_scsi_detach(args):
 
     else:
         server.xend.domain.device_configure(dom, scsi)
+
+def xm_usb_detach(args):
+    xenapi_unsupported()
+    arg_check(args, 'usb-detach', 3)
+    dom = args[0]
+    dev = args[1]
+    port = args[2]
+    usb = ['vusb', ['port', [port, '']]]
+    server.xend.domain.device_configure(dom, usb, dev)
+
+def xm_usb_hc_destroy(args):
+    xenapi_unsupported()
+    arg_check(args, 'usb-hc-destroy', 2)
+    dom = args[0]
+    dev = args[1]
+    server.xend.domain.destroyDevice(dom, 'vusb', dev)
 
 def xm_vnet_list(args):
     xenapi_unsupported()
@@ -3372,6 +3516,13 @@ commands = {
     "scsi-attach": xm_scsi_attach,
     "scsi-detach": xm_scsi_detach,
     "scsi-list": xm_scsi_list,
+    # vusb
+    "usb-attach": xm_usb_attach,
+    "usb-detach": xm_usb_detach,
+    "usb-list": xm_usb_list,
+    "usb-list-assignable-devices": xm_usb_list_assignable_devices,
+    "usb-hc-create": xm_usb_hc_create,
+    "usb-hc-destroy": xm_usb_hc_destroy,
     # tmem
     "tmem-thaw": xm_tmem_thaw,
     "tmem-freeze": xm_tmem_freeze,

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] PVUSB: xm/xend support, Xen patchbot-unstable <=