Пример #1
0
/**
 * Process any relevant changes in the attached USB devices.
 *
 * Except for the first call, this is always running on the service thread.
 */
void USBProxyService::processChanges(void)
{
    LogFlowThisFunc(("\n"));

    /*
     * Get the sorted list of USB devices.
     */
    PUSBDEVICE pDevices = getDevices();
    pDevices = sortDevices(pDevices);

    // get a list of all running machines while we're outside the lock
    // (getOpenedMachines requests higher priority locks)
    SessionMachinesList llOpenedMachines;
    mHost->parent()->getOpenedMachines(llOpenedMachines);

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    /*
     * Compare previous list with the new list of devices
     * and merge in any changes while notifying Host.
     */
    HostUSBDeviceList::iterator it = this->mDevices.begin();
    while (    it != mDevices.end()
            || pDevices)
    {
        ComObjPtr<HostUSBDevice> pHostDevice;

        if (it != mDevices.end())
            pHostDevice = *it;

        /*
         * Assert that the object is still alive (we still reference it in
         * the collection and we're the only one who calls uninit() on it.
         */
        AutoCaller devCaller(pHostDevice.isNull() ? NULL : pHostDevice);
        AssertComRC(devCaller.rc());

        /*
         * Lock the device object since we will read/write its
         * properties. All Host callbacks also imply the object is locked.
         */
        AutoWriteLock devLock(pHostDevice.isNull() ? NULL : pHostDevice
                              COMMA_LOCKVAL_SRC_POS);

        /*
         * Compare.
         */
        int iDiff;
        if (pHostDevice.isNull())
            iDiff = 1;
        else
        {
            if (!pDevices)
                iDiff = -1;
            else
                iDiff = pHostDevice->compare(pDevices);
        }
        if (!iDiff)
        {
            /*
             * The device still there, update the state and move on. The PUSBDEVICE
             * structure is eaten by updateDeviceState / HostUSBDevice::updateState().
             */
            PUSBDEVICE pCur = pDevices;
            pDevices = pDevices->pNext;
            pCur->pPrev = pCur->pNext = NULL;

            bool fRunFilters = false;
            SessionMachine *pIgnoreMachine = NULL;
            devLock.release();
            alock.release();
            if (updateDeviceState(pHostDevice, pCur, &fRunFilters, &pIgnoreMachine))
                deviceChanged(pHostDevice,
                              (fRunFilters ? &llOpenedMachines : NULL),
                              pIgnoreMachine);
            alock.acquire();
            it++;
        }
        else
        {
            if (iDiff > 0)
            {
                /*
                 * Head of pDevices was attached.
                 */
                PUSBDEVICE pNew = pDevices;
                pDevices = pDevices->pNext;
                pNew->pPrev = pNew->pNext = NULL;

                ComObjPtr<HostUSBDevice> NewObj;
                NewObj.createObject();
                NewObj->init(pNew, this);
                Log(("USBProxyService::processChanges: attached %p {%s} %s / %p:{.idVendor=%#06x, .idProduct=%#06x, .pszProduct=\"%s\", .pszManufacturer=\"%s\"}\n",
                     (HostUSBDevice *)NewObj,
                     NewObj->getName().c_str(),
                     NewObj->getStateName(),
                     pNew,
                     pNew->idVendor,
                     pNew->idProduct,
                     pNew->pszProduct,
                     pNew->pszManufacturer));

                mDevices.insert(it, NewObj);

                devLock.release();
                alock.release();
                deviceAdded(NewObj, llOpenedMachines, pNew);
                alock.acquire();
            }
            else
            {
                /*
                 * Check if the device was actually detached or logically detached
                 * as the result of a re-enumeration.
                 */
                if (!pHostDevice->wasActuallyDetached())
                    it++;
                else
                {
                    it = mDevices.erase(it);
                    devLock.release();
                    alock.release();
                    deviceRemoved(pHostDevice);
                    Log(("USBProxyService::processChanges: detached %p {%s}\n",
                         (HostUSBDevice *)pHostDevice,
                         pHostDevice->getName().c_str()));

                    /* from now on, the object is no more valid,
                     * uninitialize to avoid abuse */
                    devCaller.release();
                    pHostDevice->uninit();
                    alock.acquire();
                }
            }
        }
    } /* while */

    LogFlowThisFunc(("returns void\n"));
}
Пример #2
0
int main(int argc, char *argv[]){

    /* Local vars */
    char filename[MAX_FILENAME_LENGTH];    
    FILE* devFile = NULL;
    struct SWDeviceEntry newEntry;
    int devCnt = 0;
    struct SWDeviceEntry devices[MASTER_MAXDEVICES];
    struct SWDeviceEntry* findDev = NULL;

    /* Handel Input */
    (void) argc;
    (void) argv;

    /* Get Device Filename */
    if(buildDevFileName(filename, MAX_FILENAME_LENGTH) <= 0){
        fprintf(stderr, "masterTest: Could not create devFile name.\n");
        exit(EXIT_FAILURE);
    }
    
    /* Open Device File */
    devFile = openDevFile(filename);
    if(devFile == NULL){
        fprintf(stderr, "masterTest: Could not open devFile.\n");
        exit(EXIT_FAILURE);
    }

    /* Write Test record */
    newEntry.devInfo.swAddr = 0x0003u;
    newEntry.ipAddr = 0x33333333u;
    newEntry.devInfo.devTypes = SW_TYPE_UNIVERSAL | SW_TYPE_OUTLET;
    newEntry.devInfo.numChan = 0x03u;
    newEntry.devInfo.groupID = 0x01u;
    newEntry.devInfo.version = SW_VERSION;
    newEntry.devInfo.uid = 0x3333333333333333ull;
    newEntry.lineNum = -1;
    if(fseek(devFile, 0, SEEK_END) != 0){
        fprintf(stderr, "masterTest: Could not seek to end of devFile.\n");
        exit(EXIT_FAILURE);
    }
    if(writeDevice(&newEntry, devFile) < 0){
        fprintf(stderr, "masterTest: Error writing new device to devFile.\n");
        exit(EXIT_FAILURE);
    }
    
    /* Get Device Array */
    devCnt = getDevices(devices, MASTER_MAXDEVICES, devFile);
    if(devCnt < 0){
        fprintf(stderr, "masterTest: "
                "Error getting device list: getDevices returned %d\n",
                devCnt);
        exit(EXIT_FAILURE);
    }
    
    /* Sort Device Array */
    if(sortDevices(devices, devCnt) < 0){
        fprintf(stderr, "masterTest: Error sorting device list.\n");
        exit(EXIT_FAILURE);
    }

    /* Find new device in array */
    findDev = findDevice(newEntry.devInfo.swAddr, devices, devCnt);
    if(findDev == NULL){
        fprintf(stderr, "masterTest: Could not find new device.\n");
        exit(EXIT_FAILURE);
    }

    /* Remove new device from devFile */
    findDev->lineNum = -1;
    devFile = updateDevices(devices, &devCnt, devFile);
    if(devFile == NULL){
        fprintf(stderr, "masterTest: Could not update devFile.\n");
        exit(EXIT_FAILURE);
    }

    /* Close Device File */
    if(closeDevFile(devFile) != 0){
        fprintf(stderr, "masterTest: Could not close devFile.\n");
        exit(EXIT_FAILURE);
    }
    devFile = NULL;
        
    return 0;
}