root/trunk/libffado/src/devicemanager.cpp

Revision 739, 18.7 kB (checked in by ppalmers, 16 years ago)

- Adapt the ffado external API (upgrade to v3)

NEEDS NEW JACK BACKEND

- simplify FFADODevice constructor even more
- implement first framework support for supporting multiple adapters.

currently all firewire adapters are scanned for supported devices unless specified otherwise
however attaching devices to separate adapters is not supported. using multiple adapters at
that are connected together might work.

  • 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/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: %d, Valid: %d, Active: %d, Description: %s\n",
165                 FFADODevice::ClockSourceTypeToString(c.type), c.id, c.valid, c.active, 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                     } else if ( avDevice->discover() ) {
333                         debugOutput( DEBUG_LEVEL_VERBOSE, "discovering successful\n" );
334                     } else {
335                         debugError( "could not discover device\n" );
336                         delete avDevice;
337                         continue;
338                     }
339    
340                     if (snoopMode) {
341                         debugOutput( DEBUG_LEVEL_VERBOSE,
342                                     "Enabling snoop mode on node %d...\n", nodeId );
343    
344                         if(!avDevice->setOption("snoopMode", snoopMode)) {
345                             debugWarning("Could not set snoop mode for device on node %d\n", nodeId);
346                             delete avDevice;
347                             continue;
348                         }
349                     }
350
351                     if ( !isFromCache && !avDevice->saveCache() ) {
352                         debugOutput( DEBUG_LEVEL_VERBOSE, "No cached version of AVC model created\n" );
353                     }
354
355                     m_avDevices.push_back( avDevice );
356
357                     if (!addElement(avDevice)) {
358                         debugWarning("failed to add AvDevice to Control::Container\n");
359                     }
360
361                     debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d on port %d done...\n", nodeId, portService->getPort() );
362                 }
363             }
364         }
365
366         debugOutput( DEBUG_LEVEL_NORMAL, "Discovery finished...\n" );
367         // FIXME: do better sorting
368         // sort the m_avDevices vector on their GUID
369         // then assign reassign the id's to the devices
370         // the side effect of this is that for the same set of attached devices,
371         // a device id always corresponds to the same device
372         sort(m_avDevices.begin(), m_avDevices.end(), FFADODevice::compareGUID);
373         int i=0;
374         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
375             it != m_avDevices.end();
376             ++it )
377         {
378             if ( !(*it)->setId( i++ ) ) {
379                 debugError( "setting Id failed\n" );
380             }
381         }
382         show();
383         return true;
384     } else { // slave mode
385         Ieee1394Service *portService = m_1394Services.at(0);
386         fb_nodeid_t nodeId = portService->getLocalNodeId();
387         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId );
388
389         std::auto_ptr<ConfigRom> configRom =
390             std::auto_ptr<ConfigRom>( new ConfigRom( *portService,
391                                                      nodeId ) );
392         if ( !configRom->initialize() ) {
393             // \todo If a PHY on the bus is in power safe mode then
394             // the config rom is missing. So this might be just
395             // such this case and we can safely skip it. But it might
396             // be there is a real software problem on our side.
397             // This should be handled more carefuly.
398             debugOutput( DEBUG_LEVEL_NORMAL,
399                          "Could not read config rom from device (node id %d). "
400                          "Skip device discovering for this node\n",
401                          nodeId );
402             return false;
403         }
404
405         FFADODevice* avDevice = getSlaveDriver( configRom );
406         if ( avDevice ) {
407             debugOutput( DEBUG_LEVEL_NORMAL,
408                          "driver found for device %d\n",
409                          nodeId );
410
411             avDevice->setVerboseLevel( getDebugLevel() );
412
413             if ( !avDevice->discover() ) {
414                 debugError( "could not discover device\n" );
415                 delete avDevice;
416                 return false;
417             }
418
419             if ( !avDevice->setId( m_avDevices.size() ) ) {
420                 debugError( "setting Id failed\n" );
421             }
422             if ( getDebugLevel() >= DEBUG_LEVEL_VERBOSE ) {
423                 avDevice->showDevice();
424             }
425             m_avDevices.push_back( avDevice );
426             debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d on port %d done...\n", nodeId, portService->getPort() );
427         }
428
429         debugOutput( DEBUG_LEVEL_NORMAL, "discovery finished...\n" );
430         return true;
431     }
432 }
433
434 FFADODevice*
435 DeviceManager::getDriverForDevice( std::auto_ptr<ConfigRom>( configRom ),
436                                    int id )
437 {
438 #ifdef ENABLE_BEBOB
439     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying BeBoB...\n" );
440     if ( BeBoB::AvDevice::probe( *configRom.get() ) ) {
441         return BeBoB::AvDevice::createDevice( configRom );
442     }
443 #endif
444
445 #ifdef ENABLE_GENERICAVC
446     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Generic AV/C...\n" );
447     if ( GenericAVC::AvDevice::probe( *configRom.get() ) ) {
448         return GenericAVC::AvDevice::createDevice( configRom );
449     }
450 #endif
451
452 #ifdef ENABLE_FIREWORKS
453     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying ECHO Audio FireWorks...\n" );
454     if ( FireWorks::Device::probe( *configRom.get() ) ) {
455         return FireWorks::Device::createDevice( configRom );
456     }
457 #endif
458
459 #ifdef ENABLE_BEBOB
460     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying M-Audio...\n" );
461     if ( MAudio::AvDevice::probe( *configRom.get() ) ) {
462         return MAudio::AvDevice::createDevice( configRom );
463     }
464 #endif
465
466 #ifdef ENABLE_MOTU
467     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Motu...\n" );
468     if ( Motu::MotuDevice::probe( *configRom.get() ) ) {
469         return Motu::MotuDevice::createDevice( configRom );
470     }
471 #endif
472
473 #ifdef ENABLE_DICE
474     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Dice...\n" );
475     if ( Dice::DiceAvDevice::probe( *configRom.get() ) ) {
476         return Dice::DiceAvDevice::createDevice( configRom );
477     }
478 #endif
479
480 #ifdef ENABLE_METRIC_HALO
481     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Metric Halo...\n" );
482     if ( MetricHalo::MHAvDevice::probe( *configRom.get() ) ) {
483         return MetricHalo::MHAvDevice::createDevice( configRom );
484     }
485 #endif
486
487 #ifdef ENABLE_RME
488     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying RME...\n" );
489     if ( Rme::RmeDevice::probe( *configRom.get() ) ) {
490         return Rme::RmeDevice::createDevice( configRom );
491     }
492 #endif
493
494 #ifdef ENABLE_BOUNCE
495     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Bounce...\n" );
496     if ( Bounce::BounceDevice::probe( *configRom.get() ) ) {
497         return Bounce::BounceDevice::createDevice( configRom );
498     }
499 #endif
500
501     return 0;
502 }
503
504 FFADODevice*
505 DeviceManager::getSlaveDriver( std::auto_ptr<ConfigRom>( configRom ) )
506 {
507
508 #ifdef ENABLE_BOUNCE
509     if ( Bounce::BounceSlaveDevice::probe( *configRom.get() ) ) {
510         return Bounce::BounceSlaveDevice::createDevice( configRom );
511     }
512 #endif
513
514     return 0;
515 }
516
517 bool
518 DeviceManager::isValidNode(int node)
519 {
520     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
521           it != m_avDevices.end();
522           ++it )
523     {
524         FFADODevice* avDevice = *it;
525
526         if (avDevice->getConfigRom().getNodeId() == node) {
527             return true;
528     }
529     }
530     return false;
531 }
532
533 int
534 DeviceManager::getNbDevices()
535 {
536     return m_avDevices.size();
537 }
538
539 int
540 DeviceManager::getDeviceNodeId( int deviceNr )
541 {
542     if ( ! ( deviceNr < getNbDevices() ) ) {
543         debugError( "Device number out of range (%d)\n", deviceNr );
544         return -1;
545     }
546
547     FFADODevice* avDevice = m_avDevices.at( deviceNr );
548
549     if ( !avDevice ) {
550         debugError( "Could not get device at position (%d)\n",  deviceNr );
551     }
552
553     return avDevice->getConfigRom().getNodeId();
554 }
555
556 FFADODevice*
557 DeviceManager::getAvDevice( int nodeId )
558 {
559     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
560           it != m_avDevices.end();
561           ++it )
562     {
563         FFADODevice* avDevice = *it;
564         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
565             return avDevice;
566         }
567     }
568
569     return 0;
570 }
571
572 FFADODevice*
573 DeviceManager::getAvDeviceByIndex( int idx )
574 {
575     return m_avDevices.at(idx);
576 }
577
578 unsigned int
579 DeviceManager::getAvDeviceCount( )
580 {
581     return m_avDevices.size();
582 }
583
584 /**
585  * Return the streamprocessor that is to be used as
586  * the sync source.
587  *
588  * Algorithm still to be determined
589  *
590  * @return StreamProcessor that is sync source
591  */
592 Streaming::StreamProcessor *
593 DeviceManager::getSyncSource() {
594     FFADODevice* device = getAvDeviceByIndex(0);
595
596     bool slaveMode=false;
597     if(!getOption("slaveMode", slaveMode)) {
598         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
599     }
600
601     #warning TEST CODE FOR BOUNCE DEVICE !!
602     // this makes the bounce slave use the xmit SP as sync source
603     if (slaveMode) {
604         return device->getStreamProcessorByIndex(1);
605     } else {
606         return device->getStreamProcessorByIndex(0);
607     }
608 }
609
610 bool
611 DeviceManager::deinitialize()
612 {
613     return true;
614 }
Note: See TracBrowser for help on using the browser.