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

Revision 1763, 25.5 kB (checked in by ppalmers, 14 years ago)

Merged revisions 1536,1541,1544-1546,1549,1554-1562,1571,1579-1581,1618,1632,1634-1635,1661,1677-1679,1703-1704,1715,1720-1723,1743-1745,1755 via svnmerge from
svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0

Also fix remaining format string warnings.

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 "devicemanager.h"
27 #include "bebob/bebob_avdevice.h"
28 #include "bebob/bebob_avdevice_subunit.h"
29 #include "bebob/bebob_mixer.h"
30
31 #include "bebob/focusrite/focusrite_saffire.h"
32 #include "bebob/focusrite/focusrite_saffirepro.h"
33 #include "bebob/terratec/terratec_device.h"
34 #include "bebob/mackie/onyxmixer.h"
35 #include "bebob/edirol/edirol_fa101.h"
36 #include "bebob/edirol/edirol_fa66.h"
37 #include "bebob/esi/quatafire610.h"
38
39 #include "libieee1394/configrom.h"
40 #include "libieee1394/ieee1394service.h"
41
42 #include "libavc/general/avc_plug_info.h"
43 #include "libavc/general/avc_extended_plug_info.h"
44 #include "libavc/general/avc_subunit_info.h"
45 #include "libavc/streamformat/avc_extended_stream_format.h"
46 #include "libutil/cmd_serialize.h"
47 #include "libavc/avc_definitions.h"
48
49 #include "debugmodule/debugmodule.h"
50
51 #include <iostream>
52 #include <sstream>
53 #include <unistd.h>
54 #include <cstdlib>
55 #include <cstring>
56 #include <sys/stat.h>
57
58 using namespace AVC;
59
60 namespace BeBoB {
61
62 Device::Device( DeviceManager& d, std::auto_ptr< ConfigRom >( configRom ) )
63     : GenericAVC::Device( d, configRom )
64     , m_last_discovery_config_id ( 0xFFFFFFFFFFFFFFFFLLU )
65     , m_Mixer ( 0 )
66 {
67     debugOutput( DEBUG_LEVEL_VERBOSE, "Created BeBoB::Device (NodeID %d)\n",
68                  getConfigRom().getNodeId() );
69 }
70
71 Device::~Device()
72 {
73     destroyMixer();
74 }
75
76 bool
77 Device::probe( Util::Configuration& c, ConfigRom& configRom, bool generic )
78 {
79     if(generic) {
80         // try a bebob-specific command to check for the firmware
81         ExtendedPlugInfoCmd extPlugInfoCmd( configRom.get1394Service() );
82         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
83                                          configRom.getNodeId() );
84         extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
85                                                     PlugAddress::ePAM_Unit,
86                                                     unitPlugAddress ) );
87         extPlugInfoCmd.setNodeId( configRom.getNodeId() );
88         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
89         extPlugInfoCmd.setVerbose( configRom.getVerboseLevel() );
90         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
91             ExtendedPlugInfoInfoType::eIT_NoOfChannels );
92         extendedPlugInfoInfoType.initialize();
93         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
94
95         if ( !extPlugInfoCmd.fire() ) {
96             debugError( "Number of channels command failed\n" );
97             return false;
98         }
99
100         if((extPlugInfoCmd.getResponse() != AVCCommand::eR_Implemented)) {
101             // command not supported
102             return false;
103         }
104
105         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
106         if ( infoType
107             && infoType->m_plugNrOfChns )
108         {
109             return true;
110         }
111         return false;
112     } else {
113         // check if device is in supported devices list
114         unsigned int vendorId = configRom.getNodeVendorId();
115         unsigned int modelId = configRom.getModelId();
116
117         Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
118         return c.isValid(vme) && vme.driver == Util::Configuration::eD_BeBoB;
119     }
120 }
121
122 FFADODevice *
123 Device::createDevice(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
124 {
125     unsigned int vendorId = configRom->getNodeVendorId();
126     unsigned int modelId = configRom->getModelId();
127
128     switch (vendorId) {
129         case FW_VENDORID_MACKIE:
130             if (modelId == 0x00010065 ) {
131                 return new Mackie::OnyxMixerDevice(d, configRom);
132             }
133         case FW_VENDORID_EDIROL:
134             switch (modelId) {
135                 case 0x00010048:
136                     return new Edirol::EdirolFa101Device(d, configRom);
137                 case 0x00010049:
138                     return new Edirol::EdirolFa66Device(d, configRom);
139                 default:
140                     return new Device(d, configRom);
141             }
142         case FW_VENDORID_ESI:
143             if (modelId == 0x00010064) {
144                 return new ESI::QuataFireDevice(d, configRom);
145             }
146             break;
147         case FW_VENDORID_TERRATEC:
148             switch(modelId) {
149                 case 0x00000003:
150                     return new Terratec::Phase88Device(d, configRom);
151                 default: // return a plain BeBoB device
152                     return new Device(d, configRom);
153             }
154         case FW_VENDORID_FOCUSRITE:
155             switch(modelId) {
156                 case 0x00000003:
157                 case 0x00000006:
158                     return new Focusrite::SaffireProDevice(d, configRom);
159                 case 0x00000000:
160                     return new Focusrite::SaffireDevice(d, configRom);
161                 default: // return a plain BeBoB device
162                     return new Device(d, configRom);
163            }
164         default:
165             return new Device(d, configRom);
166     }
167     return NULL;
168 }
169
170 #define BEBOB_CHECK_AND_ADD_SR(v, x) \
171     { if(supportsSamplingFrequency(x)) \
172       v.push_back(x); }
173 bool
174 Device::discover()
175 {
176     unsigned int vendorId = getConfigRom().getNodeVendorId();
177     unsigned int modelId = getConfigRom().getModelId();
178
179     Util::Configuration &c = getDeviceManager().getConfiguration();
180     Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
181
182     if (c.isValid(vme) && vme.driver == Util::Configuration::eD_BeBoB) {
183         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
184                      vme.vendor_name.c_str(),
185                      vme.model_name.c_str());
186     } else {
187         debugWarning("Using generic BeBoB support for unsupported device '%s %s'\n",
188                      getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
189     }
190
191     if ( !Unit::discover() ) {
192         debugError( "Could not discover unit\n" );
193         return false;
194     }
195
196     if((getAudioSubunit( 0 ) == NULL)) {
197         debugError( "Unit doesn't have an Audio subunit.\n");
198         return false;
199     }
200     if((getMusicSubunit( 0 ) == NULL)) {
201         debugError( "Unit doesn't have a Music subunit.\n");
202         return false;
203     }
204
205     if(!buildMixer()) {
206         debugWarning("Could not build mixer\n");
207     }
208
209     // keep track of the config id of this discovery
210     m_last_discovery_config_id = getConfigurationId();
211
212     return true;
213 }
214
215 bool
216 Device::buildMixer()
217 {
218     debugOutput(DEBUG_LEVEL_VERBOSE, "Building a generic BeBoB mixer...\n");
219     // create a Mixer
220     // this removes the mixer if it already exists
221     // note: a mixer self-registers to it's parent
222     delete m_Mixer;
223
224     // create the mixer & register it
225     if(getAudioSubunit(0) == NULL) {
226         debugWarning("Could not find audio subunit, mixer not available.\n");
227         m_Mixer = NULL;
228     } else {
229         m_Mixer = new Mixer(*this);
230     }
231     if (m_Mixer) m_Mixer->setVerboseLevel(getDebugLevel());
232     return m_Mixer != NULL;
233 }
234
235 bool
236 Device::destroyMixer()
237 {
238     delete m_Mixer;
239     return true;
240 }
241
242 bool
243 Device::setSelectorFBValue(int id, int value) {
244     FunctionBlockCmd fbCmd( get1394Service(),
245                             FunctionBlockCmd::eFBT_Selector,
246                             id,
247                             FunctionBlockCmd::eCA_Current );
248     fbCmd.setNodeId( getNodeId() );
249     fbCmd.setSubunitId( 0x00 );
250     fbCmd.setCommandType( AVCCommand::eCT_Control );
251     fbCmd.m_pFBSelector->m_inputFbPlugNumber = (value & 0xFF);
252     fbCmd.setVerboseLevel( getDebugLevel() );
253
254     if ( !fbCmd.fire() ) {
255         debugError( "cmd failed\n" );
256         return false;
257     }
258
259 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
260 //         Util::Cmd::CoutSerializer se;
261 //         fbCmd.serialize( se );
262 //     }
263 //     
264     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
265         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
266     }
267
268     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
269 }
270
271 int
272 Device::getSelectorFBValue(int id) {
273
274     FunctionBlockCmd fbCmd( get1394Service(),
275                             FunctionBlockCmd::eFBT_Selector,
276                             id,
277                             FunctionBlockCmd::eCA_Current );
278     fbCmd.setNodeId( getNodeId() );
279     fbCmd.setSubunitId( 0x00 );
280     fbCmd.setCommandType( AVCCommand::eCT_Status );
281     fbCmd.m_pFBSelector->m_inputFbPlugNumber = 0xFF;
282     fbCmd.setVerboseLevel( getDebugLevel() );
283
284     if ( !fbCmd.fire() ) {
285         debugError( "cmd failed\n" );
286         return -1;
287     }
288    
289 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
290 //         Util::Cmd::CoutSerializer se;
291 //         fbCmd.serialize( se );
292 //     }
293
294     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
295         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
296     }
297    
298     return fbCmd.m_pFBSelector->m_inputFbPlugNumber;
299 }
300
301 bool
302 Device::setFeatureFBVolumeCurrent(int id, int channel, int v) {
303
304     FunctionBlockCmd fbCmd( get1394Service(),
305                             FunctionBlockCmd::eFBT_Feature,
306                             id,
307                             FunctionBlockCmd::eCA_Current );
308     fbCmd.setNodeId( getNodeId() );
309     fbCmd.setSubunitId( 0x00 );
310     fbCmd.setCommandType( AVCCommand::eCT_Control );
311     fbCmd.m_pFBFeature->m_audioChannelNumber = channel;
312     fbCmd.m_pFBFeature->m_controlSelector = FunctionBlockFeature::eCSE_Feature_Volume;
313     AVC::FunctionBlockFeatureVolume vl;
314     fbCmd.m_pFBFeature->m_pVolume = vl.clone();
315     fbCmd.m_pFBFeature->m_pVolume->m_volume = v;
316     fbCmd.setVerboseLevel( getDebugLevel() );
317
318     if ( !fbCmd.fire() ) {
319         debugError( "cmd failed\n" );
320         return false;
321     }
322
323 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
324 //         Util::Cmd::CoutSerializer se;
325 //         fbCmd.serialize( se );
326 //     }
327    
328     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
329         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
330     }
331
332     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
333 }
334
335 int
336 Device::getFeatureFBVolumeValue(int id, int channel, FunctionBlockCmd::EControlAttribute controlAttribute)
337 {
338     FunctionBlockCmd fbCmd( get1394Service(),
339                             FunctionBlockCmd::eFBT_Feature,
340                             id,
341                             controlAttribute);
342     fbCmd.setNodeId( getNodeId() );
343     fbCmd.setSubunitId( 0x00 );
344     fbCmd.setCommandType( AVCCommand::eCT_Status );
345     fbCmd.m_pFBFeature->m_audioChannelNumber = channel;
346     fbCmd.m_pFBFeature->m_controlSelector = FunctionBlockFeature::eCSE_Feature_Volume;
347     AVC::FunctionBlockFeatureVolume vl;
348     fbCmd.m_pFBFeature->m_pVolume = vl.clone();
349     fbCmd.m_pFBFeature->m_pVolume->m_volume = 0;
350     fbCmd.setVerboseLevel( getDebugLevel() );
351
352     if ( !fbCmd.fire() ) {
353         debugError( "cmd failed\n" );
354         return 0;
355     }
356    
357 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
358 //         Util::Cmd::CoutSerializer se;
359 //         fbCmd.serialize( se );
360 //     }
361
362     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
363         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
364     }
365    
366     int16_t volume=(int16_t)(fbCmd.m_pFBFeature->m_pVolume->m_volume);
367    
368     return volume;
369 }
370
371 int
372 Device::getFeatureFBVolumeMinimum(int id, int channel)
373 {
374     return getFeatureFBVolumeValue(id, channel, AVC::FunctionBlockCmd::eCA_Minimum);
375 }
376
377 int
378 Device::getFeatureFBVolumeMaximum(int id, int channel)
379 {
380     return getFeatureFBVolumeValue(id, channel, AVC::FunctionBlockCmd::eCA_Maximum);
381 }
382
383 int
384 Device::getFeatureFBVolumeCurrent(int id, int channel)
385 {
386     return getFeatureFBVolumeValue(id, channel, AVC::FunctionBlockCmd::eCA_Current);   
387 }
388
389 bool
390 Device::setFeatureFBLRBalanceCurrent(int id, int channel, int v) {
391
392     FunctionBlockCmd fbCmd( get1394Service(),
393                             FunctionBlockCmd::eFBT_Feature,
394                             id,
395                             FunctionBlockCmd::eCA_Current );
396     fbCmd.setNodeId( getNodeId() );
397     fbCmd.setSubunitId( 0x00 );
398     fbCmd.setCommandType( AVCCommand::eCT_Control );
399     fbCmd.m_pFBFeature->m_audioChannelNumber = channel;
400     fbCmd.m_pFBFeature->m_controlSelector = FunctionBlockFeature::eCSE_Feature_LRBalance;
401     AVC::FunctionBlockFeatureLRBalance bl;
402     fbCmd.m_pFBFeature->m_pLRBalance = bl.clone();
403     fbCmd.m_pFBFeature->m_pLRBalance->m_lrBalance = v;
404     fbCmd.setVerboseLevel( getDebugLevel() );
405
406     if ( !fbCmd.fire() ) {
407         debugError( "cmd failed\n" );
408         return false;
409     }
410
411 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
412 //         Util::Cmd::CoutSerializer se;
413 //         fbCmd.serialize( se );
414 //     }
415    
416     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
417         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
418     }
419
420     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
421 }
422
423 int
424 Device::getFeatureFBLRBalanceValue(int id, int channel, FunctionBlockCmd::EControlAttribute controlAttribute)
425 {
426     FunctionBlockCmd fbCmd( get1394Service(),
427                             FunctionBlockCmd::eFBT_Feature,
428                             id,
429                             controlAttribute);
430     fbCmd.setNodeId( getNodeId() );
431     fbCmd.setSubunitId( 0x00 );
432     fbCmd.setCommandType( AVCCommand::eCT_Status );
433     fbCmd.m_pFBFeature->m_audioChannelNumber = channel;
434     fbCmd.m_pFBFeature->m_controlSelector = FunctionBlockFeature::eCSE_Feature_LRBalance;
435     AVC::FunctionBlockFeatureLRBalance bl;
436     fbCmd.m_pFBFeature->m_pLRBalance = bl.clone();
437     fbCmd.m_pFBFeature->m_pLRBalance->m_lrBalance = 0;
438     fbCmd.setVerboseLevel( getDebugLevel() );
439
440     if ( !fbCmd.fire() ) {
441         debugError( "cmd failed\n" );
442         return 0;
443     }
444    
445 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
446 //         Util::Cmd::CoutSerializer se;
447 //         fbCmd.serialize( se );
448 //     }
449
450     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
451         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
452     }
453    
454     int16_t balance=(int16_t)(fbCmd.m_pFBFeature->m_pLRBalance->m_lrBalance);
455
456     return balance;
457 }
458
459 int
460 Device::getFeatureFBLRBalanceMinimum(int id, int channel)
461 {
462     return getFeatureFBLRBalanceValue(id, channel, AVC::FunctionBlockCmd::eCA_Minimum);
463 }
464
465 int
466 Device::getFeatureFBLRBalanceMaximum(int id, int channel)
467 {
468     return getFeatureFBLRBalanceValue(id, channel, AVC::FunctionBlockCmd::eCA_Maximum);
469 }
470
471 int
472 Device::getFeatureFBLRBalanceCurrent(int id, int channel)
473 {
474     return getFeatureFBLRBalanceValue(id, channel, AVC::FunctionBlockCmd::eCA_Current);   
475 }
476
477 void
478 Device::showDevice()
479 {
480     debugOutput(DEBUG_LEVEL_NORMAL, "Device is a BeBoB device\n");
481     GenericAVC::Device::showDevice();
482     flushDebugOutput();
483 }
484
485 void
486 Device::setVerboseLevel(int l)
487 {
488     if (m_Mixer) m_Mixer->setVerboseLevel( l );
489     GenericAVC::Device::setVerboseLevel( l );
490     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
491 }
492
493 AVC::Subunit*
494 Device::createSubunit(AVC::Unit& unit,
495                         AVC::ESubunitType type,
496                         AVC::subunit_t id )
497 {
498     AVC::Subunit* s=NULL;
499     switch (type) {
500         case eST_Audio:
501             s=new BeBoB::SubunitAudio(unit, id );
502             break;
503         case eST_Music:
504             s=new BeBoB::SubunitMusic(unit, id );
505             break;
506         default:
507             s=NULL;
508             break;
509     }
510     if(s) s->setVerboseLevel(getDebugLevel());
511     return s;
512 }
513
514
515 AVC::Plug *
516 Device::createPlug( AVC::Unit* unit,
517                       AVC::Subunit* subunit,
518                       AVC::function_block_type_t functionBlockType,
519                       AVC::function_block_type_t functionBlockId,
520                       AVC::Plug::EPlugAddressType plugAddressType,
521                       AVC::Plug::EPlugDirection plugDirection,
522                       AVC::plug_id_t plugId,
523                       int globalId )
524 {
525
526     Plug *p= new BeBoB::Plug( unit,
527                               subunit,
528                               functionBlockType,
529                               functionBlockId,
530                               plugAddressType,
531                               plugDirection,
532                               plugId,
533                               globalId );
534     if (p) p->setVerboseLevel(getDebugLevel());
535     return p;
536 }
537
538 bool
539 Device::propagatePlugInfo() {
540     // we don't have to propagate since we discover things
541     // another way
542     debugOutput(DEBUG_LEVEL_VERBOSE, "Skip plug info propagation\n");
543     return true;
544 }
545
546 uint8_t
547 Device::getConfigurationIdSampleRate()
548 {
549     ExtendedStreamFormatCmd extStreamFormatCmd( get1394Service() );
550     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, 0 );
551     extStreamFormatCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
552                                                     PlugAddress::ePAM_Unit,
553                                                     unitPlugAddress ) );
554
555     extStreamFormatCmd.setNodeId( getNodeId() );
556     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
557     extStreamFormatCmd.setVerbose( getDebugLevel() );
558
559     if ( !extStreamFormatCmd.fire() ) {
560         debugError( "Stream format command failed\n" );
561         return 0;
562     }
563
564     FormatInformation* formatInfo =
565         extStreamFormatCmd.getFormatInformation();
566     FormatInformationStreamsCompound* compoundStream
567         = dynamic_cast< FormatInformationStreamsCompound* > (
568             formatInfo->m_streams );
569     if ( compoundStream ) {
570         debugOutput(DEBUG_LEVEL_VERBOSE, "Sample rate 0x%02x\n",
571                     compoundStream->m_samplingFrequency );
572         return compoundStream->m_samplingFrequency;
573     }
574
575     debugError( "Could not retrieve sample rate\n" );
576     return 0;
577 }
578
579 uint8_t
580 Device::getConfigurationIdNumberOfChannel( PlugAddress::EPlugDirection ePlugDirection )
581 {
582     ExtendedPlugInfoCmd extPlugInfoCmd( get1394Service() );
583     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
584                                      0 );
585     extPlugInfoCmd.setPlugAddress( PlugAddress( ePlugDirection,
586                                                 PlugAddress::ePAM_Unit,
587                                                 unitPlugAddress ) );
588     extPlugInfoCmd.setNodeId( getNodeId() );
589     extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
590     extPlugInfoCmd.setVerbose( getDebugLevel() );
591     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
592         ExtendedPlugInfoInfoType::eIT_NoOfChannels );
593     extendedPlugInfoInfoType.initialize();
594     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
595
596     if ( !extPlugInfoCmd.fire() ) {
597         debugError( "Number of channels command failed\n" );
598         return 0;
599     }
600
601     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
602     if ( infoType
603          && infoType->m_plugNrOfChns )
604     {
605         debugOutput(DEBUG_LEVEL_VERBOSE, "Number of channels 0x%02x\n",
606                     infoType->m_plugNrOfChns->m_nrOfChannels );
607         return infoType->m_plugNrOfChns->m_nrOfChannels;
608     }
609
610     debugError( "Could not retrieve number of channels\n" );
611     return 0;
612 }
613
614 uint16_t
615 Device::getConfigurationIdSyncMode()
616 {
617     SignalSourceCmd signalSourceCmd( get1394Service() );
618     SignalUnitAddress signalUnitAddr;
619     signalUnitAddr.m_plugId = 0x01;
620     signalSourceCmd.setSignalDestination( signalUnitAddr );
621     signalSourceCmd.setNodeId( getNodeId() );
622     signalSourceCmd.setSubunitType( eST_Unit  );
623     signalSourceCmd.setSubunitId( 0xff );
624     signalSourceCmd.setVerbose( getDebugLevel() );
625
626     signalSourceCmd.setCommandType( AVCCommand::eCT_Status );
627
628     if ( !signalSourceCmd.fire() ) {
629         debugError( "Signal source command failed\n" );
630         return 0;
631     }
632
633     SignalAddress* pSyncPlugSignalAddress = signalSourceCmd.getSignalSource();
634     SignalSubunitAddress* pSyncPlugSubunitAddress
635         = dynamic_cast<SignalSubunitAddress*>( pSyncPlugSignalAddress );
636     if ( pSyncPlugSubunitAddress ) {
637         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
638                     ( pSyncPlugSubunitAddress->m_subunitType << 3
639                       | pSyncPlugSubunitAddress->m_subunitId ) << 8
640                     | pSyncPlugSubunitAddress->m_plugId );
641
642         return ( pSyncPlugSubunitAddress->m_subunitType << 3
643                  | pSyncPlugSubunitAddress->m_subunitId ) << 8
644             | pSyncPlugSubunitAddress->m_plugId;
645     }
646
647     SignalUnitAddress* pSyncPlugUnitAddress
648       = dynamic_cast<SignalUnitAddress*>( pSyncPlugSignalAddress );
649     if ( pSyncPlugUnitAddress ) {
650         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
651                       0xff << 8 | pSyncPlugUnitAddress->m_plugId );
652
653         return ( 0xff << 8 | pSyncPlugUnitAddress->m_plugId );
654     }
655
656     debugError( "Could not retrieve sync mode\n" );
657     return 0;
658 }
659
660 bool
661 Device::needsRediscovery()
662 {
663     // require rediscovery if the config id differs from the one saved
664     // in the previous discovery
665     return getConfigurationId() != m_last_discovery_config_id;
666 }
667
668 uint64_t
669 Device::getConfigurationId()
670 {
671     // create a unique configuration id.
672     uint64_t id = 0;
673     id = getConfigurationIdSampleRate();
674     id |= getConfigurationIdNumberOfChannel( PlugAddress::ePD_Input ) << 8;
675     id |= getConfigurationIdNumberOfChannel( PlugAddress::ePD_Output ) << 16;
676     id |= ((uint64_t)getConfigurationIdSyncMode()) << 24;
677     return id;
678 }
679
680 bool
681 Device::serialize( std::string basePath,
682                      Util::IOSerialize& ser ) const
683 {
684     bool result;
685     result  = GenericAVC::Device::serialize( basePath, ser );
686     return result;
687 }
688
689 bool
690 Device::deserialize( std::string basePath,
691                        Util::IODeserialize& deser )
692 {
693     bool result;
694     result  = GenericAVC::Device::deserialize( basePath, deser );
695     return result;
696 }
697
698 std::string
699 Device::getCachePath()
700 {
701     std::string cachePath;
702     char* pCachePath;
703
704     string path = CACHEDIR;
705     if ( path.size() && path[0] == '~' ) {
706         path.erase( 0, 1 ); // remove ~
707         path.insert( 0, getenv( "HOME" ) ); // prepend the home path
708     }
709
710     if ( asprintf( &pCachePath, "%s/cache/",  path.c_str() ) < 0 ) {
711         debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
712         cachePath == "/var/cache/libffado/";
713     } else {
714         cachePath = pCachePath;
715         free( pCachePath );
716     }
717     return cachePath;
718 }
719
720 bool
721 Device::loadFromCache()
722 {
723     std::string sDevicePath = getCachePath() + getConfigRom().getGuidString();
724
725     char* configId;
726     asprintf(&configId, "%016"PRIx64"", getConfigurationId() );
727     if ( !configId ) {
728         debugError( "could not create id string\n" );
729         return false;
730     }
731
732     std::string sFileName = sDevicePath + "/" + configId + ".xml";
733     free( configId );
734     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
735
736     struct stat buf;
737     if ( stat( sFileName.c_str(), &buf ) != 0 ) {
738         debugOutput( DEBUG_LEVEL_NORMAL,  "\"%s\" does not exist\n",  sFileName.c_str() );
739         return false;
740     } else {
741         if ( !S_ISREG( buf.st_mode ) ) {
742             debugOutput( DEBUG_LEVEL_NORMAL,  "\"%s\" is not a regular file\n",  sFileName.c_str() );
743             return false;
744         }
745     }
746
747     Util::XMLDeserialize deser( sFileName, getDebugLevel() );
748
749     if (!deser.isValid()) {
750         debugOutput( DEBUG_LEVEL_NORMAL, "cache not valid: %s\n",
751                      sFileName.c_str() );
752         return false;
753     }
754
755     bool result = deserialize( "", deser );
756     if ( result ) {
757         debugOutput( DEBUG_LEVEL_NORMAL, "could create valid bebob driver from %s\n",
758                      sFileName.c_str() );
759     }
760
761     if(result) {
762         buildMixer();
763     }
764
765     return result;
766 }
767
768 bool
769 Device::saveCache()
770 {
771     // the path looks like this:
772     // PATH_TO_CACHE + GUID + CONFIGURATION_ID
773     string tmp_path = getCachePath() + getConfigRom().getGuidString();
774
775     // the following piece should do something like
776     // 'mkdir -p some/path/with/some/dirs/which/do/not/exist'
777     vector<string> tokens;
778     tokenize( tmp_path, tokens, "/" );
779     string path;
780     for ( vector<string>::const_iterator it = tokens.begin();
781           it != tokens.end();
782           ++it )
783     {
784         path +=  "/" + *it;
785
786         struct stat buf;
787         if ( stat( path.c_str(), &buf ) == 0 ) {
788             if ( !S_ISDIR( buf.st_mode ) ) {
789                 debugError( "\"%s\" is not a directory\n",  path.c_str() );
790                 return false;
791             }
792         } else {
793             if (  mkdir( path.c_str(), S_IRWXU | S_IRWXG ) != 0 ) {
794                 debugError( "Could not create \"%s\" directory\n", path.c_str() );
795                 return false;
796             }
797         }
798     }
799
800     // come up with an unique file name for the current settings
801     char* configId;
802     asprintf(&configId, "%016"PRIx64"", BeBoB::Device::getConfigurationId() );
803     if ( !configId ) {
804         debugError( "Could not create id string\n" );
805         return false;
806     }
807     string filename = path + "/" + configId + ".xml";
808     free( configId );
809     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", filename.c_str() );
810
811     Util::XMLSerialize ser( filename );
812     return serialize( "", ser );
813 }
814
815 } // end of namespace
Note: See TracBrowser for help on using the browser.