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

Revision 728, 14.8 kB (checked in by wagi, 15 years ago)

getConfigurationIdSyncMode: consider also an address as SignalUnitAddress?. this should fix a error message for saffire users.

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