root/trunk/libffado/src/devicemanager.cpp

Revision 2107, 43.1 kB (checked in by jwoithe, 9 years ago)

The firewire and FFADO architectures impose some lower limits on the number of buffers and buffer size. Test for these and raise an error if an attempt is made to violate these limits. If an error condition is detected print a message using printMessage() so the user has some hope of seeing it. debugFatal() isn't used because it will only print its message if debug was enabled at compile-time and a non-zero debug level is set. Addresses ticket #324. Thanks to 'paradox uncreated' for the initial bug report.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2008 by Daniel Wagner
3  * Copyright (C) 2005-2008 by Pieter Palmers
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "config.h"
26 #include "fbtypes.h"
27
28 #include "devicemanager.h"
29 #include "ffadodevice.h"
30 #include "DeviceStringParser.h"
31
32 #include "libieee1394/configrom.h"
33 #include "libieee1394/ieee1394service.h"
34 #include "libieee1394/IsoHandlerManager.h"
35
36 #include "libstreaming/generic/StreamProcessor.h"
37 #include "libstreaming/StreamProcessorManager.h"
38
39 #include "debugmodule/debugmodule.h"
40
41 #include "libutil/PosixMutex.h"
42
43 #ifdef ENABLE_BEBOB
44 #include "bebob/bebob_avdevice.h"
45 #endif
46
47 #ifdef ENABLE_MAUDIO
48 #include "maudio/maudio_avdevice.h"
49 #endif
50
51 #ifdef ENABLE_GENERICAVC
52     #include "genericavc/avc_avdevice.h"
53 #endif
54
55 #ifdef ENABLE_FIREWORKS
56     #include "fireworks/fireworks_device.h"
57 #endif
58
59 #ifdef ENABLE_OXFORD
60     #include "oxford/oxford_device.h"
61 #endif
62
63 #ifdef ENABLE_BOUNCE
64 #include "bounce/bounce_avdevice.h"
65 #include "bounce/bounce_slave_avdevice.h"
66 #endif
67
68 #ifdef ENABLE_MOTU
69 #include "motu/motu_avdevice.h"
70 #endif
71
72 #ifdef ENABLE_RME
73 #include "rme/rme_avdevice.h"
74 #endif
75
76 #ifdef ENABLE_DICE
77 #include "dice/dice_avdevice.h"
78 #endif
79
80 #ifdef ENABLE_METRIC_HALO
81 #include "metrichalo/mh_avdevice.h"
82 #endif
83
84 #include <iostream>
85 #include <sstream>
86
87 #include <algorithm>
88
89 using namespace std;
90
91 IMPL_DEBUG_MODULE( DeviceManager, DeviceManager, DEBUG_LEVEL_NORMAL );
92
93 DeviceManager::DeviceManager()
94     : Control::Container(NULL, "devicemanager") // this is the control root node
95     , m_DeviceListLock( new Util::PosixMutex("DEVLST") )
96     , m_BusResetLock( new Util::PosixMutex("DEVBR") )
97     , m_processorManager( new Streaming::StreamProcessorManager( *this ) )
98     , m_deviceStringParser( new DeviceStringParser() )
99     , m_configuration ( new Util::Configuration() )
100     , m_used_cache_last_time( false )
101     , m_thread_realtime( false )
102     , m_thread_priority( 0 )
103 {
104     addOption(Util::OptionContainer::Option("slaveMode", false));
105     addOption(Util::OptionContainer::Option("snoopMode", false));
106 }
107
108 DeviceManager::~DeviceManager()
109 {
110     // save configuration
111     if(!m_configuration->save()) {
112         debugWarning("could not save configuration\n");
113     }
114
115     m_BusResetLock->Lock(); // make sure we are not handling a busreset.
116     m_DeviceListLock->Lock(); // make sure nobody is using this
117     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
118           it != m_avDevices.end();
119           ++it )
120     {
121         if (!deleteElement(*it)) {
122             debugWarning("failed to remove Device from Control::Container\n");
123         }
124         delete *it;
125     }
126     m_DeviceListLock->Unlock();
127
128     // the SP's are automatically unregistered from the SPM
129     delete m_processorManager;
130
131     // the device list is empty, so wake up any waiting
132     // reset handlers
133     m_BusResetLock->Unlock();
134
135     // remove the bus-reset handlers
136     for ( FunctorVectorIterator it = m_busreset_functors.begin();
137           it != m_busreset_functors.end();
138           ++it )
139     {
140         delete *it;
141     }
142
143     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
144           it != m_1394Services.end();
145           ++it )
146     {
147         delete *it;
148     }
149
150     delete m_DeviceListLock;
151     delete m_BusResetLock;
152     delete m_deviceStringParser;
153 }
154
155 bool
156 DeviceManager::setThreadParameters(bool rt, int priority) {
157     if (!m_processorManager->setThreadParameters(rt, priority)) {
158         debugError("Could not set processor manager thread parameters\n");
159         return false;
160     }
161     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
162           it != m_1394Services.end();
163           ++it )
164     {
165         if (!(*it)->setThreadParameters(rt, priority)) {
166             debugError("Could not set 1394 service thread parameters\n");
167             return false;
168         }
169     }
170     m_thread_realtime = rt;
171     m_thread_priority = priority;
172     return true;
173 }
174
175 bool
176 DeviceManager::initialize()
177 {
178     assert(m_1394Services.size() == 0);
179     assert(m_busreset_functors.size() == 0);
180
181     m_configuration->openFile( "temporary", Util::Configuration::eFM_Temporary );
182     m_configuration->openFile( USER_CONFIG_FILE, Util::Configuration::eFM_ReadWrite );
183     m_configuration->openFile( SYSTEM_CONFIG_FILE, Util::Configuration::eFM_ReadOnly );
184
185     int nb_detected_ports = Ieee1394Service::detectNbPorts();
186     if (nb_detected_ports < 0) {
187         debugFatal("Failed to detect the number of 1394 adapters. Is the IEEE1394 stack loaded (raw1394)?\n");
188         return false;
189     }
190     if (nb_detected_ports == 0) {
191         debugFatal("No firewire adapters (ports) found.\n");
192         return false;
193     }
194     debugOutput( DEBUG_LEVEL_VERBOSE, "Found %d firewire adapters (ports)\n", nb_detected_ports);
195     for (unsigned int port = 0; port < (unsigned int)nb_detected_ports; port++) {
196         Ieee1394Service* tmp1394Service = new Ieee1394Service();
197         if ( !tmp1394Service ) {
198             debugFatal( "Could not create Ieee1349Service object for port %d\n", port );
199             return false;
200         }
201         tmp1394Service->setVerboseLevel( getDebugLevel() );
202         m_1394Services.push_back(tmp1394Service);
203
204         if(!tmp1394Service->useConfiguration(m_configuration)) {
205             debugWarning("Could not load config to 1394service\n");
206         }
207
208         tmp1394Service->setThreadParameters(m_thread_realtime, m_thread_priority);
209         if ( !tmp1394Service->initialize( port ) ) {
210             debugFatal( "Could not initialize Ieee1349Service object for port %d\n", port );
211             return false;
212         }
213         // add the bus reset handler
214         Util::Functor* tmp_busreset_functor = new Util::MemberFunctor1< DeviceManager*,
215                     void (DeviceManager::*)(Ieee1394Service &), Ieee1394Service & >
216                     ( this, &DeviceManager::busresetHandler, *tmp1394Service, false );
217         if ( !tmp_busreset_functor ) {
218             debugFatal( "Could not create busreset handler for port %d\n", port );
219             return false;
220         }
221         m_busreset_functors.push_back(tmp_busreset_functor);
222
223         tmp1394Service->addBusResetHandler( tmp_busreset_functor );
224     }
225
226     return true;
227 }
228
229 bool
230 DeviceManager::addSpecString(char *s) {
231     std::string spec = s;
232     if(isSpecStringValid(spec)) {
233         debugOutput(DEBUG_LEVEL_VERBOSE, "Adding spec string %s\n", spec.c_str());
234         assert(m_deviceStringParser);
235         m_deviceStringParser->parseString(spec);
236         return true;
237     } else {
238         debugError("Invalid spec string: %s\n", spec.c_str());
239         return false;
240     }
241 }
242
243 bool
244 DeviceManager::isSpecStringValid(std::string s) {
245     assert(m_deviceStringParser);
246     return m_deviceStringParser->isValidString(s);
247 }
248
249 void
250 DeviceManager::busresetHandler(Ieee1394Service &service)
251 {
252     // serialize bus reset handling since it can be that a new one occurs while we're
253     // doing stuff.
254     debugOutput( DEBUG_LEVEL_NORMAL, "Bus reset detected on service %p...\n", &service );
255     Util::MutexLockHelper lock(*m_BusResetLock);
256     debugOutput( DEBUG_LEVEL_NORMAL, " handling busreset...\n" );
257
258     // FIXME: what if the devices are gone? (device should detect this!)
259     // propagate the bus reset to all avDevices
260     m_DeviceListLock->Lock(); // make sure nobody is using this
261     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
262           it != m_avDevices.end();
263           ++it )
264     {
265         if(&service == &((*it)->get1394Service())) {
266             debugOutput(DEBUG_LEVEL_NORMAL,
267                         "issue busreset on device GUID %s\n",
268                         (*it)->getConfigRom().getGuidString().c_str());
269             (*it)->handleBusReset();
270         } else {
271             debugOutput(DEBUG_LEVEL_NORMAL,
272                         "skipping device GUID %s since not on service %p\n",
273                         (*it)->getConfigRom().getGuidString().c_str(), &service);
274         }
275     }
276     m_DeviceListLock->Unlock();
277
278     // now that the devices have been updates, we can request to update the iso streams
279     if(!service.getIsoHandlerManager().handleBusReset()) {
280         debugError("IsoHandlerManager failed to handle busreset\n");
281     }
282
283     // notify the streamprocessormanager of the busreset
284 //     if(m_processorManager) {
285 //         m_processorManager->handleBusReset(service);
286 //     } else {
287 //         debugWarning("No valid SPM\n");
288 //     }
289
290     // rediscover to find new devices
291     // (only for the control server ATM, streaming can't dynamically add/remove devices)
292     if(!discover(m_used_cache_last_time, true)) {
293         debugError("Could not rediscover devices\n");
294     }
295
296     // notify any clients
297     signalNotifiers(m_busResetNotifiers);
298
299     // display the new state
300     if(getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
301         showDeviceInfo();
302     }
303 }
304
305 void
306 DeviceManager::signalNotifiers(notif_vec_t& list)
307 {
308     for ( notif_vec_t::iterator it = list.begin();
309           it != list.end();
310           ++it )
311     {
312         Util::Functor* func = *it;
313         debugOutput( DEBUG_LEVEL_VERBOSE, " running notifier %p...\n", func );
314         ( *func )();
315     }
316 }
317
318 bool
319 DeviceManager::registerNotification(notif_vec_t& list, Util::Functor *handler)
320 {
321     debugOutput( DEBUG_LEVEL_VERBOSE, "register %p...\n", handler);
322     assert(handler);
323     for ( notif_vec_t::iterator it = list.begin();
324       it != list.end();
325       ++it )
326     {
327         if ( *it == handler ) {
328             debugOutput(DEBUG_LEVEL_VERBOSE, "already registered\n");
329             return false;
330         }
331     }
332     list.push_back(handler);
333     return true;
334 }
335
336 bool
337 DeviceManager::unregisterNotification(notif_vec_t& list, Util::Functor *handler)
338 {
339     debugOutput( DEBUG_LEVEL_VERBOSE, "unregister %p...\n", handler);
340     assert(handler);
341
342     for ( notif_vec_t::iterator it = list.begin();
343       it != list.end();
344       ++it )
345     {
346         if ( *it == handler ) {
347             list.erase(it);
348             return true;
349         }
350     }
351     debugError("Could not find handler (%p)\n", handler);
352     return false; //not found
353 }
354
355 bool
356 DeviceManager::discover( bool useCache, bool rediscover )
357 {
358     debugOutput( DEBUG_LEVEL_NORMAL, "Starting discovery...\n" );
359     useCache = useCache && ENABLE_DISCOVERY_CACHE;
360     m_used_cache_last_time = useCache;
361     bool slaveMode=false;
362     if(!getOption("slaveMode", slaveMode)) {
363         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
364     }
365     bool snoopMode=false;
366     if(!getOption("snoopMode", snoopMode)) {
367         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
368     }
369
370     setVerboseLevel(getDebugLevel());
371
372     // FIXME: it could be that a 1394service has disappeared (cardbus)
373
374     ConfigRomVector configRoms;
375     // build a list of configroms on the bus.
376     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
377         it != m_1394Services.end();
378         ++it )
379     {
380         Ieee1394Service *portService = *it;
381         for ( fb_nodeid_t nodeId = 0;
382             nodeId < portService->getNodeCount();
383             ++nodeId )
384         {
385             debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId );
386
387             if (nodeId == portService->getLocalNodeId()) {
388                 debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId );
389                 continue;
390             }
391
392             ConfigRom * configRom = new ConfigRom( *portService, nodeId );
393             if ( !configRom->initialize() ) {
394                 // \todo If a PHY on the bus is in power safe mode then
395                 // the config rom is missing. So this might be just
396                 // such this case and we can safely skip it. But it might
397                 // be there is a real software problem on our side.
398                 // This should be handlede more carefuly.
399                 debugOutput( DEBUG_LEVEL_NORMAL,
400                             "Could not read config rom from device (node id %d). "
401                             "Skip device discovering for this node\n",
402                             nodeId );
403                 continue;
404             }
405             configRoms.push_back(configRom);
406         }
407     }
408
409
410     // notify that we are going to manipulate the list
411     signalNotifiers(m_preUpdateNotifiers);
412     m_DeviceListLock->Lock(); // make sure nobody starts using the list
413     if(rediscover) {
414
415         FFADODeviceVector discovered_devices_on_bus;
416         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
417             it != m_avDevices.end();
418             ++it )
419         {
420             bool seen_device = false;
421             for ( ConfigRomVectorIterator it2 = configRoms.begin();
422                 it2 != configRoms.end();
423                 ++it2 )
424             {
425                 seen_device |= ((*it)->getConfigRom().getGuid() == (*it2)->getGuid());
426             }
427
428             if(seen_device) {
429                 debugOutput( DEBUG_LEVEL_VERBOSE,
430                             "Already discovered device with GUID: %s\n",
431                             (*it)->getConfigRom().getGuidString().c_str() );
432                 // we already discovered this device, and it is still here. keep it
433                 discovered_devices_on_bus.push_back(*it);
434             } else {
435                 debugOutput( DEBUG_LEVEL_VERBOSE,
436                             "Device with GUID: %s disappeared from bus, removing...\n",
437                             (*it)->getConfigRom().getGuidString().c_str() );
438
439                 // the device has disappeared, remove it from the control tree
440                 if (!deleteElement(*it)) {
441                     debugWarning("failed to remove Device from Control::Container\n");
442                 }
443                 // delete the device
444                 // FIXME: this will mess up the any code that waits for bus resets to
445                 //        occur
446                 delete *it;
447             }
448         }
449         // prune the devices that disappeared
450         m_avDevices = discovered_devices_on_bus;
451     } else { // remove everything since we are not rediscovering
452         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
453             it != m_avDevices.end();
454             ++it )
455         {
456             if (!deleteElement(*it)) {
457                 debugWarning("failed to remove Device from Control::Container\n");
458             }
459             delete *it;
460         }
461
462         m_avDevices.clear();
463     }
464
465     // delete the config rom list entries
466     // FIXME: we should reuse it
467     for ( ConfigRomVectorIterator it = configRoms.begin();
468         it != configRoms.end();
469         ++it )
470     {
471         delete *it;
472     }
473
474     assert(m_deviceStringParser);
475     // show the spec strings we're going to use
476     if(getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
477         m_deviceStringParser->show();
478     }
479
480     if (!slaveMode) {
481         // for the devices that are still in the list check if they require re-discovery
482         FFADODeviceVector failed_to_rediscover;
483         for ( FFADODeviceVectorIterator it_dev = m_avDevices.begin();
484             it_dev != m_avDevices.end();
485             ++it_dev )
486         {
487             FFADODevice* avDevice = *it_dev;
488             if(avDevice->needsRediscovery()) {
489                 debugOutput( DEBUG_LEVEL_NORMAL,
490                              "Device with GUID %s requires rediscovery (state changed)...\n",
491                              avDevice->getConfigRom().getGuidString().c_str());
492
493                 bool isFromCache = false;
494                 if ( useCache && avDevice->loadFromCache() ) {
495                     debugOutput( DEBUG_LEVEL_VERBOSE, "could load from cache\n" );
496                     isFromCache = true;
497                     // restore the debug level for everything that was loaded
498                     avDevice->setVerboseLevel( getDebugLevel() );
499                 } else if ( avDevice->discover() ) {
500                     debugOutput( DEBUG_LEVEL_VERBOSE, "discovery successful\n" );
501                 } else {
502                     debugError( "could not discover device\n" );
503                     failed_to_rediscover.push_back(avDevice);
504                     continue;
505                 }
506                 if ( !isFromCache && !avDevice->saveCache() ) {
507                     debugOutput( DEBUG_LEVEL_VERBOSE, "No cached version of AVC model created\n" );
508                 }
509             } else {
510                 debugOutput( DEBUG_LEVEL_NORMAL,
511                              "Device with GUID %s does not require rediscovery...\n",
512                              avDevice->getConfigRom().getGuidString().c_str());
513             }
514         }
515         // remove devices that failed to rediscover
516         // FIXME: surely there has to be a better way to do this
517         FFADODeviceVector to_keep;
518         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
519             it != m_avDevices.end();
520             ++it )
521         {
522             bool keep_this_device = true;
523             for ( FFADODeviceVectorIterator it2 = failed_to_rediscover.begin();
524                 it2 != failed_to_rediscover.end();
525                 ++it2 )
526             {
527                 if(*it == *it2) {
528                     debugOutput( DEBUG_LEVEL_NORMAL,
529                                 "Removing device with GUID %s due to failed discovery...\n",
530                                 (*it)->getConfigRom().getGuidString().c_str());
531                     keep_this_device = false;
532                     break;
533                 }
534             }
535             if(keep_this_device) {
536                 to_keep.push_back(*it);
537             }
538         }
539         for ( FFADODeviceVectorIterator it2 = failed_to_rediscover.begin();
540             it2 != failed_to_rediscover.end();
541             ++it2 )
542         {
543             if (!deleteElement(*it2)) {
544                 debugWarning("failed to remove Device from Control::Container\n");
545             }
546             delete *it2;
547         }
548         m_avDevices = to_keep;
549
550         // pick up new devices
551         for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
552             it != m_1394Services.end();
553             ++it )
554         {
555             Ieee1394Service *portService = *it;
556             for ( fb_nodeid_t nodeId = 0;
557                 nodeId < portService->getNodeCount();
558                 ++nodeId )
559             {
560                 debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId );
561    
562                 if (nodeId == portService->getLocalNodeId()) {
563                     debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId );
564                     continue;
565                 }
566    
567                 ConfigRom *configRom = new ConfigRom( *portService, nodeId );
568                 if ( !configRom->initialize() ) {
569                     // \todo If a PHY on the bus is in power safe mode then
570                     // the config rom is missing. So this might be just
571                     // such this case and we can safely skip it. But it might
572                     // be there is a real software problem on our side.
573                     // This should be handlede more carefuly.
574                     debugOutput( DEBUG_LEVEL_NORMAL,
575                                 "Could not read config rom from device (node id %d). "
576                                 "Skip device discovering for this node\n",
577                                 nodeId );
578                     continue;
579                 }
580
581                 bool already_in_vector = false;
582                 for ( FFADODeviceVectorIterator it_dev = m_avDevices.begin();
583                     it_dev != m_avDevices.end();
584                     ++it_dev )
585                 {
586                     if ((*it_dev)->getConfigRom().getGuid() == configRom->getGuid()) {
587                         already_in_vector = true;
588                         break;
589                     }
590                 }
591                 if(already_in_vector) {
592                     if(!rediscover) {
593                         debugWarning("Device with GUID %s already discovered on other port, skipping device...\n",
594                                     configRom->getGuidString().c_str());
595                     }
596                     continue;
597                 }
598
599                 if(getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
600                     configRom->printConfigRomDebug();
601                 }
602
603                 // if spec strings are given, only add those devices
604                 // that match the spec string(s).
605                 // if no (valid) spec strings are present, grab all
606                 // supported devices.
607                 if(m_deviceStringParser->countDeviceStrings() &&
608                   !m_deviceStringParser->match(*configRom)) {
609                     debugOutput(DEBUG_LEVEL_VERBOSE, "Device doesn't match any of the spec strings. skipping...\n");
610                     continue;
611                 }
612
613                 // find a driver
614                 FFADODevice* avDevice = getDriverForDevice( configRom,
615                                                             nodeId );
616
617                 if ( avDevice ) {
618                     debugOutput( DEBUG_LEVEL_NORMAL,
619                                 "driver found for device %d\n",
620                                 nodeId );
621
622                     avDevice->setVerboseLevel( getDebugLevel() );
623                     bool isFromCache = false;
624                     if ( useCache && avDevice->loadFromCache() ) {
625                         debugOutput( DEBUG_LEVEL_VERBOSE, "could load from cache\n" );
626                         isFromCache = true;
627                         // restore the debug level for everything that was loaded
628                         avDevice->setVerboseLevel( getDebugLevel() );
629                     } else if ( avDevice->discover() ) {
630                         debugOutput( DEBUG_LEVEL_VERBOSE, "discovery successful\n" );
631                     } else {
632                         debugError( "could not discover device\n" );
633                         delete avDevice;
634                         continue;
635                     }
636
637                     if (snoopMode) {
638                         debugOutput( DEBUG_LEVEL_VERBOSE,
639                                     "Enabling snoop mode on node %d...\n", nodeId );
640
641                         if(!avDevice->setOption("snoopMode", snoopMode)) {
642                             debugWarning("Could not set snoop mode for device on node %d\n", nodeId);
643                             delete avDevice;
644                             continue;
645                         }
646                     }
647
648                     if ( !isFromCache && !avDevice->saveCache() ) {
649                         debugOutput( DEBUG_LEVEL_VERBOSE, "No cached version of AVC model created\n" );
650                     }
651                     m_avDevices.push_back( avDevice );
652
653                     if (!addElement(avDevice)) {
654                         debugWarning("failed to add Device to Control::Container\n");
655                     }
656
657                     debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d on port %d done...\n", nodeId, portService->getPort() );
658                 } else {
659                     // we didn't get a device, hence we have to delete the configrom ptr manually
660                     delete configRom;
661                 }
662             }
663         }
664
665         debugOutput( DEBUG_LEVEL_NORMAL, "Discovery finished...\n" );
666         // FIXME: do better sorting
667         // sort the m_avDevices vector on their GUID
668         // then assign reassign the id's to the devices
669         // the side effect of this is that for the same set of attached devices,
670         // a device id always corresponds to the same device
671         sort(m_avDevices.begin(), m_avDevices.end(), FFADODevice::compareGUID);
672
673         int i=0;
674         if(m_deviceStringParser->countDeviceStrings()) { // only if there are devicestrings
675             // first map the devices to a position using the device spec strings
676             std::map<fb_octlet_t, int> positionMap;
677             for ( FFADODeviceVectorIterator it = m_avDevices.begin();
678                 it != m_avDevices.end();
679                 ++it )
680             {
681                 int pos = m_deviceStringParser->matchPosition((*it)->getConfigRom());
682                 fb_octlet_t guid = (*it)->getConfigRom().getGuid();
683                 positionMap[guid] = pos;
684                 debugOutput( DEBUG_LEVEL_VERBOSE, "Mapping %s to position %d...\n", (*it)->getConfigRom().getGuidString().c_str(), pos );
685             }
686    
687             // now run over all positions, and add the devices that belong to it
688             FFADODeviceVector sorted;
689             int nbPositions = m_deviceStringParser->countDeviceStrings();
690             for (i=0; i < nbPositions; i++) {
691                 for ( FFADODeviceVectorIterator it = m_avDevices.begin();
692                     it != m_avDevices.end();
693                     ++it )
694                 {
695                     fb_octlet_t guid = (*it)->getConfigRom().getGuid();
696                     if(positionMap[guid] == i) {
697                         sorted.push_back(*it);
698                     }
699                 }
700             }
701             // assign the new vector
702             flushDebugOutput();
703             assert(sorted.size() == m_avDevices.size());
704             m_avDevices = sorted;
705         }
706
707         showDeviceInfo();
708
709     } else { // slave mode
710         // notify any clients
711         signalNotifiers(m_preUpdateNotifiers);
712         Ieee1394Service *portService = m_1394Services.at(0);
713         fb_nodeid_t nodeId = portService->getLocalNodeId();
714         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId );
715
716         std::auto_ptr<ConfigRom> configRom =
717             std::auto_ptr<ConfigRom>( new ConfigRom( *portService,
718                                                      nodeId ) );
719         if ( !configRom->initialize() ) {
720             // \todo If a PHY on the bus is in power safe mode then
721             // the config rom is missing. So this might be just
722             // such this case and we can safely skip it. But it might
723             // be there is a real software problem on our side.
724             // This should be handled more carefuly.
725             debugOutput( DEBUG_LEVEL_NORMAL,
726                          "Could not read config rom from device (node id %d). "
727                          "Skip device discovering for this node\n",
728                          nodeId );
729             return false;
730         }
731
732         // remove any already present devices
733         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
734             it != m_avDevices.end();
735             ++it )
736         {
737             if (!deleteElement(*it)) {
738                 debugWarning("failed to remove Device from Control::Container\n");
739             }
740             delete *it;
741         }
742
743         m_avDevices.clear();
744
745         // get the slave driver
746         FFADODevice* avDevice = getSlaveDriver( configRom );
747         if ( avDevice ) {
748             debugOutput( DEBUG_LEVEL_NORMAL,
749                          "driver found for device %d\n",
750                          nodeId );
751
752             avDevice->setVerboseLevel( getDebugLevel() );
753
754             if ( !avDevice->discover() ) {
755                 debugError( "could not discover device\n" );
756                 delete avDevice;
757                 return false;
758             }
759
760             if ( getDebugLevel() >= DEBUG_LEVEL_VERBOSE ) {
761                 avDevice->showDevice();
762             }
763             m_avDevices.push_back( avDevice );
764             debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d on port %d done...\n", nodeId, portService->getPort() );
765         }
766
767         debugOutput( DEBUG_LEVEL_NORMAL, "discovery finished...\n" );
768     }
769
770     m_DeviceListLock->Unlock();
771     // notify any clients
772     signalNotifiers(m_postUpdateNotifiers);
773     return true;
774 }
775
776 bool
777 DeviceManager::initStreaming()
778 {
779     // iterate over the found devices
780     // add the stream processors of the devices to the managers
781     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
782         it != m_avDevices.end();
783         ++it )
784     {
785         FFADODevice *device = *it;
786         assert(device);
787
788         debugOutput(DEBUG_LEVEL_VERBOSE, "Locking device (%p)\n", device);
789
790         if (!device->lock()) {
791             debugWarning("Could not lock device, skipping device (%p)!\n", device);
792             continue;
793         }
794
795         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting samplerate to %d for (%p)\n",
796                     m_processorManager->getNominalRate(), device);
797
798         // Set the device's sampling rate to that requested
799         // FIXME: does this really belong here?  If so we need to handle errors.
800         if (!device->setSamplingFrequency(m_processorManager->getNominalRate())) {
801             debugOutput(DEBUG_LEVEL_VERBOSE, " => Retry setting samplerate to %d for (%p)\n",
802                         m_processorManager->getNominalRate(), device);
803
804             // try again:
805             if (!device->setSamplingFrequency(m_processorManager->getNominalRate())) {
806                 debugFatal("Could not set sampling frequency to %d\n",m_processorManager->getNominalRate());
807                 return false;
808             }
809         }
810         // prepare the device
811         device->prepare();
812     }
813
814     // set the sync source
815     if (!m_processorManager->setSyncSource(getSyncSource())) {
816         debugWarning("Could not set processorManager sync source (%p)\n",
817             getSyncSource());
818     }
819
820     return true;
821 }
822
823 bool
824 DeviceManager::prepareStreaming()
825 {
826     if (!m_processorManager->prepare()) {
827         debugFatal("Could not prepare streaming...\n");
828         return false;
829     }
830     return true;
831 }
832
833 bool
834 DeviceManager::finishStreaming() {
835     bool result = true;
836     // iterate over the found devices
837     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
838         it != m_avDevices.end();
839         ++it )
840     {
841         debugOutput(DEBUG_LEVEL_VERBOSE, "Unlocking device (%p)\n", *it);
842
843         if (!(*it)->unlock()) {
844             debugWarning("Could not unlock device (%p)!\n", *it);
845             result = false;
846         }
847     }
848     return result;
849 }
850
851 bool
852 DeviceManager::startStreamingOnDevice(FFADODevice *device)
853 {
854     assert(device);
855
856     int j=0;
857     bool all_streams_started = true;
858     bool device_start_failed = false;
859
860     if (device->resetForStreaming() == false)
861         return false;
862
863     for(j=0; j < device->getStreamCount(); j++) {
864         debugOutput(DEBUG_LEVEL_VERBOSE,"Starting stream %d of device %p\n", j, device);
865         // start the stream
866         if (!device->startStreamByIndex(j)) {
867             debugWarning("Could not start stream %d of device %p\n", j, device);
868             all_streams_started = false;
869             break;
870         }
871     }
872
873     if(!all_streams_started) {
874         // disable all streams that did start up correctly
875         for(j = j-1; j >= 0; j--) {
876             debugOutput(DEBUG_LEVEL_VERBOSE,"Stopping stream %d of device %p\n", j, device);
877             // stop the stream
878             if (!device->stopStreamByIndex(j)) {
879                 debugWarning("Could not stop stream %d of device %p\n", j, device);
880             }
881         }
882         device_start_failed = true;
883     } else {
884         if (!device->enableStreaming()) {
885             debugWarning("Could not enable streaming on device %p!\n", device);
886             device_start_failed = true;
887         }
888     }
889     return !device_start_failed;
890 }
891
892 bool
893 DeviceManager::startStreaming() {
894     bool device_start_failed = false;
895     FFADODeviceVectorIterator it;
896
897     // create the connections for all devices
898     // iterate over the found devices
899     for ( it = m_avDevices.begin();
900         it != m_avDevices.end();
901         ++it )
902     {
903         if (!startStreamingOnDevice(*it)) {
904             debugWarning("Could not start streaming on device %p!\n", *it);
905             device_start_failed = true;
906             break;
907         }
908     }
909
910     // if one of the devices failed to start,
911     // the previous routine should have cleaned up the failing one.
912     // we still have to stop all devices that were started before this one.
913     if(device_start_failed) {
914         for (FFADODeviceVectorIterator it2 = m_avDevices.begin();
915             it2 != it;
916             ++it2 )
917         {
918             if (!stopStreamingOnDevice(*it2)) {
919                 debugWarning("Could not stop streaming on device %p!\n", *it2);
920             }
921         }
922         return false;
923     }
924
925     // start the stream processor manager to tune in to the channels
926     if(m_processorManager->start()) {
927         return true;
928     } else {
929         debugWarning("Failed to start SPM!\n");
930         for( it = m_avDevices.begin();
931              it != m_avDevices.end();
932              ++it )
933         {
934             if (!stopStreamingOnDevice(*it)) {
935                 debugWarning("Could not stop streaming on device %p!\n", *it);
936             }
937         }
938         return false;
939     }
940 }
941
942 bool
943 DeviceManager::resetStreaming() {
944     return true;
945 }
946
947 bool
948 DeviceManager::stopStreamingOnDevice(FFADODevice *device)
949 {
950     assert(device);
951     bool result = true;
952
953     if (!device->disableStreaming()) {
954         debugWarning("Could not disable streaming on device %p!\n", device);
955     }
956
957     int j=0;
958     for(j=0; j < device->getStreamCount(); j++) {
959         debugOutput(DEBUG_LEVEL_VERBOSE,"Stopping stream %d of device %p\n", j, device);
960         // stop the stream
961         // start the stream
962         if (!device->stopStreamByIndex(j)) {
963             debugWarning("Could not stop stream %d of device %p\n", j, device);
964             result = false;
965             continue;
966         }
967     }
968     return result;
969 }
970
971 bool
972 DeviceManager::stopStreaming()
973 {
974     bool result = true;
975     m_processorManager->stop();
976
977     // create the connections for all devices
978     // iterate over the found devices
979     // add the stream processors of the devices to the managers
980     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
981         it != m_avDevices.end();
982         ++it )
983     {
984         stopStreamingOnDevice(*it);
985     }
986     return result;
987 }
988
989 enum DeviceManager::eWaitResult
990 DeviceManager::waitForPeriod() {
991     if(m_processorManager->waitForPeriod()) {
992         return eWR_OK;
993     } else {
994         if(m_processorManager->shutdownNeeded()) {
995             debugWarning("Shutdown requested\n");
996             return eWR_Shutdown;
997         } else {
998             debugWarning("XRUN detected\n");
999             // do xrun recovery
1000             if(m_processorManager->handleXrun()) {
1001                 return eWR_Xrun;
1002             } else {
1003                 debugError("Could not handle XRUN\n");
1004                 return eWR_Error;
1005             }
1006         }
1007     }
1008 }
1009
1010 bool
1011 DeviceManager::setPeriodSize(unsigned int period) {
1012     // Useful for cases where only the period size needs adjusting
1013     if (!m_processorManager->streamingParamsOk(period, -1, -1)) {
1014         return false;
1015     }
1016     m_processorManager->setPeriodSize(period);
1017     return true;
1018 }
1019
1020 bool
1021 DeviceManager::setStreamingParams(unsigned int period, unsigned int rate, unsigned int nb_buffers) {
1022     if (!m_processorManager->streamingParamsOk(period, rate, nb_buffers)) {
1023         return false;
1024     }
1025     m_processorManager->setPeriodSize(period);
1026     m_processorManager->setNominalRate(rate);
1027     m_processorManager->setNbBuffers(nb_buffers);
1028     return true;
1029 }
1030
1031 FFADODevice*
1032 DeviceManager::getDriverForDeviceDo( ConfigRom *configRom,
1033                                    int id, bool generic )
1034 {
1035 #ifdef ENABLE_BEBOB
1036     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying BeBoB...\n" );
1037     if ( BeBoB::Device::probe( getConfiguration(), *configRom, generic ) ) {
1038         return BeBoB::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
1039     }
1040 #endif
1041
1042 #ifdef ENABLE_FIREWORKS
1043     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying ECHO Audio FireWorks...\n" );
1044     if ( FireWorks::Device::probe( getConfiguration(), *configRom, generic ) ) {
1045         return FireWorks::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
1046     }
1047 #endif
1048
1049 #ifdef ENABLE_OXFORD
1050     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Oxford FW90x...\n" );
1051     if ( Oxford::Device::probe( getConfiguration(), *configRom, generic ) ) {
1052         return Oxford::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
1053     }
1054 #endif
1055
1056 #ifdef ENABLE_MAUDIO
1057     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying M-Audio...\n" );
1058     if ( MAudio::Device::probe( getConfiguration(), *configRom, generic ) ) {
1059         return MAudio::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
1060     }
1061 #endif
1062
1063 // we want to try the non-generic AV/C platforms before trying the generic ones
1064 #ifdef ENABLE_GENERICAVC
1065     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Generic AV/C...\n" );
1066     if ( GenericAVC::Device::probe( getConfiguration(), *configRom, generic ) ) {
1067         return GenericAVC::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
1068     }
1069 #endif
1070
1071 #ifdef ENABLE_MOTU
1072     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Motu...\n" );
1073     if ( Motu::MotuDevice::probe( getConfiguration(), *configRom, generic ) ) {
1074         return Motu::MotuDevice::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
1075     }
1076 #endif
1077
1078 #ifdef ENABLE_DICE
1079     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Dice...\n" );
1080     if ( Dice::Device::probe( getConfiguration(), *configRom, generic ) ) {
1081         return Dice::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
1082     }
1083 #endif
1084
1085 #ifdef ENABLE_METRIC_HALO
1086     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Metric Halo...\n" );
1087     if ( MetricHalo::Device::probe( getConfiguration(), *configRom, generic ) ) {
1088         return MetricHalo::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
1089     }
1090 #endif
1091
1092 #ifdef ENABLE_RME
1093     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying RME...\n" );
1094     if ( Rme::Device::probe( getConfiguration(), *configRom, generic ) ) {
1095         return Rme::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
1096     }
1097 #endif
1098
1099 #ifdef ENABLE_BOUNCE
1100     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Bounce...\n" );
1101     if ( Bounce::Device::probe( getConfiguration(), *configRom, generic ) ) {
1102         return Bounce::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
1103     }
1104 #endif
1105
1106     return NULL;
1107 }
1108
1109 FFADODevice*
1110 DeviceManager::getDriverForDevice( ConfigRom *configRom,
1111                                    int id )
1112 {
1113     debugOutput( DEBUG_LEVEL_VERBOSE, "Probing for supported device...\n" );
1114     FFADODevice* dev = getDriverForDeviceDo(configRom, id, false);
1115     if(dev) {
1116         debugOutput( DEBUG_LEVEL_VERBOSE, " found supported device...\n" );
1117         dev->setVerboseLevel(getDebugLevel());
1118         return dev;
1119     }
1120
1121     debugOutput( DEBUG_LEVEL_VERBOSE, " no supported device found, trying generic support...\n" );
1122     dev = getDriverForDeviceDo(configRom, id, true);
1123     if(dev) {
1124         debugOutput( DEBUG_LEVEL_VERBOSE, " found generic support for device...\n" );
1125         dev->setVerboseLevel(getDebugLevel());
1126         return dev;
1127     }
1128     debugOutput( DEBUG_LEVEL_VERBOSE, " device not supported...\n" );
1129     return NULL;
1130 }
1131
1132 FFADODevice*
1133 DeviceManager::getSlaveDriver( std::auto_ptr<ConfigRom>( configRom ) )
1134 {
1135 #ifdef ENABLE_BOUNCE
1136     if ( Bounce::SlaveDevice::probe( getConfiguration(), *configRom, false ) ) {
1137         return Bounce::SlaveDevice::createDevice(  *this, std::auto_ptr<ConfigRom>( configRom ) );
1138     }
1139 #endif
1140     return NULL;
1141 }
1142
1143 bool
1144 DeviceManager::isValidNode(int node)
1145 {
1146     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
1147           it != m_avDevices.end();
1148           ++it )
1149     {
1150         FFADODevice* avDevice = *it;
1151
1152         if (avDevice->getConfigRom().getNodeId() == node) {
1153             return true;
1154     }
1155     }
1156     return false;
1157 }
1158
1159 int
1160 DeviceManager::getNbDevices()
1161 {
1162     return m_avDevices.size();
1163 }
1164
1165 int
1166 DeviceManager::getDeviceNodeId( int deviceNr )
1167 {
1168     if ( ! ( deviceNr < getNbDevices() ) ) {
1169         debugError( "Device number out of range (%d)\n", deviceNr );
1170         return -1;
1171     }
1172
1173     FFADODevice* avDevice = m_avDevices.at( deviceNr );
1174
1175     if ( !avDevice ) {
1176         debugError( "Could not get device at position (%d)\n",  deviceNr );
1177     }
1178
1179     return avDevice->getConfigRom().getNodeId();
1180 }
1181
1182 FFADODevice*
1183 DeviceManager::getAvDevice( int nodeId )
1184 {
1185     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
1186           it != m_avDevices.end();
1187           ++it )
1188     {
1189         FFADODevice* avDevice = *it;
1190         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
1191             return avDevice;
1192         }
1193     }
1194
1195     return 0;
1196 }
1197
1198 FFADODevice*
1199 DeviceManager::getAvDeviceByIndex( int idx )
1200 {
1201     return m_avDevices.at(idx);
1202 }
1203
1204 unsigned int
1205 DeviceManager::getAvDeviceCount( )
1206 {
1207     return m_avDevices.size();
1208 }
1209
1210 /**
1211  * Return the streamprocessor that is to be used as
1212  * the sync source.
1213  *
1214  * Algorithm still to be determined
1215  *
1216  * @return StreamProcessor that is sync source
1217  */
1218 Streaming::StreamProcessor *
1219 DeviceManager::getSyncSource() {
1220     FFADODevice* device = getAvDeviceByIndex(0);
1221
1222     bool slaveMode=false;
1223     if(!getOption("slaveMode", slaveMode)) {
1224         debugOutput(DEBUG_LEVEL_NORMAL,
1225                     "Could not retrieve slaveMode parameter, defauling to false\n");
1226     }
1227     return device->getStreamProcessorByIndex(0);
1228 /*
1229     #warning TEST CODE FOR BOUNCE DEVICE !!
1230     // this makes the bounce slave use the xmit SP as sync source
1231     if (slaveMode) {
1232         return device->getStreamProcessorByIndex(1);
1233     } else {
1234         return device->getStreamProcessorByIndex(0);
1235     }*/
1236 }
1237
1238 bool
1239 DeviceManager::deinitialize()
1240 {
1241     return true;
1242 }
1243
1244 void
1245 DeviceManager::setVerboseLevel(int l)
1246 {
1247     setDebugLevel(l);
1248     Control::Element::setVerboseLevel(l);
1249     m_processorManager->setVerboseLevel(l);
1250     m_deviceStringParser->setVerboseLevel(l);
1251     m_configuration->setVerboseLevel(l);
1252     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
1253           it != m_avDevices.end();
1254           ++it )
1255     {
1256         (*it)->setVerboseLevel(l);
1257     }
1258     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
1259           it != m_1394Services.end();
1260           ++it )
1261     {
1262         (*it)->setVerboseLevel(l);
1263     }
1264     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
1265 }
1266
1267 void
1268 DeviceManager::showDeviceInfo() {
1269     debugOutput(DEBUG_LEVEL_NORMAL, "===== Device Manager =====\n");
1270     Control::Element::show();
1271
1272     int i=0;
1273     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
1274           it != m_1394Services.end();
1275           ++it )
1276     {
1277         debugOutput(DEBUG_LEVEL_NORMAL, "--- IEEE1394 Service %2d ---\n", i++);
1278         (*it)->show();
1279     }
1280
1281     i=0;
1282     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
1283         it != m_avDevices.end();
1284         ++it )
1285     {
1286         FFADODevice* avDevice = *it;
1287         debugOutput(DEBUG_LEVEL_NORMAL, "--- Device %2d ---\n", i++);
1288         avDevice->showDevice();
1289
1290         debugOutput(DEBUG_LEVEL_NORMAL, "Clock sync sources:\n");
1291         FFADODevice::ClockSourceVector sources=avDevice->getSupportedClockSources();
1292         for ( FFADODevice::ClockSourceVector::const_iterator it
1293                 = sources.begin();
1294             it != sources.end();
1295             ++it )
1296         {
1297             FFADODevice::ClockSource c=*it;
1298             debugOutput(DEBUG_LEVEL_NORMAL, " Type: %s, Id: %2d, Valid: %1d, Active: %1d, Locked %1d, Slipping: %1d, Description: %s\n",
1299                 FFADODevice::ClockSourceTypeToString(c.type), c.id, c.valid, c.active, c.locked, c.slipping, c.description.c_str());
1300         }
1301     }
1302 }
1303 void
1304 DeviceManager::showStreamingInfo() {
1305     m_processorManager->dumpInfo();
1306 }
Note: See TracBrowser for help on using the browser.