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

Revision 864, 15.1 kB (checked in by ppalmers, 16 years ago)

update license to GPLv2 or GPLv3 instead of GPLv2 or any later version. Update copyrights to reflect the new year

Line 
1 /*
2  * Copyright (C) 2005-2008 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 2 of the License, or
12  * (at your option) version 3 of the License.
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.