Index: /trunk/src/VBox/Frontends/VirtualBox/include/VBoxConsoleWnd.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/include/VBoxConsoleWnd.h	(revision 280)
+++ /trunk/src/VBox/Frontends/VirtualBox/include/VBoxConsoleWnd.h	(revision 281)
@@ -202,4 +202,5 @@
         devicesMountDVDMenuId,
         devicesUSBMenuId,
+        devicesUSBMenuNoDevicesId,
 #ifdef VBOX_WITH_DEBUGGER_GUI
         dbgMenuId,
Index: /trunk/src/VBox/Frontends/VirtualBox/include/VBoxGlobal.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/include/VBoxGlobal.h	(revision 280)
+++ /trunk/src/VBox/Frontends/VirtualBox/include/VBoxGlobal.h	(revision 281)
@@ -278,4 +278,10 @@
     }
 
+    QString toString (CEnums::USBDeviceState aState) const
+    {
+        AssertMsg (!USBDeviceStates [aState].isNull(), ("No text for %d", aState));
+        return USBDeviceStates [aState];
+    }
+
     QPixmap snapshotIcon (bool online) const
     {
@@ -283,13 +289,16 @@
     }
 
-    // details generators
+    /* details generators */
 
     QString details (const CHardDisk &aHD, bool aPredict = false) const;
 
+    QString details (const CUSBDevice &aDevice) const;
+    QString toolTip (const CUSBDevice &aDevice) const;
+
     QString prepareFileNameForHTML (const QString &fn) const;
 
     QString detailsReport (const CMachine &m, bool isNewVM, bool withLinks) const;
 
-    // VirtualBox helpers
+    /* VirtualBox helpers */
 
     CSession openSession (const QUuid &id);
@@ -304,11 +313,12 @@
     VBoxMediaList currentMediaList() const { return media_list; }
 
-    // various helpers
+    /* various helpers */
 
     void languageChange();
 
-    void cleanup(); // made public for internal purposes
-
-    // public static stuff
+    /* made public for internal purposes */
+    void cleanup();
+
+    /* public static stuff */
 
     static QIconSet iconSet (const char *aNormal,
@@ -345,7 +355,7 @@
     void mediaEnumerated (const VBoxMediaList &list);
 
-    // signals emitted when the VirtualBox callback is called by the server
-    // (not that currently these signals are emitted only when the application
-    //  is the in the VM selector mode)
+    /* signals emitted when the VirtualBox callback is called by the server
+     * (not that currently these signals are emitted only when the application
+     * is the in the VM selector mode) */
 
     void machineStateChanged (const VBoxMachineStateChangeEvent &e);
@@ -414,4 +424,5 @@
     QStringVector audioDriverTypes;
     QStringVector networkAttachmentTypes;
+    QStringVector USBDeviceStates;
 
     mutable bool detailReportTemplatesReady;
@@ -423,4 +434,4 @@
 inline VBoxGlobal &vboxGlobal() { return VBoxGlobal::instance(); }
 
-#endif // __VBoxGlobal_h__
-
+#endif /* __VBoxGlobal_h__ */
+
Index: /trunk/src/VBox/Frontends/VirtualBox/include/VBoxProblemReporter.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/include/VBoxProblemReporter.h	(revision 280)
+++ /trunk/src/VBox/Frontends/VirtualBox/include/VBoxProblemReporter.h	(revision 281)
@@ -180,4 +180,7 @@
 #endif
 
+    void cannotAttachUSBDevice (const CConsole &console, const QString &device);
+    void cannotDetachUSBDevice (const CConsole &console, const QString &device);
+
     bool confirmReleaseImage (QWidget*, QString);
 
Index: /trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleWnd.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleWnd.cpp	(revision 280)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleWnd.cpp	(revision 281)
@@ -71,33 +71,45 @@
 public:
 
-    VBoxUSBLedTip (QWidget *aWidget, const CSession &aSession) :
-        QToolTip (aWidget), mSession (aSession) {}
+    VBoxUSBLedTip (QWidget *aWidget, const CConsole &aConsole, bool aUSBEnabled) :
+        QToolTip (aWidget), mConsole (aConsole), mUSBEnabled (aUSBEnabled) {}
+
     ~VBoxUSBLedTip() { remove (parentWidget()); }
-
+    
 protected:
 
     void maybeTip (const QPoint &/* aPoint */)
     {
-        CUSBDeviceEnumerator en = mSession.GetConsole().GetUSBDevices().Enumerate();
+        QString toolTip = VBoxConsoleWnd::tr (
+            "<qt>Indicates&nbsp;the&nbsp;activity&nbsp;of&nbsp;"
+            "attached&nbsp;USB&nbsp;devices<br>"
+            "%1</qt>",
+            "USB device indicator");
+
         QString devices;
-        while (en.HasMore())
-        {
-            CUSBDevice usb = en.GetNext();
-            devices += QString ("[<b><nobr>%1 %2 (%3)</nobr></b>]<br>")
-                               .arg (usb.GetManufacturer())
-                               .arg (usb.GetProduct())
-                               .arg (usb.GetRevision());
-        }
-        QString toolTip = QObject::tr (
-            "<qt>Indicates&nbsp;the&nbsp;activity&nbsp;of&nbsp;"
-            "the&nbsp;attached&nbsp;USB&nbsp;devices"
-            "<br>%1</qt>"
-        );
-        if (devices.isNull())
-            devices += QObject::tr ("[<b>not attached</b>]");
+
+        if (mUSBEnabled)
+        {
+            CUSBDeviceEnumerator en = mConsole.GetUSBDevices().Enumerate();
+            while (en.HasMore())
+            {
+                CUSBDevice usb = en.GetNext();
+                devices += QString ("[<b><nobr>%1</nobr></b>]<br>")
+                                    .arg (vboxGlobal().details (usb));
+            }
+            if (devices.isNull())
+                devices = VBoxConsoleWnd::tr ("<nobr>[<b>not attached</b>]</nobr>",
+                                              "USB device indicator");
+        }
+        else
+            devices = VBoxConsoleWnd::tr ("<nobr>[<b>USB Controller is disabled</b>]</nobr>",
+                                          "USB device indicator");
+
         tip (parentWidget()->rect(), toolTip.arg (devices));
     }
 
-    const CSession &mSession;
+private:
+
+    CConsole mConsole;
+    bool mUSBEnabled;
 };
 
