root/trunk/libffado/src/devicemanager.cpp

Revision 587, 14.5 kB (checked in by ppalmers, 17 years ago)

- moved all vendor id's to one include file
- introduced the framework for the ECHO FireWorks? platform

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