VirtualBox

Changeset 3034 in vbox


Ignore:
Timestamp:
Jun 4, 2007 3:51:26 PM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
21789
Message:

Main: Fixed async USB (added proper detection of device re-cycle on Win32; changed manual release sequence so that a detach is made in VMM first, the USB proxy is notified afterwards on success; some other small fixes).

Location:
trunk/src/VBox/Main
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r3007 r3034  
    19471947            tr ("The virtual machine does not have a USB controller"));
    19481948
     1949    /* leave the lock because the USB Proxy service may call us back
     1950     * (via onUSBDeviceAttach()) */
     1951    alock.leave();
     1952
    19491953    /* Request the device capture */
    19501954    HRESULT rc = mControl->CaptureUSBDevice (aId);
     
    19821986            Guid (aId).raw());
    19831987
    1984     /* Request the device release */
    1985     HRESULT rc = mControl->ReleaseUSBDevice (aId);
    1986     CheckComRCReturnRC (rc);
     1988    /* First, request VMM to detach the device */
     1989    HRESULT rc = detachUSBDevice (it);
     1990
     1991    if (SUCCEEDED (rc))
     1992    {
     1993        /* leave the lock since we don't need it any more (note though that
     1994         * the USB Proxy service must not call us back here) */
     1995        alock.leave();
     1996
     1997        /* Request the device release. Even if it fails, the device will
     1998         * remain as held by proxy, which is OK for us (the VM process). */
     1999        rc = mControl->ReleaseUSBDevice (aId);
     2000    }
    19872001
    19882002    return rc;
     
    32173231    ComAssertRet (pRhConfig, E_FAIL);
    32183232
     3233    HRESULT rc = attachUSBDevice (aDevice, pRhConfig);
     3234
    32193235    /// @todo notify listeners of IConsoleCallback in case of error
    3220     return attachUSBDevice (aDevice, pRhConfig);
     3236    return rc;
    32213237}
    32223238
     
    32733289    }
    32743290
    3275     /* protect mpVM */
    3276     AutoVMCaller autoVMCaller (this);
    3277     CheckComRCReturnRC (autoVMCaller.rc());
    3278 
    3279     PPDMIBASE pBase = NULL;
    3280     int vrc = PDMR3QueryLun (mpVM, "usb-ohci", 0, 0, &pBase);
    3281 
    3282     /* if the device is attached, then there must be a USB controller */
    3283     AssertRCReturn (vrc, E_FAIL);
    3284 
    3285     PVUSBIRHCONFIG pRhConfig = (PVUSBIRHCONFIG) pBase->
    3286         pfnQueryInterface (pBase, PDMINTERFACE_VUSB_RH_CONFIG);
    3287     AssertReturn (pRhConfig, E_FAIL);
    3288 
    3289     LogFlowThisFunc (("Detaching USB proxy device {%Vuuid}...\n", Uuid.raw()));
    3290 
    3291     /* leave the lock before a VMR3* call (EMT will call us back)! */
    3292     alock.leave();
    3293 
    3294     PVMREQ pReq;
    3295     vrc = VMR3ReqCall (mpVM, &pReq, RT_INDEFINITE_WAIT,
    3296                        (PFNRT) usbDetachCallback, 5,
    3297                        this, &it, pRhConfig, Uuid.raw());
    3298     if (VBOX_SUCCESS (vrc))
    3299         vrc = pReq->iStatus;
    3300     VMR3ReqFree (pReq);
    3301 
    3302     AssertRC (vrc);
     3291    HRESULT rc = detachUSBDevice (it);
    33033292
    33043293    /// @todo notify listeners of IConsoleCallback in case of error
    3305     return VBOX_SUCCESS (vrc) ? S_OK : E_FAIL;
     3294    return rc;
    33063295}
    33073296
     
    41784167 *  @param aHostDevice  device to attach
    41794168 *
    4180  *  @note Locks this object for writing.
    41814169 *  @note Synchronously calls EMT.
     4170 *  @note Must be called from under this object's lock.
    41824171 */
    41834172HRESULT Console::attachUSBDevice (IUSBDevice *aHostDevice, PVUSBIRHCONFIG aConfig)
     
    41854174    AssertReturn (aHostDevice && aConfig, E_FAIL);
    41864175
     4176    AssertReturn (isLockedOnCurrentThread(), E_FAIL);
     4177
     4178    /* still want a lock object because we need to leave it */
    41874179    AutoLock alock (this);
    41884180
     
    43284320    LogFlowFuncLeave();
    43294321    return vrc;
     4322}
     4323
     4324/**
     4325 *  Sends a request to VMM to detach the given host device.  After this method
     4326 *  succeeds, the detached device will disappear from the mUSBDevices
     4327 *  collection.
     4328 *
     4329 *  @param aIt  Iterator pointing to the device to detach.
     4330 *
     4331 *  @note Synchronously calls EMT.
     4332 *  @note Must be called from under this object's lock.
     4333 */
     4334HRESULT Console::detachUSBDevice (USBDeviceList::iterator &aIt)
     4335{
     4336    AssertReturn (isLockedOnCurrentThread(), E_FAIL);
     4337
     4338    /* still want a lock object because we need to leave it */
     4339    AutoLock alock (this);
     4340
     4341    /* protect mpVM */
     4342    AutoVMCaller autoVMCaller (this);
     4343    CheckComRCReturnRC (autoVMCaller.rc());
     4344
     4345    PPDMIBASE pBase = NULL;
     4346    int vrc = PDMR3QueryLun (mpVM, "usb-ohci", 0, 0, &pBase);
     4347
     4348    /* if the device is attached, then there must be a USB controller */
     4349    AssertRCReturn (vrc, E_FAIL);
     4350
     4351    PVUSBIRHCONFIG pRhConfig = (PVUSBIRHCONFIG) pBase->
     4352        pfnQueryInterface (pBase, PDMINTERFACE_VUSB_RH_CONFIG);
     4353    AssertReturn (pRhConfig, E_FAIL);
     4354
     4355    LogFlowThisFunc (("Detaching USB proxy device {%Vuuid}...\n",
     4356                      (*aIt)->id().raw()));
     4357
     4358    /* leave the lock before a VMR3* call (EMT will call us back)! */
     4359    alock.leave();
     4360
     4361    PVMREQ pReq;
     4362    vrc = VMR3ReqCall (mpVM, &pReq, RT_INDEFINITE_WAIT,
     4363                       (PFNRT) usbDetachCallback, 5,
     4364                       this, &aIt, pRhConfig, (*aIt)->id().raw());
     4365    if (VBOX_SUCCESS (vrc))
     4366        vrc = pReq->iStatus;
     4367    VMR3ReqFree (pReq);
     4368
     4369    ComAssertRCRet (vrc, E_FAIL);
     4370
     4371    return S_OK;
    43304372}
    43314373
  • trunk/src/VBox/Main/HostImpl.cpp

    r3001 r3034  
    13151315    /* re-apply filters on the device before giving it back to the host */
    13161316    device->setHeld();
    1317     HRESULT rc = applyAllUSBFilters (device);
     1317    HRESULT rc = applyAllUSBFilters (device, aMachine);
    13181318    ComAssertComRC (rc);
    13191319
     
    13971397                 * host */
    13981398                device->setHeld();
    1399                 HRESULT rc = applyAllUSBFilters (device);
     1399                HRESULT rc = applyAllUSBFilters (device, aMachine);
    14001400                AssertComRC (rc);
    14011401            }
     
    18451845 *
    18461846 *  @param aDevice  USB device to apply filters to.
     1847 *  @param aMachine Machine the device was released by or @c NULL.
    18471848 *
    18481849 *  @note the method must be called from under this object's write lock and
    18491850 *  from the aDevice's write lock.
    18501851 */
    1851 HRESULT Host::applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice)
     1852HRESULT Host::applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice,
     1853                                  SessionMachine *aMachine /* = NULL */)
    18521854{
    18531855    LogFlowThisFunc (("\n"));
     
    19011903    {
    19021904        /* skip the machine the device was just detached from */
    1903         if (aDevice->machine() && machines [i] == aDevice->machine())
     1905        if (aMachine && machines [i] == aMachine)
    19041906            continue;
    19051907
     
    20512053    mUSBDevices.erase (it);
    20522054
    2053     /* reset all data */
     2055    /* reset all data and uninitialize the device object */
    20542056    device->reset();
    20552057}
  • trunk/src/VBox/Main/HostUSBDeviceImpl.cpp

    r3029 r3034  
    332332        name = Utf8StrFmt ("%s %s", mUsb->pszManufacturer,
    333333                                     mUsb->pszProduct);
    334     else if(haveManufacturer)
     334    else if (haveManufacturer)
    335335        name = Utf8StrFmt ("%s", mUsb->pszManufacturer);
    336     else if(haveProduct)
    337         name = Utf8StrFmt ("%s", mUsb->pszManufacturer);
     336    else if (haveProduct)
     337        name = Utf8StrFmt ("%s", mUsb->pszProduct);
    338338    else
    339339        name = "<unknown>";
     
    389389
    390390        HRESULT rc = aMachine->onUSBDeviceAttach (d, NULL);
     391
     392        /* The VM process has a legal reason to fail (for example, incorrect
     393         * usbfs permissions or out of virtual USB ports). More over, the VM
     394         * process might have been accidentially crashed and not accessible
     395         * any more (so that calling an uninitialized SessionMachine returns a
     396         * failure). So don't assert. */
    391397
    392398        LogFlowThisFunc (("Done machine->onUSBDeviceAttach()=%08X\n", rc));
     
    481487
    482488/**
    483  *  Sets the device state from Captured to Held and preserves the machine
     489 *  Sets the device state from Captured to Held and resets the machine
    484490 *  association (if any). Usually called before applying filters.
    485491 *
     
    497503
    498504    mState = USBDeviceState_USBDeviceHeld;
     505    mMachine.setNull();
    499506}
    500507
     
    525532
    526533        HRESULT rc = mMachine->onUSBDeviceDetach (mId, NULL);
    527         AssertComRC (rc);
     534
     535        /* This call may expectedly fail with rc = NS_ERROR_FAILURE (on XPCOM)
     536         * if the VM process requests device release right before termination
     537         * and then terminates before onUSBDeviceDetach() reached
     538         * it. Therefore, we don't assert here. On MS COM, there should be
     539         * something similar (with the different error code). More over, the
     540         * VM process might have been accidentially crashed and not accessible
     541         * any more (so that calling an uninitialized SessionMachine returns a
     542         * failure). So don't assert. */
    528543
    529544        LogFlowThisFunc (("Done machine->onUSBDeviceDetach()=%08X\n", rc));
     
    531546        alock.enter();
    532547
     548        /* Reset all fields. Tthe object should have been
     549         * uninitialized after this method returns, so it doesn't really
     550         * matter what state we put it in. */
    533551        mIsStatePending = false;
    534552        mState = mPendingState = USBDeviceState_USBDeviceNotSupported;
     553        mMachine.setNull();
    535554    }
    536555}
     
    552571
    553572    bool wasCapture = false;
    554     bool wasRelease = false;
    555573
    556574    HRESULT requestRC = S_OK;
     
    594612        case USBDeviceState_USBDeviceAvailable:
    595613        {
     614            Assert (mMachine.isNull());
     615
    596616            if (mState == USBDeviceState_USBDeviceHeld)
    597617            {
    598                 /* couldn't release the device */
    599                 wasRelease = true;
    600 
    601                 Assert (!mMachine.isNull());
    602 
    603                 /* return the captured state back */
    604                 mState = USBDeviceState_USBDeviceCaptured;
    605 
    606                 /// @todo more detailed error message depending on the state?
    607                 //  probably need some error code/string from the USB proxy itself
    608 
    609                 requestRC = E_FAIL;
    610                 errorText = Utf8StrFmt (
    611                     tr ("USB device '%s' with UUID {%Vuuid} is being accessed by the guest "
    612                         "computer and cannot be attached from the virtual machine."
    613                         "Please try later"),
    614                     name().raw(), id().raw());
     618                /* couldn't release the device (give it back to the host).
     619                 * there is nobody to report an error to (the machine has
     620                 * already been deassociated because VMM has already detached
     621                 * the device before requesting a release). */
    615622            }
    616623            else
    617624            {
    618                 if (!mMachine.isNull())
    619                     wasRelease = true;
    620                 else
    621                 {
    622                     /* it is a canceled release request. Leave at the host */
    623                     /// @todo we may want to re-run all filters in this case
    624                 }
     625                /* it is a canceled release request. Leave at the host */
     626                /// @todo we may want to re-run all filters in this case
    625627            }
    626628            break;
     
    630632            if (mState == USBDeviceState_USBDeviceHeld)
    631633            {
     634                /* All right, the device is now held (due to some global
     635                 * filter). */
    632636                break;
    633637            }
     
    670674
    671675        /* The VM process has a legal reason to fail (for example, incorrect
    672          * usbfs permissions or out of virtual USB ports), so don't assert */
     676         * usbfs permissions or out of virtual USB ports). More over, the VM
     677         * process might have been accidentially crashed and not accessible
     678         * any more (so that calling an uninitialized SessionMachine returns a
     679         * failure). So don't assert. */
    673680
    674681        /// @todo we will probably want to re-run all filters on failure
     
    689696        mMachine.setNull();
    690697    }
    691     else if (wasRelease)
    692     {
    693         /* inform the VM process */
    694 
    695         /* the VM process will query the object, so leave the lock */
    696         AutoLock alock (this);
    697         alock.leave();
    698 
    699         LogFlowThisFunc (("Calling machine->onUSBDeviceDetach()...\n"));
    700 
    701         HRESULT rc = mMachine->onUSBDeviceDetach (mId, error);
    702 
    703         /* This call may expectedly fail with rc = NS_ERROR_FAILURE (on XPCOM)
    704          * if the VM process requests device release right before termination
    705          * and then terminates before onUSBDeviceDetach() is reached
    706          * it. Therefore, we don't assert here. On MS COM, there should be
    707          * something similar (with the different error code). */
    708 
    709         LogFlowThisFunc (("Done machine->onUSBDeviceDetach()=%08X\n", rc));
    710 
    711         alock.enter();
    712 
    713         if (SUCCEEDED (requestRC))
    714         {
    715             /* deassociate from the machine */
    716             mMachine.setNull();
    717         }
    718     }
    719698
    720699    mIsStatePending = false;
     
    739718    {
    740719        case USBDeviceState_USBDeviceCaptured:
    741         {
    742             /* reset mMachine to deassociate it from the filter and tell
    743              * handlePendingStateChange() what to do */
    744             mMachine.setNull();
    745             break;
    746         }
    747         case USBDeviceState_USBDeviceAvailable:
    748720        {
    749721            /* reset mMachine to deassociate it from the filter and tell
     
    859831 *  Compares this device with a USBDEVICE and decides which comes first.
    860832 *
    861  *  @return < 0 if this should come before pDev2.
    862  *  @return   0 if this and pDev2 are equal.
    863  *  @return > 0 if this should come after pDev2.
    864  *
    865  *  @param   pDev2   Device 2.
     833 *  If the device has a pending state request, a non-strict comparison is made
     834 *  (to properly detect a re-attached device). Otherwise, a strict comparison
     835 *  is performed.
     836 *
     837 *  @param   aDev2   Device 2.
     838 *
     839 *  @return < 0 if this should come before aDev2.
     840 *  @return   0 if this and aDev2 are equal.
     841 *  @return > 0 if this should come after aDev2.
    866842 *
    867843 *  @note Must be called from under the object write lock.
    868844 */
    869 int HostUSBDevice::compare (PCUSBDEVICE pDev2)
     845int HostUSBDevice::compare (PCUSBDEVICE aDev2)
    870846{
    871847    AssertReturn (isLockedOnCurrentThread(), -1);
    872848
    873     return compare (mUsb, pDev2);
    874 }
    875 
     849    return compare (mUsb, aDev2, !isStatePending());
     850}
    876851
    877852/**
    878853 *  Compares two USB devices and decides which comes first.
    879  *
    880  *  @return < 0 if pDev1 should come before pDev2.
    881  *  @return   0 if pDev1 and pDev2 are equal.
    882  *  @return > 0 if pDev1 should come after pDev2.
    883  *
    884  *  @param   pDev1   Device 1.
    885  *  @param   pDev2   Device 2.
    886  */
    887 /*static*/ int HostUSBDevice::compare (PCUSBDEVICE pDev1, PCUSBDEVICE pDev2)
    888 {
    889     int iDiff = pDev1->idVendor - pDev2->idVendor;
     854 *
     855 *  If @a aIsStrict is @c true then the comparison will indicate a difference
     856 *  even if the same physical device (represented by @a aDev1) has been just
     857 *  re-attached to the host computer (represented by @a aDev2) and got a
     858 *  different address from the host OS, etc.
     859 *
     860 *  If @a aIsStrict is @c false, then such a re-attached device will be
     861 *  considered equal to the previous device definition and this function will
     862 *  retrun 0.
     863 *
     864 *  @param   aDev1      Device 1.
     865 *  @param   aDev2      Device 2.
     866 *  @param   aIsStrict  @c true to do a strict check and @c false otherwise.
     867
     868 *  @return < 0 if aDev1 should come before aDev2.
     869 *  @return   0 if aDev1 and aDev2 are equal.
     870 *  @return > 0 if aDev1 should come after aDev2.
     871 */
     872/*static*/
     873int HostUSBDevice::compare (PCUSBDEVICE aDev1, PCUSBDEVICE aDev2,
     874                            bool aIsStrict /* = true */)
     875{
     876    int iDiff = aDev1->idVendor - aDev2->idVendor;
    890877    if (iDiff)
    891878        return iDiff;
    892879
    893     iDiff = pDev1->idProduct - pDev2->idProduct;
     880    iDiff = aDev1->idProduct - aDev2->idProduct;
    894881    if (iDiff)
    895882        return iDiff;
    896883
    897     /** @todo Sander, will this work on windows as well? Linux won't reuse an address for quite a while. */
    898     return strcmp(pDev1->pszAddress, pDev2->pszAddress);
     884    if (!aIsStrict)
     885        return 0;
     886
     887    /* The rest is considered as a strict check. */
     888
     889    return strcmp (aDev1->pszAddress, aDev2->pszAddress);
    899890}
    900891
     
    956947                case USBDeviceState_USBDeviceAvailable:
    957948                    isImportant = false;
     949                    break;
    958950                default:
    959951                    isImportant = true;
     
    973965                case USBDeviceState_USBDeviceAvailable:
    974966                    isImportant = false;
     967                    break;
    975968                default:
    976969                    isImportant = true;
     
    997990                case USBDeviceState_USBDeviceBusy:
    998991                    isImportant = false;
     992                    break;
    999993                default:
    1000994                    isImportant = true;
  • trunk/src/VBox/Main/MachineImpl.cpp

    r3007 r3034  
    77157715
    77167716    AutoCaller autoCaller (this);
    7717     AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
    7718 
    7719     // if cautureUSBDevice() fails, it must have set extended error info
     7717    AssertComRCReturnRC (autoCaller.rc());
     7718
     7719    /* if cautureUSBDevice() fails, it must have set extended error info */
    77207720    return mParent->host()->captureUSBDevice (this, aId);
    77217721}
     
    85878587
    85888588    AutoCaller autoCaller (this);
    8589     AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
     8589
     8590    /* This notification may happen after the machine object has been
     8591     * uninitialized (the session was closed), so don't assert. */
     8592    CheckComRCReturnRC (autoCaller.rc());
    85908593
    85918594    ComPtr <IInternalSessionControl> directControl;
     
    85958598    }
    85968599
    8597     /* ignore notifications sent after #OnSessionEnd() is called */
     8600    /* fail on notifications sent after #OnSessionEnd() is called, it is
     8601     * expected by the caller */
    85988602    if (!directControl)
    8599         return S_OK;
     8603        return E_FAIL;
    86008604
    86018605    return directControl->OnUSBDeviceAttach (aDevice, aError);
     
    86118615
    86128616    AutoCaller autoCaller (this);
    8613     AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
     8617
     8618    /* This notification may happen after the machine object has been
     8619     * uninitialized (the session was closed), so don't assert. */
     8620    CheckComRCReturnRC (autoCaller.rc());
    86148621
    86158622    ComPtr <IInternalSessionControl> directControl;
     
    86198626    }
    86208627
    8621     /* ignore notifications sent after #OnSessionEnd() is called */
     8628    /* fail on notifications sent after #OnSessionEnd() is called, it is
     8629     * expected by the caller */
    86228630    if (!directControl)
    8623         return S_OK;
     8631        return E_FAIL;
    86248632
    86258633    return directControl->OnUSBDeviceDetach (aId, aError);
  • trunk/src/VBox/Main/USBProxyService.cpp

    r3030 r3034  
    218218                DevPtr = *It;
    219219
    220             /// @todo we want to AddCaller here to make sure the device hasn't
    221             //  been uninitialized (needs support for the no-op AddCaller when
    222             //  its argument is NULL)
     220            /* assert that the object is still alive (we still reference it in
     221             * the collection and we're the only one who calls uninit() on it */
     222            HostUSBDevice::AutoCaller devCaller (DevPtr.isNull() ? NULL : DevPtr);
     223            AssertComRC (devCaller.rc());
    223224
    224225            /* Lock the device object since we will read/write it's
     
    290291                        It = mDevices.erase (It);
    291292                        mHost->onUSBDeviceDetached (DevPtr);
    292                         Log (("USBProxyService::processChanges: detached %p\n", (HostUSBDevice *)DevPtr)); /** @todo add details .*/
     293                        Log (("USBProxyService::processChanges: detached %p\n",
     294                              (HostUSBDevice *)DevPtr)); /** @todo add details .*/
     295
     296                        /* from now on, the object is no more valid,
     297                         * uninitialize to avoid abuse */
     298                        devCaller.release();
     299                        DevPtr->uninit();
    293300                    }
    294301                    else
     
    321328            ComObjPtr <HostUSBDevice> DevPtr = *It;
    322329
     330            /* assert that the object is still alive (we still reference it in
     331             * the collection and we're the only one who calls uninit() on it */
     332            HostUSBDevice::AutoCaller devCaller (DevPtr);
     333            AssertComRC (devCaller.rc());
     334
    323335            AutoLock devLock (DevPtr);
    324336
     
    328340            It = mDevices.erase (It);
    329341            mHost->onUSBDeviceDetached (DevPtr);
    330             Log (("USBProxyService::processChanges: detached %p\n", (HostUSBDevice *)DevPtr)); /** @todo add details .*/
     342            Log (("USBProxyService::processChanges: detached %p\n",
     343                  (HostUSBDevice *)DevPtr)); /** @todo add details .*/
     344
     345            /* from now on, the object is no more valid,
     346             * uninitialize to avoid abuse */
     347            devCaller.release();
     348            DevPtr->uninit();
    331349        }
    332350    }
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r3001 r3034  
    372372
    373373    HRESULT attachUSBDevice (IUSBDevice *aHostDevice, PVUSBIRHCONFIG aConfig);
     374    HRESULT detachUSBDevice (USBDeviceList::iterator &aIt);
    374375
    375376    static DECLCALLBACK(int)
  • trunk/src/VBox/Main/include/HostImpl.h

    r3001 r3034  
    147147    }
    148148
    149     HRESULT applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice);
     149    HRESULT applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice,
     150                                SessionMachine *aMachine = NULL);
    150151
    151152    bool applyMachineUSBFilters (SessionMachine *aMachine,
  • trunk/src/VBox/Main/include/HostUSBDeviceImpl.h

    r3001 r3034  
    9595
    9696    /* @note Must be called from under the object read lock. */
    97     ComObjPtr <SessionMachine, ComWeakRef> &machine() { return mMachine; }
     97    ComObjPtr <SessionMachine> &machine() { return mMachine; }
    9898
    9999    /* @note Must be called from under the object read lock. */
     
    117117    bool isMatch (const USBDeviceFilter::Data &aData);
    118118
    119     int compare (PCUSBDEVICE pDev2);
    120     static int compare (PCUSBDEVICE pDev1, PCUSBDEVICE pDev2);
     119    int compare (PCUSBDEVICE aDev2);
     120    static int compare (PCUSBDEVICE aDev1, PCUSBDEVICE aDev2,
     121                        bool aIsStrict = true);
    121122
    122123    bool updateState (PCUSBDEVICE aDev);
     
    130131    USBDeviceState_T mState;
    131132    USBDeviceState_T mPendingState;
    132     ComObjPtr <SessionMachine, ComWeakRef> mMachine;
     133    ComObjPtr <SessionMachine> mMachine;
    133134    bool mIsStatePending : 1;
    134135
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette