<table cellspacing="0" cellpadding="0" border="0" ><tr><td valign="top" style="font: inherit;"><DIV>since there are other changes, so I post here manual changes, instead of a pacth file.</DIV>
<DIV> </DIV>
<DIV>The patch is attached as a text file, also shown as below:</DIV>
<DIV> </DIV>
<DIV>UIMachineWindow.h:</DIV>
<DIV>public:<BR> /* usb support, monitor usb device insertion */<BR>#ifdef Q_WS_WIN32<BR> QStringList m_hostUSBDevices; <BR> void updateHostUSBDeviceList(); <BR> QString getDriverKey(QString devId);<BR> QString getDeviceIdFromDriverKey(QString driverKey);<BR>#endif</DIV>
<DIV><BR>protected:</DIV>
<DIV> /* vmlite, usb support, monitor usb device insertion */<BR>#ifdef Q_WS_WIN32 <BR> void registerUSBDeviceNotification();<BR> void onDeviceChange(MSG *aMsg); <BR>#endif</DIV>
<DIV>UIMachineWindow.cpp:</DIV>
<DIV>#ifdef Q_WS_WIN32<BR>#include <Dbt.h><BR>#include <setupapi.h><BR>#endif</DIV>
<DIV>/* vmlite, usb support, monitor usb device insertion */<BR>#ifdef Q_WS_WIN32<BR>void UIMachineWindow::registerUSBDeviceNotification()<BR>{<BR> //return; // this disables USB insertion detection</DIV>
<DIV> const GUID GUID_DEVINTERFACE_USB_DEVICE =<BR> { 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };</DIV>
<DIV> const GUID GUID_DEVINTERFACE_HID =<BR> { 0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };</DIV>
<DIV> updateHostUSBDeviceList();</DIV>
<DIV> DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;<BR> ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );<BR> NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);<BR> NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; <BR> NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;<BR> HDEVNOTIFY hDevNotify = RegisterDeviceNotification(m_pMachineWindow->winId(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);</DIV>
<DIV> NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_HID;<BR> hDevNotify = RegisterDeviceNotification(m_pMachineWindow->winId(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);<BR>}</DIV>
<DIV>// sync the following with our usb drivers<BR>//#define VMLITE_USB_DEVICE_ID "USB\\VID_80EE&PID_CAFE"<BR>#define VMLITE_USB_DEVICE_ID "USB\\VMLITEUSBSTUB"</DIV>
<DIV>typedef struct _DEVICE_CHANGE_PARAMETER<BR>{<BR> UIMachineWindow* pThis;<BR> DWORD dbch_devicetype;<BR> WPARAM kind;<BR> WCHAR dbcc_name[MAX_PATH];</DIV>
<DIV>} DEVICE_CHANGE_PARAMETER, *PDEVICE_CHANGE_PARAMETER;</DIV>
<DIV>static DWORD WINAPI deviceChangeThreadProc(LPVOID Parameter)<BR>{<BR> PDEVICE_CHANGE_PARAMETER pDeviceChange = (PDEVICE_CHANGE_PARAMETER)Parameter;<BR> UIMachineWindow* pThis = pDeviceChange->pThis;<BR> WPARAM kind = pDeviceChange->kind; <BR> <BR> /* pDevInf->dbcc_name, e.g. <A href="file://\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed">\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed</A>}<BR> szDevId: USB#VID_04e8&PID_503b#0002F9A9828E0F06<BR> szClass: USB<BR> */<BR> // extract the devId portion, covert '#' to '\' <BR> QString devIdStr((QChar *)pDeviceChange->dbcc_name + 4, wcslen(pDeviceChange->dbcc_name + 4)); <BR> devIdStr = devIdStr.left(devIdStr.lastIndexOf('#'));<BR> devIdStr = devIdStr.replace('#', '\\');</DIV>
<DIV> free(pDeviceChange); </DIV>
<DIV> // address is the driver key, e.g., {36FC9E60-C465-11CF-8056-444553540000}\0025 <BR> QString address = pThis->getDriverKey(devIdStr);</DIV>
<DIV> // only hanlde devices that are really inserted, <BR> // when an attached device is released, arrival event will come here too, ignore such insertion<BR> if (pThis->m_hostUSBDevices.contains(address))<BR> { <BR> return -1;<BR> }<BR> <BR> /* Get HOST: */<BR> CHost host = vboxGlobal().virtualBox().GetHost();<BR> <BR> /* find the host usb device, and attach it, try 180 secs */<BR> for (int i=0; i<2 * 180; i++)<BR> {<BR> // this is extremely import, freezes otherwise<BR> QCoreApplication::processEvents();</DIV>
<DIV> /* Get USB devices list: */<BR> CHostUSBDeviceVector devices = host.GetUSBDevices();</DIV>
<DIV> foreach (const CHostUSBDevice hostDevice, devices)<BR> { <BR> if (hostDevice.GetAddress() == address)<BR> {<BR> /* Get current console: */<BR> CConsole console = pThis->session().GetConsole();<BR> CUSBDevice attachedDevice = console.FindUSBDeviceById(hostDevice.GetId());<BR> if (attachedDevice.isNull())<BR> {<BR> console.AttachUSBDevice(hostDevice.GetId()); <BR> return console.isOk() ? 0 : -1;<BR> }<BR> else<BR> { <BR> return -1;<BR> }<BR> }<BR> }</DIV>
<DIV> Sleep(500);<BR> }<BR> <BR> return -1;<BR>}</DIV>
<DIV>/* get driver key for the specified usb device id, from registry, so works even if device is off or deteched<BR> use registry to read the driver key, we don't use Setup api because the device is not active<BR>e.g., devId: USB\VID_046D&PID_C016\5&9e58382&0&1<BR>*/<BR>static QString getDriverKeyThroughRegistry(const QString& devId)<BR>{ <BR> WCHAR keyName[MAX_PATH];<BR> //e.g., HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_046D&PID_C016\5&9e58382&0&1<BR> swprintf(keyName, L"SYSTEM\\CurrentControlSet\\Enum\\%ls", (WCHAR *)devId.unicode());</DIV>
<DIV> HKEY hkey;<BR> long lret = RegOpenKeyW(HKEY_LOCAL_MACHINE, keyName, &hkey);<BR> if (lret != ERROR_SUCCESS) <BR> return "";</DIV>
<DIV> WCHAR driver[MAX_PATH];<BR> DWORD type;<BR> DWORD size = sizeof(driver);<BR> lret = RegQueryValueExW(hkey, L"Driver", 0, &type, (PBYTE)driver, &size);<BR> RegCloseKey(hkey);<BR> if (lret == ERROR_SUCCESS) <BR> {<BR> return QString((QChar *)driver, wcslen(driver));<BR> }<BR> else<BR> {<BR> return "";<BR> } <BR>}</DIV>
<DIV>void UIMachineWindow::onDeviceChange(MSG *aMsg)<BR>{<BR> if (aMsg->wParam != DBT_DEVICEREMOVECOMPLETE && aMsg->wParam != DBT_DEVICEARRIVAL)<BR> return;</DIV>
<DIV> PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)aMsg->lParam;</DIV>
<DIV> if ( pHdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE)<BR> { <BR> return;<BR> }</DIV>
<DIV> if ( DBT_DEVICEREMOVECOMPLETE == aMsg->wParam)<BR> {<BR> updateHostUSBDeviceList();</DIV>
<DIV> // need to remove the device that is just removed, in case our updated list still has it in the list<BR> PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;<BR> /* pDevInf->dbcc_name, e.g. <A href="file://\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed">\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed</A>} <BR> */ <BR> // extract the devId portion, covert '#' to '\' <BR> QString devIdStr((QChar *)pDevInf->dbcc_name + 4, wcslen(pDevInf->dbcc_name + 4)); <BR> devIdStr = devIdStr.left(devIdStr.lastIndexOf('#'));<BR> devIdStr = devIdStr.replace('#', '\\');</DIV>
<DIV> // address is the driver key, e.g., {36FC9E60-C465-11CF-8056-444553540000}\0025 <BR> QString address = getDriverKeyThroughRegistry(devIdStr); <BR> if (!address.isEmpty() && m_hostUSBDevices.contains(address))<BR> { <BR> m_hostUSBDevices.removeAll(address);<BR> } <BR> }<BR> else if ( DBT_DEVICEARRIVAL == aMsg->wParam)<BR> {<BR> PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;</DIV>
<DIV> if (!m_pMachineWindow->isActiveWindow())<BR> {<BR> updateHostUSBDeviceList();<BR> return;<BR> }<BR> <BR> /* pDevInf->dbcc_name, e.g. <A href="file://\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed">\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed</A>}<BR> szDevId: USB#VID_04e8&PID_503b#0002F9A9828E0F06<BR> szClass: USB<BR> */ <BR> // extract the devId portion, covert '#' to '\' <BR> QString devIdStr((QChar *)pDevInf->dbcc_name + 4, wcslen(pDevInf->dbcc_name + 4)); <BR> devIdStr = devIdStr.left(devIdStr.lastIndexOf('#'));<BR> devIdStr = devIdStr.replace('#', '\\');<BR> // when an usb device is attached, our vmlite virtualizazed usb will come here,
ignore them<BR> if (devIdStr.startsWith(VMLITE_USB_DEVICE_ID, Qt::CaseInsensitive))<BR> {<BR> updateHostUSBDeviceList();<BR> return;<BR> }</DIV>
<DIV> DWORD ThreadId;<BR> PDEVICE_CHANGE_PARAMETER param = (PDEVICE_CHANGE_PARAMETER)malloc(sizeof(DEVICE_CHANGE_PARAMETER));<BR> if (param)<BR> { <BR> param->pThis = this;<BR> param->dbch_devicetype = pHdr->dbch_devicetype;<BR> param->kind = aMsg->wParam;<BR> wcscpy(param->dbcc_name, pDevInf->dbcc_name);<BR> HANDLE ThreadHandle = CreateThread(<BR> NULL,<BR> 0,<BR> deviceChangeThreadProc,<BR> param,<BR> 0,<BR> &ThreadId
<BR> );<BR> }<BR> }<BR>}</DIV>
<DIV>/* get driver key for the original host usb device being attached from the attached device<BR>*/<BR>static QString getDriverKeyForOriginalDevice(const CHostUSBDevice& attachedDevice)<BR>{<BR> // the attached device and the host device have same vendor id, product id, etc.<BR> unsigned short vid = attachedDevice.GetVendorId();<BR> unsigned short pid = attachedDevice.GetProductId();</DIV>
<DIV> // for non attached usb device, address is the driver key, e.g., {36FC9E60-C465-11CF-8056-444553540000}\0025 <BR> // attached host device has address of device name<BR> QString address = attachedDevice.GetAddress();<BR> if (!address.startsWith("<A>\\\\?\\</A>"))<BR> {<BR> return address;<BR> }</DIV>
<DIV> /* pDevInf->dbcc_name, e.g. <A href="file://\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed">\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed</A>}<BR> szDevId: USB#VID_04e8&PID_503b#0002F9A9828E0F06 <BR> */ <BR> address = address.right(address.length() - 4);</DIV>
<DIV> int pos = address.lastIndexOf('#');<BR> address = address.left(pos);</DIV>
<DIV> // the string after 2nd # is the serial #, same as the original device being attached<BR> pos = address.indexOf("#");<BR> address = address.right(address.length() - pos - 1);<BR> pos = address.indexOf("#");<BR> address = address.right(address.length() - pos - 1);</DIV>
<DIV> WCHAR *serial = (WCHAR *)address.unicode(); </DIV>
<DIV> // use registry to read the driver key, we don't use Setup api because the device is not active<BR> // e.g., HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_046D&PID_C016\5&9e58382&0&1<BR> WCHAR devId[MAX_PATH];<BR> swprintf(devId, L"SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_%04x&PID_%04x\\%ls", vid, pid, serial);</DIV>
<DIV> HKEY hkey;<BR> long lret = RegOpenKeyW(HKEY_LOCAL_MACHINE, devId, &hkey);<BR> if (lret != ERROR_SUCCESS) <BR> return "";</DIV>
<DIV> WCHAR driver[MAX_PATH];<BR> DWORD type;<BR> DWORD size = sizeof(driver);<BR> lret = RegQueryValueExW(hkey, L"Driver", 0, &type, (PBYTE)driver, &size);<BR> RegCloseKey(hkey);<BR> if (lret == ERROR_SUCCESS) <BR> {<BR> return QString((QChar *)driver, wcslen(driver));<BR> }<BR> else<BR> {<BR> return "";<BR> } <BR>}</DIV>
<DIV>void UIMachineWindow::updateHostUSBDeviceList()<BR>{<BR> m_hostUSBDevices.clear();</DIV>
<DIV> /* Get HOST: */<BR> CHost host = vboxGlobal().virtualBox().GetHost();<BR> <BR> /* Get USB devices list: */<BR> CHostUSBDeviceVector devices = host.GetUSBDevices(); </DIV>
<DIV> foreach (const CHostUSBDevice hostDevice, devices)<BR> {<BR> // address is the driver key, e.g., {36FC9E60-C465-11CF-8056-444553540000}\0025 <BR> QString address = hostDevice.GetAddress();</DIV>
<DIV> if (address.startsWith("<A>\\\\?\\</A>")) /* attached host device has address of device name */<BR> { <BR> address = getDriverKeyForOriginalDevice(hostDevice); <BR> }<BR> <BR> m_hostUSBDevices << address;<BR> }<BR>}</DIV>
<DIV>/* <BR>Get driver key from a usb id, devId: USB\Vid_04e8&Pid_503b\0002F9A9828E0F06<BR>we use driver key to identify a host usb device, as this is unique, <BR>vid/pid/serial is not unique because serial might be emppty<BR>*/<BR>QString UIMachineWindow::getDriverKey(QString devId)<BR>{<BR> HDEVINFO hDevInfo = SetupDiGetClassDevsW(NULL, L"USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);<BR> if( INVALID_HANDLE_VALUE == hDevInfo ) <BR> {<BR> return "";<BR> }</DIV>
<DIV> WCHAR driverKey[MAX_PATH] = L"";<BR> SP_DEVINFO_DATA spDevInfoData;<BR> spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);<BR> for(int i=0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++) <BR> {<BR> DWORD nSize = 0;<BR> WCHAR buf[MAX_PATH];<BR> if ( !SetupDiGetDeviceInstanceIdW(hDevInfo, &spDevInfoData, buf, sizeof(buf), &nSize) ) <BR> return "";</DIV>
<DIV> if (0 == QString((QChar *)buf, wcslen(buf)).compare(devId, Qt::CaseInsensitive))<BR> {<BR> nSize = 0;<BR> if ( SetupDiGetDeviceRegistryPropertyW(hDevInfo, &spDevInfoData, <BR> SPDRP_DRIVER, NULL, (PBYTE)buf, sizeof(buf), &nSize) ) <BR> {<BR> wcscpy(driverKey, buf);<BR> }<BR> break;<BR> }<BR> }</DIV>
<DIV> SetupDiDestroyDeviceInfoList(hDevInfo);</DIV>
<DIV> if (driverKey[0])<BR> return QString((QChar *)driverKey, wcslen(driverKey));<BR> else<BR> return "";<BR>}</DIV>
<DIV>/* <BR>Get usb id from driver key, devId: USB\Vid_04e8&Pid_503b\0002F9A9828E0F06, driver key: {36FC9E60-C465-11CF-8056-444553540000}\0025<BR>*/<BR>QString UIMachineWindow::getDeviceIdFromDriverKey(QString driverKey)<BR>{<BR> HDEVINFO hDevInfo = SetupDiGetClassDevsW(NULL, L"USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);<BR> if( INVALID_HANDLE_VALUE == hDevInfo ) <BR> {<BR> return "";<BR> }</DIV>
<DIV> WCHAR deviceId[MAX_PATH] = L"";<BR> SP_DEVINFO_DATA spDevInfoData;<BR> spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);<BR> for(int i=0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++) <BR> {<BR> DWORD nSize = 0;<BR> WCHAR buf[MAX_PATH];<BR> if ( !SetupDiGetDeviceInstanceIdW(hDevInfo, &spDevInfoData, buf, sizeof(buf), &nSize) ) <BR> return "";</DIV>
<DIV> wcscpy(deviceId, buf);</DIV>
<DIV> nSize = 0;<BR> if ( SetupDiGetDeviceRegistryPropertyW(hDevInfo, &spDevInfoData, <BR> SPDRP_DRIVER, NULL, (PBYTE)buf, sizeof(buf), &nSize) ) <BR> {<BR> if (0 == QString((QChar *)buf, wcslen(buf)).compare(driverKey, Qt::CaseInsensitive))<BR> { <BR> break;<BR> } <BR> }</DIV>
<DIV> deviceId[0] = 0;<BR> }</DIV>
<DIV> SetupDiDestroyDeviceInfoList(hDevInfo);</DIV>
<DIV> if (deviceId[0])<BR> return QString((QChar *)deviceId, wcslen(deviceId));<BR> else<BR> return "";<BR>}</DIV>
<DIV>#endif /* Q_WS_WIN32 */</DIV>
<DIV><BR>UIMachineWindowNormal.cpp:</DIV>
<DIV>UIMachineWindowNormal::UIMachineWindowNormal(UIMachineLogic *pMachineLogic, ulong uScreenId)<BR> : QIWithRetranslateUI2<QMainWindow>(0, Qt::Window)<BR> , UIMachineWindow(pMachineLogic, uScreenId)<BR> , m_pIndicatorsPool(new UIIndicatorsPool(pMachineLogic->uisession()->session(), this))<BR> , m_pIdleTimer(0)<BR>{<BR>........</DIV>
<DIV>// add as last line</DIV>
<DIV>/* vmlite, usb and dnd support, monitor usb device insertion */<BR>#ifdef Q_WS_WIN32 <BR> registerUSBDeviceNotification();<BR>#endif<BR>}</DIV>
<DIV>UIMachineWindowFullscreen.cpp:</DIV>
<DIV>UIMachineWindowFullscreen::UIMachineWindowFullscreen(UIMachineLogic *pMachineLogic, ulong uScreenId)<BR> : QIWithRetranslateUI2<QMainWindow>(0, Qt::FramelessWindowHint)<BR> , UIMachineWindow(pMachineLogic, uScreenId)<BR> , m_pMainMenu(0)<BR> , m_pMiniToolBar(0)<BR>{<BR>........</DIV>
<DIV>// add as last line</DIV>
<DIV>/* vmlite, usb and dnd support, monitor usb device insertion */<BR>#ifdef Q_WS_WIN32 <BR> registerUSBDeviceNotification();<BR>#endif<BR>}<BR></DIV>
<DIV><BR>--- On <B>Thu, 9/15/11, Michael Thayer <I><michael.thayer@oracle.com></I></B> wrote:<BR></DIV>
<BLOCKQUOTE style="BORDER-LEFT: rgb(16,16,255) 2px solid; PADDING-LEFT: 5px; MARGIN-LEFT: 5px"><BR>From: Michael Thayer <michael.thayer@oracle.com><BR>Subject: Re: [vbox-dev] code patch to auto detect USB insertion<BR>To: "Huihong Luo" <huisinro@yahoo.com><BR>Cc: vbox-dev@virtualbox.org<BR>Date: Thursday, September 15, 2011, 2:31 AM<BR><BR>
<DIV class=plainMail>Hello Huihong,<BR><BR>On 09/13/2011 11:49 PM, Huihong Luo wrote:<BR>> I have some code (around 600 lines) that auto attaches usb device when<BR>> inserted to the windows host while vm window is on focus, similar to<BR>> vmware's handling.<BR>> not sure if vbox team wants to integrate this patch.<BR>We might do if it is something which can be enabled or disabled by the user, but we would have to see the patch first (the usual requirements apply [1]). Would you like to include it?<BR><BR>Regards and thanks,<BR><BR>Michael<BR><BR>[1] <A href="http://www.virtualbox.org/wiki/Contributor_information" target=_blank>http://www.virtualbox.org/wiki/Contributor_information</A><BR>-- ORACLE Deutschland B.V. & Co. KG Michael Thayer<BR>Werkstrasse 24 VirtualBox engineering<BR>71384 Weinstadt, Germany
mailto:<A href="http://us.mc1603.mail.yahoo.com/mc/compose?to=michael.thayer@oracle.com" ymailto="mailto:michael.thayer@oracle.com">michael.thayer@oracle.com</A><BR><BR>Hauptverwaltung: Riesstr. 25, D-80992 München<BR>Registergericht: Amtsgericht München, HRA 95603<BR><BR>Komplementärin: ORACLE Deutschland Verwaltung B.V.<BR>Hertogswetering 163/167, 3543 AS Utrecht, Niederlande<BR>Handelsregister der Handelskammer Midden-Niederlande, Nr. 30143697<BR>Geschäftsführer: Jürgen Kunz, Marcel van de Molen, Alexander van der Ven<BR></DIV></BLOCKQUOTE></td></tr></table>