root/trunk/libffado/src/devicemanager.cpp

Revision 745, 18.9 kB (checked in by ppalmers, 16 years ago)

implement clock source selection for DICE EVM

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2007 by Daniel Wagner
3  * Copyright (C) 2005-2007 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 3 of the License, or
13  * (at your option) any later version.
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 "fbtypes.h"
26
27 #include "devicemanager.h"
28 #include "ffadodevice.h"
29
30 #include "libieee1394/configrom.h"
31 #include "libieee1394/ieee1394service.h"
32
33 #include "libstreaming/generic/StreamProcessor.h"
34
35 #include "debugmodule/debugmodule.h"
36
37 #ifdef ENABLE_BEBOB
38 #include "bebob/bebob_avdevice.h"
39 #include "maudio/maudio_avdevice.h"
40 #endif
41
42 #ifdef ENABLE_GENERICAVC
43     #include "genericavc/avc_avdevice.h"
44 #endif
45
46 #ifdef ENABLE_FIREWORKS
47     #include "fireworks/fireworks_device.h"
48 #endif
49
50 #ifdef ENABLE_BOUNCE
51 #include "bounce/bounce_avdevice.h"
52 #include "bounce/bounce_slave_avdevice.h"
53 #endif
54
55 #ifdef ENABLE_MOTU
56 #include "motu/motu_avdevice.h"
57 #endif
58
59 #ifdef ENABLE_RME
60 #include "rme/rme_avdevice.h"
61 #endif
62
63 #ifdef ENABLE_DICE
64 #include "dice/dice_avdevice.h"
65 #endif
66
67 #ifdef ENABLE_METRIC_HALO
68 #include "metrichalo/mh_avdevice.h"
69 #endif
70
71 #include <iostream>
72 #include <sstream>
73
74 #include <algorithm>
75
76 using namespace std;
77
78 IMPL_DEBUG_MODULE( DeviceManager, DeviceManager, DEBUG_LEVEL_NORMAL );
79
80 DeviceManager::DeviceManager()
81     : Control::Container("devicemanager")
82 {
83     addOption(Util::OptionContainer::Option("slaveMode",false));
84     addOption(Util::OptionContainer::Option("snoopMode",false));
85 }
86
87 DeviceManager::~DeviceManager()
88 {
89     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
90           it != m_avDevices.end();
91           ++it )
92     {
93         if (!deleteElement(*it)) {
94             debugWarning("failed to remove AvDevice from Control::Container\n");
95         }
96         delete *it;
97     }
98
99     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
100           it != m_1394Services.end();
101           ++it )
102     {
103         delete *it;
104     }
105     for ( FunctorVectorIterator it = m_busreset_functors.begin();
106           it != m_busreset_functors.end();
107           ++it )
108     {
109         delete *it;
110     }
111 }
112
113 void
114 DeviceManager::setVerboseLevel(int l)
115 {
116     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
117     setDebugLevel(l);
118     Control::Element::setVerboseLevel(l);
119     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
120           it != m_avDevices.end();
121           ++it )
122     {
123         (*it)->setVerboseLevel(l);
124     }
125     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
126           it != m_1394Services.end();
127           ++it )
128     {
129         (*it)->setVerboseLevel(l);
130     }
131 }
132
133 void
134 DeviceManager::show() {
135     debugOutput(DEBUG_LEVEL_NORMAL, "===== Device Manager =====\n");
136     Control::Element::show();
137
138     int i=0;
139     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
140           it != m_1394Services.end();
141           ++it )
142     {
143         debugOutput(DEBUG_LEVEL_NORMAL, "--- IEEE1394 Service %2d ---\n", i++);
144         (*it)->show();
145     }
146
147     i=0;
148     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
149         it != m_avDevices.end();
150         ++it )
151     {
152         FFADODevice* avDevice = *it;
153         debugOutput(DEBUG_LEVEL_NORMAL, "--- Device %2d ---\n", i++);
154         avDevice->showDevice();
155
156         debugOutput(DEBUG_LEVEL_NORMAL, "Clock sync sources:\n");
157         FFADODevice::ClockSourceVector sources=avDevice->getSupportedClockSources();
158         for ( FFADODevice::ClockSourceVector::const_iterator it
159                 = sources.begin();
160             it != sources.end();
161             ++it )
162         {
163             FFADODevice::ClockSource c=*it;
164             debugOutput(DEBUG_LEVEL_NORMAL, " Type: %s, Id: %2d, Valid: %1d, Active: %1d, Locked %1d, Slipping: %1d, Description: %s\n",
165                 FFADODevice::ClockSourceTypeToString(c.type), c.id, c.valid, c.active, c.locked, c.slipping, c.description.c_str());
166         }
167     }
168 }
169
170 bool
171 DeviceManager::initialize()
172 {
173     assert(m_1394Services.size() == 0);
174     assert(m_busreset_functors.size() == 0);
175
176     unsigned int nb_detected_ports = Ieee1394Service::detectNbPorts();
177     if (nb_detected_ports == 0) {
178         debugFatal("No firewire ports found.\n");
179         return false;
180     }
181     debugOutput( DEBUG_LEVEL_VERBOSE, "Found %d firewire adapters (ports)\n", nb_detected_ports);
182     for (unsigned int port = 0; port < nb_detected_ports; port++) {
183         Ieee1394Service* tmp1394Service = new Ieee1394Service();
184         if ( !tmp1394Service ) {
185             debugFatal( "Could not create Ieee1349Service object for port %d\n", port );
186             return false;
187         }
188         m_1394Services.push_back(tmp1394Service);
189
190         if ( !tmp1394Service->initialize( port ) ) {
191             debugFatal( "Could not initialize Ieee1349Service object for port %d\n", port );
192             return false;
193         }
194         // add the bus reset handler
195         Functor* tmp_busreset_functor = new MemberFunctor0< DeviceManager*,
196                     void (DeviceManager::*)() >
197                     ( this, &DeviceManager::busresetHandler, false );
198         if ( !tmp_busreset_functor ) {
199             debugFatal( "Could not create busreset handler for port %d\n", port );
200             return false;
201         }
202         m_busreset_functors.push_back(tmp_busreset_functor);
203
204         tmp1394Service->addBusResetHandler( tmp_busreset_functor );
205         tmp1394Service->setVerboseLevel( getDebugLevel() );
206     }
207     return true;
208 }
209
210 bool
211 DeviceManager::addSpecString(char *s) {
212     std::string spec = s;
213     if(isSpecStringValid(spec)) {
214         debugOutput(DEBUG_LEVEL_VERBOSE, "Adding spec string %s\n", spec.c_str());
215         m_SpecStrings.push_back(spec);
216         return true;
217     } else {
218         debugError("Invalid spec string: %s\n", spec.c_str());
219         return false;
220     }
221 }
222
223 bool
224 DeviceManager::isSpecStringValid(std::string s) {
225     return true;
226 }
227
228 void
229 DeviceManager::busresetHandler()
230 {
231     debugOutput( DEBUG_LEVEL_VERBOSE, "Bus reset...\n" );
232     // FIXME: what port was the bus reset on?
233     // propagate the bus reset to all avDevices
234     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
235           it != m_avDevices.end();
236           ++it )
237     {
238         (*it)->handleBusReset();
239     }
240 }
241
242 bool
243 DeviceManager::discover( )
244 {
245     bool slaveMode=false;
246     if(!getOption("slaveMode", slaveMode)) {
247         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
248     }
249     bool snoopMode=false;
250     if(!getOption("snoopMode", snoopMode)) {
251         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
252     }
253
254     setVerboseLevel(getDebugLevel());
255
256     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
257           it != m_avDevices.end();
258           ++it )
259     {
260         if (!deleteElement(*it)) {
261             debugWarning("failed to remove AvDevice from Control::Container\n");
262         }
263         delete *it;
264     }
265     m_avDevices.clear();
266
267     if (!slaveMode) {
268         for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
269             it != m_1394Services.end();
270             ++it )
271         {
272             Ieee1394Service *portService = *it;
273             for ( fb_nodeid_t nodeId = 0;
274                 nodeId < portService->getNodeCount();
275                 ++nodeId )
276             {
277                 debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId );
278    
279                 if (nodeId == portService->getLocalNodeId()) {
280                     debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId );
281                     continue;
282                 }
283    
284                 std::auto_ptr<ConfigRom> configRom =
285                     std::auto_ptr<ConfigRom>( new ConfigRom( *portService, nodeId ) );
286                 if ( !configRom->initialize() ) {
287                     // \todo If a PHY on the bus is in power safe mode then
288                     // the config rom is missing. So this might be just
289                     // such this case and we can safely skip it. But it might
290                     // be there is a real software problem on our side.
291                     // This should be handlede more carefuly.
292                     debugOutput( DEBUG_LEVEL_NORMAL,
293                                 "Could not read config rom from device (node id %d). "
294                                 "Skip device discovering for this node\n",
295                                 nodeId );
296                     continue;
297                 }
298
299                 bool already_in_vector = false;
300                 for ( FFADODeviceVectorIterator it = m_avDevices.begin();
301                     it != m_avDevices.end();
302                     ++it )
303                 {
304                     if ((*it)->getConfigRom().getGuid() == configRom->getGuid()) {
305                         already_in_vector = true;
306                         break;
307                     }
308                 }
309                 if (already_in_vector) {
310                     debugWarning("Device with GUID %s already discovered on other port, skipping device...\n",
311                                  configRom->getGuidString().c_str());
312                     continue;
313                 }
314
315                 if( getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
316                     configRom->printConfigRom();
317                 }
318
319                 FFADODevice* avDevice = getDriverForDevice( configRom,
320                                                             nodeId );
321
322                 if ( avDevice ) {
323                     debugOutput( DEBUG_LEVEL_NORMAL,
324                                 "driver found for device %d\n",
325                                 nodeId );
326
327                     avDevice->setVerboseLevel( getDebugLevel() );
328                     bool isFromCache = false;
329                     if ( avDevice->loadFromCache() ) {
330                         debugOutput( DEBUG_LEVEL_VERBOSE, "could load from cache\n" );
331                         isFromCache = true;
332                         // restore the debug level for everything that was loaded
333                         avDevice->setVerboseLevel( getDebugLevel() );
334                     } else if ( avDevice->discover() ) {
335                         debugOutput( DEBUG_LEVEL_VERBOSE, "discovering successful\n" );
336                     } else {
337                         debugError( "could not discover device\n" );
338                         delete avDevice;
339                         continue;
340                     }
341
342                     if (snoopMode) {
343                         debugOutput( DEBUG_LEVEL_VERBOSE,
344                                     "Enabling snoop mode on node %d...\n", nodeId );
345
346                         if(!avDevice->setOption("snoopMode", snoopMode)) {
347                             debugWarning("Could not set snoop mode for device on node %d\n", nodeId);
348                             delete avDevice;
349                             continue;
350                         }
351                     }
352
353                     if ( !isFromCache && !avDevice->saveCache() ) {
354                         debugOutput( DEBUG_LEVEL_VERBOSE, "No cached version of AVC model created\n" );
355                     }
356
357                     m_avDevices.push_back( avDevice );
358
359                     if (!addElement(avDevice)) {
360                         debugWarning("failed to add AvDevice to Control::Container\n");
361                     }
362
363                     debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d on port %d done...\n", nodeId, portService->getPort() );
364                 }
365             }
366         }
367
368         debugOutput( DEBUG_LEVEL_NORMAL, "Discovery finished...\n" );
369         // FIXME: do better sorting
370         // sort the m_avDevices vector on their GUID
371         // then assign reassign the id's to the devices
372         // the side effect of this is that for the same set of attached devices,
373         // a device id always corresponds to the same device
374         sort(m_avDevices.begin(), m_avDevices.end(), FFADODevice::compareGUID);
375         int i=0;
376         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
377             it != m_avDevices.end();
378             ++it )
379         {
380             if ( !(*it)->setId( i++ ) ) {
381                 debugError( "setting Id failed\n" );
382             }
383         }
384         show();
385         return true;
386     } else { // slave mode
387         Ieee1394Service *portService = m_1394Services.at(0);
388         fb_nodeid_t nodeId = portService->getLocalNodeId();
389         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId );
390
391         std::auto_ptr<ConfigRom> configRom =
392             std::auto_ptr<ConfigRom>( new ConfigRom( *portService,
393                                                      nodeId ) );
394         if ( !configRom->initialize() ) {
395             // \todo If a PHY on the bus is in power safe mode then
396             // the config rom is missing. So this might be just
397             // such this case and we can safely skip it. But it might
398             // be there is a real software problem on our side.
399             // This should be handled more carefuly.
400             debugOutput( DEBUG_LEVEL_NORMAL,
401                          "Could not read config rom from device (node id %d). "
402                          "Skip device discovering for this node\n",
403                          nodeId );
404             return false;
405         }
406
407         FFADODevice* avDevice = getSlaveDriver( configRom );
408         if ( avDevice ) {
409             debugOutput( DEBUG_LEVEL_NORMAL,
410                          "driver found for device %d\n",
411                          nodeId );
412
413             avDevice->setVerboseLevel( getDebugLevel() );
414
415             if ( !avDevice->discover() ) {
416                 debugError( "could not discover device\n" );
417                 delete avDevice;
418                 return false;
419             }
420
421             if ( !avDevice->setId( m_avDevices.size() ) ) {
422                 debugError( "setting Id failed\n" );
423             }
424             if ( getDebugLevel() >= DEBUG_LEVEL_VERBOSE ) {
425                 avDevice->showDevice();
426             }
427             m_avDevices.push_back( avDevice );
428             debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d on port %d done...\n", nodeId, portService->getPort() );
429         }
430
431         debugOutput( DEBUG_LEVEL_NORMAL, "discovery finished...\n" );
432         return true;
433     }
434 }
435
436 FFADODevice*
437 DeviceManager::getDriverForDevice( std::auto_ptr<ConfigRom>( configRom ),
438                                    int id )
439 {
440 #ifdef ENABLE_BEBOB
441     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying BeBoB...\n" );
442     if ( BeBoB::AvDevice::probe( *configRom.get() ) ) {
443         return BeBoB::AvDevice::createDevice( configRom );
444     }
445 #endif
446
447 #ifdef ENABLE_GENERICAVC
448     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Generic AV/C...\n" );
449     if ( GenericAVC::AvDevice::probe( *configRom.get() ) ) {
450         return GenericAVC::AvDevice::createDevice( configRom );
451     }
452 #endif
453
454 #ifdef ENABLE_FIREWORKS
455     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying ECHO Audio FireWorks...\n" );
456     if ( FireWorks::Device::probe( *configRom.get() ) ) {
457         return FireWorks::Device::createDevice( configRom );
458     }
459 #endif
460
461 #ifdef ENABLE_BEBOB
462     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying M-Audio...\n" );
463     if ( MAudio::AvDevice::probe( *configRom.get() ) ) {
464         return MAudio::AvDevice::createDevice( configRom );
465     }
466 #endif
467
468 #ifdef ENABLE_MOTU
469     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Motu...\n" );
470     if ( Motu::MotuDevice::probe( *configRom.get() ) ) {
471         return Motu::MotuDevice::createDevice( configRom );
472     }
473 #endif
474
475 #ifdef ENABLE_DICE
476     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Dice...\n" );
477     if ( Dice::DiceAvDevice::probe( *configRom.get() ) ) {
478         return Dice::DiceAvDevice::createDevice( configRom );
479     }
480 #endif
481
482 #ifdef ENABLE_METRIC_HALO
483     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Metric Halo...\n" );
484     if ( MetricHalo::MHAvDevice::probe( *configRom.get() ) ) {
485         return MetricHalo::MHAvDevice::createDevice( configRom );
486     }
487 #endif
488
489 #ifdef ENABLE_RME
490     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying RME...\n" );
491     if ( Rme::RmeDevice::probe( *configRom.get() ) ) {
492         return Rme::RmeDevice::createDevice( configRom );
493     }
494 #endif
495
496 #ifdef ENABLE_BOUNCE
497     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Bounce...\n" );
498     if ( Bounce::BounceDevice::probe( *configRom.get() ) ) {
499         return Bounce::BounceDevice::createDevice( configRom );
500     }
501 #endif
502
503     return 0;
504 }
505
506 FFADODevice*
507 DeviceManager::getSlaveDriver( std::auto_ptr<ConfigRom>( configRom ) )
508 {
509
510 #ifdef ENABLE_BOUNCE
511     if ( Bounce::BounceSlaveDevice::probe( *configRom.get() ) ) {
512         return Bounce::BounceSlaveDevice::createDevice( configRom );
513     }
514 #endif
515
516     return 0;
517 }
518
519 bool
520 DeviceManager::isValidNode(int node)
521 {
522     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
523           it != m_avDevices.end();
524           ++it )
525     {
526         FFADODevice* avDevice = *it;
527
528         if (avDevice->getConfigRom().getNodeId() == node) {
529             return true;
530     }
531     }
532     return false;
533 }
534
535 int
536 DeviceManager::getNbDevices()
537 {
538     return m_avDevices.size();
539 }
540
541 int
542 DeviceManager::getDeviceNodeId( int deviceNr )
543 {
544     if ( ! ( deviceNr < getNbDevices() ) ) {
545         debugError( "Device number out of range (%d)\n", deviceNr );
546         return -1;
547     }
548
549     FFADODevice* avDevice = m_avDevices.at( deviceNr );
550
551     if ( !avDevice ) {
552         debugError( "Could not get device at position (%d)\n",  deviceNr );
553     }
554
555     return avDevice->getConfigRom().getNodeId();
556 }
557
558 FFADODevice*
559 DeviceManager::getAvDevice( int nodeId )
560 {
561     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
562           it != m_avDevices.end();
563           ++it )
564     {
565         FFADODevice* avDevice = *it;
566         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
567             return avDevice;
568         }
569     }
570
571     return 0;
572 }
573
574 FFADODevice*
575 DeviceManager::getAvDeviceByIndex( int idx )
576 {
577     return m_avDevices.at(idx);
578 }
579
580 unsigned int
581 DeviceManager::getAvDeviceCount( )
582 {
583     return m_avDevices.size();
584 }
585
586 /**
587  * Return the streamprocessor that is to be used as
588  * the sync source.
589  *
590  * Algorithm still to be determined
591  *
592  * @return StreamProcessor that is sync source
593  */
594 Streaming::StreamProcessor *
595 DeviceManager::getSyncSource() {
596     FFADODevice* device = getAvDeviceByIndex(0);
597
598     bool slaveMode=false;
599     if(!getOption("slaveMode", slaveMode)) {
600         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
601     }
602
603     #warning TEST CODE FOR BOUNCE DEVICE !!
604     // this makes the bounce slave use the xmit SP as sync source
605     if (slaveMode) {
606         return device->getStreamProcessorByIndex(1);
607     } else {
608         return device->getStreamProcessorByIndex(0);
609     }
610 }
611
612 bool
613 DeviceManager::deinitialize()
614 {
615     return true;
616 }
Note: See TracBrowser for help on using the browser.