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

Revision 599, 16.0 kB (checked in by wagi, 14 years ago)

Instead of static compiled in vendor/model table use configuration files.

Maybe needs some more cleanup but I wanted to check in this baby before
someone else screws me up with some majors changes in the repos :)

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