/** * 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")); }
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; }