@@ -293,4 +305,5 @@
     devicesMenu->insertItem (VBoxGlobal::iconSet ("usb_16px.png", "usb_disabled_16px.png"),
         QString::null, devicesUSBMenu, devicesUSBMenuId);
+    devicesMenu->insertSeparator();
     devicesInstallGuestToolsAction->addTo (devicesMenu);
     menuBar()->insertItem (QString::null, devicesMenu, devicesMenuId);
@@ -451,5 +464,6 @@
 VBoxConsoleWnd::~VBoxConsoleWnd()
 {
-    delete mUsbLedTip;
+    if (mUsbLedTip)
+        delete mUsbLedTip;
 }
 
@@ -561,7 +575,8 @@
 
     /* initialize usb stuff */
-    bool isUsbAvailable = cmachine.GetUSBController().GetEnabled();
-    devicesMenu->setItemVisible (devicesUSBMenuId, isUsbAvailable);
-    mUsbLedTip = new VBoxUSBLedTip (usb_light, csession);
+    bool isUSBEnabled = cmachine.GetUSBController().GetEnabled();
+    devicesUSBMenu->setEnabled (isUSBEnabled);
+    usb_light->setState (CEnums::InvalidActivity);
+    mUsbLedTip = new VBoxUSBLedTip (usb_light, cconsole, isUSBEnabled);
 
     /* start an idle timer that will update device lighths */
@@ -1778,4 +1793,6 @@
 
     devicesUSBMenu->clear();
+    hostUSBMap.clear();
+
     CHost host = vboxGlobal().virtualBox().GetHost();
 
@@ -1783,6 +1800,8 @@
     if (isUSBEmpty)
     {
-        int id = devicesUSBMenu->insertItem (tr ("[No device attached to host]"));
-        devicesUSBMenu->setItemEnabled (id, !isUSBEmpty);
+        devicesUSBMenu->insertItem (
+            tr ("<no available devices>", "USB devices"),
+            devicesUSBMenuNoDevicesId);
+        devicesUSBMenu->setItemEnabled (devicesUSBMenuNoDevicesId, false);
         return;
     }
@@ -1793,8 +1812,5 @@
         CHostUSBDevice iterator = en.GetNext();
         CUSBDevice usb = CUnknown (iterator);
-        int id = devicesUSBMenu->insertItem (QString ("%1 %2 [%3]")
-                                             .arg (usb.GetManufacturer())
-                                             .arg (usb.GetProduct())
-                                             .arg (usb.GetRevision()));
+        int id = devicesUSBMenu->insertItem (vboxGlobal().details (usb));
         hostUSBMap [id] = usb;
         CUSBDevice attachedUSB =
@@ -1859,12 +1875,37 @@
     if (!console) return;
 
+    CConsole cconsole = csession.GetConsole();
+    AssertWrapperOk (csession);
+
+    /* the <no available devices> item should be always disabled */
+    AssertReturnVoid (id != devicesUSBMenuNoDevicesId);
+    
     CUSBDevice usb = hostUSBMap [id];
