[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.