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

Revision 557, 16.5 kB (checked in by wagi, 15 years ago)

moved&renamed configparser from bebob to genericavc

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 AVC::Subunit*
102 AvDevice::createSubunit(AVC::Unit& unit,
103                                AVC::ESubunitType type,
104                                AVC::subunit_t id )
105 {
106     switch (type) {
107         case AVC::eST_Audio:
108             return new BeBoB::SubunitAudio(unit, id );
109         case AVC::eST_Music:
110             return new BeBoB::SubunitMusic(unit, id );
111         default:
112             return NULL;
113     }
114 }
115
116 AVC::Plug *
117 AvDevice::createPlug( AVC::Unit* unit,
118                      AVC::Subunit* subunit,
119                      AVC::function_block_type_t functionBlockType,
120                      AVC::function_block_type_t functionBlockId,
121                      AVC::Plug::EPlugAddressType plugAddressType,
122                      AVC::Plug::EPlugDirection plugDirection,
123                      AVC::plug_id_t plugId )
124 {
125
126     return new BeBoB::Plug( unit,
127                      subunit,
128                      functionBlockType,
129                      functionBlockId,
130                      plugAddressType,
131                      plugDirection,
132                      plugId );
133 }
134
135 bool
136 AvDevice::probe( ConfigRom& configRom )
137 {
138     unsigned int vendorId = configRom.getNodeVendorId();
139     unsigned int modelId = configRom.getModelId();
140
141     //GenericAVC::VendorModel vendorModel( "/home/wagi/src/libffado/src/bebob/ffado_driver_bebob.txt" );
142
143     for ( unsigned int i = 0;
144           i < ( sizeof( supportedDeviceList )/sizeof( GenericAVC::VendorModelEntry ) );
145           ++i )
146     {
147         if ( ( supportedDeviceList[i].vendor_id == vendorId )
148              && ( supportedDeviceList[i].model_id == modelId ) )
149         {
150             return true;
151         }
152     }
153     return false;
154 }
155
156 bool
157 AvDevice::discover()
158 {
159     unsigned int vendorId = m_pConfigRom->getNodeVendorId();
160     unsigned int modelId = m_pConfigRom->getModelId();
161
162     for ( unsigned int i = 0;
163           i < ( sizeof( supportedDeviceList )/sizeof( GenericAVC::VendorModelEntry ) );
164           ++i )
165     {
166         if ( ( supportedDeviceList[i].vendor_id == vendorId )
167              && ( supportedDeviceList[i].model_id == modelId )
168            )
169         {
170             m_model = &(supportedDeviceList[i]);
171             break;
172         }
173     }
174
175     if (m_model != NULL) {
176         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
177                 m_model->vendor_name, m_model->model_name);
178     } else return false;
179
180     if ( !Unit::discover() ) {
181         debugError( "Could not discover unit\n" );
182         return false;
183     }
184
185     if((getAudioSubunit( 0 ) == NULL)) {
186         debugError( "Unit doesn't have an Audio subunit.\n");
187         return false;
188     }
189     if((getMusicSubunit( 0 ) == NULL)) {
190         debugError( "Unit doesn't have a Music subunit.\n");
191         return false;
192     }
193
194 // replaced by the previous Unit discovery
195 //     if ( !enumerateSubUnits() ) {
196 //         debugError( "Could not enumarate sub units\n" );
197 //         return false;
198 //     }
199
200     // create a GenericMixer and add it as an OSC child node
201     //  remove if already there
202     if(m_Mixer != NULL) {
203         if (!removeChildOscNode(m_Mixer)) {
204             debugWarning("failed to unregister mixer from OSC namespace\n");
205         }
206         delete m_Mixer;
207     }
208
209     //  create the mixer & register it
210     if(getAudioSubunit(0) == NULL) {
211         debugWarning("Could not find audio subunit, mixer not available.\n");
212         m_Mixer = NULL;
213     } else {
214         m_Mixer = new GenericMixer(*m_p1394Service , *this);
215         if (!addChildOscNode(m_Mixer)) {
216             debugWarning("failed to register mixer in OSC namespace\n");
217         }
218     }
219     return true;
220 }
221
222 bool
223 AvDevice::propagatePlugInfo() {
224     // we don't have to propagate since we discover things
225     // another way
226     debugOutput(DEBUG_LEVEL_VERBOSE, "Skip plug info propagation\n");
227     return true;
228 }
229
230
231 int
232 AvDevice::getConfigurationIdSampleRate()
233 {
234     ExtendedStreamFormatCmd extStreamFormatCmd( *m_p1394Service );
235     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
236                                      m_nodeId );
237     extStreamFormatCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
238                                                     PlugAddress::ePAM_Unit,
239                                                     unitPlugAddress ) );
240
241     extStreamFormatCmd.setNodeId( m_nodeId );
242     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
243     extStreamFormatCmd.setVerbose( true );
244
245     if ( !extStreamFormatCmd.fire() ) {
246         debugError( "Stream format command failed\n" );
247         return false;
248     }
249
250     FormatInformation* formatInfo =
251         extStreamFormatCmd.getFormatInformation();
252     FormatInformationStreamsCompound* compoundStream
253         = dynamic_cast< FormatInformationStreamsCompound* > (
254             formatInfo->m_streams );
255     if ( compoundStream ) {
256         debugOutput(DEBUG_LEVEL_VERBOSE, "Sample rate 0x%02x\n",
257                     compoundStream->m_samplingFrequency );
258         return compoundStream->m_samplingFrequency;
259     }
260
261     debugError( "Could not retrieve sample rate\n" );
262     return 0;
263 }
264
265 int
266 AvDevice::getConfigurationIdNumberOfChannel( PlugAddress::EPlugDirection ePlugDirection )
267 {
268     ExtendedPlugInfoCmd extPlugInfoCmd( *m_p1394Service );
269     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
270                                      m_nodeId );
271     extPlugInfoCmd.setPlugAddress( PlugAddress( ePlugDirection,
272                                                 PlugAddress::ePAM_Unit,
273                                                 unitPlugAddress ) );
274     extPlugInfoCmd.setNodeId( m_nodeId );
275     extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
276     extPlugInfoCmd.setVerbose( true );
277     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
278         ExtendedPlugInfoInfoType::eIT_NoOfChannels );
279     extendedPlugInfoInfoType.initialize();
280     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
281
282     if ( !extPlugInfoCmd.fire() ) {
283         debugError( "Number of channels command failed\n" );
284         return false;
285     }
286
287     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
288     if ( infoType
289          && infoType->m_plugNrOfChns )
290     {
291         debugOutput(DEBUG_LEVEL_VERBOSE, "Number of channels 0x%02x\n",
292                     infoType->m_plugNrOfChns->m_nrOfChannels );
293         return infoType->m_plugNrOfChns->m_nrOfChannels;
294     }
295
296     debugError( "Could not retrieve number of channels\n" );
297     return 0;
298 }
299
300 int
301 AvDevice::getConfigurationIdSyncMode()
302 {
303     SignalSourceCmd signalSourceCmd( *m_p1394Service );
304     SignalUnitAddress signalUnitAddr;
305     signalUnitAddr.m_plugId = 0x01;
306     signalSourceCmd.setSignalDestination( signalUnitAddr );
307     signalSourceCmd.setNodeId( m_nodeId );
308     signalSourceCmd.setSubunitType( eST_Unit  );
309     signalSourceCmd.setSubunitId( 0xff );
310
311     signalSourceCmd.setCommandType( AVCCommand::eCT_Status );
312
313     if ( !signalSourceCmd.fire() ) {
314         debugError( "Number of channels command failed\n" );
315         return false;
316     }
317
318     SignalAddress* pSyncPlugSignalAddress = signalSourceCmd.getSignalSource();
319     SignalSubunitAddress* pSyncPlugSubunitAddress
320         = dynamic_cast<SignalSubunitAddress*>( pSyncPlugSignalAddress );
321     if ( pSyncPlugSubunitAddress ) {
322         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
323                     ( pSyncPlugSubunitAddress->m_subunitType << 3
324                       | pSyncPlugSubunitAddress->m_subunitId ) << 8
325                     | pSyncPlugSubunitAddress->m_plugId );
326
327         return ( pSyncPlugSubunitAddress->m_subunitType << 3
328                  | pSyncPlugSubunitAddress->m_subunitId ) << 8
329             | pSyncPlugSubunitAddress->m_plugId;
330     }
331
332     debugError( "Could not retrieve sync mode\n" );
333     return 0;
334 }
335
336 int
337 AvDevice::getConfigurationId()
338 {
339     // create a unique configuration id.
340     int id = 0;
341     id = getConfigurationIdSampleRate();
342     id |= ( getConfigurationIdNumberOfChannel( PlugAddress::ePD_Input )
343             + getConfigurationIdNumberOfChannel( PlugAddress::ePD_Output ) ) << 8;
344     id |= getConfigurationIdSyncMode() << 16;
345
346     return id;
347 }
348
349
350 template <typename T> bool serializeVector( Glib::ustring path,
351                                             Util::IOSerialize& ser,
352                                             const T& vec )
353 {
354     bool result = true; // if vec.size() == 0
355     int i = 0;
356     for ( typename T::const_iterator it = vec.begin(); it != vec.end(); ++it ) {
357         std::ostringstream strstrm;
358         strstrm << path << i;
359         result &= ( *it )->serialize( strstrm.str() + "/", ser );
360         i++;
361     }
362     return result;
363 }
364
365 template <typename T, typename VT> bool deserializeVector( Glib::ustring path,
366                                                            Util::IODeserialize& deser,
367                                                            Unit& avDevice,
368                                                            VT& vec )
369 {
370     int i = 0;
371     bool bFinished = false;
372     do {
373         std::ostringstream strstrm;
374         strstrm << path << i << "/";
375         T* ptr = T::deserialize( strstrm.str(),
376                                  deser,
377                                  avDevice );
378         if ( ptr ) {
379             vec.push_back( ptr );
380             i++;
381         } else {
382             bFinished = true;
383         }
384     } while ( !bFinished );
385
386     return true;
387 }
388
389 bool
390 AvDevice::serialize( Glib::ustring basePath,
391                      Util::IOSerialize& ser ) const
392 {
393
394     bool result;
395     result  = m_pConfigRom->serialize( basePath + "m_pConfigRom/", ser );
396     result &= ser.write( basePath + "m_verboseLevel", getDebugLevel() );
397     result &= m_pPlugManager->serialize( basePath + "Plug", ser ); // serialize all av plugs
398     result &= serializeVector( basePath + "PlugConnection", ser, m_plugConnections );
399     result &= serializeVector( basePath + "Subunit", ser, m_subunits );
400     #warning broken at echoaudio merge
401     //result &= serializeSyncInfoVector( basePath + "SyncInfo", ser, m_syncInfos );
402
403     int i = 0;
404     for ( SyncInfoVector::const_iterator it = m_syncInfos.begin();
405           it != m_syncInfos.end();
406           ++it )
407     {
408         const SyncInfo& info = *it;
409         if ( m_activeSyncInfo == &info ) {
410             result &= ser.write( basePath + "m_activeSyncInfo",  i );
411             break;
412         }
413         i++;
414     }
415
416     result &= serializeOptions( basePath + "Options", ser );
417
418 //     result &= ser.write( basePath + "m_id", id );
419
420     return result;
421 }
422
423 AvDevice*
424 AvDevice::deserialize( Glib::ustring basePath,
425                        Util::IODeserialize& deser,
426                        Ieee1394Service& ieee1394Service )
427 {
428
429 //     ConfigRom *configRom =
430 //         ConfigRom::deserialize( basePath + "m_pConfigRom/", deser, ieee1394Service );
431 //
432 //     if ( !configRom ) {
433 //         return NULL;
434 //     }
435 //
436 //     AvDevice* pDev = new AvDevice(
437 //         std::auto_ptr<ConfigRom>(configRom),
438 //         ieee1394Service, configRom->getNodeId());
439 //
440 //     if ( pDev ) {
441 //         bool result;
442 //         int verboseLevel;
443 //         result  = deser.read( basePath + "m_verboseLevel", verboseLevel );
444 //         setDebugLevel( verboseLevel );
445 //
446 //         result &= AVC::Unit::deserialize(basePath, pDev, deser, ieee1394Service);
447 //
448 //         result &= deserializeOptions( basePath + "Options", deser, *pDev );
449 //     }
450 //
451 //     return pDev;
452     return NULL;
453 }
454
455 Glib::ustring
456 AvDevice::getCachePath()
457 {
458     Glib::ustring cachePath;
459     char* pCachePath;
460     if ( asprintf( &pCachePath, "%s/cache/libffado/",  CACHEDIR ) < 0 ) {
461         debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
462         cachePath == "/var/cache/libffado/";
463     } else {
464         cachePath = pCachePath;
465         free( pCachePath );
466     }
467     return cachePath;
468 }
469
470 bool
471 AvDevice::loadFromCache()
472 {
473 /*    Glib::ustring sDevicePath = getCachePath() + m_pConfigRom->getGuidString();
474
475     char* configId;
476     asprintf(&configId, "%08x", getConfigurationId() );
477     if ( !configId ) {
478         debugError( "could not create id string\n" );
479         return false;
480     }
481
482     Glib::ustring sFileName = sDevicePath + "/" + configId + ".xml";
483     free( configId );
484     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
485
486     Util::XMLDeserialize deser( sFileName, m_verboseLevel );
487
488     bool result = deserialize( "", deser );
489     if ( result ) {
490         debugOutput( DEBUG_LEVEL_NORMAL, "could create valid bebob driver from %s\n",
491                      sFileName.c_str() );
492     }
493
494     return result;*/
495     return false;
496 }
497
498 bool
499 AvDevice::saveCache()
500 {
501 //     // the path looks like this:
502 //     // PATH_TO_CACHE + GUID + CONFIGURATION_ID
503 //
504 //     Glib::ustring sDevicePath = getCachePath() + m_pConfigRom->getGuidString();
505 //     struct stat buf;
506 //     if ( stat( sDevicePath.c_str(), &buf ) == 0 ) {
507 //         if ( !S_ISDIR( buf.st_mode ) ) {
508 //             debugError( "\"%s\" is not a directory\n",  sDevicePath.c_str() );
509 //             return false;
510 //         }
511 //     } else {
512 //         if (  mkdir( sDevicePath.c_str(), S_IRWXU | S_IRWXG ) != 0 ) {
513 //             debugError( "Could not create \"%s\" directory\n", sDevicePath.c_str() );
514 //             return false;
515 //         }
516 //     }
517 //
518 //     char* configId;
519 //     asprintf(&configId, "%08x", BeBoB::AvDevice::getConfigurationId() );
520 //     if ( !configId ) {
521 //         debugError( "Could not create id string\n" );
522 //         return false;
523 //     }
524 //     Glib::ustring sFileName = sDevicePath + "/" + configId + ".xml";
525 //     free( configId );
526 //     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
527 //
528 //     Util::XMLSerialize ser( sFileName );
529 //     return serialize( "", ser );
530     return false;
531 }
532
533 } // end of namespace
Note: See TracBrowser for help on using the browser.