Index: /trunk/include/VBox/settings.h
===================================================================
--- /trunk/include/VBox/settings.h	(revision 47400)
+++ /trunk/include/VBox/settings.h	(revision 47401)
@@ -447,12 +447,23 @@
 {
     USBController()
-        : fEnabled(false),
-          fEnabledEHCI(false)
+        : enmType(USBControllerType_Null)
     {}
 
     bool operator==(const USBController &u) const;
 
-    bool                    fEnabled;
-    bool                    fEnabledEHCI;
+    com::Utf8Str            strName;
+    USBControllerType_T     enmType;
+};
+typedef std::list<USBController> USBControllerList;
+
+struct USB
+{
+    USB() {}
+
+    bool operator==(const USB &u) const;
+
+    /** List of USB controllers present. */
+    USBControllerList       llUSBControllers;
+    /** List of USB device filters. */
     USBDeviceFiltersList    llDeviceFilters;
 };
@@ -876,5 +887,5 @@
 
     BIOSSettings        biosSettings;
-    USBController       usbController;
+    USB                 usbSettings;
     NetworkAdaptersList llNetworkAdapters;
     SerialPortsList     llSerialPorts;
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp	(revision 47400)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp	(revision 47401)
@@ -1749,25 +1749,41 @@
      * USB.
      */
