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

Revision 758, 15.1 kB (checked in by ppalmers, 15 years ago)

fix bug

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