root/trunk/libffado/src/devicemanager.cpp

Revision 639, 15.1 kB (checked in by ppalmers, 15 years ago)

- Introduce a generic infrastructure for FFADODevices to present the clock sources they support and their state
- Implement this infrastructure for BeBoB devices
- Implement this infrastructure for ECHO Fireworks devices

  • 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 library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License version 2.1, as published by the Free Software Foundation;
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22  * MA 02110-1301 USA
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/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     , m_1394Service( 0 )
83 {
84     addOption(Util::OptionContainer::Option("slaveMode",false));
85     addOption(Util::OptionContainer::Option("snoopMode",false));
86 }
87
88 DeviceManager::~DeviceManager()
89 {
90     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
91           it != m_avDevices.end();
92           ++it )
93     {
94         delete *it;
95     }
96
97     delete m_1394Service;
98 }
99
100 void
101 DeviceManager::setVerboseLevel(int l)
102 {
103     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
104     setDebugLevel(l);
105
106     if (m_1394Service) m_1394Service->setVerboseLevel(l);
107     Control::Element::setVerboseLevel(l);
108
109     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
110           it != m_avDevices.end();
111           ++it )
112     {
113         (*it)->setVerboseLevel(l);
114     }
115 }
116
117 void
118 DeviceManager::show() {
119     debugOutput(DEBUG_LEVEL_NORMAL, "===== Device Manager =====\n");
120     Control::Element::show();
121    
122     if (m_1394Service) debugOutput(DEBUG_LEVEL_NORMAL, "1394 port: %d\n", m_1394Service->getPort());
123
124     int i=0;
125     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
126         it != m_avDevices.end();
127         ++it )
128     {
129         FFADODevice* avDevice = *it;
130         debugOutput(DEBUG_LEVEL_NORMAL, "--- Device %2d ---\n", i++);
131         avDevice->showDevice();
132
133         debugOutput(DEBUG_LEVEL_NORMAL, "Clock sync sources:\n");
134         FFADODevice::ClockSourceVector sources=avDevice->getSupportedClockSources();
135         for ( FFADODevice::ClockSourceVector::const_iterator it
136                 = sources.begin();
137             it != sources.end();
138             ++it )
139         {
140             FFADODevice::ClockSource c=*it;
141             debugOutput(DEBUG_LEVEL_NORMAL, " Type: %s, Id: %d, Valid: %d, Active: %d, Description: %s\n",
142                 FFADODevice::ClockSourceTypeToString(c.type), c.id, c.valid, c.active, c.description.c_str());
143         }
144
145     }
146 }
147
148 bool
149 DeviceManager::initialize( int port )
150 {
151     m_1394Service = new Ieee1394Service();
152     if ( !m_1394Service ) {
153         debugFatal( "Could not create Ieee1349Service object\n" );
154         return false;
155     }
156
157     if ( !m_1394Service->initialize( port ) ) {
158         debugFatal( "Could not initialize Ieee1349Service object\n" );
159         delete m_1394Service;
160         m_1394Service = 0;
161         return false;
162     }
163
164     setVerboseLevel(getDebugLevel());
165     return true;
166 }
167
168 bool
169 DeviceManager::discover( )
170 {
171     bool slaveMode=false;
172     if(!getOption("slaveMode", slaveMode)) {
173         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
174     }
175     bool snoopMode=false;
176     if(!getOption("snoopMode", snoopMode)) {
177         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
178     }
179
180     setVerboseLevel(getDebugLevel());
181
182     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
183           it != m_avDevices.end();
184           ++it )
185     {
186         if (!deleteElement(*it)) {
187             debugWarning("failed to remove AvDevice from Control::Container\n");
188         }
189         delete *it;
190     }
191     m_avDevices.clear();
192
193     if (!slaveMode) {
194         for ( fb_nodeid_t nodeId = 0;
195               nodeId < m_1394Service->getNodeCount();
196               ++nodeId )
197         {
198             debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId );
199
200             if (nodeId == m_1394Service->getLocalNodeId()) {
201                 debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId );
202                 continue;
203             }
204
205             std::auto_ptr<ConfigRom> configRom =
206                 std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
207                                                          nodeId ) );
208             if ( !configRom->initialize() ) {
209                 // \todo If a PHY on the bus is in power safe mode then
210                 // the config rom is missing. So this might be just
211                 // such this case and we can safely skip it. But it might
212                 // be there is a real software problem on our side.
213                 // This should be handlede more carefuly.
214                 debugOutput( DEBUG_LEVEL_NORMAL,
215                              "Could not read config rom from device (node id %d). "
216                              "Skip device discovering for this node\n",
217                              nodeId );
218                 continue;
219             }
220
221             FFADODevice* avDevice = getDriverForDevice( configRom,
222                                                         nodeId );
223
224             if ( avDevice ) {
225                 debugOutput( DEBUG_LEVEL_NORMAL,
226                              "driver found for device %d\n",
227                              nodeId );
228
229                 avDevice->setVerboseLevel( getDebugLevel() );
230                 bool isFromCache = false;
231                 if ( avDevice->loadFromCache() ) {
232                     debugOutput( DEBUG_LEVEL_VERBOSE, "could load from cache\n" );
233                     isFromCache = true;
234                 } else if ( avDevice->discover() ) {
235                     debugOutput( DEBUG_LEVEL_VERBOSE, "discovering successful\n" );
236                 } else {
237                     debugError( "could not discover device\n" );
238                     delete avDevice;
239                     continue;
240                 }
241
242                 if (snoopMode) {
243                     debugOutput( DEBUG_LEVEL_VERBOSE,
244                                  "Enabling snoop mode on node %d...\n", nodeId );
245
246                     if(!avDevice->setOption("snoopMode", snoopMode)) {
247                         debugWarning("Could not set snoop mode for device on node %d\n", nodeId);
248                         delete avDevice;
249                         continue;
250                     }
251                 }
252
253                 if ( !isFromCache && !avDevice->saveCache() ) {
254                     debugOutput( DEBUG_LEVEL_VERBOSE, "No cached version of AVC model created\n" );
255                 }
256
257                 m_avDevices.push_back( avDevice );
258
259                 if (!addElement(avDevice)) {
260                     debugWarning("failed to add AvDevice to Control::Container\n");
261                 }
262                
263                 debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d done...\n", nodeId );
264
265             }
266         }
267
268         debugOutput( DEBUG_LEVEL_NORMAL, "Discovery finished...\n" );
269
270         // sort the m_avDevices vector on their GUID
271         // then assign reassign the id's to the devices
272         // the side effect of this is that for the same set of attached devices,
273         // a device id always corresponds to the same device
274         sort(m_avDevices.begin(), m_avDevices.end(), FFADODevice::compareGUID);
275        
276         int i=0;
277         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
278             it != m_avDevices.end();
279             ++it )
280         {
281             if ( !(*it)->setId( i++ ) ) {
282                 debugError( "setting Id failed\n" );
283             }
284         }
285
286         show();
287         return true;
288
289     } else { // slave mode
290         fb_nodeid_t nodeId = m_1394Service->getLocalNodeId();
291         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId );
292
293         std::auto_ptr<ConfigRom> configRom =
294             std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
295                                                      nodeId ) );
296         if ( !configRom->initialize() ) {
297             // \todo If a PHY on the bus is in power safe mode then
298             // the config rom is missing. So this might be just
299             // such this case and we can safely skip it. But it might
300             // be there is a real software problem on our side.
301             // This should be handled more carefuly.
302             debugOutput( DEBUG_LEVEL_NORMAL,
303                          "Could not read config rom from device (node id %d). "
304                          "Skip device discovering for this node\n",
305                          nodeId );
306             return false;
307         }
308
309         FFADODevice* avDevice = getSlaveDriver( configRom );
310         if ( avDevice ) {
311             debugOutput( DEBUG_LEVEL_NORMAL,
312                          "driver found for device %d\n",
313                          nodeId );
314
315             avDevice->setVerboseLevel( getDebugLevel() );
316
317             if ( !avDevice->discover() ) {
318                 debugError( "could not discover device\n" );
319                 delete avDevice;
320                 return false;
321             }
322
323             if ( !avDevice->setId( m_avDevices.size() ) ) {
324                 debugError( "setting Id failed\n" );
325             }
326             if ( getDebugLevel() >= DEBUG_LEVEL_VERBOSE ) {
327                 avDevice->showDevice();
328             }
329
330             m_avDevices.push_back( avDevice );
331
332             debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d done...\n", nodeId );
333         }
334
335         debugOutput( DEBUG_LEVEL_NORMAL, "discovery finished...\n" );
336
337         return true;
338     }
339 }
340
341 FFADODevice*
342 DeviceManager::getDriverForDevice( std::auto_ptr<ConfigRom>( configRom ),
343                                    int id )
344 {
345 #ifdef ENABLE_BEBOB
346     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying BeBoB...\n" );
347     if ( BeBoB::AvDevice::probe( *configRom.get() ) ) {
348         return BeBoB::AvDevice::createDevice( *m_1394Service, configRom );
349     }
350 #endif
351
352 #ifdef ENABLE_GENERICAVC
353     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Generic AV/C...\n" );
354     if ( GenericAVC::AvDevice::probe( *configRom.get() ) ) {
355         return GenericAVC::AvDevice::createDevice( *m_1394Service, configRom );
356     }
357 #endif
358
359 #ifdef ENABLE_FIREWORKS
360     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying ECHO Audio FireWorks...\n" );
361     if ( FireWorks::Device::probe( *configRom.get() ) ) {
362         return FireWorks::Device::createDevice( *m_1394Service, configRom );
363     }
364 #endif
365
366 #ifdef ENABLE_BEBOB
367     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying M-Audio...\n" );
368     if ( MAudio::AvDevice::probe( *configRom.get() ) ) {
369         return MAudio::AvDevice::createDevice( *m_1394Service, configRom );
370     }
371 #endif
372
373 #ifdef ENABLE_MOTU
374     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Motu...\n" );
375     if ( Motu::MotuDevice::probe( *configRom.get() ) ) {
376         return Motu::MotuDevice::createDevice( *m_1394Service, configRom );
377     }
378 #endif
379
380 #ifdef ENABLE_DICE
381     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Dice...\n" );
382     if ( Dice::DiceAvDevice::probe( *configRom.get() ) ) {
383         return Dice::DiceAvDevice::createDevice( *m_1394Service, configRom );
384     }
385 #endif
386
387 #ifdef ENABLE_METRIC_HALO
388     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Metric Halo...\n" );
389     if ( MetricHalo::MHAvDevice::probe( *configRom.get() ) ) {
390         return MetricHalo::MHAvDevice::createDevice( *m_1394Service, configRom );
391     }
392 #endif
393
394 #ifdef ENABLE_RME
395     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying RME...\n" );
396     if ( Rme::RmeDevice::probe( *configRom.get() ) ) {
397         return Rme::RmeDevice::createDevice( *m_1394Service, configRom );
398     }
399 #endif
400
401 #ifdef ENABLE_BOUNCE
402     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Bounce...\n" );
403     if ( Bounce::BounceDevice::probe( *configRom.get() ) ) {
404         return Bounce::BounceDevice::createDevice( *m_1394Service, configRom );
405     }
406 #endif
407
408     return 0;
409 }
410
411 FFADODevice*
412 DeviceManager::getSlaveDriver( std::auto_ptr<ConfigRom>( configRom ) )
413 {
414
415 #ifdef ENABLE_BOUNCE
416     if ( Bounce::BounceSlaveDevice::probe( *configRom.get() ) ) {
417         return Bounce::BounceSlaveDevice::createDevice( *m_1394Service, configRom );
418     }
419 #endif
420
421     return 0;
422 }
423
424 bool
425 DeviceManager::isValidNode(int node)
426 {
427     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
428           it != m_avDevices.end();
429           ++it )
430     {
431         FFADODevice* avDevice = *it;
432
433         if (avDevice->getConfigRom().getNodeId() == node) {
434             return true;
435     }
436     }
437     return false;
438 }
439
440 int
441 DeviceManager::getNbDevices()
442 {
443     return m_avDevices.size();
444 }
445
446 int
447 DeviceManager::getDeviceNodeId( int deviceNr )
448 {
449     if ( ! ( deviceNr < getNbDevices() ) ) {
450         debugError( "Device number out of range (%d)\n", deviceNr );
451         return -1;
452     }
453
454     FFADODevice* avDevice = m_avDevices.at( deviceNr );
455
456     if ( !avDevice ) {
457         debugError( "Could not get device at position (%d)\n",  deviceNr );
458     }
459
460     return avDevice->getConfigRom().getNodeId();
461 }
462
463 FFADODevice*
464 DeviceManager::getAvDevice( int nodeId )
465 {
466     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
467           it != m_avDevices.end();
468           ++it )
469     {
470         FFADODevice* avDevice = *it;
471         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
472             return avDevice;
473         }
474     }
475
476     return 0;
477 }
478
479 FFADODevice*
480 DeviceManager::getAvDeviceByIndex( int idx )
481 {
482     return m_avDevices.at(idx);
483 }
484
485 unsigned int
486 DeviceManager::getAvDeviceCount( )
487 {
488     return m_avDevices.size();
489 }
490
491 /**
492  * Return the streamprocessor that is to be used as
493  * the sync source.
494  *
495  * Algorithm still to be determined
496  *
497  * @return StreamProcessor that is sync source
498  */
499 Streaming::StreamProcessor *
500 DeviceManager::getSyncSource() {
501     FFADODevice* device = getAvDeviceByIndex(0);
502
503     bool slaveMode=false;
504     if(!getOption("slaveMode", slaveMode)) {
505         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
506     }
507
508     #warning TEST CODE FOR BOUNCE DEVICE !!
509     // this makes the bounce slave use the xmit SP as sync source
510     if (slaveMode) {
511         return device->getStreamProcessorByIndex(1);
512     } else {
513         return device->getStreamProcessorByIndex(0);
514     }
515 }
516
517 bool
518 DeviceManager::deinitialize()
519 {
520     return true;
521 }
Note: See TracBrowser for help on using the browser.