-    ComPtr<IUSBController> USBCtl;
-    rc = machine->COMGETTER(USBController)(USBCtl.asOutParam());
+    SafeIfaceArray<IUSBController> USBCtlColl;
+    rc = machine->COMGETTER(USBControllers)(ComSafeArrayAsOutParam(USBCtlColl));
     if (SUCCEEDED(rc))
     {
-        BOOL fEnabled;
-        BOOL fEHCIEnabled;
-        rc = USBCtl->COMGETTER(Enabled)(&fEnabled);
-        if (FAILED(rc))
-            fEnabled = false;
+        bool fOhciEnabled = false;
+        bool fEhciEnabled = false;
+
+        for (unsigned i = 0; i < USBCtlColl.size(); i++)
+        {
+            USBControllerType_T enmType;
+
+            rc = USBCtlColl[i]->COMGETTER(Type)(&enmType);
+            if (SUCCEEDED(rc))
+            {
+                switch (enmType)
+                {
+                    case USBControllerType_OHCI:
+                        fOhciEnabled = true;
+                        break;
+                    case USBControllerType_EHCI:
+                        fEhciEnabled = true;
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
         if (details == VMINFO_MACHINEREADABLE)
-            RTPrintf("usb=\"%s\"\n", fEnabled ? "on" : "off");
+            RTPrintf("usb=\"%s\"\n", fOhciEnabled ? "on" : "off");
         else
-            RTPrintf("USB:             %s\n", fEnabled ? "enabled" : "disabled");
-
-        rc = USBCtl->COMGETTER(EnabledEHCI)(&fEHCIEnabled);
-        if (FAILED(rc))
-            fEHCIEnabled = false;
+            RTPrintf("USB:             %s\n", fOhciEnabled ? "enabled" : "disabled");
+
         if (details == VMINFO_MACHINEREADABLE)
-            RTPrintf("ehci=\"%s\"\n", fEHCIEnabled ? "on" : "off");
+            RTPrintf("ehci=\"%s\"\n", fEhciEnabled ? "on" : "off");
         else
-            RTPrintf("EHCI:            %s\n", fEHCIEnabled ? "enabled" : "disabled");
+            RTPrintf("EHCI:            %s\n", fEhciEnabled ? "enabled" : "disabled");
     }
 
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 47400)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 47401)
@@ -1772,14 +1772,12 @@
                 {
                     /* Make sure the OHCI controller is enabled. */
-                    ComPtr<IUSBController> UsbCtl;
-                    rc = machine->COMGETTER(USBController)(UsbCtl.asOutParam());
-                    if (SUCCEEDED(rc))
+                    ULONG cOhciCtrls = 0;
+                    rc = machine->COMGETTER(USBControllerCountByType)(USBControllerType_OHCI, &cOhciCtrls);
+                    if (   SUCCEEDED(rc)
+                        && !cOhciCtrls)
                     {
-                        BOOL fEnabled;
-                        rc = UsbCtl->COMGETTER(Enabled)(&fEnabled);
-                        if (FAILED(rc))
-                            fEnabled = false;
-                        if (!fEnabled)
-                            CHECK_ERROR(UsbCtl, COMSETTER(Enabled)(true));
+                        ComPtr<IUSBController> UsbCtl;
+                        CHECK_ERROR(machine, AddUSBController(Bstr("OHCI").raw(), USBControllerType_OHCI,
+                                                              UsbCtl.asOutParam()));
                     }
                 }
@@ -1808,14 +1806,12 @@
                 {
                     /* Make sure the OHCI controller is enabled. */
-                    ComPtr<IUSBController> UsbCtl;
-                    rc = machine->COMGETTER(USBController)(UsbCtl.asOutParam());
-                    if (SUCCEEDED(rc))
+                    ULONG cOhciCtrls = 0;
+                    rc = machine->COMGETTER(USBControllerCountByType)(USBControllerType_OHCI, &cOhciCtrls);
+                    if (   SUCCEEDED(rc)
+                        && !cOhciCtrls)
                     {
-                        BOOL fEnabled;
-                        rc = UsbCtl->COMGETTER(Enabled)(&fEnabled);
-                        if (FAILED(rc))
-                            fEnabled = false;
-                        if (!fEnabled)
-                            CHECK_ERROR(UsbCtl, COMSETTER(Enabled)(true));
+                        ComPtr<IUSBController> UsbCtl;
+                        CHECK_ERROR(machine, AddUSBController(Bstr("OHCI").raw(), USBControllerType_OHCI,
+                                                              UsbCtl.asOutParam()));
                     }
                 }
@@ -2311,8 +2307,17 @@
             case MODIFYVM_USBEHCI:
             {
-                ComPtr<IUSBController> UsbCtl;
-                CHECK_ERROR(machine, COMGETTER(USBController)(UsbCtl.asOutParam()));
+                ULONG cEhciCtrls = 0;
+                rc = machine->COMGETTER(USBControllerCountByType)(USBControllerType_EHCI, &cEhciCtrls);
                 if (SUCCEEDED(rc))
-                    CHECK_ERROR(UsbCtl, COMSETTER(EnabledEHCI)(ValueUnion.f));
+                {
+                    if (!cEhciCtrls && ValueUnion.f)
+                    {
+                        ComPtr<IUSBController> UsbCtl;
+                        CHECK_ERROR(machine, AddUSBController(Bstr("EHCI").raw(), USBControllerType_EHCI,
+                                                              UsbCtl.asOutParam()));
+                    }
+                    else if (cEhciCtrls && !ValueUnion.f)
+                        CHECK_ERROR(machine, RemoveUSBController(Bstr("EHCI").raw()));
+                }
                 break;
             }
@@ -2320,8 +2325,17 @@
             case MODIFYVM_USB:
             {
-                ComPtr<IUSBController> UsbCtl;
-                CHECK_ERROR(machine, COMGETTER(USBController)(UsbCtl.asOutParam()));
+                ULONG cOhciCtrls = 0;
+                rc = machine->COMGETTER(USBControllerCountByType)(USBControllerType_OHCI, &cOhciCtrls);
                 if (SUCCEEDED(rc))
-                    CHECK_ERROR(UsbCtl, COMSETTER(Enabled)(ValueUnion.f));
+                {
+                    if (!cOhciCtrls && ValueUnion.f)
+                    {
+                        ComPtr<IUSBController> UsbCtl;
+                        CHECK_ERROR(machine, AddUSBController(Bstr("OHCI").raw(), USBControllerType_OHCI,
+                                                              UsbCtl.asOutParam()));
+                    }
+                    else if (cOhciCtrls && !ValueUnion.f)
+                        CHECK_ERROR(machine, RemoveUSBController(Bstr("OHCI").raw()));
+                }
                 break;
             }
Index: /trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp	(revision 47400)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp	(revision 47401)
@@ -1512,13 +1512,13 @@
         QString item;
 
-        CUSBController ctl = aMachine.GetUSBController();
         CUSBDeviceFilters flts = aMachine.GetUSBDeviceFilters();
-        if (   !ctl.isNull()
-            && !flts.isNull()
-            && ctl.GetProxyAvailable())
+        if (   !flts.isNull()
+            && aMachine.GetUSBProxyAvailable())
         {
             /* the USB controller may be unavailable (i.e. in VirtualBox OSE) */
 
-            if (ctl.GetEnabled())
+            ULONG cOhciCtls = aMachine.GetUSBControllerCountByType(KUSBControllerType_OHCI);
+
+            if (cOhciCtls)
             {
                 CUSBDeviceFilterVector coll = flts.GetDeviceFilters();
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIIndicatorsPool.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIIndicatorsPool.cpp	(revision 47400)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIIndicatorsPool.cpp	(revision 47401)
@@ -39,4 +39,5 @@
 #include "CNetworkAdapter.h"
 #include "CUSBController.h"
+#include "CUSBDeviceFilters.h"
 #include "CUSBDevice.h"
 #include "CSharedFolder.h"
@@ -388,7 +389,15 @@
         QString strFullData;
 
-        const CUSBController &usbctl = machine.GetUSBController();
-        setState(!usbctl.isNull() && usbctl.GetEnabled() && usbctl.GetProxyAvailable() ? KDeviceActivity_Idle : KDeviceActivity_Null);
-        if (!usbctl.isNull() && usbctl.GetEnabled())
+
+        /*
+         * Check whether there is at least one OHCI USB controllers with
+         * an available proxy.
+         */
+        const CUSBDeviceFilters &filters = machine.GetUSBDeviceFilters();
+        ULONG cOhciCtls = machine.GetUSBControllerCountByType(KUSBControllerType_OHCI);
+        bool fUSBEnabled = !filters.isNull() && cOhciCtls && machine.GetUSBProxyAvailable();
+
+        setState(fUSBEnabled ? KDeviceActivity_Idle : KDeviceActivity_Null);
+        if (fUSBEnabled)
         {
             const CConsole &console = m_session.GetConsole();
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp	(revision 47400)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp	(revision 47401)
@@ -68,4 +68,5 @@
 #include "CVRDEServer.h"
 #include "CUSBController.h"
+#include "CUSBDeviceFilters.h"
 #include "CSnapshot.h"
 
@@ -1296,9 +1297,14 @@
     /* USB stuff: */
     {
-        /* Get USB controller: */
-        const CUSBController &usbController = machine.GetUSBController();
-        bool fUSBControllerEnabled = !usbController.isNull() && usbController.GetEnabled() && usbController.GetProxyAvailable();
+        /*
+         * Check whether there is at least one OHCI USB controllers with
+         * an available proxy.
+         */
+        const CUSBDeviceFilters &filters = machine.GetUSBDeviceFilters();
+        ULONG cOhciCtls = machine.GetUSBControllerCountByType(KUSBControllerType_OHCI);
+        bool fUSBEnabled = !filters.isNull() && cOhciCtls && machine.GetUSBProxyAvailable();
+
         /* Show/Hide USB menu depending on controller availability, activity and USB-proxy presence: */
-        gActionPool->action(UIActionIndexRuntime_Menu_USBDevices)->setVisible(fUSBControllerEnabled);
+        gActionPool->action(UIActionIndexRuntime_Menu_USBDevices)->setVisible(fUSBEnabled);
     }
 }
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp	(revision 47400)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp	(revision 47401)
@@ -47,4 +47,5 @@
 #include "CMediumAttachment.h"
 #include "CUSBController.h"
+#include "CUSBDeviceFilters.h"
 
 UIMachineWindowNormal::UIMachineWindowNormal(UIMachineLogic *pMachineLogic, ulong uScreenId)
@@ -488,8 +489,9 @@
         if (indicatorsPool()->indicator(IndicatorType_USB))
         {
-            const CUSBController &usbController = m.GetUSBController();
-            if (    usbController.isNull()
-                || !usbController.GetEnabled()
-                || !usbController.GetProxyAvailable())
+            const CUSBDeviceFilters &filters = m.GetUSBDeviceFilters();
+            ULONG cOhciCtls = m.GetUSBControllerCountByType(KUSBControllerType_OHCI);
+            bool fUSBEnabled = !filters.isNull() && cOhciCtls && m.GetUSBProxyAvailable();
+
+            if (!fUSBEnabled)
             {
                 /* Hide USB menu: */
@@ -499,6 +501,5 @@
             {
                 /* Toggle USB LED: */
-                indicatorsPool()->indicator(IndicatorType_USB)->setState(
-                    usbController.GetEnabled() ? KDeviceActivity_Idle : KDeviceActivity_Null);
+                indicatorsPool()->indicator(IndicatorType_USB)->setState(KDeviceActivity_Idle);
             }
         }
Index: /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElements.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElements.cpp	(revision 47400)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElements.cpp	(revision 47401)
@@ -889,9 +889,9 @@
         {
             /* Iterate over all the USB filters: */
-            const CUSBController &ctl = machine().GetUSBController();
-            if (!ctl.isNull() && ctl.GetProxyAvailable())
+            const CUSBDeviceFilters &filters = machine().GetUSBDeviceFilters();
+            if (!filters.isNull() && machine().GetUSBProxyAvailable())
             {
                 const CUSBDeviceFilters &flts = machine().GetUSBDeviceFilters();
-                if (!flts.isNull() && ctl.GetEnabled())
+                if (!flts.isNull() && machine().GetUSBControllerCountByType(KUSBControllerType_OHCI))
                 {
                     const CUSBDeviceFilterVector &coll = flts.GetDeviceFilters();
Index: /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsSet.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsSet.cpp	(revision 47400)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsSet.cpp	(revision 47401)
@@ -29,4 +29,5 @@
 /* COM includes: */
 #include "CUSBController.h"
+#include "CUSBDeviceFilters.h"
 
 UIGDetailsSet::UIGDetailsSet(UIGDetailsItem *pParent)
@@ -96,6 +97,6 @@
 
     /* Fetch USB controller restrictions: */
-    const CUSBController &ctl = m_machine.GetUSBController();
-    if (ctl.isNull() || !ctl.GetProxyAvailable())
+    const CUSBDeviceFilters &filters = m_machine.GetUSBDeviceFilters();
+    if (filters.isNull() || !m_machine.GetUSBProxyAvailable())
     {
         QString strElementTypeOpened = gpConverter->toInternalString(DetailsElementType_USB);
Index: /trunk/src/VBox/Frontends/VirtualBox/src/settings/UISettingsDialogSpecific.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/settings/UISettingsDialogSpecific.cpp	(revision 47400)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/settings/UISettingsDialogSpecific.cpp	(revision 47401)
@@ -858,7 +858,7 @@
         if (pSystemPage && pSystemPage->isHIDEnabled())
         {
-            CUSBController controller = m_machine.GetUSBController();
-            if (!controller.isNull())
-                controller.SetEnabled(true);
+            ULONG cOhciCtls = m_machine.GetUSBControllerCountByType(KUSBControllerType_OHCI);
+            if (!cOhciCtls)
+                m_machine.AddUSBController("OHCI", KUSBControllerType_OHCI);
         }
 
@@ -1124,12 +1124,14 @@
             if (!isPageAvailable(MachineSettingsPageType_Ports))
                 return false;
+            /* Check if USB is implemented: */
+            if (!m_machine.GetUSBProxyAvailable())
+                return false;
             /* Get the USB controller object: */
-            CUSBController controller = m_machine.GetUSBController();
+            CUSBControllerVector controllerColl = m_machine.GetUSBControllers();
             /* Show the machine error message if any: */
-            if (!m_machine.isReallyOk() && !controller.isNull() && controller.GetEnabled())
+            if (   !m_machine.isReallyOk()
+                && controllerColl.size() > 0
+                && m_machine.GetUSBControllerCountByType(KUSBControllerType_OHCI))
                 msgCenter().warnAboutUnaccessibleUSB(m_machine, parentWidget());
-            /* Check if USB is implemented: */
-            if (controller.isNull() || !controller.GetProxyAvailable())
-                return false;
             break;
         }
Index: /trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsUSB.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsUSB.cpp	(revision 47400)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsUSB.cpp	(revision 47401)
@@ -294,40 +294,36 @@
 
             /* Check if controller is valid: */
-            const CUSBController &controller = m_machine.GetUSBController();
-            if (!controller.isNull())
+            const CUSBDeviceFilters &filters = m_machine.GetUSBDeviceFilters();
+            if (!filters.isNull())
             {
                 /* Gather USB values: */
-                usbData.m_fUSBEnabled = controller.GetEnabled();
-                usbData.m_fEHCIEnabled = controller.GetEnabledEHCI();
+                usbData.m_fUSBEnabled = m_machine.GetUSBControllerCountByType(KUSBControllerType_OHCI) > 0;
+                usbData.m_fEHCIEnabled = m_machine.GetUSBControllerCountByType(KUSBControllerType_EHCI) > 0;
 
                 /* For each USB filter: */
-                const CUSBDeviceFilters &filters = m_machine.GetUSBDeviceFilters();
-                if (!filters.isNull())
+                const CUSBDeviceFilterVector &coll = filters.GetDeviceFilters();
+                for (int iFilterIndex = 0; iFilterIndex < coll.size(); ++iFilterIndex)
                 {
-                    const CUSBDeviceFilterVector &coll = filters.GetDeviceFilters();
-                    for (int iFilterIndex = 0; iFilterIndex < coll.size(); ++iFilterIndex)
+                    /* Prepare USB filter data: */
+                    UIDataSettingsMachineUSBFilter usbFilterData;
+
+                    /* Check if filter is valid: */
+                    const CUSBDeviceFilter &filter = coll[iFilterIndex];
+                    if (!filter.isNull())
                     {
-                        /* Prepare USB filter data: */
-                        UIDataSettingsMachineUSBFilter usbFilterData;
-
-                        /* Check if filter is valid: */
-                        const CUSBDeviceFilter &filter = coll[iFilterIndex];
-                        if (!filter.isNull())
-                        {
-                            usbFilterData.m_fActive = filter.GetActive();
-                            usbFilterData.m_strName = filter.GetName();
-                            usbFilterData.m_strVendorId = filter.GetVendorId();
-                            usbFilterData.m_strProductId = filter.GetProductId();
-                            usbFilterData.m_strRevision = filter.GetRevision();
-                            usbFilterData.m_strManufacturer = filter.GetManufacturer();
-                            usbFilterData.m_strProduct = filter.GetProduct();
-                            usbFilterData.m_strSerialNumber = filter.GetSerialNumber();
-                            usbFilterData.m_strPort = filter.GetPort();
-                            usbFilterData.m_strRemote = filter.GetRemote();
-                        }
-
-                        /* Cache USB filter data: */
-                        m_cache.child(iFilterIndex).cacheInitialData(usbFilterData);
+                        usbFilterData.m_fActive = filter.GetActive();
+                        usbFilterData.m_strName = filter.GetName();
+                        usbFilterData.m_strVendorId = filter.GetVendorId();
+                        usbFilterData.m_strProductId = filter.GetProductId();
+                        usbFilterData.m_strRevision = filter.GetRevision();
+                        usbFilterData.m_strManufacturer = filter.GetManufacturer();
+                        usbFilterData.m_strProduct = filter.GetProduct();
+                        usbFilterData.m_strSerialNumber = filter.GetSerialNumber();
+                        usbFilterData.m_strPort = filter.GetPort();
+                        usbFilterData.m_strRemote = filter.GetRemote();
                     }
+
+                    /* Cache USB filter data: */
+                    m_cache.child(iFilterIndex).cacheInitialData(usbFilterData);
                 }
             }
@@ -491,19 +487,28 @@
             {
                 /* Check if controller is valid: */
-                CUSBController controller = m_machine.GetUSBController();
-                if (!controller.isNull())
+                CUSBDeviceFilters filters = m_machine.GetUSBDeviceFilters();
+                if (!filters.isNull())
                 {
                     /* Get USB data from cache: */
-                    CUSBDeviceFilters filters = m_machine.GetUSBDeviceFilters();
+
                     const UIDataSettingsMachineUSB &usbData = m_cache.data();
                     /* Store USB data: */
                     if (isMachineOffline())
                     {
-                        controller.SetEnabled(usbData.m_fUSBEnabled);
-                        controller.SetEnabledEHCI(usbData.m_fEHCIEnabled);
+                        ULONG cOhciCtls = m_machine.GetUSBControllerCountByType(KUSBControllerType_OHCI);
+                        ULONG cEhciCtls = m_machine.GetUSBControllerCountByType(KUSBControllerType_EHCI);
+
+                        if (!cOhciCtls && usbData.m_fUSBEnabled)
+                            m_machine.AddUSBController("OHCI", KUSBControllerType_OHCI);
+                        else if (cOhciCtls && !usbData.m_fUSBEnabled)
+                            m_machine.RemoveUSBController("OHCI");
+
+                        if (!cEhciCtls && usbData.m_fEHCIEnabled)
+                            m_machine.AddUSBController("EHCI", KUSBControllerType_EHCI);
+                        else if (cEhciCtls && !usbData.m_fEHCIEnabled)
+                            m_machine.RemoveUSBController("EHCI");
                     }
                     /* Store USB filters data: */
-                    if (   isMachineInValidMode()
-                        && !filters.isNull())
+                    if (isMachineInValidMode())
                     {
                         /* For each USB filter data set: */
Index: /trunk/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVM.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVM.cpp	(revision 47400)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVM.cpp	(revision 47401)
@@ -30,4 +30,5 @@
 #include "CAudioAdapter.h"
 #include "CUSBController.h"
+#include "CUSBDeviceFilters.h"
 #include "CExtPackManager.h"
 #include "CStorageController.h"
@@ -94,8 +95,10 @@
 
     /* Enable the OHCI and EHCI controller by default for new VMs. (new in 2.2): */
-    CUSBController usbController = m_machine.GetUSBController();
-    if (!usbController.isNull() && type.GetRecommendedUSB() && usbController.GetProxyAvailable())
-    {
-        usbController.SetEnabled(true);
+    CUSBDeviceFilters usbDeviceFilters = m_machine.GetUSBDeviceFilters();
+    bool fOhciEnabled = false;
+    if (!usbDeviceFilters.isNull() && type.GetRecommendedUSB() && m_machine.GetUSBProxyAvailable())
+    {
+        m_machine.AddUSBController("OHCI", KUSBControllerType_OHCI);
+        fOhciEnabled = true;
         /* USB 2.0 is only available if the proper ExtPack is installed.
          * Note. Configuring EHCI here and providing messages about
@@ -105,5 +108,5 @@
         CExtPackManager manager = vboxGlobal().virtualBox().GetExtensionPackManager();
         if (manager.IsExtPackUsable(GUI_ExtPackName))
-            usbController.SetEnabledEHCI(true);
+            m_machine.AddUSBController("EHCI", KUSBControllerType_EHCI);
     }
 
@@ -162,6 +165,6 @@
         m_machine.SetKeyboardHIDType(KKeyboardHIDType_USBKeyboard);
         m_machine.SetPointingHIDType(KPointingHIDType_USBMouse);
-        if (!usbController.isNull())
-            usbController.SetEnabled(true);
+        if (!fOhciEnabled && !usbDeviceFilters.isNull())
+            m_machine.AddUSBController("OHCI", KUSBControllerType_OHCI);
     }
 
@@ -169,6 +172,6 @@
     {
         m_machine.SetPointingHIDType(KPointingHIDType_USBTablet);
-        if (!usbController.isNull())
-            usbController.SetEnabled(true);
+        if (!fOhciEnabled && !usbDeviceFilters.isNull())
+            m_machine.AddUSBController("OHCI", KUSBControllerType_OHCI);
     }
 
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 47400)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 47401)
@@ -545,5 +545,5 @@
       <desc>Settings version "1.14", written by VirtualBox 4.3.x.</desc>
       <!--
-          Machine changes: default frontend.
+          Machine changes: default frontend, USB rework.
       -->
     </const>
@@ -4127,5 +4127,5 @@
   <interface
     name="IMachine" extends="$unknown"
-    uuid="00daa773-1d35-40ae-ac06-336aa64959ef"
+    uuid="b6057c6f-2176-4820-a8d6-cb6687ed1583"
     wsmap="managed"
     >
@@ -4524,7 +4524,7 @@
     </attribute>
 
-    <attribute name="USBController" type="IUSBController" readonly="yes">
-      <desc>
-        Associated USB controller object.
+    <attribute name="USBControllers" type="IUSBController" readonly="yes" safearray="yes">
+      <desc>
+        Array of USB controllers attached to this machine.
 
         <note>
@@ -4909,4 +4909,10 @@
     </attribute>
 
+    <attribute name="USBProxyAvailable" type="boolean" readonly="yes">
+      <desc>
+        Returns whether there is an USB proxy available.
+      </desc>
+    </attribute>
+
     <method name="lockMachine">
       <desc>
@@ -5947,4 +5953,52 @@
       <param name="name" type="wstring" dir="in"/>
       <param name="bootable" type="boolean" dir="in"/>
+    </method>
+
+    <method name="addUSBController">
+      <desc>
+        Adds a new USB controller to the machine and returns it as an instance of
+        <link to="IUSBController" />.
+
+        <result name="VBOX_E_OBJECT_IN_USE">
+          A USB controller with given type exists already.
+        </result>
+        <result name="E_INVALIDARG">
+          Invalid @a controllerType.
+        </result>
+      </desc>
+      <param name="name" type="wstring" dir="in"/>
+      <param name="type" type="USBControllerType" dir="in"/>
+      <param name="controller" type="IUSBController" dir="return"/>
+    </method>
+
+    <method name="removeUSBController">
+      <desc>
+        Removes a USB controller from the machine.
+
+        <result name="VBOX_E_OBJECT_NOT_FOUND">
+          A USB controller with given type doesn't exist.
+        </result>
+      </desc>
+      <param name="name" type="wstring" dir="in"/>
+    </method>
+
+    <method name="getUSBControllerByName" const="yes">
+      <desc>
+        Returns a USB controller with the given type.
+
+        <result name="VBOX_E_OBJECT_NOT_FOUND">
+          A USB controller with given name doesn't exist.
+        </result>
+      </desc>
+      <param name="name" type="wstring" dir="in"/>
+      <param name="controller" type="IUSBController" dir="return"/>
+    </method>
+
+    <method name="getUSBControllerCountByType" const="yes">
+      <desc>
+        Returns the number of USB controllers of the given type attached to the VM.
+      </desc>
+      <param name="type" type="USBControllerType" dir="in"/>
+      <param name="controllers" type="unsigned long" dir="return"/>
     </method>
 
@@ -8654,5 +8708,5 @@
     name="ISystemProperties"
     extends="$unknown"
-    uuid="55699910-cc50-11e2-8b8b-0800200c9a66"
+    uuid="856be1bc-0525-46b1-a27a-fe17d9a4939f"
     wsmap="managed"
     >
@@ -9059,4 +9113,23 @@
       <param name="enabled" type="boolean" dir="return">
         <desc>Returned flag indicating the default value</desc>
+      </param>
+    </method>
+
+    <method name="getMaxInstancesOfUSBControllerType">
+      <desc>Returns the maximum number of USB controller instances which
+        can be configured for each VM. This corresponds to the number of
+        USB controllers one can have. Value may depend on chipset type
+        used.</desc>
+
+      <param name="chipset" type="ChipsetType" dir="in">
+        <desc>The chipset type to get the value for.</desc>
+      </param>
+
+      <param name="type" type="USBControllerType" dir="in">
+        <desc>The USB controller type to get the value for.</desc>
+      </param>
+
+      <param name="maxInstances" type="unsigned long" dir="return">
+        <desc>The maximum number of instances for the given USB controller type.</desc>
       </param>
     </method>
@@ -16455,30 +16528,36 @@
   -->
 
+  <enum
+    name="USBControllerType"
+    uuid="8fdd1c6a-5412-41da-ab07-7baed7d6e18e"
+    >
+    <desc>
+      The USB controller type. <link to="IUSBController::type" />.
+    </desc>
+    <const name="Null"      value="0">
+      <desc>@c null value. Never used by the API.</desc>
+    </const>
+    <const name="OHCI"      value="1"/>
+    <const name="EHCI"      value="2"/>
+    <const name="Last"      value="3">
+      <desc>Last element (invalid). Used for parameter checks.</desc>
+    </const>
+  </enum>
+
   <interface
     name="IUSBController" extends="$unknown"
-    uuid="f12e6dda-2bad-40c4-8f2e-2d08fe8b74d4"
+    uuid="d2745291-65f7-4d75-9556-38047d802319"
     wsmap="managed"
     >
-    <attribute name="enabled" type="boolean">
-      <desc>
-        Flag whether the USB controller is present in the
-        guest system. If disabled, the virtual guest hardware will
-        not contain any USB controller. Can only be changed when
-        the VM is powered off.
-      </desc>
-    </attribute>
-
-    <attribute name="enabledEHCI" type="boolean">
-      <desc>
-        Flag whether the USB EHCI controller is present in the
-        guest system. If disabled, the virtual guest hardware will
-        not contain a USB EHCI controller. Can only be changed when
-        the VM is powered off.
-      </desc>
-    </attribute>
-
-    <attribute name="proxyAvailable" type="boolean" readonly="yes">
-      <desc>
-        Flag whether there is an USB proxy available.
+
+    <attribute name="name" type="wstring" readonly="yes">
+      <desc>
+        The USB Controller name.
+      </desc>
+    </attribute>
+
+    <attribute name="type" type="USBControllerType" readonly="yes">
+      <desc>
+        The USB Controller type.
       </desc>
     </attribute>
@@ -20899,5 +20978,5 @@
     <desc>
       Notification when a property of the virtual
-      <link to="IMachine::USBController">USB controller</link> changes.
+      <link to="IMachine::USBControllers">USB controllers</link> changes.
       Interested callees should use IUSBController methods and attributes to
       find out what has changed.
Index: /trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MachineImpl.h	(revision 47400)
+++ /trunk/src/VBox/Main/include/MachineImpl.h	(revision 47401)
@@ -457,5 +457,5 @@
     STDMETHOD(COMGETTER(VRDEServer))(IVRDEServer **vrdeServer);
     STDMETHOD(COMGETTER(AudioAdapter))(IAudioAdapter **audioAdapter);
-    STDMETHOD(COMGETTER(USBController))(IUSBController * *aUSBController);
+    STDMETHOD(COMGETTER(USBControllers))(ComSafeArrayOut(IUSBController *, aUSBControllers));
     STDMETHOD(COMGETTER(USBDeviceFilters))(IUSBDeviceFilters * *aUSBDeviceFilters);
     STDMETHOD(COMGETTER(SettingsFilePath))(BSTR *aFilePath);
@@ -529,4 +529,5 @@
     STDMETHOD(COMGETTER(Icon))(ComSafeArrayOut(BYTE, aIcon));
     STDMETHOD(COMSETTER(Icon))(ComSafeArrayIn(BYTE, aIcon));
+    STDMETHOD(COMGETTER(USBProxyAvailable))(BOOL *aAvailable);
 
     // IMachine methods
@@ -593,4 +594,8 @@
     STDMETHOD(GetStorageControllerByInstance(ULONG aInstance, IStorageController **storageController));
     STDMETHOD(SetStorageControllerBootable)(IN_BSTR aName, BOOL fBootable);
+    STDMETHOD(AddUSBController)(IN_BSTR aName, StorageBus_T aConnectionType, IUSBController **controller);
+    STDMETHOD(RemoveUSBController(IN_BSTR aName));
+    STDMETHOD(GetUSBControllerByName(IN_BSTR aName, IUSBController **usbController));
+    STDMETHOD(GetUSBControllerCountByType(USBControllerType_T aType, ULONG *aControllers));
     STDMETHOD(QuerySavedGuestScreenInfo)(ULONG uScreenId, ULONG *puOriginX, ULONG *puOriginY, ULONG *puWidth, ULONG *puHeight, BOOL *pfEnabled);
     STDMETHOD(QuerySavedThumbnailSize)(ULONG aScreenId, ULONG *aSize, ULONG *aWidth, ULONG *aHeight);
@@ -886,4 +891,10 @@
     HRESULT getMediumAttachmentsOfController(CBSTR aName,
                                              MediaData::AttachmentList &aAttachments);
+
+    HRESULT getUSBControllerByName(const Utf8Str &aName,
+                                   ComObjPtr<USBController> &aUSBController,
+                                   bool aSetError = false);
+
+    ULONG   getUSBControllerCountByType(USBControllerType_T enmType);
 
     enum
@@ -998,13 +1009,16 @@
     const ComObjPtr<ParallelPort>      mParallelPorts[SchemaDefs::ParallelPortCount];
     const ComObjPtr<AudioAdapter>      mAudioAdapter;
-    const ComObjPtr<USBController>     mUSBController;
     const ComObjPtr<USBDeviceFilters>  mUSBDeviceFilters;
     const ComObjPtr<BIOSSettings>      mBIOSSettings;
+    const ComObjPtr<BandwidthControl>  mBandwidthControl;
+
     typedef std::vector<ComObjPtr<NetworkAdapter> > NetworkAdapterVector;
-    NetworkAdapterVector            mNetworkAdapters;
-    const ComObjPtr<BandwidthControl> mBandwidthControl;
+    NetworkAdapterVector               mNetworkAdapters;
 
     typedef std::list<ComObjPtr<StorageController> > StorageControllerList;
-    Backupable<StorageControllerList> mStorageControllers;
+    Backupable<StorageControllerList>  mStorageControllers;
+
+    typedef std::list<ComObjPtr<USBController> > USBControllerList;
+    Backupable<USBControllerList>      mUSBControllers;
 
     uint64_t                        uRegistryNeedsSaving;
Index: /trunk/src/VBox/Main/include/SystemPropertiesImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/SystemPropertiesImpl.h	(revision 47400)
+++ /trunk/src/VBox/Main/include/SystemPropertiesImpl.h	(revision 47401)
@@ -109,4 +109,5 @@
     STDMETHOD(GetDeviceTypesForStorageBus)(StorageBus_T aBus, ComSafeArrayOut(DeviceType_T, aDeviceTypes));
     STDMETHOD(GetDefaultIoCacheSettingForStorageController)(StorageControllerType_T aControllerType, BOOL *aEnabled);
+    STDMETHOD(GetMaxInstancesOfUSBControllerType)(ChipsetType_T aChipset, USBControllerType_T aType, ULONG *aMaxInstances);
 
     // public methods only for internal purposes
Index: /trunk/src/VBox/Main/include/USBControllerImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/USBControllerImpl.h	(revision 47400)
+++ /trunk/src/VBox/Main/include/USBControllerImpl.h	(revision 47401)
@@ -52,25 +52,25 @@
 
     // public initializer/uninitializer for internal purposes only
-    HRESULT init(Machine *aParent);
-    HRESULT init(Machine *aParent, USBController *aThat);
+    HRESULT init(Machine *aParent, const Utf8Str &aName, USBControllerType_T enmType);
+    HRESULT init(Machine *aParent, USBController *aThat, bool fReshare = false);
     HRESULT initCopy(Machine *aParent, USBController *aThat);
     void uninit();
 
     // IUSBController properties
-    STDMETHOD(COMGETTER(Enabled))(BOOL *aEnabled);
-    STDMETHOD(COMSETTER(Enabled))(BOOL aEnabled);
-    STDMETHOD(COMGETTER(EnabledEHCI))(BOOL *aEnabled);
-    STDMETHOD(COMSETTER(EnabledEHCI))(BOOL aEnabled);
-    STDMETHOD(COMGETTER(ProxyAvailable))(BOOL *aEnabled);
+    STDMETHOD(COMGETTER(Name))(BSTR *aName);
+    STDMETHOD(COMGETTER(Type))(USBControllerType_T *enmType);
     STDMETHOD(COMGETTER(USBStandard))(USHORT *aUSBStandard);
 
     // public methods only for internal purposes
 
-    HRESULT loadSettings(const settings::USBController &data);
-    HRESULT saveSettings(settings::USBController &data);
-
     void rollback();
     void commit();
     void copyFrom(USBController *aThat);
+    void unshare();
+
+    const Utf8Str &getName() const;
+    USBControllerType_T getControllerType() const;
+
+    ComObjPtr<USBController> getPeer();
 
 private:
Index: /trunk/src/VBox/Main/include/USBDeviceFiltersImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/USBDeviceFiltersImpl.h	(revision 47400)
+++ /trunk/src/VBox/Main/include/USBDeviceFiltersImpl.h	(revision 47401)
@@ -28,5 +28,5 @@
 namespace settings
 {
-    struct USBController;
+    struct USB;
 }
 
@@ -67,6 +67,6 @@
     // public methods only for internal purposes
 
-    HRESULT loadSettings(const settings::USBController &data);
-    HRESULT saveSettings(settings::USBController &data);
+    HRESULT loadSettings(const settings::USB &data);
+    HRESULT saveSettings(settings::USB &data);
 
     void rollback();
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 47400)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 47401)
@@ -2266,33 +2266,53 @@
 
         /*
-         * The USB Controller.
+         * The USB Controllers.
          */
-        ComPtr<IUSBController> USBCtlPtr;
-        hrc = pMachine->COMGETTER(USBController)(USBCtlPtr.asOutParam());
-        if (USBCtlPtr)
-        {
-            BOOL fOhciEnabled;
-            hrc = USBCtlPtr->COMGETTER(Enabled)(&fOhciEnabled);                             H();
-            if (fOhciEnabled)
-            {
-                InsertConfigNode(pDevices, "usb-ohci", &pDev);
-                InsertConfigNode(pDev,     "0", &pInst);
-                InsertConfigNode(pInst,    "Config", &pCfg);
-                InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
-                hrc = pBusMgr->assignPCIDevice("usb-ohci", pInst);                          H();
-                InsertConfigNode(pInst,    "LUN#0", &pLunL0);
-                InsertConfigString(pLunL0, "Driver",               "VUSBRootHub");
-                InsertConfigNode(pLunL0,   "Config", &pCfg);
-
-                /*
-                 * Attach the status driver.
-                 */
-                attachStatusDriver(pInst, &mapUSBLed[0], 0, 0, NULL, NULL, 0);
-
-                mfVMHasUsbController = true;
+        com::SafeIfaceArray<IUSBController> usbCtrls;
+        hrc = pMachine->COMGETTER(USBControllers)(ComSafeArrayAsOutParam(usbCtrls));        H();
+        bool fOhciPresent = false; /**< Flag whether at least one OHCI controller is presnet. */
+
+        for (size_t i = 0; i < usbCtrls.size(); ++i)
+        {
+            USBControllerType_T enmCtrlType;
+            rc = usbCtrls[i]->COMGETTER(Type)(&enmCtrlType);                                   H();
+            if (enmCtrlType == USBControllerType_OHCI)
+            {
+                fOhciPresent = true;
+                break;
+            }
+        }
+
+        /*
+         * Currently EHCI is only enabled when a OHCI controller is present too.
+         * This might change when XHCI is supported.
+         */
+        if (fOhciPresent)
+            mfVMHasUsbController = true;
+
+        if (mfVMHasUsbController)
+        {
+            for (size_t i = 0; i < usbCtrls.size(); ++i)
+            {
+                USBControllerType_T enmCtrlType;
+                rc = usbCtrls[i]->COMGETTER(Type)(&enmCtrlType);                                   H();
+
+                if (enmCtrlType == USBControllerType_OHCI)
+                {
+                    InsertConfigNode(pDevices, "usb-ohci", &pDev);
+                    InsertConfigNode(pDev,     "0", &pInst);
+                    InsertConfigNode(pInst,    "Config", &pCfg);
+                    InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
+                    hrc = pBusMgr->assignPCIDevice("usb-ohci", pInst);                          H();
+                    InsertConfigNode(pInst,    "LUN#0", &pLunL0);
+                    InsertConfigString(pLunL0, "Driver",               "VUSBRootHub");
+                    InsertConfigNode(pLunL0,   "Config", &pCfg);
+
+                    /*
+                     * Attach the status driver.
+                     */
+                    attachStatusDriver(pInst, &mapUSBLed[0], 0, 0, NULL, NULL, 0);
+                }
 #ifdef VBOX_WITH_EHCI
-                BOOL fEHCIEnabled;
-                hrc = USBCtlPtr->COMGETTER(EnabledEHCI)(&fEHCIEnabled);                     H();
-                if (fEHCIEnabled)
+                else if (enmCtrlType == USBControllerType_EHCI)
                 {
                     /*
@@ -2340,162 +2360,162 @@
                 }
 #endif
-
+            } /* for every USB controller. */
+
+
+            /*
+             * Virtual USB Devices.
+             */
+            PCFGMNODE pUsbDevices = NULL;
+            InsertConfigNode(pRoot, "USB", &pUsbDevices);
+
+#ifdef VBOX_WITH_USB
+            {
                 /*
-                 * Virtual USB Devices.
+                 * Global USB options, currently unused as we'll apply the 2.0 -> 1.1 morphing
+                 * on a per device level now.
                  */
-                PCFGMNODE pUsbDevices = NULL;
-                InsertConfigNode(pRoot, "USB", &pUsbDevices);
-
-#ifdef VBOX_WITH_USB
-                {
-                    /*
-                    * Global USB options, currently unused as we'll apply the 2.0 -> 1.1 morphing
-                    * on a per device level now.
-                    */
-                    InsertConfigNode(pUsbDevices, "USBProxy", &pCfg);
-                    InsertConfigNode(pCfg, "GlobalConfig", &pCfg);
-                    // This globally enables the 2.0 -> 1.1 device morphing of proxied devices to keep windows quiet.
-                    //InsertConfigInteger(pCfg, "Force11Device", true);
-                    // The following breaks stuff, but it makes MSDs work in vista. (I include it here so
-                    // that it's documented somewhere.) Users needing it can use:
-                    //      VBoxManage setextradata "myvm" "VBoxInternal/USB/USBProxy/GlobalConfig/Force11PacketSize" 1
-                    //InsertConfigInteger(pCfg, "Force11PacketSize", true);
-                }
+                InsertConfigNode(pUsbDevices, "USBProxy", &pCfg);
+                InsertConfigNode(pCfg, "GlobalConfig", &pCfg);
+                // This globally enables the 2.0 -> 1.1 device morphing of proxied devices to keep windows quiet.
+                //InsertConfigInteger(pCfg, "Force11Device", true);
+                // The following breaks stuff, but it makes MSDs work in vista. (I include it here so
+                // that it's documented somewhere.) Users needing it can use:
+                //      VBoxManage setextradata "myvm" "VBoxInternal/USB/USBProxy/GlobalConfig/Force11PacketSize" 1
+                //InsertConfigInteger(pCfg, "Force11PacketSize", true);
+            }
 #endif
 
 #ifdef VBOX_WITH_USB_VIDEO
-                BOOL aEmulatedUSBWebcamEnabled = FALSE;
-                hrc = pMachine->COMGETTER(EmulatedUSBWebcameraEnabled)(&aEmulatedUSBWebcamEnabled);    H();
-                if (aEmulatedUSBWebcamEnabled)
-                {
-                    InsertConfigNode(pUsbDevices, "Webcam", &pDev);
-                    InsertConfigNode(pDev,     "0", &pInst);
-                    InsertConfigNode(pInst,    "Config", &pCfg);
-                    InsertConfigNode(pInst,    "LUN#0", &pLunL0);
-                    InsertConfigString(pLunL0, "Driver", "EmWebcam");
-                    InsertConfigNode(pLunL0,   "Config", &pCfg);
-                    InsertConfigInteger(pCfg,  "Object", (uintptr_t)mEmWebcam);
-                }
-#endif
-
-#ifdef VBOX_WITH_USB_CARDREADER
-                BOOL aEmulatedUSBCardReaderEnabled = FALSE;
-                hrc = pMachine->COMGETTER(EmulatedUSBCardReaderEnabled)(&aEmulatedUSBCardReaderEnabled);    H();
-                if (aEmulatedUSBCardReaderEnabled)
-                {
-                    InsertConfigNode(pUsbDevices, "CardReader", &pDev);
-                    InsertConfigNode(pDev,     "0", &pInst);
-                    InsertConfigNode(pInst,    "Config", &pCfg);
-
-                    InsertConfigNode(pInst,    "LUN#0", &pLunL0);
-# ifdef VBOX_WITH_USB_CARDREADER_TEST
-                    InsertConfigString(pLunL0, "Driver", "DrvDirectCardReader");
-                    InsertConfigNode(pLunL0,   "Config", &pCfg);
-# else
-                    InsertConfigString(pLunL0, "Driver", "UsbCardReader");
-                    InsertConfigNode(pLunL0,   "Config", &pCfg);
-                    InsertConfigInteger(pCfg,  "Object", (uintptr_t)mUsbCardReader);
-# endif
-                }
-#endif
-
-# if 0  /* Virtual MSD*/
-
-                InsertConfigNode(pUsbDevices, "Msd", &pDev);
+            BOOL aEmulatedUSBWebcamEnabled = FALSE;
+            hrc = pMachine->COMGETTER(EmulatedUSBWebcameraEnabled)(&aEmulatedUSBWebcamEnabled);    H();
+            if (aEmulatedUSBWebcamEnabled)
+            {
+                InsertConfigNode(pUsbDevices, "Webcam", &pDev);
                 InsertConfigNode(pDev,     "0", &pInst);
                 InsertConfigNode(pInst,    "Config", &pCfg);
                 InsertConfigNode(pInst,    "LUN#0", &pLunL0);
-
-                InsertConfigString(pLunL0, "Driver", "SCSI");
+                InsertConfigString(pLunL0, "Driver", "EmWebcam");
                 InsertConfigNode(pLunL0,   "Config", &pCfg);
+                InsertConfigInteger(pCfg,  "Object", (uintptr_t)mEmWebcam);
+            }
+#endif
+
+#ifdef VBOX_WITH_USB_CARDREADER
+            BOOL aEmulatedUSBCardReaderEnabled = FALSE;
+            hrc = pMachine->COMGETTER(EmulatedUSBCardReaderEnabled)(&aEmulatedUSBCardReaderEnabled);    H();
+            if (aEmulatedUSBCardReaderEnabled)
+            {
+                InsertConfigNode(pUsbDevices, "CardReader", &pDev);
+                InsertConfigNode(pDev,     "0", &pInst);
+                InsertConfigNode(pInst,    "Config", &pCfg);
+
+                InsertConfigNode(pInst,    "LUN#0", &pLunL0);
+# ifdef VBOX_WITH_USB_CARDREADER_TEST
+                InsertConfigString(pLunL0, "Driver", "DrvDirectCardReader");
+                InsertConfigNode(pLunL0,   "Config", &pCfg);
+# else
+                InsertConfigString(pLunL0, "Driver", "UsbCardReader");
+                InsertConfigNode(pLunL0,   "Config", &pCfg);
+                InsertConfigInteger(pCfg,  "Object", (uintptr_t)mUsbCardReader);
+# endif
+             }
+#endif
+
+# if 0  /* Virtual MSD*/
+            InsertConfigNode(pUsbDevices, "Msd", &pDev);
+            InsertConfigNode(pDev,     "0", &pInst);
+            InsertConfigNode(pInst,    "Config", &pCfg);
+            InsertConfigNode(pInst,    "LUN#0", &pLunL0);
+
+            InsertConfigString(pLunL0, "Driver", "SCSI");
+            InsertConfigNode(pLunL0,   "Config", &pCfg);
+
+            InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
+            InsertConfigString(pLunL1, "Driver", "Block");
+            InsertConfigNode(pLunL1,   "Config", &pCfg);
+            InsertConfigString(pCfg,   "Type", "HardDisk");
+            InsertConfigInteger(pCfg,  "Mountable", 0);
+
+            InsertConfigNode(pLunL1,   "AttachedDriver", &pLunL2);
+            InsertConfigString(pLunL2, "Driver", "VD");
+            InsertConfigNode(pLunL2,   "Config", &pCfg);
+            InsertConfigString(pCfg,   "Path", "/Volumes/DataHFS/bird/VDIs/linux.vdi");
+            InsertConfigString(pCfg,   "Format", "VDI");
+# endif
+
+            /* Virtual USB Mouse/Tablet */
+            if (   aPointingHID == PointingHIDType_USBMouse
+                || aPointingHID == PointingHIDType_ComboMouse
+                || aPointingHID == PointingHIDType_USBTablet
+                || aPointingHID == PointingHIDType_USBMultiTouch)
+            {
+                InsertConfigNode(pUsbDevices, "HidMouse", &pDev);
+                InsertConfigNode(pDev,     "0", &pInst);
+                InsertConfigNode(pInst,    "Config", &pCfg);
+
+                InsertConfigString(pCfg,   "Mode", "relative");
+                InsertConfigNode(pInst,    "LUN#0", &pLunL0);
+                InsertConfigString(pLunL0, "Driver",        "MouseQueue");
+                InsertConfigNode(pLunL0,   "Config", &pCfg);
+                InsertConfigInteger(pCfg,  "QueueSize",            128);
 
                 InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
-                InsertConfigString(pLunL1, "Driver", "Block");
+                InsertConfigString(pLunL1, "Driver",        "MainMouse");
                 InsertConfigNode(pLunL1,   "Config", &pCfg);
-                InsertConfigString(pCfg,   "Type", "HardDisk");
-                InsertConfigInteger(pCfg,  "Mountable", 0);
-
-                InsertConfigNode(pLunL1,   "AttachedDriver", &pLunL2);
-                InsertConfigString(pLunL2, "Driver", "VD");
-                InsertConfigNode(pLunL2,   "Config", &pCfg);
-                InsertConfigString(pCfg,   "Path", "/Volumes/DataHFS/bird/VDIs/linux.vdi");
-                InsertConfigString(pCfg,   "Format", "VDI");
-# endif
-
-                /* Virtual USB Mouse/Tablet */
-                if (   aPointingHID == PointingHIDType_USBMouse
-                    || aPointingHID == PointingHIDType_ComboMouse
-                    || aPointingHID == PointingHIDType_USBTablet
-                    || aPointingHID == PointingHIDType_USBMultiTouch)
-                {
-                    InsertConfigNode(pUsbDevices, "HidMouse", &pDev);
-                    InsertConfigNode(pDev,     "0", &pInst);
-                    InsertConfigNode(pInst,    "Config", &pCfg);
-
-                    InsertConfigString(pCfg,   "Mode", "relative");
-                    InsertConfigNode(pInst,    "LUN#0", &pLunL0);
-                    InsertConfigString(pLunL0, "Driver",        "MouseQueue");
-                    InsertConfigNode(pLunL0,   "Config", &pCfg);
-                    InsertConfigInteger(pCfg,  "QueueSize",            128);
-
-                    InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
-                    InsertConfigString(pLunL1, "Driver",        "MainMouse");
-                    InsertConfigNode(pLunL1,   "Config", &pCfg);
-                    InsertConfigInteger(pCfg,  "Object",     (uintptr_t)pMouse);
-                }
-                if (   aPointingHID == PointingHIDType_USBTablet
-                    || aPointingHID == PointingHIDType_USBMultiTouch)
-                {
-                    InsertConfigNode(pDev,     "1", &pInst);
-                    InsertConfigNode(pInst,    "Config", &pCfg);
-
-                    InsertConfigString(pCfg,   "Mode", "absolute");
-                    InsertConfigNode(pInst,    "LUN#0", &pLunL0);
-                    InsertConfigString(pLunL0, "Driver",        "MouseQueue");
-                    InsertConfigNode(pLunL0,   "Config", &pCfg);
-                    InsertConfigInteger(pCfg,  "QueueSize",            128);
-
-                    InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
-                    InsertConfigString(pLunL1, "Driver",        "MainMouse");
-                    InsertConfigNode(pLunL1,   "Config", &pCfg);
-                    InsertConfigInteger(pCfg,  "Object",     (uintptr_t)pMouse);
-                }
-                if (aPointingHID == PointingHIDType_USBMultiTouch)
-                {
-                    InsertConfigNode(pDev,     "2", &pInst);
-                    InsertConfigNode(pInst,    "Config", &pCfg);
-
-                    InsertConfigString(pCfg,   "Mode", "multitouch");
-                    InsertConfigNode(pInst,    "LUN#0", &pLunL0);
-                    InsertConfigString(pLunL0, "Driver",        "MouseQueue");
-                    InsertConfigNode(pLunL0,   "Config", &pCfg);
-                    InsertConfigInteger(pCfg,  "QueueSize",            128);
-
-                    InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
-                    InsertConfigString(pLunL1, "Driver",        "MainMouse");
-                    InsertConfigNode(pLunL1,   "Config", &pCfg);
-                    InsertConfigInteger(pCfg,  "Object",     (uintptr_t)pMouse);
-                }
-
-                /* Virtual USB Keyboard */
-                KeyboardHIDType_T aKbdHID;
-                hrc = pMachine->COMGETTER(KeyboardHIDType)(&aKbdHID);                       H();
-                if (aKbdHID == KeyboardHIDType_USBKeyboard)
-                {
-                    InsertConfigNode(pUsbDevices, "HidKeyboard", &pDev);
-                    InsertConfigNode(pDev,     "0", &pInst);
-                    InsertConfigNode(pInst,    "Config", &pCfg);
-
-                    InsertConfigNode(pInst,    "LUN#0", &pLunL0);
-                    InsertConfigString(pLunL0, "Driver",               "KeyboardQueue");
-                    InsertConfigNode(pLunL0,   "Config", &pCfg);
-                    InsertConfigInteger(pCfg,  "QueueSize",            64);
-
-                    InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
-                    InsertConfigString(pLunL1, "Driver",               "MainKeyboard");
-                    InsertConfigNode(pLunL1,   "Config", &pCfg);
-                    pKeyboard = mKeyboard;
-                    InsertConfigInteger(pCfg,  "Object",     (uintptr_t)pKeyboard);
-                }
+                InsertConfigInteger(pCfg,  "Object",     (uintptr_t)pMouse);
+            }
+            if (   aPointingHID == PointingHIDType_USBTablet
+                || aPointingHID == PointingHIDType_USBMultiTouch)
+            {
+                InsertConfigNode(pDev,     "1", &pInst);
+                InsertConfigNode(pInst,    "Config", &pCfg);
+
+                InsertConfigString(pCfg,   "Mode", "absolute");
+                InsertConfigNode(pInst,    "LUN#0", &pLunL0);
+                InsertConfigString(pLunL0, "Driver",        "MouseQueue");
+                InsertConfigNode(pLunL0,   "Config", &pCfg);
+                InsertConfigInteger(pCfg,  "QueueSize",            128);
+
+                InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
+                InsertConfigString(pLunL1, "Driver",        "MainMouse");
+                InsertConfigNode(pLunL1,   "Config", &pCfg);
+                InsertConfigInteger(pCfg,  "Object",     (uintptr_t)pMouse);
+            }
+            if (aPointingHID == PointingHIDType_USBMultiTouch)
+            {
+                InsertConfigNode(pDev,     "2", &pInst);
+                InsertConfigNode(pInst,    "Config", &pCfg);
+
+                InsertConfigString(pCfg,   "Mode", "multitouch");
+                InsertConfigNode(pInst,    "LUN#0", &pLunL0);
+                InsertConfigString(pLunL0, "Driver",        "MouseQueue");
+                InsertConfigNode(pLunL0,   "Config", &pCfg);
+                InsertConfigInteger(pCfg,  "QueueSize",            128);
+
+                InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
+                InsertConfigString(pLunL1, "Driver",        "MainMouse");
+                InsertConfigNode(pLunL1,   "Config", &pCfg);
+                InsertConfigInteger(pCfg,  "Object",     (uintptr_t)pMouse);
+            }
+
+            /* Virtual USB Keyboard */
+            KeyboardHIDType_T aKbdHID;
+            hrc = pMachine->COMGETTER(KeyboardHIDType)(&aKbdHID);                       H();
+            if (aKbdHID == KeyboardHIDType_USBKeyboard)
+            {
+                InsertConfigNode(pUsbDevices, "HidKeyboard", &pDev);
+                InsertConfigNode(pDev,     "0", &pInst);
+                InsertConfigNode(pInst,    "Config", &pCfg);
+
+                InsertConfigNode(pInst,    "LUN#0", &pLunL0);
+                InsertConfigString(pLunL0, "Driver",               "KeyboardQueue");
+                InsertConfigNode(pLunL0,   "Config", &pCfg);
+                InsertConfigInteger(pCfg,  "QueueSize",            64);
+
+                InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
+                InsertConfigString(pLunL1, "Driver",               "MainKeyboard");
+                InsertConfigNode(pLunL1,   "Config", &pCfg);
+                pKeyboard = mKeyboard;
+                InsertConfigInteger(pCfg,  "Object",     (uintptr_t)pKeyboard);
             }
         }
Index: /trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp	(revision 47400)
+++ /trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp	(revision 47401)
@@ -88,13 +88,19 @@
 
         // first, call the COM methods, as they request locks
-        ComPtr<IUSBController> pUsbController;
-        rc = COMGETTER(USBController)(pUsbController.asOutParam());
-        BOOL fUSBEnabled;
-        if (FAILED(rc))
-            fUSBEnabled = false;
-        else
-        {
-            rc = pUsbController->COMGETTER(Enabled)(&fUSBEnabled);
-            if (FAILED(rc)) throw rc;
+        BOOL fUSBEnabled = FALSE;
+        com::SafeIfaceArray<IUSBController> usbControllers;
+        rc = COMGETTER(USBControllers)(ComSafeArrayAsOutParam(usbControllers));
+        if (SUCCEEDED(rc))
+        {
+            for (unsigned i = 0; i < usbControllers.size(); i++)
+            {
+                USBControllerType_T enmType;
+
+                rc = usbControllers[i]->COMGETTER(Type)(&enmType);
+                if (FAILED(rc)) throw rc;
+
+                if (enmType == USBControllerType_OHCI)
+                    fUSBEnabled = TRUE;
+            }
         }
 
Index: /trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp	(revision 47400)
+++ /trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp	(revision 47401)
@@ -354,5 +354,5 @@
             /* If there is a <vbox:Machine>, we always prefer the setting from there. */
             if (   (   vsysThis.pelmVboxMachine
-                    && pNewDesc->m->pConfig->hardwareMachine.usbController.fEnabled)
+                    && pNewDesc->m->pConfig->hardwareMachine.usbSettings.llUSBControllers.size() > 0)
                 || vsysThis.fHasUsbController)
                 pNewDesc->addEntry(VirtualSystemDescriptionType_USBController, "", "", "");
@@ -2619,9 +2619,10 @@
 #ifdef VBOX_WITH_USB
     /* USB Controller */
-    ComPtr<IUSBController> usbController;
-    rc = pNewMachine->COMGETTER(USBController)(usbController.asOutParam());
-    if (FAILED(rc)) throw rc;
-    rc = usbController->COMSETTER(Enabled)(stack.fUSBEnabled);
-    if (FAILED(rc)) throw rc;
+    if (stack.fUSBEnabled)
+    {
+        ComPtr<IUSBController> usbController;
+        rc = pNewMachine->AddUSBController(Bstr("OHCI").raw(), USBControllerType_OHCI, usbController.asOutParam());
+        if (FAILED(rc)) throw rc;
+    }
 #endif /* VBOX_WITH_USB */
 
@@ -3256,5 +3257,13 @@
 #ifdef VBOX_WITH_USB
     /* USB controller */
-    config.hardwareMachine.usbController.fEnabled = stack.fUSBEnabled;
+    if (stack.fUSBEnabled)
+    {
+        settings::USBController ctrl;
+
+        ctrl.strName = "OHCI";
+        ctrl.enmType = USBControllerType_OHCI;
+
+        config.hardwareMachine.usbSettings.llUSBControllers.push_back(ctrl);
+    }
 #endif
     /* Audio adapter */
Index: /trunk/src/VBox/Main/src-server/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 47400)
+++ /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 47401)
@@ -52,4 +52,5 @@
 #include "MachineImplCloneVM.h"
 #include "AutostartDb.h"
+#include "SystemPropertiesImpl.h"
 
 // generated header
@@ -2741,8 +2742,8 @@
 }
 
-STDMETHODIMP Machine::COMGETTER(USBController)(IUSBController **aUSBController)
+STDMETHODIMP Machine::COMGETTER(USBControllers)(ComSafeArrayOut(IUSBController *, aUSBControllers))
 {
 #ifdef VBOX_WITH_VUSB
-    CheckComArgOutPointerValid(aUSBController);
+    CheckComArgOutPointerValid(aUSBControllers);
 
     AutoCaller autoCaller(this);
@@ -2759,10 +2760,12 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    return rc = mUSBController.queryInterfaceTo(aUSBController);
+    SafeIfaceArray<IUSBController> ctrls(*mUSBControllers.data());
+    ctrls.detachTo(ComSafeArrayOutArg(aUSBControllers));
+    return S_OK;
 #else
     /* Note: The GUI depends on this method returning E_NOTIMPL with no
      * extended error info to indicate that USB is simply not available
      * (w/o treating it as a failure), for example, as in OSE */
-    NOREF(aUSBController);
+    NOREF(aUSBControllers);
     ReturnComNotImplemented();
 #endif /* VBOX_WITH_VUSB */
@@ -6554,4 +6557,130 @@
 }
 
+STDMETHODIMP Machine::AddUSBController(IN_BSTR aName, USBControllerType_T aType,
+                                       IUSBController **controller)
+{
+    if (   (aType <= USBControllerType_Null)
+        || (aType >= USBControllerType_Last))
+        return setError(E_INVALIDARG,
+                        tr("Invalid USB controller type: %d"),
+                        aType);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    HRESULT rc = checkStateDependency(MutableStateDep);
+    if (FAILED(rc)) return rc;
+
+    /* try to find one with the same type first. */
+    ComObjPtr<USBController> ctrl;
+
+    rc = getUSBControllerByName(aName, ctrl, false /* aSetError */);
+    if (SUCCEEDED(rc))
+        return setError(VBOX_E_OBJECT_IN_USE,
+                        tr("USB controller named '%ls' already exists"),
+                        aName);
+
+    /* Check that we don't exceed the maximum number of USB controllers for the given type. */
+    ULONG maxInstances;
+    rc = mParent->getSystemProperties()->GetMaxInstancesOfUSBControllerType(mHWData->mChipsetType, aType, &maxInstances);
+    if (FAILED(rc))
+        return rc;
+
+    ULONG cInstances = getUSBControllerCountByType(aType);
+    if (cInstances >= maxInstances)
+        return setError(E_INVALIDARG,
+                        tr("Too many USB controllers of this type"));
+
+    ctrl.createObject();
+
+    rc = ctrl->init(this, aName, aType);
+    if (FAILED(rc)) return rc;
+
+    setModified(IsModified_USB);
+    mUSBControllers.backup();
+    mUSBControllers->push_back(ctrl);
+
+    ctrl.queryInterfaceTo(controller);
+
+    /* inform the direct session if any */
+    alock.release();
+    onUSBControllerChange();
+
+    return S_OK;
+}
+
+STDMETHODIMP Machine::GetUSBControllerByName(IN_BSTR aName, IUSBController **aUSBController)
+{
+    CheckComArgStrNotEmptyOrNull(aName);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    ComObjPtr<USBController> ctrl;
+
+    HRESULT rc = getUSBControllerByName(aName, ctrl, true /* aSetError */);
+    if (SUCCEEDED(rc))
+        ctrl.queryInterfaceTo(aUSBController);
+
+    return rc;
+}
+
+STDMETHODIMP Machine::GetUSBControllerCountByType(USBControllerType_T aType,
+                                                  ULONG *aControllers)
+{
+    CheckComArgOutPointerValid(aControllers);
+
+    if (   (aType <= USBControllerType_Null)
+        || (aType >= USBControllerType_Last))
+        return setError(E_INVALIDARG,
+                        tr("Invalid USB controller type: %d"),
+                        aType);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    ComObjPtr<USBController> ctrl;
+
+    *aControllers = getUSBControllerCountByType(aType);
+
+    return S_OK;
+}
+
+STDMETHODIMP Machine::RemoveUSBController(IN_BSTR aName)
+{
+    CheckComArgStrNotEmptyOrNull(aName);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    HRESULT rc = checkStateDependency(MutableStateDep);
+    if (FAILED(rc)) return rc;
+
+    ComObjPtr<USBController> ctrl;
+    rc = getUSBControllerByName(aName, ctrl, true /* aSetError */);
+    if (FAILED(rc)) return rc;
+
+    setModified(IsModified_USB);
+    mUSBControllers.backup();
+
+    ctrl->unshare();
+
+    mUSBControllers->remove(ctrl);
+
+    /* inform the direct session if any */
+    alock.release();
+    onUSBControllerChange();
+
+    return S_OK;
+}
+
 STDMETHODIMP Machine::QuerySavedGuestScreenInfo(ULONG uScreenId,
                                                 ULONG *puOriginX,
@@ -7477,4 +7606,19 @@
 }
 
+STDMETHODIMP Machine::COMGETTER(USBProxyAvailable)(BOOL *aAvailable)
+{
+    CheckComArgOutPointerValid(aAvailable);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+#ifdef VBOX_WITH_USB
+    *aAvailable = true;
+#else
+    *aAvailable = false;
+#endif
+    return S_OK;
+}
+
 STDMETHODIMP Machine::CloneTo(IMachine *pTarget, CloneMode_T mode, ComSafeArrayIn(CloneOptions_T, options), IProgress **pProgress)
 {
@@ -7746,10 +7890,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    BOOL fEnabled = FALSE;
-    HRESULT rc = mUSBController->COMGETTER(Enabled)(&fEnabled);
-    if (SUCCEEDED(rc))
-        return !!fEnabled;
-    else
-        return false;
+    return (mUSBControllers->size() > 0);
 }
 
@@ -8484,4 +8623,5 @@
     mMediaData.allocate();
     mStorageControllers.allocate();
+    mUSBControllers.allocate();
 
     /* initialize mOSTypeId */
@@ -8513,8 +8653,4 @@
     unconst(mAudioAdapter).createObject();
     mAudioAdapter->init(this);
-
-    /* create the USB controller object (always present, default is disabled) */
-    unconst(mUSBController).createObject();
-    mUSBController->init(this);
 
     /* create the USB device filters object (always present) */
@@ -8567,10 +8703,4 @@
             unconst(mNetworkAdapters[slot]).setNull();
         }
-    }
-
-    if (mUSBController)
-    {
-        mUSBController->uninit();
-        unconst(mUSBController).setNull();
     }
 
@@ -8661,4 +8791,5 @@
     mMediaData.free();
     mStorageControllers.free();
+    mUSBControllers.free();
     mHWData.free();
     mUserData.free();
@@ -9174,10 +9305,19 @@
         if (FAILED(rc)) return rc;
 
-        /* USB Controller */
-        rc = mUSBController->loadSettings(data.usbController);
-        if (FAILED(rc)) return rc;
+        /* Shared folders */
+        for (settings::USBControllerList::const_iterator it = data.usbSettings.llUSBControllers.begin();
+             it != data.usbSettings.llUSBControllers.end();
+             ++it)
+        {
+            const settings::USBController &settingsCtrl = *it;
+            ComObjPtr<USBController> newCtrl;
+
+            newCtrl.createObject();
+            newCtrl->init(this, settingsCtrl.strName, settingsCtrl.enmType);
+            mUSBControllers->push_back(newCtrl);
+        }
 
         /* USB device filters */
-        rc = mUSBDeviceFilters->loadSettings(data.usbController);
+        rc = mUSBDeviceFilters->loadSettings(data.usbSettings);
         if (FAILED(rc)) return rc;
 
@@ -9746,4 +9886,55 @@
                         aName.c_str());
     return VBOX_E_OBJECT_NOT_FOUND;
+}
+
+/**
+ * Returns a USB controller object with the given name.
+ *
+ *  @param aName                 USB controller name to find
+ *  @param aUSBController        where to return the found USB controller
+ *  @param aSetError             true to set extended error info on failure
+ */
+HRESULT Machine::getUSBControllerByName(const Utf8Str &aName,
+                                        ComObjPtr<USBController> &aUSBController,
+                                        bool aSetError /* = false */)
+{
+    AssertReturn(!aName.isEmpty(), E_INVALIDARG);
+
+    for (USBControllerList::const_iterator it = mUSBControllers->begin();
+         it != mUSBControllers->end();
+         ++it)
+    {
+        if ((*it)->getName() == aName)
+        {
+            aUSBController = (*it);
+            return S_OK;
+        }
+    }
+
+    if (aSetError)
+        return setError(VBOX_E_OBJECT_NOT_FOUND,
+                        tr("Could not find a storage controller named '%s'"),
+                        aName.c_str());
+    return VBOX_E_OBJECT_NOT_FOUND;
+}
+
+/**
+ * Returns the number of USB controller instance of the given type.
+ *
+ * @param enmType                USB controller type.
+ */
+ULONG Machine::getUSBControllerCountByType(USBControllerType_T enmType)
+{
+    ULONG cCtrls = 0;
+
+    for (USBControllerList::const_iterator it = mUSBControllers->begin();
+         it != mUSBControllers->end();
+         ++it)
+    {
+        if ((*it)->getControllerType() == enmType)
+            cCtrls++;
+    }
+
+    return cCtrls;
 }
 
@@ -10416,9 +10607,19 @@
 
         /* USB Controller (required) */
-        rc = mUSBController->saveSettings(data.usbController);
-        if (FAILED(rc)) throw rc;
+        for (USBControllerList::const_iterator it = mUSBControllers->begin();
+             it != mUSBControllers->end();
+             ++it)
+        {
+            ComObjPtr<USBController> ctrl = *it;
+            settings::USBController settingsCtrl;
+
+            settingsCtrl.strName = ctrl->getName();
+            settingsCtrl.enmType = ctrl->getControllerType();
+
+            data.usbSettings.llUSBControllers.push_back(settingsCtrl);
+        }
 
         /* USB device filters (required) */
-        rc = mUSBDeviceFilters->saveSettings(data.usbController);
+        rc = mUSBDeviceFilters->saveSettings(data.usbSettings);
         if (FAILED(rc)) throw rc;
 
@@ -11809,4 +12010,38 @@
     }
 
+    if (!mUSBControllers.isNull())
+    {
+        if (mUSBControllers.isBackedUp())
+        {
+            /* unitialize all new devices (absent in the backed up list). */
+            USBControllerList::const_iterator it = mUSBControllers->begin();
+            USBControllerList *backedList = mUSBControllers.backedUpData();
+            while (it != mUSBControllers->end())
+            {
+                if (   std::find(backedList->begin(), backedList->end(), *it)
+                    == backedList->end()
+                   )
+                {
+                    (*it)->uninit();
+                }
+                ++it;
+            }
+
+            /* restore the list */
+            mUSBControllers.rollback();
+        }
+
+        /* rollback any changes to devices after restoring the list */
+        if (mData->flModifications & IsModified_USB)
+        {
+            USBControllerList::const_iterator it = mUSBControllers->begin();
+            while (it != mUSBControllers->end())
+            {
+                (*it)->rollback();
+                ++it;
+            }
+        }
+    }
+
     mUserData.rollback();
 
@@ -11824,7 +12059,4 @@
     if (mAudioAdapter)
         mAudioAdapter->rollback();
-
-    if (mUSBController && (mData->flModifications & IsModified_USB))
-        mUSBController->rollback();
 
     if (mUSBDeviceFilters && (mData->flModifications & IsModified_USB))
@@ -11934,5 +12166,4 @@
     mVRDEServer->commit();
     mAudioAdapter->commit();
-    mUSBController->commit();
     mUSBDeviceFilters->commit();
     mBandwidthControl->commit();
@@ -12065,4 +12296,75 @@
     }
 
+    bool commitUSBControllers = false;
+
+    if (mUSBControllers.isBackedUp())
+    {
+        mUSBControllers.commit();
+
+        if (mPeer)
+        {
+            /* Commit all changes to new controllers (this will reshare data with
+             * peers for those who have peers) */
+            USBControllerList *newList = new USBControllerList();
+            USBControllerList::const_iterator it = mUSBControllers->begin();
+            while (it != mUSBControllers->end())
+            {
+                (*it)->commit();
+
+                /* look if this controller has a peer device */
+                ComObjPtr<USBController> peer = (*it)->getPeer();
+                if (!peer)
+                {
+                    /* no peer means the device is a newly created one;
+                     * create a peer owning data this device share it with */
+                    peer.createObject();
+                    peer->init(mPeer, *it, true /* aReshare */);
+                }
+                else
+                {
+                    /* remove peer from the old list */
+                    mPeer->mUSBControllers->remove(peer);
+                }
+                /* and add it to the new list */
+                newList->push_back(peer);
+
+                ++it;
+            }
+
+            /* uninit old peer's controllers that are left */
+            it = mPeer->mUSBControllers->begin();
+            while (it != mPeer->mUSBControllers->end())
+            {
+                (*it)->uninit();
+                ++it;
+            }
+
+            /* attach new list of controllers to our peer */
+            mPeer->mUSBControllers.attach(newList);
+        }
+        else
+        {
+            /* we have no peer (our parent is the newly created machine);
+             * just commit changes to devices */
+            commitUSBControllers = true;
+        }
+    }
+    else
+    {
+        /* the list of controllers itself is not changed,
+         * just commit changes to controllers themselves */
+        commitUSBControllers = true;
+    }
+
+    if (commitUSBControllers)
+    {
+        USBControllerList::const_iterator it = mUSBControllers->begin();
+        while (it != mUSBControllers->end())
+        {
+            (*it)->commit();
+            ++it;
+        }
+    }
+
     if (isSessionMachine())
     {
@@ -12113,5 +12415,4 @@
     mVRDEServer->copyFrom(aThat->mVRDEServer);
     mAudioAdapter->copyFrom(aThat->mAudioAdapter);
-    mUSBController->copyFrom(aThat->mUSBController);
     mUSBDeviceFilters->copyFrom(aThat->mUSBDeviceFilters);
     mBandwidthControl->copyFrom(aThat->mBandwidthControl);
@@ -12128,4 +12429,17 @@
         ctrl->initCopy(this, *it);
         mStorageControllers->push_back(ctrl);
+    }
+
+    /* create private copies of all USB controllers */
+    mUSBControllers.backup();
+    mUSBControllers->clear();
+    for (USBControllerList::iterator it = aThat->mUSBControllers->begin();
+         it != aThat->mUSBControllers->end();
+         ++it)
+    {
+        ComObjPtr<USBController> ctrl;
+        ctrl.createObject();
+        ctrl->initCopy(this, *it);
+        mUSBControllers->push_back(ctrl);
     }
 
@@ -12519,4 +12833,15 @@
     }
 
+    mUSBControllers.allocate();
+    for (USBControllerList::const_iterator it = aMachine->mUSBControllers->begin();
+         it != aMachine->mUSBControllers->end();
+         ++it)
+    {
+        ComObjPtr<USBController> ctl;
+        ctl.createObject();
+        ctl->init(this, *it);
+        mUSBControllers->push_back(ctl);
+    }
+
     unconst(mBIOSSettings).createObject();
     mBIOSSettings->init(this, aMachine->mBIOSSettings);
@@ -12539,7 +12864,4 @@
         mParallelPorts[slot]->init(this, aMachine->mParallelPorts[slot]);
     }
-    /* create another USB controller object that will be mutable */
-    unconst(mUSBController).createObject();
-    mUSBController->init(this, aMachine->mUSBController);
 
     /* create another USB device filters object that will be mutable */
Index: /trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/SnapshotImpl.cpp	(revision 47400)
+++ /trunk/src/VBox/Main/src-server/SnapshotImpl.cpp	(revision 47401)
@@ -1078,6 +1078,17 @@
     mAudioAdapter->initCopy(this, pMachine->mAudioAdapter);
 
-    unconst(mUSBController).createObject();
-    mUSBController->initCopy(this, pMachine->mUSBController);
+    /* create copies of all USB controllers (mUSBControllerData
+     * after attaching a copy contains just references to original objects) */
+    mUSBControllers.allocate();
+    for (USBControllerList::const_iterator
+         it = aSessionMachine->mUSBControllers->begin();
+         it != aSessionMachine->mUSBControllers->end();
+         ++it)
+    {
+        ComObjPtr<USBController> ctrl;
+        ctrl.createObject();
+        ctrl->initCopy(this, *it);
+        mUSBControllers->push_back(ctrl);
+    }
 
     unconst(mUSBDeviceFilters).createObject();
@@ -1164,4 +1175,5 @@
     mMediaData.allocate();
     mStorageControllers.allocate();
+    mUSBControllers.allocate();
 
     /* SSData is always unique for SnapshotMachine */
@@ -1179,7 +1191,4 @@
     unconst(mAudioAdapter).createObject();
     mAudioAdapter->init(this);
-
-    unconst(mUSBController).createObject();
-    mUSBController->init(this);
 
     unconst(mUSBDeviceFilters).createObject();
Index: /trunk/src/VBox/Main/src-server/SystemPropertiesImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/SystemPropertiesImpl.cpp	(revision 47400)
+++ /trunk/src/VBox/Main/src-server/SystemPropertiesImpl.cpp	(revision 47401)
@@ -581,4 +581,33 @@
             AssertMsgFailed(("Invalid controller type %d\n", aControllerType));
     }
+    return S_OK;
+}
+
+STDMETHODIMP SystemProperties::GetMaxInstancesOfUSBControllerType(ChipsetType_T aChipset,
+                                                                  USBControllerType_T aType,
+                                                                  ULONG *aMaxInstances)
+{
+    CheckComArgOutPointerValid(aMaxInstances);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    ULONG cCtrs = 0;
+
+    /* no need to lock, this is const */
+    switch (aType)
+    {
+        case USBControllerType_OHCI:
+        case USBControllerType_EHCI:
+        {
+            cCtrs = 1;
+            break;
+        }
+        default:
+            AssertMsgFailed(("Invalid bus type %d\n", aType));
+    }
+
+    *aMaxInstances = cCtrs;
+
     return S_OK;
 }
Index: /trunk/src/VBox/Main/src-server/USBControllerImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/USBControllerImpl.cpp	(revision 47400)
+++ /trunk/src/VBox/Main/src-server/USBControllerImpl.cpp	(revision 47401)
@@ -42,10 +42,9 @@
 {
     BackupableUSBData()
-        : fEnabled(false),
-          fEnabledEHCI(false)
+        : enmType(USBControllerType_Null)
     { }
 
-    BOOL fEnabled;
-    BOOL fEnabledEHCI;
+    Utf8Str             strName;
+    USBControllerType_T enmType;
 };
 
@@ -93,10 +92,16 @@
  * @returns COM result indicator.
  * @param aParent       Pointer to our parent object.
- */
-HRESULT USBController::init(Machine *aParent)
-{
-    LogFlowThisFunc(("aParent=%p\n", aParent));
-
-    ComAssertRet(aParent, E_INVALIDARG);
+ * @param aName         The name of the USB controller.
+ * @param enmType       The USB controller type.
+ */
+HRESULT USBController::init(Machine *aParent, const Utf8Str &aName, USBControllerType_T enmType)
+{
+    LogFlowThisFunc(("aParent=%p aName=\"%s\"\n", aParent, aName.c_str()));
+
+    ComAssertRet(aParent && !aName.isEmpty(), E_INVALIDARG);
+    if (   (enmType <= USBControllerType_Null)
+        || (enmType >  USBControllerType_EHCI))
+        return setError(E_INVALIDARG,
+                        tr("Invalid USB controller type"));
 
     /* Enclose the state transition NotReady->InInit->Ready */
@@ -109,4 +114,6 @@
 
     m->bd.allocate();
+    m->bd->strName = aName;
+    m->bd->enmType = enmType;
 
     /* Confirm a successful initialization */
@@ -124,11 +131,20 @@
  * @param aParent       Pointer to our parent object.
  * @param aPeer         The object to share.
- *
- * @note This object must be destroyed before the original object
- * it shares data with is destroyed.
- */
-HRESULT USBController::init(Machine *aParent, USBController *aPeer)
-{
-    LogFlowThisFunc(("aParent=%p, aPeer=%p\n", aParent, aPeer));
+ *  @param  aReshare
+ *      When false, the original object will remain a data owner.
+ *      Otherwise, data ownership will be transferred from the original
+ *      object to this one.
+ *
+ *  @note This object must be destroyed before the original object
+ *  it shares data with is destroyed.
+ *
+ *  @note Locks @a aThat object for writing if @a aReshare is @c true, or for
+ *  reading if @a aReshare is false.
+ */
+HRESULT USBController::init(Machine *aParent, USBController *aPeer,
+                            bool fReshare /* = false */)
+{
+    LogFlowThisFunc(("aParent=%p, aPeer=%p, fReshare=%RTbool\n",
+                      aParent, aPeer, fReshare));
 
     ComAssertRet(aParent && aPeer, E_INVALIDARG);
@@ -140,8 +156,22 @@
     m = new Data(aParent);
 
-    unconst(m->pPeer) = aPeer;
-
-    AutoWriteLock thatlock(aPeer COMMA_LOCKVAL_SRC_POS);
-    m->bd.share(aPeer->m->bd);
+    /* sanity */
+    AutoCaller peerCaller(aPeer);
+    AssertComRCReturnRC(peerCaller.rc());
+
+    if (fReshare)
+    {
+        AutoWriteLock peerLock(aPeer COMMA_LOCKVAL_SRC_POS);
+
+        unconst(aPeer->m->pPeer) = this;
+        m->bd.attach (aPeer->m->bd);
+    }
+    else
+    {
+        unconst(m->pPeer) = aPeer;
+
+        AutoReadLock peerLock(aPeer COMMA_LOCKVAL_SRC_POS);
+        m->bd.share (aPeer->m->bd);
+    }
 
     /* Confirm a successful initialization */
@@ -206,46 +236,51 @@
 // IUSBController properties
 /////////////////////////////////////////////////////////////////////////////
-
-STDMETHODIMP USBController::COMGETTER(Enabled)(BOOL *aEnabled)
-{
-    CheckComArgOutPointerValid(aEnabled);
+STDMETHODIMP USBController::COMGETTER(Name) (BSTR *aName)
+{
+    CheckComArgOutPointerValid(aName);
 
     AutoCaller autoCaller(this);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
+    /* strName is constant during life time, no need to lock */
+    m->bd->strName.cloneTo(aName);
+
+    return S_OK;
+}
+
+STDMETHODIMP USBController::COMGETTER(Type)(USBControllerType_T *aType)
+{
+    CheckComArgOutPointerValid(aType);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    *aEnabled = m->bd->fEnabled;
-
-    return S_OK;
-}
-
-
-STDMETHODIMP USBController::COMSETTER(Enabled)(BOOL aEnabled)
-{
-    LogFlowThisFunc(("aEnabled=%RTbool\n", aEnabled));
+    *aType = m->bd->enmType;
+
+    return S_OK;
+}
+
+STDMETHODIMP USBController::COMGETTER(USBStandard)(USHORT *aUSBStandard)
+{
+    CheckComArgOutPointerValid(aUSBStandard);
 
     AutoCaller autoCaller(this);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
-    /* the machine needs to be mutable */
-    AutoMutableStateDependency adep(m->pParent);
-    if (FAILED(adep.rc())) return adep.rc();
-
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    if (m->bd->fEnabled != aEnabled)
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    switch (m->bd->enmType)
     {
-        m->bd.backup();
-        m->bd->fEnabled = aEnabled;
-
-        // leave the lock for safety
-        alock.release();
-
-        AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS);
-        m->pParent->setModified(Machine::IsModified_USB);
-        mlock.release();
-
-        m->pParent->onUSBControllerChange();
+        case USBControllerType_OHCI:
+            *aUSBStandard = 0x0101;
+            break;
+        case USBControllerType_EHCI:
+            *aUSBStandard = 0x0200;
+            break;
+        default:
+            AssertMsgFailedReturn(("Invalid controller type %d\n", m->bd->enmType),
+                                  E_FAIL);
     }
 
@@ -253,134 +288,6 @@
 }
 
-STDMETHODIMP USBController::COMGETTER(EnabledEHCI)(BOOL *aEnabled)
-{
-    CheckComArgOutPointerValid(aEnabled);
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    *aEnabled = m->bd->fEnabledEHCI;
-
-    return S_OK;
-}
-
-STDMETHODIMP USBController::COMSETTER(EnabledEHCI)(BOOL aEnabled)
-{
-    LogFlowThisFunc(("aEnabled=%RTbool\n", aEnabled));
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-    /* the machine needs to be mutable */
-    AutoMutableStateDependency adep(m->pParent);
-    if (FAILED(adep.rc())) return adep.rc();
-
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    if (m->bd->fEnabledEHCI != aEnabled)
-    {
-        m->bd.backup();
-        m->bd->fEnabledEHCI = aEnabled;
-
-        // leave the lock for safety
-        alock.release();
-
-        AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS);
-        m->pParent->setModified(Machine::IsModified_USB);
-        mlock.release();
-
-        m->pParent->onUSBControllerChange();
-    }
-
-    return S_OK;
-}
-
-STDMETHODIMP USBController::COMGETTER(ProxyAvailable)(BOOL *aEnabled)
-{
-    CheckComArgOutPointerValid(aEnabled);
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-#ifdef VBOX_WITH_USB
-    *aEnabled = true;
-#else
-    *aEnabled = false;
-#endif
-
-    return S_OK;
-}
-
-STDMETHODIMP USBController::COMGETTER(USBStandard)(USHORT *aUSBStandard)
-{
-    CheckComArgOutPointerValid(aUSBStandard);
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-    /* not accessing data -- no need to lock */
-
-    /** @todo This is no longer correct */
-    *aUSBStandard = 0x0101;
-
-    return S_OK;
-}
-
 // public methods only for internal purposes
 /////////////////////////////////////////////////////////////////////////////
-
-/**
- *  Loads settings from the given machine node.
- *  May be called once right after this object creation.
- *
- *  @param aMachineNode <Machine> node.
- *
- *  @note Does not lock "this" as Machine::loadHardware, which calls this, does not lock either.
- */
-HRESULT USBController::loadSettings(const settings::USBController &data)
-{
-    AutoCaller autoCaller(this);
-    AssertComRCReturnRC(autoCaller.rc());
-
-    /* Note: we assume that the default values for attributes of optional
-     * nodes are assigned in the Data::Data() constructor and don't do it
-     * here. It implies that this method may only be called after constructing
-     * a new BIOSSettings object while all its data fields are in the default
-     * values. Exceptions are fields whose creation time defaults don't match
-     * values that should be applied when these fields are not explicitly set
-     * in the settings file (for backwards compatibility reasons). This takes
-     * place when a setting of a newly created object must default to A while
-     * the same setting of an object loaded from the old settings file must
-     * default to B. */
-
-    m->bd->fEnabled = data.fEnabled;
-    m->bd->fEnabledEHCI = data.fEnabledEHCI;
-
-    return S_OK;
-}
-
-/**
- *  Saves settings to the given machine node.
- *
- *  @param aMachineNode <Machine> node.
- *
- *  @note Locks this object for reading.
- */
-HRESULT USBController::saveSettings(settings::USBController &data)
-{
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    data.fEnabled = !!m->bd->fEnabled;
-    data.fEnabledEHCI = !!m->bd->fEnabledEHCI;
-
-    return S_OK;
-}
 
 /** @note Locks objects for writing! */
@@ -460,4 +367,52 @@
 }
 
+/**
+ *  Cancels sharing (if any) by making an independent copy of data.
+ *  This operation also resets this object's peer to NULL.
+ *
+ *  @note Locks this object for writing, together with the peer object
+ *  represented by @a aThat (locked for reading).
+ */
+void USBController::unshare()
+{
+    /* sanity */
+    AutoCaller autoCaller(this);
+    AssertComRCReturnVoid (autoCaller.rc());
+
+    /* sanity too */
+    AutoCaller peerCaller (m->pPeer);
+    AssertComRCReturnVoid (peerCaller.rc());
+
+    /* peer is not modified, lock it for reading (m->pPeer is "master" so locked
+     * first) */
+    AutoReadLock rl(m->pPeer COMMA_LOCKVAL_SRC_POS);
+    AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
+
+    if (m->bd.isShared())
+    {
+        if (!m->bd.isBackedUp())
+            m->bd.backup();
+
+        m->bd.commit();
+    }
+
+    unconst(m->pPeer) = NULL;
+}
+
+const Utf8Str& USBController::getName() const
+{
+    return m->bd->strName;
+}
+
+USBControllerType_T USBController::getControllerType() const
+{
+    return m->bd->enmType;
+}
+
+ComObjPtr<USBController> USBController::getPeer()
+{
+    return m->pPeer;
+}
+
 // private methods
 /////////////////////////////////////////////////////////////////////////////
Index: /trunk/src/VBox/Main/src-server/USBDeviceFiltersImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/USBDeviceFiltersImpl.cpp	(revision 47400)
+++ /trunk/src/VBox/Main/src-server/USBDeviceFiltersImpl.cpp	(revision 47401)
@@ -497,5 +497,5 @@
  *  @note Does not lock "this" as Machine::loadHardware, which calls this, does not lock either.
  */
-HRESULT USBDeviceFilters::loadSettings(const settings::USBController &data)
+HRESULT USBDeviceFilters::loadSettings(const settings::USB &data)
 {
     AutoCaller autoCaller(this);
@@ -540,5 +540,5 @@
  *  @note Locks this object for reading.
  */
-HRESULT USBDeviceFilters::saveSettings(settings::USBController &data)
+HRESULT USBDeviceFilters::saveSettings(settings::USB &data)
 {
     AutoCaller autoCaller(this);
Index: /trunk/src/VBox/Main/xml/Settings.cpp
===================================================================
--- /trunk/src/VBox/Main/xml/Settings.cpp	(revision 47400)
+++ /trunk/src/VBox/Main/xml/Settings.cpp	(revision 47401)
@@ -1711,7 +1711,20 @@
 {
     return (    (this == &u)
-                 || (    (fEnabled          == u.fEnabled)
-                      && (fEnabledEHCI      == u.fEnabledEHCI)
-                      && (llDeviceFilters   == u.llDeviceFilters)
+                 || (    (strName == u.strName)
+                      && (enmType == u.enmType)
+                    )
+           );
+}
+
+/**
+ * Comparison operator. This gets called from MachineConfigFile::operator==,
+ * which in turn gets called from Machine::saveSettings to figure out whether
+ * machine settings have really changed and thus need to be written out to disk.
+ */
+bool USB::operator==(const USB &u) const
+{
+    return (    (this == &u)
+                 || (    (llUSBControllers == u.llUSBControllers)
+                      && (llDeviceFilters  == u.llDeviceFilters)
                     )
            );
@@ -1936,5 +1949,5 @@
                   && (vrdeSettings              == h.vrdeSettings)
                   && (biosSettings              == h.biosSettings)
-                  && (usbController             == h.usbController)
+                  && (usbSettings               == h.usbSettings)
                   && (llNetworkAdapters         == h.llNetworkAdapters)
                   && (llSerialPorts             == h.llSerialPorts)
@@ -2968,11 +2981,66 @@
             }
         }
-        else if (pelmHwChild->nameEquals("USBController"))
-        {
-            pelmHwChild->getAttributeValue("enabled", hw.usbController.fEnabled);
-            pelmHwChild->getAttributeValue("enabledEhci", hw.usbController.fEnabledEHCI);
+        else if (   (m->sv <= SettingsVersion_v1_14)
+                 && pelmHwChild->nameEquals("USBController"))
+        {
+            bool fEnabled = false;
+
+            pelmHwChild->getAttributeValue("enabled", fEnabled);
+            if (fEnabled)
+            {
+                /* Create OHCI controller with default name. */
+                USBController ctrl;
+
+                ctrl.strName = "OHCI";
+                ctrl.enmType = USBControllerType_OHCI;
+                hw.usbSettings.llUSBControllers.push_back(ctrl);
+            }
+
+            pelmHwChild->getAttributeValue("enabledEhci", fEnabled);
+            if (fEnabled)
+            {
+                /* Create OHCI controller with default name. */
+                USBController ctrl;
+
+                ctrl.strName = "EHCI";
+                ctrl.enmType = USBControllerType_EHCI;
+                hw.usbSettings.llUSBControllers.push_back(ctrl);
+            }
 
             readUSBDeviceFilters(*pelmHwChild,
-                                 hw.usbController.llDeviceFilters);
+                                 hw.usbSettings.llDeviceFilters);
+        }
+        else if (pelmHwChild->nameEquals("USB"))
+        {
+            const xml::ElementNode *pelmUSBChild;
+
+            if ((pelmUSBChild = pelmHwChild->findChildElement("Controllers")))
+            {
+                xml::NodesLoop nl2(*pelmUSBChild, "Controller");
+                const xml::ElementNode *pelmCtrl;
+
+                while ((pelmCtrl = nl2.forAllNodes()))
+                {
+                    USBController ctrl;
+                    com::Utf8Str strCtrlType;
+
+                    pelmCtrl->getAttributeValue("name", ctrl.strName);
+
+                    if (pelmCtrl->getAttributeValue("type", strCtrlType))
+                    {
+                        if (strCtrlType == "OHCI")
+                            ctrl.enmType = USBControllerType_OHCI;
+                        else if (strCtrlType == "EHCI")
+                            ctrl.enmType = USBControllerType_EHCI;
+                        else
+                            throw ConfigFileError(this, pelmCtrl, N_("Invalid value '%s' for Controller/@type attribute"), strCtrlType.c_str());
+                    }
+
+                    hw.usbSettings.llUSBControllers.push_back(ctrl);
+                }
+            }
+
+            if ((pelmUSBChild = pelmHwChild->findChildElement("DeviceFilters")))
+                readUSBDeviceFilters(*pelmUSBChild, hw.usbSettings.llDeviceFilters);
         }
         else if (    (m->sv < SettingsVersion_v1_7)
@@ -4206,11 +4274,66 @@
     }
 
-    xml::ElementNode *pelmUSB = pelmHardware->createChild("USBController");
-    pelmUSB->setAttribute("enabled", hw.usbController.fEnabled);
-    pelmUSB->setAttribute("enabledEhci", hw.usbController.fEnabledEHCI);
-
-    buildUSBDeviceFilters(*pelmUSB,
-                          hw.usbController.llDeviceFilters,
-                          false);               // fHostMode
+    if (m->sv < SettingsVersion_v1_14)
+    {
+        bool fOhciEnabled = false;
+        bool fEhciEnabled = false;
+        xml::ElementNode *pelmUSB = pelmHardware->createChild("USBController");
+
+        for (USBControllerList::const_iterator it = hardwareMachine.usbSettings.llUSBControllers.begin();
+             it != hardwareMachine.usbSettings.llUSBControllers.end();
+             ++it)
+        {
+            const USBController &ctrl = *it;
+
+            switch (ctrl.enmType)
+            {
+                case USBControllerType_OHCI:
+                    fOhciEnabled = true;
+                    break;
+                case USBControllerType_EHCI:
+                    fEhciEnabled = true;
+                    break;
+                default:
+                    AssertMsgFailed(("Unknown USB controller type %d\n", ctrl.enmType));
+            }
+        }
+
+        pelmUSB->setAttribute("enabled", fOhciEnabled);
+        pelmUSB->setAttribute("enabledEhci", fEhciEnabled);
+
+        buildUSBDeviceFilters(*pelmUSB, hw.usbSettings.llDeviceFilters, false /* fHostMode */);
+    }
+    else
+    {
+        xml::ElementNode *pelmUSB = pelmHardware->createChild("USB");
+        xml::ElementNode *pelmCtrls = pelmUSB->createChild("Controllers");
+
+        for (USBControllerList::const_iterator it = hardwareMachine.usbSettings.llUSBControllers.begin();
+             it != hardwareMachine.usbSettings.llUSBControllers.end();
+             ++it)
+        {
+            const USBController &ctrl = *it;
+            com::Utf8Str strType;
+            xml::ElementNode *pelmCtrl = pelmCtrls->createChild("Controller");
+
+            switch (ctrl.enmType)
+            {
+                case USBControllerType_OHCI:
+                    strType = "OHCI";
+                    break;
+                case USBControllerType_EHCI:
+                    strType = "EHCI";
+                    break;
+                default:
+                    AssertMsgFailed(("Unknown USB controller type %d\n", ctrl.enmType));
+            }
+
+            pelmCtrl->setAttribute("name", ctrl.strName);
+            pelmCtrl->setAttribute("type", strType);
+        }
+
+        xml::ElementNode *pelmFilters = pelmUSB->createChild("DeviceFilters");
+        buildUSBDeviceFilters(*pelmFilters, hw.usbSettings.llDeviceFilters, false /* fHostMode */);
+    }
 
     xml::ElementNode *pelmNetwork = pelmHardware->createChild("Network");
@@ -5176,4 +5299,41 @@
     }
 
+    if (m->sv < SettingsVersion_v1_14)
+    {
+        unsigned cOhciCtrls = 0;
+        unsigned cEhciCtrls = 0;
+        bool fNonStdName = false;
+
+        for (USBControllerList::const_iterator it = hardwareMachine.usbSettings.llUSBControllers.begin();
+             it != hardwareMachine.usbSettings.llUSBControllers.end();
+             ++it)
+        {
+            const USBController &ctrl = *it;
+
+            switch (ctrl.enmType)
+            {
+                case USBControllerType_OHCI:
+                    cOhciCtrls++;
+                    if (ctrl.strName != "OHCI")
+                        fNonStdName = true;
+                    break;
+               case USBControllerType_EHCI:
+                    cEhciCtrls++;
+                    if (ctrl.strName != "EHCI")
+                        fNonStdName = true;
+                    break;
+                default:
+                    AssertMsgFailed(("Unknown USB controller type %d\n", ctrl.enmType));
+            }
+
+            /* Skip checking other controllers if the settings bump is necessary. */
+            if (cOhciCtrls > 1 || cEhciCtrls > 1 || fNonStdName)
+            {
+                m->sv = SettingsVersion_v1_14;
+                break;
+            }
+        }
+    }
+
     if (m->sv < SettingsVersion_v1_13)
     {
