Exemple #1
0
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;
    }
}
Exemple #2
0
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;
}