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

Revision 1183, 19.6 kB (checked in by wagi, 13 years ago)

Slow down AV/C model discovering for the FA101. Maybe this fixes
the problem reported in #15 #108 and #109

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 #include "bebob/edirol/edirol_fa101.h"
34 #include "bebob/esi/quatafire610.h"
35
36 #include "libieee1394/configrom.h"
37 #include "libieee1394/ieee1394service.h"
38
39 #include "genericavc/avc_vendormodel.h"
40
41 #include "libavc/general/avc_plug_info.h"
42 #include "libavc/general/avc_extended_plug_info.h"
43 #include "libavc/general/avc_subunit_info.h"
44 #include "libavc/streamformat/avc_extended_stream_format.h"
45 #include "libutil/cmd_serialize.h"
46 #include "libavc/avc_definitions.h"
47
48 #include "debugmodule/debugmodule.h"
49
50 #include <iostream>
51 #include <sstream>
52 #include <unistd.h>
53 #include <sys/stat.h>
54
55 using namespace AVC;
56
57 namespace BeBoB {
58
59 AvDevice::AvDevice( DeviceManager& d, std::auto_ptr< ConfigRom >( configRom ) )
60     : GenericAVC::AvDevice( d, configRom )
61     , m_Mixer ( 0 )
62 {
63     debugOutput( DEBUG_LEVEL_VERBOSE, "Created BeBoB::AvDevice (NodeID %d)\n",
64                  getConfigRom().getNodeId() );
65
66     // DM1500 based devices seem to upset the linux1394 stack when commands are
67     // sent too fast.
68     if (AVC::AVCCommand::getSleepAfterAVCCommand() < 200) {
69         AVC::AVCCommand::setSleepAfterAVCCommand( 200 );
70     }
71
72 }
73
74 AvDevice::~AvDevice()
75 {
76     destroyMixer();
77 }
78
79 bool
80 AvDevice::probe( ConfigRom& configRom )
81 {
82     unsigned int vendorId = configRom.getNodeVendorId();
83     unsigned int modelId = configRom.getModelId();
84
85     GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_bebob.txt" );
86     if ( vendorModel.parse() ) {
87         return vendorModel.isPresent( vendorId, modelId );
88     }
89
90     return false;
91 }
92
93 FFADODevice *
94 AvDevice::createDevice(DeviceManager& d, 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_EDIROL:
101             if (modelId == 0x00010048 ) {
102                 return new Edirol::EdirolFa101Device(d, configRom);
103             }
104         case FW_VENDORID_ESI:
105             if (modelId == 0x00010064) {
106                 return new ESI::QuataFireDevice(d, configRom);
107             }
108             break;
109         case FW_VENDORID_TERRATEC:
110             switch(modelId) {
111                 case 0x00000003:
112                     return new Terratec::Phase88Device(d, configRom);
113                 default: // return a plain BeBoB device
114                     return new AvDevice(d, configRom);
115             }
116         case FW_VENDORID_FOCUSRITE:
117             switch(modelId) {
118                 case 0x00000003:
119                 case 0x00000006:
120                     return new Focusrite::SaffireProDevice(d, configRom);
121                 case 0x00000000:
122                     return new Focusrite::SaffireDevice(d, configRom);
123                 default: // return a plain BeBoB device
124                     return new AvDevice(d, configRom);
125            }
126         default:
127             return new AvDevice(d, configRom);
128     }
129     return NULL;
130 }
131
132 bool
133 AvDevice::discover()
134 {
135     unsigned int vendorId = getConfigRom().getNodeVendorId();
136     unsigned int modelId = getConfigRom().getModelId();
137
138     GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_bebob.txt" );
139     if ( vendorModel.parse() ) {
140         m_model = vendorModel.find( vendorId, modelId );
141     }
142
143     if (GenericAVC::VendorModel::isValid(m_model)) {
144         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
145                      m_model.vendor_name.c_str(),
146                      m_model.model_name.c_str());
147     } else return false;
148
149     if ( !Unit::discover() ) {
150         debugError( "Could not discover unit\n" );
151         return false;
152     }
153
154     if((getAudioSubunit( 0 ) == NULL)) {
155         debugError( "Unit doesn't have an Audio subunit.\n");
156         return false;
157     }
158     if((getMusicSubunit( 0 ) == NULL)) {
159         debugError( "Unit doesn't have a Music subunit.\n");
160         return false;
161     }
162
163     if(!buildMixer()) {
164         debugWarning("Could not build mixer\n");
165     }
166     return true;
167 }
168
169 bool
170 AvDevice::buildMixer()
171 {
172     debugOutput(DEBUG_LEVEL_VERBOSE, "Building a generic BeBoB mixer...\n");
173     // create a Mixer
174     // this removes the mixer if it already exists
175     // note: a mixer self-registers to it's parent
176     delete m_Mixer;
177
178     // create the mixer & register it
179     if(getAudioSubunit(0) == NULL) {
180         debugWarning("Could not find audio subunit, mixer not available.\n");
181         m_Mixer = NULL;
182     } else {
183         m_Mixer = new Mixer(*this);
184     }
185     if (m_Mixer) m_Mixer->setVerboseLevel(getDebugLevel());
186     return m_Mixer != NULL;
187 }
188
189 bool
190 AvDevice::destroyMixer()
191 {
192     delete m_Mixer;
193     return true;
194 }
195
196 bool
197 AvDevice::setSelectorFBValue(int id, int value) {
198     FunctionBlockCmd fbCmd( get1394Service(),
199                             FunctionBlockCmd::eFBT_Selector,
200                             id,
201                             FunctionBlockCmd::eCA_Current );
202     fbCmd.setNodeId( getNodeId() );
203     fbCmd.setSubunitId( 0x00 );
204     fbCmd.setCommandType( AVCCommand::eCT_Control );
205     fbCmd.m_pFBSelector->m_inputFbPlugNumber = (value & 0xFF);
206     fbCmd.setVerboseLevel( getDebugLevel() );
207
208     if ( !fbCmd.fire() ) {
209         debugError( "cmd failed\n" );
210         return false;
211     }
212
213 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
214 //         Util::CoutSerializer se;
215 //         fbCmd.serialize( se );
216 //     }
217 //     
218     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
219         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
220     }
221
222     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
223 }
224
225 int
226 AvDevice::getSelectorFBValue(int id) {
227
228     FunctionBlockCmd fbCmd( get1394Service(),
229                             FunctionBlockCmd::eFBT_Selector,
230                             id,
231                             FunctionBlockCmd::eCA_Current );
232     fbCmd.setNodeId( getNodeId() );
233     fbCmd.setSubunitId( 0x00 );
234     fbCmd.setCommandType( AVCCommand::eCT_Status );
235     fbCmd.m_pFBSelector->m_inputFbPlugNumber = 0xFF;
236     fbCmd.setVerboseLevel( getDebugLevel() );
237
238     if ( !fbCmd.fire() ) {
239         debugError( "cmd failed\n" );
240         return -1;
241     }
242    
243 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
244 //         Util::CoutSerializer se;
245 //         fbCmd.serialize( se );
246 //     }
247
248     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
249         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
250     }
251    
252     return fbCmd.m_pFBSelector->m_inputFbPlugNumber;
253 }
254
255 bool
256 AvDevice::setFeatureFBVolumeValue(int id, int channel, int v) {
257
258     FunctionBlockCmd fbCmd( get1394Service(),
259                             FunctionBlockCmd::eFBT_Feature,
260                             id,
261                             FunctionBlockCmd::eCA_Current );
262     fbCmd.setNodeId( getNodeId() );
263     fbCmd.setSubunitId( 0x00 );
264     fbCmd.setCommandType( AVCCommand::eCT_Control );
265     fbCmd.m_pFBFeature->m_audioChannelNumber = channel;
266     fbCmd.m_pFBFeature->m_controlSelector = FunctionBlockFeature::eCSE_Feature_Volume;
267     fbCmd.m_pFBFeature->m_pVolume->m_volume = v;
268     fbCmd.setVerboseLevel( getDebugLevel() );
269
270     if ( !fbCmd.fire() ) {
271         debugError( "cmd failed\n" );
272         return false;
273     }
274
275 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
276 //         Util::CoutSerializer se;
277 //         fbCmd.serialize( se );
278 //     }
279    
280     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
281         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
282     }
283
284     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
285 }
286
287 int
288 AvDevice::getFeatureFBVolumeValue(int id, int channel) {
289     FunctionBlockCmd fbCmd( get1394Service(),
290                             FunctionBlockCmd::eFBT_Feature,
291                             id,
292                             FunctionBlockCmd::eCA_Current );
293     fbCmd.setNodeId( getNodeId() );
294     fbCmd.setSubunitId( 0x00 );
295     fbCmd.setCommandType( AVCCommand::eCT_Status );
296     fbCmd.m_pFBFeature->m_audioChannelNumber = channel;
297     fbCmd.m_pFBFeature->m_controlSelector = FunctionBlockFeature::eCSE_Feature_Volume;
298     fbCmd.m_pFBFeature->m_pVolume->m_volume = 0;
299     fbCmd.setVerboseLevel( getDebugLevel() );
300
301     if ( !fbCmd.fire() ) {
302         debugError( "cmd failed\n" );
303         return 0;
304     }
305    
306 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
307 //         Util::CoutSerializer se;
308 //         fbCmd.serialize( se );
309 //     }
310
311     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
312         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
313     }
314    
315     int16_t volume=(int16_t)(fbCmd.m_pFBFeature->m_pVolume->m_volume);
316    
317     return volume;
318 }
319
320 void
321 AvDevice::showDevice()
322 {
323     debugOutput(DEBUG_LEVEL_NORMAL, "Device is a BeBoB device\n");
324     GenericAVC::AvDevice::showDevice();
325     flushDebugOutput();
326 }
327
328 void
329 AvDevice::setVerboseLevel(int l)
330 {
331     if (m_Mixer) m_Mixer->setVerboseLevel( l );
332     GenericAVC::AvDevice::setVerboseLevel( l );
333     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
334 }
335
336 AVC::Subunit*
337 AvDevice::createSubunit(AVC::Unit& unit,
338                         AVC::ESubunitType type,
339                         AVC::subunit_t id )
340 {
341     AVC::Subunit* s=NULL;
342     switch (type) {
343         case eST_Audio:
344             s=new BeBoB::SubunitAudio(unit, id );
345             break;
346         case eST_Music:
347             s=new BeBoB::SubunitMusic(unit, id );
348             break;
349         default:
350             s=NULL;
351             break;
352     }
353     if(s) s->setVerboseLevel(getDebugLevel());
354     return s;
355 }
356
357
358 AVC::Plug *
359 AvDevice::createPlug( AVC::Unit* unit,
360                       AVC::Subunit* subunit,
361                       AVC::function_block_type_t functionBlockType,
362                       AVC::function_block_type_t functionBlockId,
363                       AVC::Plug::EPlugAddressType plugAddressType,
364                       AVC::Plug::EPlugDirection plugDirection,
365                       AVC::plug_id_t plugId )
366 {
367
368     Plug *p= new BeBoB::Plug( unit,
369                               subunit,
370                               functionBlockType,
371                               functionBlockId,
372                               plugAddressType,
373                               plugDirection,
374                               plugId );
375     if (p) p->setVerboseLevel(getDebugLevel());
376     return p;
377 }
378
379 bool
380 AvDevice::propagatePlugInfo() {
381     // we don't have to propagate since we discover things
382     // another way
383     debugOutput(DEBUG_LEVEL_VERBOSE, "Skip plug info propagation\n");
384     return true;
385 }
386
387
388 uint8_t
389 AvDevice::getConfigurationIdSampleRate()
390 {
391     ExtendedStreamFormatCmd extStreamFormatCmd( get1394Service() );
392     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, 0 );
393     extStreamFormatCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
394                                                     PlugAddress::ePAM_Unit,
395                                                     unitPlugAddress ) );
396
397     extStreamFormatCmd.setNodeId( getNodeId() );
398     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
399     extStreamFormatCmd.setVerbose( getDebugLevel() );
400
401     if ( !extStreamFormatCmd.fire() ) {
402         debugError( "Stream format command failed\n" );
403         return false;
404     }
405
406     FormatInformation* formatInfo =
407         extStreamFormatCmd.getFormatInformation();
408     FormatInformationStreamsCompound* compoundStream
409         = dynamic_cast< FormatInformationStreamsCompound* > (
410             formatInfo->m_streams );
411     if ( compoundStream ) {
412         debugOutput(DEBUG_LEVEL_VERBOSE, "Sample rate 0x%02x\n",
413                     compoundStream->m_samplingFrequency );
414         return compoundStream->m_samplingFrequency;
415     }
416
417     debugError( "Could not retrieve sample rate\n" );
418     return 0;
419 }
420
421 uint8_t
422 AvDevice::getConfigurationIdNumberOfChannel( PlugAddress::EPlugDirection ePlugDirection )
423 {
424     ExtendedPlugInfoCmd extPlugInfoCmd( get1394Service() );
425     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
426                                      getNodeId() );
427     extPlugInfoCmd.setPlugAddress( PlugAddress( ePlugDirection,
428                                                 PlugAddress::ePAM_Unit,
429                                                 unitPlugAddress ) );
430     extPlugInfoCmd.setNodeId( getNodeId() );
431     extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
432     extPlugInfoCmd.setVerbose( getDebugLevel() );
433     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
434         ExtendedPlugInfoInfoType::eIT_NoOfChannels );
435     extendedPlugInfoInfoType.initialize();
436     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
437
438     if ( !extPlugInfoCmd.fire() ) {
439         debugError( "Number of channels command failed\n" );
440         return false;
441     }
442
443     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
444     if ( infoType
445          && infoType->m_plugNrOfChns )
446     {
447         debugOutput(DEBUG_LEVEL_VERBOSE, "Number of channels 0x%02x\n",
448                     infoType->m_plugNrOfChns->m_nrOfChannels );
449         return infoType->m_plugNrOfChns->m_nrOfChannels;
450     }
451
452     debugError( "Could not retrieve number of channels\n" );
453     return 0;
454 }
455
456 uint8_t
457 AvDevice::getConfigurationIdSyncMode()
458 {
459     SignalSourceCmd signalSourceCmd( get1394Service() );
460     SignalUnitAddress signalUnitAddr;
461     signalUnitAddr.m_plugId = 0x01;
462     signalSourceCmd.setSignalDestination( signalUnitAddr );
463     signalSourceCmd.setNodeId( getNodeId() );
464     signalSourceCmd.setSubunitType( eST_Unit  );
465     signalSourceCmd.setSubunitId( 0xff );
466     signalSourceCmd.setVerbose( getDebugLevel() );
467
468     signalSourceCmd.setCommandType( AVCCommand::eCT_Status );
469
470     if ( !signalSourceCmd.fire() ) {
471         debugError( "Signal source command failed\n" );
472         return false;
473     }
474
475     SignalAddress* pSyncPlugSignalAddress = signalSourceCmd.getSignalSource();
476     SignalSubunitAddress* pSyncPlugSubunitAddress
477         = dynamic_cast<SignalSubunitAddress*>( pSyncPlugSignalAddress );
478     if ( pSyncPlugSubunitAddress ) {
479         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
480                     ( pSyncPlugSubunitAddress->m_subunitType << 3
481                       | pSyncPlugSubunitAddress->m_subunitId ) << 8
482                     | pSyncPlugSubunitAddress->m_plugId );
483
484         return ( pSyncPlugSubunitAddress->m_subunitType << 3
485                  | pSyncPlugSubunitAddress->m_subunitId ) << 8
486             | pSyncPlugSubunitAddress->m_plugId;
487     }
488
489     SignalUnitAddress* pSyncPlugUnitAddress
490       = dynamic_cast<SignalUnitAddress*>( pSyncPlugSignalAddress );
491     if ( pSyncPlugUnitAddress ) {
492         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
493                       0xff << 8 | pSyncPlugUnitAddress->m_plugId );
494
495         return ( 0xff << 8 | pSyncPlugUnitAddress->m_plugId );
496     }
497
498     debugError( "Could not retrieve sync mode\n" );
499     return 0;
500 }
501
502 uint64_t
503 AvDevice::getConfigurationId()
504 {
505     // create a unique configuration id.
506     uint64_t id = 0;
507     id = getConfigurationIdSampleRate();
508     id |= ( getConfigurationIdNumberOfChannel( PlugAddress::ePD_Input )
509             + getConfigurationIdNumberOfChannel( PlugAddress::ePD_Output ) ) << 8;
510     id |= getConfigurationIdSyncMode() << 16;
511
512     return id;
513 }
514
515 bool
516 AvDevice::serialize( std::string basePath,
517                      Util::IOSerialize& ser ) const
518 {
519     bool result;
520     result  = GenericAVC::AvDevice::serialize( basePath, ser );
521     return result;
522 }
523
524 bool
525 AvDevice::deserialize( std::string basePath,
526                        Util::IODeserialize& deser )
527 {
528     bool result;
529     result  = GenericAVC::AvDevice::deserialize( basePath, deser );
530     return result;
531 }
532
533 std::string
534 AvDevice::getCachePath()
535 {
536     std::string cachePath;
537     char* pCachePath;
538
539     string path = CACHEDIR;
540     if ( path.size() && path[0] == '~' ) {
541         path.erase( 0, 1 ); // remove ~
542         path.insert( 0, getenv( "HOME" ) ); // prepend the home path
543     }
544
545     if ( asprintf( &pCachePath, "%s/cache/",  path.c_str() ) < 0 ) {
546         debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
547         cachePath == "/var/cache/libffado/";
548     } else {
549         cachePath = pCachePath;
550         free( pCachePath );
551     }
552     return cachePath;
553 }
554
555 bool
556 AvDevice::loadFromCache()
557 {
558     std::string sDevicePath = getCachePath() + getConfigRom().getGuidString();
559
560     char* configId;
561     asprintf(&configId, "%016llx", getConfigurationId() );
562     if ( !configId ) {
563         debugError( "could not create id string\n" );
564         return false;
565     }
566
567     std::string sFileName = sDevicePath + "/" + configId + ".xml";
568     free( configId );
569     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
570
571     struct stat buf;
572     if ( stat( sFileName.c_str(), &buf ) != 0 ) {
573         debugOutput( DEBUG_LEVEL_NORMAL,  "\"%s\" does not exist\n",  sFileName.c_str() );
574         return false;
575     } else {
576         if ( !S_ISREG( buf.st_mode ) ) {
577             debugOutput( DEBUG_LEVEL_NORMAL,  "\"%s\" is not a regular file\n",  sFileName.c_str() );
578             return false;
579         }
580     }
581
582     Util::XMLDeserialize deser( sFileName, getDebugLevel() );
583
584     if (!deser.isValid()) {
585         debugOutput( DEBUG_LEVEL_NORMAL, "cache not valid: %s\n",
586                      sFileName.c_str() );
587         return false;
588     }
589
590     bool result = deserialize( "", deser );
591     if ( result ) {
592         debugOutput( DEBUG_LEVEL_NORMAL, "could create valid bebob driver from %s\n",
593                      sFileName.c_str() );
594     }
595
596     if(result) {
597         buildMixer();
598     }
599
600     return result;
601 }
602
603 bool
604 AvDevice::saveCache()
605 {
606     // the path looks like this:
607     // PATH_TO_CACHE + GUID + CONFIGURATION_ID
608     string tmp_path = getCachePath() + getConfigRom().getGuidString();
609
610     // the following piece should do something like
611     // 'mkdir -p some/path/with/some/dirs/which/do/not/exist'
612     vector<string> tokens;
613     tokenize( tmp_path, tokens, "/" );
614     string path;
615     for ( vector<string>::const_iterator it = tokens.begin();
616           it != tokens.end();
617           ++it )
618     {
619         path +=  "/" + *it;
620
621         struct stat buf;
622         if ( stat( path.c_str(), &buf ) == 0 ) {
623             if ( !S_ISDIR( buf.st_mode ) ) {
624                 debugError( "\"%s\" is not a directory\n",  path.c_str() );
625                 return false;
626             }
627         } else {
628             if (  mkdir( path.c_str(), S_IRWXU | S_IRWXG ) != 0 ) {
629                 debugError( "Could not create \"%s\" directory\n", path.c_str() );
630                 return false;
631             }
632         }
633     }
634
635     // come up with an unique file name for the current settings
636     char* configId;
637     asprintf(&configId, "%016llx", BeBoB::AvDevice::getConfigurationId() );
638     if ( !configId ) {
639         debugError( "Could not create id string\n" );
640         return false;
641     }
642     string filename = path + "/" + configId + ".xml";
643     free( configId );
644     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", filename.c_str() );
645
646     Util::XMLSerialize ser( filename );
647     return serialize( "", ser );
648 }
649
650 } // end of namespace
Note: See TracBrowser for help on using the browser.