Changeset 960

Show
Ignore:
Timestamp:
03/18/08 15:45:38 (13 years ago)
Author:
ppalmers
Message:

make dbus server handle bus resets and dynamic add/remove of devices

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libffado/src/bebob/focusrite/focusrite_saffirepro.cpp

    r957 r960  
    2525#include "focusrite_cmd.h" 
    2626 
     27#include "devicemanager.h" 
    2728#include "libutil/Time.h" 
    2829 
     
    403404        int ntries = max_tries+1; 
    404405         
     406        // FIXME: not very clean 
     407        getDeviceManager().ignoreBusResets(true); 
     408         
    405409        unsigned int gen_before = get1394Service().getGeneration(); 
    406410         
     
    489493            debugOutput( DEBUG_LEVEL_VERBOSE, "setSampleRate (try %d) failed. Try again...\n" ); 
    490494        } 
     495 
     496        // FIXME: not very clean 
     497        getDeviceManager().ignoreBusResets(false); 
    491498 
    492499        if (ntries==0) { 
  • trunk/libffado/src/devicemanager.cpp

    r942 r960  
    8484    , m_processorManager( new Streaming::StreamProcessorManager() ) 
    8585    , m_deviceStringParser( new DeviceStringParser() ) 
     86    , m_used_cache_last_time( false ) 
     87    , m_ignore_busreset( false ) 
    8688{ 
    8789    addOption(Util::OptionContainer::Option("slaveMode",false)); 
     
    211213{ 
    212214    debugOutput( DEBUG_LEVEL_VERBOSE, "Bus reset...\n" ); 
     215    if(m_ignore_busreset) { 
     216        debugOutput( DEBUG_LEVEL_VERBOSE, " ignoring...\n" ); 
     217        return; 
     218    } 
     219 
    213220    // FIXME: what port was the bus reset on? 
    214221    // propagate the bus reset to all avDevices 
     
    219226        (*it)->handleBusReset(); 
    220227    } 
    221 
    222  
    223 bool 
    224 DeviceManager::discover( bool useCache ) 
    225 
     228 
     229    // rediscover to find new devices 
     230    // (only for the control server ATM, streaming can't dynamically add/remove devices) 
     231    if(!discover(m_used_cache_last_time, true)) { 
     232        debugError("Could not rediscover devices\n"); 
     233    } 
     234 
     235    // notify any clients 
     236    for ( busreset_notif_vec_t::iterator it = m_busResetNotifiers.begin(); 
     237          it != m_busResetNotifiers.end(); 
     238          ++it ) 
     239    { 
     240        Util::Functor* func = *it; 
     241        debugOutput( DEBUG_LEVEL_VERBOSE, " running notifier %p...\n", func ); 
     242        ( *func )(); 
     243    } 
     244
     245 
     246bool 
     247DeviceManager::registerBusresetNotification(Util::Functor *handler) 
     248
     249    debugOutput( DEBUG_LEVEL_VERBOSE, "register %p...\n", handler); 
     250    assert(handler); 
     251    for ( busreset_notif_vec_t::iterator it = m_busResetNotifiers.begin(); 
     252      it != m_busResetNotifiers.end(); 
     253      ++it ) 
     254    { 
     255        if ( *it == handler ) { 
     256            debugOutput(DEBUG_LEVEL_VERBOSE, "already registered\n"); 
     257            return false; 
     258        } 
     259    } 
     260    m_busResetNotifiers.push_back(handler); 
     261    return true; 
     262
     263 
     264bool 
     265DeviceManager::unregisterBusresetNotification(Util::Functor *handler) 
     266
     267    debugOutput( DEBUG_LEVEL_VERBOSE, "unregister %p...\n", handler); 
     268    assert(handler); 
     269 
     270    for ( busreset_notif_vec_t::iterator it = m_busResetNotifiers.begin(); 
     271      it != m_busResetNotifiers.end(); 
     272      ++it ) 
     273    { 
     274        if ( *it == handler ) { 
     275            m_busResetNotifiers.erase(it); 
     276            return true; 
     277        } 
     278    } 
     279    debugError("Could not find handler (%p)\n", handler); 
     280    return false; //not found 
     281
     282 
     283bool 
     284DeviceManager::discover( bool useCache, bool rediscover ) 
     285
     286    m_used_cache_last_time = useCache; 
    226287    bool slaveMode=false; 
    227288    if(!getOption("slaveMode", slaveMode)) { 
     
    235296    setVerboseLevel(getDebugLevel()); 
    236297 
    237     for ( FFADODeviceVectorIterator it = m_avDevices.begin(); 
    238           it != m_avDevices.end(); 
    239           ++it ) 
    240     { 
    241         if (!deleteElement(*it)) { 
    242             debugWarning("failed to remove AvDevice from Control::Container\n"); 
    243         } 
     298    ConfigRomVector configRoms; 
     299    // build a list of configroms on the bus. 
     300    for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin(); 
     301        it != m_1394Services.end(); 
     302        ++it ) 
     303    { 
     304        Ieee1394Service *portService = *it; 
     305        for ( fb_nodeid_t nodeId = 0; 
     306            nodeId < portService->getNodeCount(); 
     307            ++nodeId ) 
     308        { 
     309            debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId ); 
     310 
     311            if (nodeId == portService->getLocalNodeId()) { 
     312                debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId ); 
     313                continue; 
     314            } 
     315 
     316            ConfigRom * configRom = new ConfigRom( *portService, nodeId ); 
     317            if ( !configRom->initialize() ) { 
     318                // \todo If a PHY on the bus is in power safe mode then 
     319                // the config rom is missing. So this might be just 
     320                // such this case and we can safely skip it. But it might 
     321                // be there is a real software problem on our side. 
     322                // This should be handlede more carefuly. 
     323                debugOutput( DEBUG_LEVEL_NORMAL, 
     324                            "Could not read config rom from device (node id %d). " 
     325                            "Skip device discovering for this node\n", 
     326                            nodeId ); 
     327                continue; 
     328            } 
     329            configRoms.push_back(configRom); 
     330        } 
     331    } 
     332 
     333    if(rediscover) { 
     334        FFADODeviceVector discovered_devices_on_bus; 
     335        for ( FFADODeviceVectorIterator it = m_avDevices.begin(); 
     336            it != m_avDevices.end(); 
     337            ++it ) 
     338        { 
     339            bool seen_device = false; 
     340            for ( ConfigRomVectorIterator it2 = configRoms.begin(); 
     341                it2 != configRoms.end(); 
     342                ++it2 ) 
     343            { 
     344                seen_device |= ((*it)->getConfigRom().getGuid() == (*it2)->getGuid()); 
     345            } 
     346 
     347            if(seen_device) { 
     348                debugOutput( DEBUG_LEVEL_VERBOSE, 
     349                            "Already discovered device with GUID: %s\n", 
     350                            (*it)->getConfigRom().getGuidString().c_str() ); 
     351                // we already discovered this device, and it is still here. keep it 
     352                discovered_devices_on_bus.push_back(*it); 
     353            } else { 
     354                debugOutput( DEBUG_LEVEL_VERBOSE, 
     355                            "Device with GUID: %s disappeared from bus, removing...\n", 
     356                            (*it)->getConfigRom().getGuidString().c_str() ); 
     357 
     358                // the device has disappeared, remove it from the control tree 
     359                if (!deleteElement(*it)) { 
     360                    debugWarning("failed to remove AvDevice from Control::Container\n"); 
     361                } 
     362                // delete the device 
     363                // FIXME: this will mess up the any code that waits for bus resets to 
     364                //        occur 
     365                delete *it; 
     366            } 
     367        } 
     368        // prune the devices that disappeared 
     369        m_avDevices = discovered_devices_on_bus; 
     370    } else { // remove everything since we are not rediscovering 
     371        for ( FFADODeviceVectorIterator it = m_avDevices.begin(); 
     372            it != m_avDevices.end(); 
     373            ++it ) 
     374        { 
     375            if (!deleteElement(*it)) { 
     376                debugWarning("failed to remove AvDevice from Control::Container\n"); 
     377            } 
     378            delete *it; 
     379        } 
     380 
     381        m_avDevices.clear(); 
     382    } 
     383 
     384    // delete the config rom list entries 
     385    // FIXME: we should reuse it 
     386    for ( ConfigRomVectorIterator it = configRoms.begin(); 
     387        it != configRoms.end(); 
     388        ++it ) 
     389    { 
    244390        delete *it; 
    245391    } 
    246     m_avDevices.clear(); 
    247392 
    248393    assert(m_deviceStringParser); 
     
    295440                } 
    296441                if(already_in_vector) { 
    297                     debugWarning("Device with GUID %s already discovered on other port, skipping device...\n", 
    298                                  configRom->getGuidString().c_str()); 
     442                    if(!rediscover) { 
     443                        debugWarning("Device with GUID %s already discovered on other port, skipping device...\n", 
     444                                    configRom->getGuidString().c_str()); 
     445                    } 
    299446                    continue; 
    300447                } 
  • trunk/libffado/src/devicemanager.h

    r942 r960  
    3838#include <glibmm/ustring.h> 
    3939 
     40#include "libutil/Functors.h" 
     41 
    4042#include <vector> 
    4143#include <string> 
     
    5759typedef std::vector< Util::Functor* > FunctorVector; 
    5860typedef std::vector< Util::Functor* >::iterator FunctorVectorIterator; 
     61 
     62typedef std::vector< ConfigRom* > ConfigRomVector; 
     63typedef std::vector< ConfigRom* >::iterator ConfigRomVectorIterator; 
    5964 
    6065class DeviceManager 
     
    8085    bool isSpecStringValid(std::string s); 
    8186 
    82     bool discover(bool userCache=true); 
     87    bool discover(bool useCache=true, bool rediscover=false); 
    8388    bool initStreaming(); 
    8489    bool prepareStreaming(); 
     
    99104 
    100105    Streaming::StreamProcessor *getSyncSource(); 
     106 
     107    void ignoreBusResets(bool b) {m_ignore_busreset = b;}; 
     108    bool registerBusresetNotification(Util::Functor *); 
     109    bool unregisterBusresetNotification(Util::Functor *); 
    101110 
    102111    void showDeviceInfo(); 
     
    129138    Streaming::StreamProcessorManager*  m_processorManager; 
    130139    DeviceStringParser*                 m_deviceStringParser; 
     140    bool                                m_used_cache_last_time; 
     141    bool                                m_ignore_busreset; 
     142 
     143    typedef std::vector< Util::Functor* > busreset_notif_vec_t; 
     144    busreset_notif_vec_t                m_busResetNotifiers; 
     145 
    131146protected: 
    132147    std::vector<std::string>            m_SpecStrings; 
  • trunk/libffado/src/libutil/Functors.h

    r932 r960  
    134134}; 
    135135 
     136template< typename FunPtr > 
     137class CallbackFunctor0 
     138    : public Functor 
     139{ 
     140public: 
     141    CallbackFunctor0( FunPtr pMemFun, 
     142            bool bDelete = true ) 
     143        : m_pMemFun( pMemFun ) 
     144        , m_pSem( 0 ) 
     145        , m_bDelete( bDelete ) 
     146        {} 
     147 
     148    CallbackFunctor0( FunPtr pMemFun, 
     149            sem_t* pSem, 
     150            bool bDelete = true ) 
     151        : m_pMemFun( pMemFun ) 
     152        , m_pSem( pSem ) 
     153        , m_bDelete( bDelete ) 
     154        {} 
     155 
     156    virtual ~CallbackFunctor0() 
     157        {} 
     158 
     159    virtual void operator() () 
     160        { 
     161            ( *m_pMemFun )(); 
     162            if ( m_pSem ) { 
     163                sem_post( m_pSem); 
     164            } 
     165            if (m_bDelete) { 
     166                delete this; 
     167            } 
     168        } 
     169 
     170private: 
     171    FunPtr      m_pMemFun; 
     172    sem_t*      m_pSem; 
     173    bool        m_bDelete; 
     174}; 
    136175}; // end of namespace Util 
    137176 
  • trunk/libffado/support/dbus/ffado-dbus-server.cpp

    r864 r960  
    2828 
    2929#include <config.h> 
     30#include <semaphore.h> 
    3031 
    3132#include "libffado/ffado.h" 
     
    4041#include "libcontrol/BasicElements.h" 
    4142 
     43#include "libutil/Functors.h" 
     44 
    4245#include <signal.h> 
    4346 
     
    5861// DBUS stuff 
    5962DBus::BusDispatcher dispatcher; 
     63DBusControl::Container *container = NULL; 
     64DBus::Connection * global_conn; 
     65DeviceManager *m_deviceManager = NULL; 
    6066 
    6167// signal handler 
    6268int run=1; 
     69sem_t run_sem; 
     70 
    6371static void sighandler (int sig) 
    6472{ 
    6573    run = 0; 
    6674    dispatcher.leave(); 
     75    sem_post(&run_sem); 
    6776} 
    6877 
     
    135144            } 
    136145        } 
    137         break;       
     146        break; 
    138147    case 'p': 
    139148        if (arg) { 
     
    193202} 
    194203 
     204void 
     205busresetHandler() 
     206{ 
     207    debugOutput( DEBUG_LEVEL_NORMAL, "notified of bus reset...\n" ); 
     208    dispatcher.leave(); 
     209 
     210    // delete old container 
     211    delete container; 
     212    container = NULL; 
     213 
     214    // build new one 
     215    if(m_deviceManager) { 
     216        container = new DBusControl::Container(*global_conn, "/org/ffado/Control/DeviceManager", *m_deviceManager); 
     217    } else { 
     218        debugError("no device manager, bailing out\n"); 
     219        run=0; 
     220    } 
     221    sem_post(&run_sem); 
     222} 
     223 
    195224int 
    196225main( int argc, char **argv ) 
     
    200229    // Default values. 
    201230    arguments.silent      = 0; 
    202     arguments.verbose     = 0
     231    arguments.verbose     = DEBUG_LEVEL_NORMAL
    203232    arguments.use_cache   = 0; 
    204233    arguments.port        = 0; 
     
    220249    debugOutput( DEBUG_LEVEL_NORMAL, "Using ffado library version: %s\n\n", ffado_get_version() ); 
    221250 
    222         DeviceManager *m_deviceManager = new DeviceManager(); 
     251        m_deviceManager = new DeviceManager(); 
    223252        if ( !m_deviceManager ) { 
    224253            debugError("Could not allocate device manager\n" ); 
     
    238267            return exitfunction(-1); 
    239268        } 
    240         
     269 
     270        // add busreset handler 
     271        Util::Functor* tmp_busreset_functor = new Util::CallbackFunctor0< void (*)() > 
     272                    ( &busresetHandler, false ); 
     273        if ( !tmp_busreset_functor ) { 
     274            debugFatal( "Could not create busreset handler\n" ); 
     275            return false; 
     276        } 
     277        if(!m_deviceManager->registerBusresetNotification(tmp_busreset_functor)) { 
     278            debugError("could not register busreset notifier"); 
     279        } 
     280 
    241281        signal (SIGINT, sighandler); 
    242282         
     
    245285        // test DBUS stuff 
    246286        DBus::default_dispatcher = &dispatcher; 
    247      
    248287        DBus::Connection conn = DBus::Connection::SessionBus(); 
     288        global_conn = &conn; 
    249289        conn.request_name("org.ffado.Control"); 
    250          
    251         DBusControl::Container *container 
    252             = new DBusControl::Container(conn, "/org/ffado/Control/DeviceManager", *m_deviceManager); 
     290 
     291        container = new DBusControl::Container(conn, "/org/ffado/Control/DeviceManager", *m_deviceManager); 
    253292         
    254293        printMessage("DBUS test service running\n"); 
    255         printMessage("press ctrl-c to stop it & continue\n"); 
     294        printMessage("press ctrl-c to stop it & exit\n"); 
    256295         
    257         dispatcher.enter(); 
    258      
     296        while(run) { 
     297            debugOutput( DEBUG_LEVEL_NORMAL, "dispatching...\n"); 
     298            dispatcher.enter(); 
     299            sem_wait(&run_sem); 
     300        } 
     301         
     302        if(!m_deviceManager->unregisterBusresetNotification(tmp_busreset_functor)) { 
     303            debugError("could not unregister busreset notifier"); 
     304        } 
     305        delete tmp_busreset_functor; 
    259306        delete container; 
    260307