-    /* if null then some other item but usb device is selected */
-    if (usb.isNull()) return;
+    /* if null then some other item but a USB device is selected */
+    if (usb.isNull())
+        return;
 
     if (devicesUSBMenu->isItemChecked (id))
-        csession.GetConsole().DetachUSBDevice (usb.GetId());
+    {
+        cconsole.DetachUSBDevice (usb.GetId());
+        if (!cconsole.isOk())
+        {
+            /// @todo (r=dmik) the dialog should be either modeless
+            //  or we have to pause the VM
+            vboxProblem().cannotDetachUSBDevice (cconsole,
+                                                 vboxGlobal().details (usb));
+        }
+    }
     else
-        csession.GetConsole().AttachUSBDevice (usb.GetId());
+    {
+        cconsole.AttachUSBDevice (usb.GetId());
+        if (!cconsole.isOk())
+        {
+            /// @todo (r=dmik) the dialog should be either modeless
+            //  or we have to pause the VM
+            vboxProblem().cannotAttachUSBDevice (cconsole,
+                                                 vboxGlobal().details (usb));
+        }
+    }
 }
 
@@ -1876,11 +1917,23 @@
     if (!console) return;
 
+    /* the <no available devices> item is highlighted */
+    if (id == devicesUSBMenuNoDevicesId)
+    {
+        QToolTip::add (devicesUSBMenu,
+            tr ("No supported devices connected to the host PC",
+                "USB device tooltip"));
+        return;
+    }
+    
     CUSBDevice usb = hostUSBMap [id];
-    /* if null then some other item but usb device is selected */
-    if (usb.isNull()) return;
-
-    QString tip = tr ("Vendor ID: %1\nProduct ID: %2\nSerial Number: %3")
-        .arg (usb.GetVendorId()).arg (usb.GetProductId()).arg (usb.GetSerialNumber());
-    QToolTip::remove (devicesUSBMenu);
+    /* if null then some other item but a USB device is highlighted */
+    if (usb.isNull())
+    {
+        QToolTip::remove (devicesUSBMenu);
+        return;
+    }
+
+    QString tip = vboxGlobal().toolTip (usb);
+
     QToolTip::add (devicesUSBMenu, tip);
 }
