void printDeviceList() { Ieee1394Service service; // switch off all messages since they mess up the list service.setVerboseLevel(0); if ( !service.initialize( args->port ) ) { cerr << "Could not initialize IEEE 1394 service" << endl; exit(-1); } cout << "Node id GUID Vendor - Model" << endl; for (int i = 0; i < service.getNodeCount(); i++) { ConfigRom crom(service, i); if (!crom.initialize()) break; cout << i << " " << " 0x" << crom.getGuidString() << " '" << crom.getVendorName() << "' - '" << crom.getModelName() << "'" << endl; } }
bool DeviceManager::discover( bool useCache, bool rediscover ) { debugOutput( DEBUG_LEVEL_NORMAL, "Starting discovery...\n" ); useCache = useCache && ENABLE_DISCOVERY_CACHE; m_used_cache_last_time = useCache; bool slaveMode=false; if(!getOption("slaveMode", slaveMode)) { debugWarning("Could not retrieve slaveMode parameter, defauling to false\n"); } bool snoopMode=false; if(!getOption("snoopMode", snoopMode)) { debugWarning("Could not retrieve snoopMode parameter, defauling to false\n"); } setVerboseLevel(getDebugLevel()); // FIXME: it could be that a 1394service has disappeared (cardbus) ConfigRomVector configRoms; // build a list of configroms on the bus. for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin(); it != m_1394Services.end(); ++it ) { Ieee1394Service *portService = *it; for ( fb_nodeid_t nodeId = 0; nodeId < portService->getNodeCount(); ++nodeId ) { debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId ); if (nodeId == portService->getLocalNodeId()) { debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId ); continue; } ConfigRom * configRom = new ConfigRom( *portService, nodeId ); if ( !configRom->initialize() ) { // \todo If a PHY on the bus is in power safe mode then // the config rom is missing. So this might be just // such this case and we can safely skip it. But it might // be there is a real software problem on our side. // This should be handlede more carefuly. debugOutput( DEBUG_LEVEL_NORMAL, "Could not read config rom from device (node id %d). " "Skip device discovering for this node\n", nodeId ); continue; } configRoms.push_back(configRom); } } // notify that we are going to manipulate the list signalNotifiers(m_preUpdateNotifiers); m_DeviceListLock->Lock(); // make sure nobody starts using the list if(rediscover) { FFADODeviceVector discovered_devices_on_bus; for ( FFADODeviceVectorIterator it = m_avDevices.begin(); it != m_avDevices.end(); ++it ) { bool seen_device = false; for ( ConfigRomVectorIterator it2 = configRoms.begin(); it2 != configRoms.end(); ++it2 ) { seen_device |= ((*it)->getConfigRom().getGuid() == (*it2)->getGuid()); } if(seen_device) { debugOutput( DEBUG_LEVEL_VERBOSE, "Already discovered device with GUID: %s\n", (*it)->getConfigRom().getGuidString().c_str() ); // we already discovered this device, and it is still here. keep it discovered_devices_on_bus.push_back(*it); } else { debugOutput( DEBUG_LEVEL_VERBOSE, "Device with GUID: %s disappeared from bus, removing...\n", (*it)->getConfigRom().getGuidString().c_str() ); // the device has disappeared, remove it from the control tree if (!deleteElement(*it)) { debugWarning("failed to remove Device from Control::Container\n"); } // delete the device // FIXME: this will mess up the any code that waits for bus resets to // occur delete *it; } } // prune the devices that disappeared m_avDevices = discovered_devices_on_bus; } else { // remove everything since we are not rediscovering for ( FFADODeviceVectorIterator it = m_avDevices.begin(); it != m_avDevices.end(); ++it ) { if (!deleteElement(*it)) { debugWarning("failed to remove Device from Control::Container\n"); } delete *it; } m_avDevices.clear(); } // delete the config rom list entries // FIXME: we should reuse it for ( ConfigRomVectorIterator it = configRoms.begin(); it != configRoms.end(); ++it ) { delete *it; } assert(m_deviceStringParser); // show the spec strings we're going to use if(getDebugLevel() >= DEBUG_LEVEL_VERBOSE) { m_deviceStringParser->show(); } if (!slaveMode) { // for the devices that are still in the list check if they require re-discovery FFADODeviceVector failed_to_rediscover; for ( FFADODeviceVectorIterator it_dev = m_avDevices.begin(); it_dev != m_avDevices.end(); ++it_dev ) { FFADODevice* avDevice = *it_dev; if(avDevice->needsRediscovery()) { debugOutput( DEBUG_LEVEL_NORMAL, "Device with GUID %s requires rediscovery (state changed)...\n", avDevice->getConfigRom().getGuidString().c_str()); bool isFromCache = false; if ( useCache && avDevice->loadFromCache() ) { debugOutput( DEBUG_LEVEL_VERBOSE, "could load from cache\n" ); isFromCache = true; // restore the debug level for everything that was loaded avDevice->setVerboseLevel( getDebugLevel() ); } else if ( avDevice->discover() ) { debugOutput( DEBUG_LEVEL_VERBOSE, "discovery successful\n" ); } else { debugError( "could not discover device\n" ); failed_to_rediscover.push_back(avDevice); continue; } if ( !isFromCache && !avDevice->saveCache() ) { debugOutput( DEBUG_LEVEL_VERBOSE, "No cached version of AVC model created\n" ); } } else { debugOutput( DEBUG_LEVEL_NORMAL, "Device with GUID %s does not require rediscovery...\n", avDevice->getConfigRom().getGuidString().c_str()); } } // remove devices that failed to rediscover // FIXME: surely there has to be a better way to do this FFADODeviceVector to_keep; for ( FFADODeviceVectorIterator it = m_avDevices.begin(); it != m_avDevices.end(); ++it ) { bool keep_this_device = true; for ( FFADODeviceVectorIterator it2 = failed_to_rediscover.begin(); it2 != failed_to_rediscover.end(); ++it2 ) { if(*it == *it2) { debugOutput( DEBUG_LEVEL_NORMAL, "Removing device with GUID %s due to failed discovery...\n", (*it)->getConfigRom().getGuidString().c_str()); keep_this_device = false; break; } } if(keep_this_device) { to_keep.push_back(*it); } } for ( FFADODeviceVectorIterator it2 = failed_to_rediscover.begin(); it2 != failed_to_rediscover.end(); ++it2 ) { if (!deleteElement(*it2)) { debugWarning("failed to remove Device from Control::Container\n"); } delete *it2; } m_avDevices = to_keep; // pick up new devices for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin(); it != m_1394Services.end(); ++it ) { Ieee1394Service *portService = *it; for ( fb_nodeid_t nodeId = 0; nodeId < portService->getNodeCount(); ++nodeId ) { debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId ); if (nodeId == portService->getLocalNodeId()) { debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId ); continue; } ConfigRom *configRom = new ConfigRom( *portService, nodeId ); if ( !configRom->initialize() ) { // \todo If a PHY on the bus is in power safe mode then // the config rom is missing. So this might be just // such this case and we can safely skip it. But it might // be there is a real software problem on our side. // This should be handlede more carefuly. debugOutput( DEBUG_LEVEL_NORMAL, "Could not read config rom from device (node id %d). " "Skip device discovering for this node\n", nodeId ); continue; } bool already_in_vector = false; for ( FFADODeviceVectorIterator it_dev = m_avDevices.begin(); it_dev != m_avDevices.end(); ++it_dev ) { if ((*it_dev)->getConfigRom().getGuid() == configRom->getGuid()) { already_in_vector = true; break; } } if(already_in_vector) { if(!rediscover) { debugWarning("Device with GUID %s already discovered on other port, skipping device...\n", configRom->getGuidString().c_str()); } continue; } if(getDebugLevel() >= DEBUG_LEVEL_VERBOSE) { configRom->printConfigRomDebug(); } // if spec strings are given, only add those devices // that match the spec string(s). // if no (valid) spec strings are present, grab all // supported devices. if(m_deviceStringParser->countDeviceStrings() && !m_deviceStringParser->match(*configRom)) { debugOutput(DEBUG_LEVEL_VERBOSE, "Device doesn't match any of the spec strings. skipping...\n"); continue; } // find a driver FFADODevice* avDevice = getDriverForDevice( configRom, nodeId ); if ( avDevice ) { debugOutput( DEBUG_LEVEL_NORMAL, "driver found for device %d\n", nodeId ); avDevice->setVerboseLevel( getDebugLevel() ); bool isFromCache = false; if ( useCache && avDevice->loadFromCache() ) { debugOutput( DEBUG_LEVEL_VERBOSE, "could load from cache\n" ); isFromCache = true; // restore the debug level for everything that was loaded avDevice->setVerboseLevel( getDebugLevel() ); } else if ( avDevice->discover() ) { debugOutput( DEBUG_LEVEL_VERBOSE, "discovery successful\n" ); } else { debugError( "could not discover device\n" ); delete avDevice; continue; } if (snoopMode) { debugOutput( DEBUG_LEVEL_VERBOSE, "Enabling snoop mode on node %d...\n", nodeId ); if(!avDevice->setOption("snoopMode", snoopMode)) { debugWarning("Could not set snoop mode for device on node %d\n", nodeId); delete avDevice; continue; } } if ( !isFromCache && !avDevice->saveCache() ) { debugOutput( DEBUG_LEVEL_VERBOSE, "No cached version of AVC model created\n" ); } m_avDevices.push_back( avDevice ); if (!addElement(avDevice)) { debugWarning("failed to add Device to Control::Container\n"); } debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d on port %d done...\n", nodeId, portService->getPort() ); } else { // we didn't get a device, hence we have to delete the configrom ptr manually delete configRom; } } } debugOutput( DEBUG_LEVEL_NORMAL, "Discovery finished...\n" ); // FIXME: do better sorting // sort the m_avDevices vector on their GUID // then assign reassign the id's to the devices // the side effect of this is that for the same set of attached devices, // a device id always corresponds to the same device sort(m_avDevices.begin(), m_avDevices.end(), FFADODevice::compareGUID); int i=0; if(m_deviceStringParser->countDeviceStrings()) { // only if there are devicestrings // first map the devices to a position using the device spec strings std::map<fb_octlet_t, int> positionMap; for ( FFADODeviceVectorIterator it = m_avDevices.begin(); it != m_avDevices.end(); ++it ) { int pos = m_deviceStringParser->matchPosition((*it)->getConfigRom()); fb_octlet_t guid = (*it)->getConfigRom().getGuid(); positionMap[guid] = pos; debugOutput( DEBUG_LEVEL_VERBOSE, "Mapping %s to position %d...\n", (*it)->getConfigRom().getGuidString().c_str(), pos ); } // now run over all positions, and add the devices that belong to it FFADODeviceVector sorted; int nbPositions = m_deviceStringParser->countDeviceStrings(); for (i=0; i < nbPositions; i++) { for ( FFADODeviceVectorIterator it = m_avDevices.begin(); it != m_avDevices.end(); ++it ) { fb_octlet_t guid = (*it)->getConfigRom().getGuid(); if(positionMap[guid] == i) { sorted.push_back(*it); } } } // assign the new vector flushDebugOutput(); assert(sorted.size() == m_avDevices.size()); m_avDevices = sorted; } showDeviceInfo(); } else { // slave mode // notify any clients signalNotifiers(m_preUpdateNotifiers); Ieee1394Service *portService = m_1394Services.at(0); fb_nodeid_t nodeId = portService->getLocalNodeId(); debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId ); std::auto_ptr<ConfigRom> configRom = std::auto_ptr<ConfigRom>( new ConfigRom( *portService, nodeId ) ); if ( !configRom->initialize() ) { // \todo If a PHY on the bus is in power safe mode then // the config rom is missing. So this might be just // such this case and we can safely skip it. But it might // be there is a real software problem on our side. // This should be handled more carefuly. debugOutput( DEBUG_LEVEL_NORMAL, "Could not read config rom from device (node id %d). " "Skip device discovering for this node\n", nodeId ); return false; } // remove any already present devices for ( FFADODeviceVectorIterator it = m_avDevices.begin(); it != m_avDevices.end(); ++it ) { if (!deleteElement(*it)) { debugWarning("failed to remove Device from Control::Container\n"); } delete *it; } m_avDevices.clear(); // get the slave driver FFADODevice* avDevice = getSlaveDriver( configRom ); if ( avDevice ) { debugOutput( DEBUG_LEVEL_NORMAL, "driver found for device %d\n", nodeId ); avDevice->setVerboseLevel( getDebugLevel() ); if ( !avDevice->discover() ) { debugError( "could not discover device\n" ); delete avDevice; return false; } if ( getDebugLevel() >= DEBUG_LEVEL_VERBOSE ) { avDevice->showDevice(); } m_avDevices.push_back( avDevice ); debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d on port %d done...\n", nodeId, portService->getPort() ); } debugOutput( DEBUG_LEVEL_NORMAL, "discovery finished...\n" ); } m_DeviceListLock->Unlock(); // notify any clients signalNotifiers(m_postUpdateNotifiers); return true; }
int main( int argc, char** argv ) { printf("-----------------------------------------------\n"); printf("BridgeCo BeBoB platform firmware downloader\n"); printf("Part of the FFADO project -- www.ffado.org\n"); printf("Version: %s\n", PACKAGE_VERSION); printf("(C) 2008, Daniel Wagner, Pieter Palmers\n"); printf("This program comes with ABSOLUTELY NO WARRANTY.\n"); printf("-----------------------------------------------\n\n"); // arg parsing argp_parse (argp, argc, argv, 0, 0, args); if (args->nargs < 2) { printDeviceList(); exit(0); } errno = 0; char* tail; int node_id = -1; fb_octlet_t guid = strtoll(args->args[0], &tail, 0); if (errno) { perror("argument parsing failed:"); return -1; } if(args->magic != MAGIC_THAT_SAYS_I_KNOW_WHAT_IM_DOING) { printf("Magic number not correct. Please specify the correct magic using the '-m' option.\n"); printf("Manipulating firmware can cause your device to magically stop working (a.k.a. 'bricking').\n"); printf("Specifying the magic number indicates that you accept the risks involved\n"); printf("with using this tool. The magic number can be found in the source code.\n\n"); return -1; } else { printf("YOU HAVE SPECIFIED THE CORRECT MAGIC NUMBER.\n"); printf("HENCE YOU ACCEPT THE RISKS INVOLVED.\n"); } Ieee1394Service service; if ( !service.initialize( args->port ) ) { cerr << "Could not initialize IEEE 1394 service" << endl; return -1; } service.setVerboseLevel( args->verbose ); for (int i = 0; i < service.getNodeCount(); i++) { ConfigRom configRom(service, i); configRom.initialize(); if (configRom.getGuid() == guid) node_id = configRom.getNodeId(); } if (node_id < 0) { cerr << "Could not find device with matching GUID" << endl; return -1; } service.setVerboseLevel( args->verbose ); BeBoB::BootloaderManager blMgr( service, node_id ); if ( args->force == 1 ) { blMgr.setForceOperations( true ); } blMgr.getConfigRom()->printConfigRom(); blMgr.printInfoRegisters(); if ( strcmp( args->args[1], "setguid" ) == 0 ) { if (!args->args[2] ) { cerr << "guid argument is missing" << endl; return -1; } char* tail; fb_octlet_t guid = strtoll(args->args[2], &tail, 0 ); if ( !blMgr.programGUID( guid ) ) { cerr << "Failed to set GUID" << endl; return -1; } else { cout << "new GUID programmed" << endl; } } else if ( strcmp( args->args[1], "firmware" ) == 0 ) { if (!args->args[2] ) { cerr << "FILE argument is missing" << endl; return -1; } std::string str( args->args[2] ); blMgr.setStartBootloader( args->no_bootloader_restart != 1 ); if ( !blMgr.downloadFirmware( str ) ) { cerr << "Failed to download firmware" << endl; return -1; } else { cout << "Firmware download was successful" << endl; cout << "Please reboot the device by removing the power and firewire connections." << endl; } } else if ( strcmp( args->args[1], "cne" ) == 0 ) { if (!args->args[2] ) { cerr << "FILE argument is missing" << endl; return -1; } std::string str( args->args[2] ); if ( !blMgr.downloadCnE( str ) ) { cerr << "Failed to download CnE" << endl; return -1; } else { cout << "CnE download was successful" << endl; cout << "Please reboot the device by removing the power and firewire connections." << endl; } } else if ( strcmp( args->args[1], "display" ) == 0 ) { // nothing to do } else if ( strcmp( args->args[1], "bcd" ) == 0 ) { if ( !args->args[2] ) { cerr << "FILE arguments is missing" << endl; return -1; } BeBoB::BCD* bcd = new BeBoB::BCD::BCD( args->args[2] ); if ( !bcd ) { cerr << "Could no open file " << args->args[2] << endl; return -1; } if ( !bcd->parse() ) { cerr << "Could not parse file " << args->args[2] << endl; return -1; } bcd->displayInfo(); delete bcd; } else { cout << "Unknown operation" << endl; } return 0; }