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

Revision 1156, 19.4 kB (checked in by ppalmers, 16 years ago)

- implement clocksource control for the phase88
- restructure the function block mess a bit.

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