root/trunk/libffado/src/bebob/bebob_avdevice.cpp

Revision 560, 16.9 kB (checked in by ppalmers, 15 years ago)

- Sort the FFADODevice vector on GUID before assigning device id's

This results in the same device id for identical device setups,
independent of the way they are connected or the node numbers they
have been assigned.

- Sanitized debug message reporting a bit
- Cosmetic changes

Line 
1 /*
2  * Copyright (C) 2005-2007 by Daniel Wagner
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23
24 #include "bebob/bebob_avdevice.h"
25 #include "bebob/bebob_avdevice_subunit.h"
26 #include "bebob/GenericMixer.h"
27 #include "bebob/vendorspecific/focusrite.h"
28 #include "bebob/vendorspecific/terratec.h"
29
30 #include "libieee1394/configrom.h"
31 #include "libieee1394/ieee1394service.h"
32
33 #include "genericavc/avc_vendormodel.h"
34
35 #include "libavc/general/avc_plug_info.h"
36 #include "libavc/general/avc_extended_plug_info.h"
37 #include "libavc/general/avc_subunit_info.h"
38 #include "libavc/streamformat/avc_extended_stream_format.h"
39 #include "libavc/util/avc_serialize.h"
40 #include "libavc/avc_definitions.h"
41
42 #include "debugmodule/debugmodule.h"
43
44 #include <iostream>
45 #include <sstream>
46 #include <unistd.h>
47 #include <sys/stat.h>
48
49 using namespace AVC;
50
51 namespace BeBoB {
52
53 static GenericAVC::VendorModelEntry supportedDeviceList[] =
54 {
55     {0x00000f, 0x00010065, "Mackie", "Onyx Firewire"},
56
57     {0x0003db, 0x00010048, "Apogee Electronics", "Rosetta 200"},
58
59     {0x0007f5, 0x00010048, "BridgeCo", "RD Audio1"},
60
61     {0x000a92, 0x00010000, "PreSonus", "FIREBOX"},
62     {0x000a92, 0x00010066, "PreSonus", "FirePOD"},
63
64     {0x000aac, 0x00000003, "TerraTec Electronic GmbH", "Phase 88 FW"},
65     {0x000aac, 0x00000004, "TerraTec Electronic GmbH", "Phase X24 FW (model version 4)"},
66     {0x000aac, 0x00000007, "TerraTec Electronic GmbH", "Phase X24 FW (model version 7)"},
67
68     {0x000f1b, 0x00010064, "ESI", "Quatafire 610"},
69
70     {0x00130e, 0x00000000, "Focusrite", "Saffire (LE)"},
71     {0x00130e, 0x00000003, "Focusrite", "Saffire Pro26IO"},
72     {0x00130e, 0x00000006, "Focusrite", "Saffire Pro10IO"},
73
74     {0x0040ab, 0x00010048, "EDIROL", "FA-101"},
75     {0x0040ab, 0x00010049, "EDIROL", "FA-66"},
76
77     {0x000d6c, 0x00010062, "M-Audio", "FW Solo"},
78     {0x000d6c, 0x00010081, "M-Audio", "NRV10"},
79 };
80
81 AvDevice::AvDevice( std::auto_ptr< ConfigRom >( configRom ),
82                     Ieee1394Service& ieee1394service,
83                     int nodeId )
84     : GenericAVC::AvDevice( configRom, ieee1394service, nodeId )
85     , m_Mixer ( NULL )
86 {
87     debugOutput( DEBUG_LEVEL_VERBOSE, "Created BeBoB::AvDevice (NodeID %d)\n",
88                  nodeId );
89 }
90
91 AvDevice::~AvDevice()
92 {
93     if(m_Mixer != NULL) {
94         if (!removeChildOscNode(m_Mixer)) {
95             debugWarning("failed to unregister mixer from OSC namespace\n");
96         }
97         delete m_Mixer;
98     }
99 }
100
101 void
102 AvDevice::showDevice()
103 {
104     debugOutput(DEBUG_LEVEL_NORMAL, "Device is a BeBoB device\n");
105     GenericAVC::AvDevice::showDevice();
106     flushDebugOutput();
107 }
108
109 AVC::Subunit*
110 AvDevice::createSubunit(AVC::Unit& unit,
111                         AVC::ESubunitType type,
112                         AVC::subunit_t id )
113 {
114     AVC::Subunit* s=NULL;
115     switch (type) {
116         case eST_Audio:
117             s=new BeBoB::SubunitAudio(unit, id );
118             break;
119         case eST_Music:
120             s=new BeBoB::SubunitMusic(unit, id );
121             break;
122         default:
123             s=NULL;
124             break;
125     }
126     if(s) s->setVerboseLevel(getDebugLevel());
127     return s;
128 }
129
130
131 AVC::Plug *
132 AvDevice::createPlug( AVC::Unit* unit,
133                       AVC::Subunit* subunit,
134                       AVC::function_block_type_t functionBlockType,
135                       AVC::function_block_type_t functionBlockId,
136                       AVC::Plug::EPlugAddressType plugAddressType,
137                       AVC::Plug::EPlugDirection plugDirection,
138                       AVC::plug_id_t plugId )
139 {
140
141     Plug *p= new BeBoB::Plug( unit,
142                               subunit,
143                               functionBlockType,
144                               functionBlockId,
145                               plugAddressType,
146                               plugDirection,
147                               plugId );
148     if (p) p->setVerboseLevel(getDebugLevel());
149     return p;
150 }
151
152 bool
153 AvDevice::probe( ConfigRom& configRom )
154 {
155     unsigned int vendorId = configRom.getNodeVendorId();
156     unsigned int modelId = configRom.getModelId();
157
158     //GenericAVC::VendorModel vendorModel( "/home/wagi/src/libffado/src/bebob/ffado_driver_bebob.txt" );
159
160     for ( unsigned int i = 0;
161           i < ( sizeof( supportedDeviceList )/sizeof( GenericAVC::VendorModelEntry ) );
162           ++i )
163     {
164         if ( ( supportedDeviceList[i].vendor_id == vendorId )
165              && ( supportedDeviceList[i].model_id == modelId ) )
166         {
167             return true;
168         }
169     }
170     return false;
171 }
172
173 bool
174 AvDevice::discover()
175 {
176     unsigned int vendorId = m_pConfigRom->getNodeVendorId();
177     unsigned int modelId = m_pConfigRom->getModelId();
178
179     for ( unsigned int i = 0;
180           i < ( sizeof( supportedDeviceList )/sizeof( GenericAVC::VendorModelEntry ) );
181           ++i )
182     {
183         if ( ( supportedDeviceList[i].vendor_id == vendorId )
184              && ( supportedDeviceList[i].model_id == modelId )
185            )
186         {
187             m_model = &(supportedDeviceList[i]);
188             break;
189         }
190     }
191
192     if (m_model != NULL) {
193         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
194                 m_model->vendor_name, m_model->model_name);
195     } else return false;
196
197     if ( !Unit::discover() ) {
198         debugError( "Could not discover unit\n" );
199         return false;
200     }
201
202     if((getAudioSubunit( 0 ) == NULL)) {
203         debugError( "Unit doesn't have an Audio subunit.\n");
204         return false;
205     }
206     if((getMusicSubunit( 0 ) == NULL)) {
207         debugError( "Unit doesn't have a Music subunit.\n");
208         return false;
209     }
210
211 // replaced by the previous Unit discovery
212 //     if ( !enumerateSubUnits() ) {
213 //         debugError( "Could not enumarate sub units\n" );
214 //         return false;
215 //     }
216
217     // create a GenericMixer and add it as an OSC child node
218     //  remove if already there
219     if(m_Mixer != NULL) {
220         if (!removeChildOscNode(m_Mixer)) {
221             debugWarning("failed to unregister mixer from OSC namespace\n");
222         }
223         delete m_Mixer;
224     }
225
226     //  create the mixer & register it
227     if(getAudioSubunit(0) == NULL) {
228         debugWarning("Could not find audio subunit, mixer not available.\n");
229         m_Mixer = NULL;
230     } else {
231         m_Mixer = new GenericMixer(*m_p1394Service , *this);
232         if (!addChildOscNode(m_Mixer)) {
233             debugWarning("failed to register mixer in OSC namespace\n");
234         }
235     }
236     return true;
237 }
238
239 bool
240 AvDevice::propagatePlugInfo() {
241     // we don't have to propagate since we discover things
242     // another way
243     debugOutput(DEBUG_LEVEL_VERBOSE, "Skip plug info propagation\n");
244     return true;
245 }
246
247
248 int
249 AvDevice::getConfigurationIdSampleRate()
250 {
251     ExtendedStreamFormatCmd extStreamFormatCmd( *m_p1394Service );
252     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
253                                      m_nodeId );
254     extStreamFormatCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
255                                                     PlugAddress::ePAM_Unit,
256                                                     unitPlugAddress ) );
257
258     extStreamFormatCmd.setNodeId( m_nodeId );
259     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
260     extStreamFormatCmd.setVerbose( true );
261
262     if ( !extStreamFormatCmd.fire() ) {
263         debugError( "Stream format command failed\n" );
264         return false;
265     }
266
267     FormatInformation* formatInfo =
268         extStreamFormatCmd.getFormatInformation();
269     FormatInformationStreamsCompound* compoundStream
270         = dynamic_cast< FormatInformationStreamsCompound* > (
271             formatInfo->m_streams );
272     if ( compoundStream ) {
273         debugOutput(DEBUG_LEVEL_VERBOSE, "Sample rate 0x%02x\n",
274                     compoundStream->m_samplingFrequency );
275         return compoundStream->m_samplingFrequency;
276     }
277
278     debugError( "Could not retrieve sample rate\n" );
279     return 0;
280 }
281
282 int
283 AvDevice::getConfigurationIdNumberOfChannel( PlugAddress::EPlugDirection ePlugDirection )
284 {
285     ExtendedPlugInfoCmd extPlugInfoCmd( *m_p1394Service );
286     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
287                                      m_nodeId );
288     extPlugInfoCmd.setPlugAddress( PlugAddress( ePlugDirection,
289                                                 PlugAddress::ePAM_Unit,
290                                                 unitPlugAddress ) );
291     extPlugInfoCmd.setNodeId( m_nodeId );
292     extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
293     extPlugInfoCmd.setVerbose( true );
294     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
295         ExtendedPlugInfoInfoType::eIT_NoOfChannels );
296     extendedPlugInfoInfoType.initialize();
297     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
298
299     if ( !extPlugInfoCmd.fire() ) {
300         debugError( "Number of channels command failed\n" );
301         return false;
302     }
303
304     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
305     if ( infoType
306          && infoType->m_plugNrOfChns )
307     {
308         debugOutput(DEBUG_LEVEL_VERBOSE, "Number of channels 0x%02x\n",
309                     infoType->m_plugNrOfChns->m_nrOfChannels );
310         return infoType->m_plugNrOfChns->m_nrOfChannels;
311     }
312
313     debugError( "Could not retrieve number of channels\n" );
314     return 0;
315 }
316
317 int
318 AvDevice::getConfigurationIdSyncMode()
319 {
320     SignalSourceCmd signalSourceCmd( *m_p1394Service );
321     SignalUnitAddress signalUnitAddr;
322     signalUnitAddr.m_plugId = 0x01;
323     signalSourceCmd.setSignalDestination( signalUnitAddr );
324     signalSourceCmd.setNodeId( m_nodeId );
325     signalSourceCmd.setSubunitType( eST_Unit  );
326     signalSourceCmd.setSubunitId( 0xff );
327
328     signalSourceCmd.setCommandType( AVCCommand::eCT_Status );
329
330     if ( !signalSourceCmd.fire() ) {
331         debugError( "Number of channels command failed\n" );
332         return false;
333     }
334
335     SignalAddress* pSyncPlugSignalAddress = signalSourceCmd.getSignalSource();
336     SignalSubunitAddress* pSyncPlugSubunitAddress
337         = dynamic_cast<SignalSubunitAddress*>( pSyncPlugSignalAddress );
338     if ( pSyncPlugSubunitAddress ) {
339         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
340                     ( pSyncPlugSubunitAddress->m_subunitType << 3
341                       | pSyncPlugSubunitAddress->m_subunitId ) << 8
342                     | pSyncPlugSubunitAddress->m_plugId );
343
344         return ( pSyncPlugSubunitAddress->m_subunitType << 3
345                  | pSyncPlugSubunitAddress->m_subunitId ) << 8
346             | pSyncPlugSubunitAddress->m_plugId;
347     }
348
349     debugError( "Could not retrieve sync mode\n" );
350     return 0;
351 }
352
353 int
354 AvDevice::getConfigurationId()
355 {
356     // create a unique configuration id.
357     int id = 0;
358     id = getConfigurationIdSampleRate();
359     id |= ( getConfigurationIdNumberOfChannel( PlugAddress::ePD_Input )
360             + getConfigurationIdNumberOfChannel( PlugAddress::ePD_Output ) ) << 8;
361     id |= getConfigurationIdSyncMode() << 16;
362
363     return id;
364 }
365
366
367 template <typename T> bool serializeVector( Glib::ustring path,
368                                             Util::IOSerialize& ser,
369                                             const T& vec )
370 {
371     bool result = true; // if vec.size() == 0
372     int i = 0;
373     for ( typename T::const_iterator it = vec.begin(); it != vec.end(); ++it ) {
374         std::ostringstream strstrm;
375         strstrm << path << i;
376         result &= ( *it )->serialize( strstrm.str() + "/", ser );
377         i++;
378     }
379     return result;
380 }
381
382 template <typename T, typename VT> bool deserializeVector( Glib::ustring path,
383                                                            Util::IODeserialize& deser,
384                                                            Unit& avDevice,
385                                                            VT& vec )
386 {
387     int i = 0;
388     bool bFinished = false;
389     do {
390         std::ostringstream strstrm;
391         strstrm << path << i << "/";
392         T* ptr = T::deserialize( strstrm.str(),
393                                  deser,
394                                  avDevice );
395         if ( ptr ) {
396             vec.push_back( ptr );
397             i++;
398         } else {
399             bFinished = true;
400         }
401     } while ( !bFinished );
402
403     return true;
404 }
405
406 bool
407 AvDevice::serialize( Glib::ustring basePath,
408                      Util::IOSerialize& ser ) const
409 {
410
411     bool result;
412     result  = m_pConfigRom->serialize( basePath + "m_pConfigRom/", ser );
413     result &= ser.write( basePath + "m_verboseLevel", getDebugLevel() );
414     result &= m_pPlugManager->serialize( basePath + "Plug", ser ); // serialize all av plugs
415     result &= serializeVector( basePath + "PlugConnection", ser, m_plugConnections );
416     result &= serializeVector( basePath + "Subunit", ser, m_subunits );
417     #warning broken at echoaudio merge
418     //result &= serializeSyncInfoVector( basePath + "SyncInfo", ser, m_syncInfos );
419
420     int i = 0;
421     for ( SyncInfoVector::const_iterator it = m_syncInfos.begin();
422           it != m_syncInfos.end();
423           ++it )
424     {
425         const SyncInfo& info = *it;
426         if ( m_activeSyncInfo == &info ) {
427             result &= ser.write( basePath + "m_activeSyncInfo",  i );
428             break;
429         }
430         i++;
431     }
432
433     result &= serializeOptions( basePath + "Options", ser );
434
435 //     result &= ser.write( basePath + "m_id", id );
436
437     return result;
438 }
439
440 AvDevice*
441 AvDevice::deserialize( Glib::ustring basePath,
442                        Util::IODeserialize& deser,
443                        Ieee1394Service& ieee1394Service )
444 {
445
446 //     ConfigRom *configRom =
447 //         ConfigRom::deserialize( basePath + "m_pConfigRom/", deser, ieee1394Service );
448 //
449 //     if ( !configRom ) {
450 //         return NULL;
451 //     }
452 //
453 //     AvDevice* pDev = new AvDevice(
454 //         std::auto_ptr<ConfigRom>(configRom),
455 //         ieee1394Service, configRom->getNodeId());
456 //
457 //     if ( pDev ) {
458 //         bool result;
459 //         int verboseLevel;
460 //         result  = deser.read( basePath + "m_verboseLevel", verboseLevel );
461 //         setDebugLevel( verboseLevel );
462 //
463 //         result &= AVC::Unit::deserialize(basePath, pDev, deser, ieee1394Service);
464 //
465 //         result &= deserializeOptions( basePath + "Options", deser, *pDev );
466 //     }
467 //
468 //     return pDev;
469     return NULL;
470 }
471
472 Glib::ustring
473 AvDevice::getCachePath()
474 {
475     Glib::ustring cachePath;
476     char* pCachePath;
477     if ( asprintf( &pCachePath, "%s/cache/libffado/",  CACHEDIR ) < 0 ) {
478         debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
479         cachePath == "/var/cache/libffado/";
480     } else {
481         cachePath = pCachePath;
482         free( pCachePath );
483     }
484     return cachePath;
485 }
486
487 bool
488 AvDevice::loadFromCache()
489 {
490 /*    Glib::ustring sDevicePath = getCachePath() + m_pConfigRom->getGuidString();
491
492     char* configId;
493     asprintf(&configId, "%08x", getConfigurationId() );
494     if ( !configId ) {
495         debugError( "could not create id string\n" );
496         return false;
497     }
498
499     Glib::ustring sFileName = sDevicePath + "/" + configId + ".xml";
500     free( configId );
501     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
502
503     Util::XMLDeserialize deser( sFileName, m_verboseLevel );
504
505     bool result = deserialize( "", deser );
506     if ( result ) {
507         debugOutput( DEBUG_LEVEL_NORMAL, "could create valid bebob driver from %s\n",
508                      sFileName.c_str() );
509     }
510
511     return result;*/
512     return false;
513 }
514
515 bool
516 AvDevice::saveCache()
517 {
518 //     // the path looks like this:
519 //     // PATH_TO_CACHE + GUID + CONFIGURATION_ID
520 //
521 //     Glib::ustring sDevicePath = getCachePath() + m_pConfigRom->getGuidString();
522 //     struct stat buf;
523 //     if ( stat( sDevicePath.c_str(), &buf ) == 0 ) {
524 //         if ( !S_ISDIR( buf.st_mode ) ) {
525 //             debugError( "\"%s\" is not a directory\n",  sDevicePath.c_str() );
526 //             return false;
527 //         }
528 //     } else {
529 //         if (  mkdir( sDevicePath.c_str(), S_IRWXU | S_IRWXG ) != 0 ) {
530 //             debugError( "Could not create \"%s\" directory\n", sDevicePath.c_str() );
531 //             return false;
532 //         }
533 //     }
534 //
535 //     char* configId;
536 //     asprintf(&configId, "%08x", BeBoB::AvDevice::getConfigurationId() );
537 //     if ( !configId ) {
538 //         debugError( "Could not create id string\n" );
539 //         return false;
540 //     }
541 //     Glib::ustring sFileName = sDevicePath + "/" + configId + ".xml";
542 //     free( configId );
543 //     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
544 //
545 //     Util::XMLSerialize ser( sFileName );
546 //     return serialize( "", ser );
547     return false;
548 }
549
550 } // end of namespace
Note: See TracBrowser for help on using the browser.