@@ -1890,5 +1943,5 @@
     if (ind == cd_light)
     {
-        // set "this is a context menu" flag
+        /* set "this is a context menu" flag */
         devicesMenu->setItemParameter (devicesMountDVDMenuId, 1);
         devicesMountDVDMenu->exec (e->globalPos());
@@ -1898,5 +1951,5 @@
     if (ind == fd_light)
     {
-        // set "this is a context menu" flag
+        /* set "this is a context menu" flag */
         devicesMenu->setItemParameter (devicesMountFloppyMenuId, 1);
         devicesMountFloppyMenu->exec (e->globalPos());
@@ -1906,8 +1959,11 @@
     if (ind == usb_light)
     {
-        // set "this is a context menu" flag
-        devicesMenu->setItemParameter (devicesUSBMenuId, 1);
-        devicesUSBMenu->exec (e->globalPos());
-        devicesMenu->setItemParameter (devicesUSBMenuId, 0);
+        if (devicesUSBMenu->isEnabled())
+        {
+            /* set "this is a context menu" flag */
+            devicesMenu->setItemParameter (devicesUSBMenuId, 1);
+            devicesUSBMenu->exec (e->globalPos());
+            devicesMenu->setItemParameter (devicesUSBMenuId, 0);
+        }
     }
 }
Index: /trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp	(revision 280)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp	(revision 281)
@@ -329,4 +329,5 @@
     , audioDriverTypes (CEnums::AudioDriverType_COUNT)
     , networkAttachmentTypes (CEnums::NetworkAttachmentType_COUNT)
+    , USBDeviceStates (CEnums::USBDeviceState_COUNT)
     , detailReportTemplatesReady (false)
 {
@@ -588,4 +589,58 @@
     
     return details;
+}
+
+/**
+ *  Returns the details of the given USB device as a single-line string.
+ */
+QString VBoxGlobal::details (const CUSBDevice &aDevice) const
+{
+    QString details;
+    QString m = aDevice.GetManufacturer();
+    QString p = aDevice.GetProduct();
+    if (m.isEmpty() && p.isEmpty())
+        details += QString().sprintf (
+            tr ("Unknown device %04hX:%04hX", "USB device details"),
+            aDevice.GetVendorId(), aDevice.GetProductId());
+    else
+    {
+        if (!m.isEmpty())
+            details += m;
+        if (!p.isEmpty())
+            details += " " + p;
+    }
+    ushort r = aDevice.GetRevision();                    
+    if (r != 0)
+        details += QString().sprintf (" [%04hX]", r);
+
+    return details;        
+}
+
+/**
+ *  Returns the multi-line description of the given USB device.
+ */
+QString VBoxGlobal::toolTip (const CUSBDevice &aDevice) const
+{
+    QString tip = QString().sprintf (
+        tr ("<nobr>Vendor ID: %04hX</nobr><br>"
+            "<nobr>Product ID: %04hX</nobr><br>"
+            "<nobr>Revision: %04hX</nobr>", "USB device tooltip"),
+            aDevice.GetVendorId(), aDevice.GetProductId(),
+            aDevice.GetRevision());
+
+    QString ser = aDevice.GetSerialNumber();
+    if (!ser.isEmpty())
+        tip += QString (tr ("<br><nobr>Serial No. %1</nobr>", "USB device tooltip"))
+                        .arg (ser);
+
+    /* add the state field if it's a host USB device */
+    CHostUSBDevice hostDev = CUnknown (aDevice);
+    if (!hostDev.isNull())
+    {
+        tip += QString (tr ("<br><nobr>State: %1</nobr>", "USB device tooltip"))
+                        .arg (vboxGlobal().toString (hostDev.GetState()));
+    }
+                        
+    return tip;        
 }
 
@@ -1164,4 +1219,17 @@
     networkAttachmentTypes [CEnums::HostInterfaceNetworkAttachment] =
         tr ("Host Interface", "NetworkAttachmentType");
+
+    USBDeviceStates [CEnums::USBDeviceNotSupported] =
+        tr ("Not supported", "USBDeviceState");
+    USBDeviceStates [CEnums::USBDeviceUnavailable] =
+        tr ("Unavailable", "USBDeviceState");
+    USBDeviceStates [CEnums::USBDeviceBusy] =
+        tr ("Busy", "USBDeviceState");
+    USBDeviceStates [CEnums::USBDeviceAvailable] =
+        tr ("Available", "USBDeviceState");
+    USBDeviceStates [CEnums::USBDeviceHeld] =
+        tr ("Held", "USBDeviceState");
+    USBDeviceStates [CEnums::USBDeviceCaptured] =
+        tr ("Captured", "USBDeviceState");
 
     detailReportTemplatesReady = false;
Index: /trunk/src/VBox/Frontends/VirtualBox/src/VBoxProblemReporter.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/VBoxProblemReporter.cpp	(revision 280)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/VBoxProblemReporter.cpp	(revision 281)
@@ -1101,4 +1101,32 @@
 #endif
 
+void VBoxProblemReporter::cannotAttachUSBDevice (const CConsole &console,
+                                                 const QString &device)
+{
+    /* preserve the current error info before calling the object again */
+    COMErrorInfo errInfo = console.errorInfo();
+
+    message (&vboxGlobal().consoleWnd(), Error,
+        tr ("Failed to attach the USB device <b>%1</b> "
+            "to the virtual machine <b>%2</b>.")
+            .arg (device)
+            .arg (console.GetMachine().GetName()),
+        formatErrorInfo (errInfo));
+}
+
+void VBoxProblemReporter::cannotDetachUSBDevice (const CConsole &console,
+                                                 const QString &device)
+{
+    /* preserve the current error info before calling the object again */
+    COMErrorInfo errInfo = console.errorInfo();
+
+    message (&vboxGlobal().consoleWnd(), Error,
+        tr ("Failed to detach the USB device <b>%1</b> "
+            "from the virtual machine <b>%2</b>.")
+            .arg (device)
+            .arg (console.GetMachine().GetName()),
+        formatErrorInfo (errInfo));
+}
+
 /** @return false if the dialog wasn't actually shown (i.e. it was autoconfirmed) */
 bool VBoxProblemReporter::remindAboutInputCapture()
@@ -1288,15 +1316,15 @@
             console.Pause();
         type = Critical;
-        severity = tr ("Fatal Error", "runtime error info");
+        severity = tr ("<nobr>Fatal Error</nobr>", "runtime error info");
     }
     else if (state == CEnums::Paused)
     {
         type = Error;
-        severity = tr ("Non-Fatal Error", "runtime error info");
+        severity = tr ("<nobr>Non-Fatal Error</nobr>", "runtime error info");
     }
     else
     {
         type = Warning;
-        severity = tr ("Warning", "runtime error info");
+        severity = tr ("<nobr>Warning</nobr>", "runtime error info");
     }
     
@@ -1316,7 +1344,7 @@
                               "<tr><td>%3</td><td>%4</td></tr>"
                               "</table>")
-                              .arg (tr ("Error ID: ", "runtime error info"),
+                              .arg (tr ("<nobrl>Error ID: </nobr>", "runtime error info"),
                                     errorID)
-                              .arg (tr ("Error Severity: ", "runtime error info"),
+                              .arg (tr ("Severity: ", "runtime error info"),
                                     severity);
     
