2 * Copyright (C) 2005-2008 by Daniel Wagner
4 * This file is part of FFADO
5 * FFADO = Free Firewire (pro-)audio drivers for linux
7 * FFADO is based upon FreeBoB
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.
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.
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/>.
26 #include "devicemanager.h"
27 #include "bebob/bebob_avdevice.h"
28 #include "bebob/bebob_avdevice_subunit.h"
29 #include "bebob/bebob_mixer.h"
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 #include "bebob/yamaha/yamaha_avdevice.h"
40 #include "libieee1394/configrom.h"
41 #include "libieee1394/ieee1394service.h"
43 #include "libavc/general/avc_plug_info.h"
44 #include "libavc/general/avc_extended_plug_info.h"
45 #include "libavc/general/avc_subunit_info.h"
46 #include "libavc/streamformat/avc_extended_stream_format.h"
47 #include "libutil/cmd_serialize.h"
48 #include "libavc/avc_definitions.h"
50 #include "debugmodule/debugmodule.h"
63 Device::Device( DeviceManager
& d
, std::auto_ptr
< ConfigRom
>( configRom
) )
64 : GenericAVC::Device( d
, configRom
)
65 , m_last_discovery_config_id ( 0xFFFFFFFFFFFFFFFFLLU
)
68 debugOutput( DEBUG_LEVEL_VERBOSE
, "Created BeBoB::Device (NodeID %d)\n",
69 getConfigRom().getNodeId() );
78 Device::probe( Util::Configuration
& c
, ConfigRom
& configRom
, bool generic
)
81 // try a bebob-specific command to check for the firmware
82 ExtendedPlugInfoCmd
extPlugInfoCmd( configRom
.get1394Service() );
83 UnitPlugAddress
unitPlugAddress( UnitPlugAddress::ePT_PCR
,
84 configRom
.getNodeId() );
85 extPlugInfoCmd
.setPlugAddress( PlugAddress( PlugAddress::ePD_Input
,
86 PlugAddress::ePAM_Unit
,
88 extPlugInfoCmd
.setNodeId( configRom
.getNodeId() );
89 extPlugInfoCmd
.setCommandType( AVCCommand::eCT_Status
);
90 extPlugInfoCmd
.setVerbose( configRom
.getVerboseLevel() );
91 ExtendedPlugInfoInfoType
extendedPlugInfoInfoType(
92 ExtendedPlugInfoInfoType::eIT_NoOfChannels
);
93 extendedPlugInfoInfoType
.initialize();
94 extPlugInfoCmd
.setInfoType( extendedPlugInfoInfoType
);
96 if ( !extPlugInfoCmd
.fire() ) {
97 debugError( "Number of channels command failed\n" );
101 if((extPlugInfoCmd
.getResponse() != AVCCommand::eR_Implemented
)) {
102 // command not supported
106 ExtendedPlugInfoInfoType
* infoType
= extPlugInfoCmd
.getInfoType();
108 && infoType
->m_plugNrOfChns
)
114 // check if device is in supported devices list
115 unsigned int vendorId
= configRom
.getNodeVendorId();
116 unsigned int modelId
= configRom
.getModelId();
118 Util::Configuration::VendorModelEntry vme
= c
.findDeviceVME( vendorId
, modelId
);
119 return c
.isValid(vme
) && vme
.driver
== Util::Configuration::eD_BeBoB
;
124 Device::createDevice(DeviceManager
& d
, std::auto_ptr
<ConfigRom
>( configRom
))
126 unsigned int vendorId
= configRom
->getNodeVendorId();
127 unsigned int modelId
= configRom
->getModelId();
130 case FW_VENDORID_MACKIE
:
131 if (modelId
== 0x00010065 ) {
132 return new Mackie::OnyxMixerDevice(d
, configRom
);
134 case FW_VENDORID_EDIROL
:
137 return new Edirol::EdirolFa101Device(d
, configRom
);
139 return new Edirol::EdirolFa66Device(d
, configRom
);
141 return new Device(d
, configRom
);
143 case FW_VENDORID_ESI
:
144 if (modelId
== 0x00010064) {
145 return new ESI::QuataFireDevice(d
, configRom
);
148 case FW_VENDORID_TERRATEC
:
151 return new Terratec::Phase88Device(d
, configRom
);
152 default: // return a plain BeBoB device
153 return new Device(d
, configRom
);
155 case FW_VENDORID_FOCUSRITE
:
159 return new Focusrite::SaffireProDevice(d
, configRom
);
161 return new Focusrite::SaffireDevice(d
, configRom
);
162 default: // return a plain BeBoB device
163 return new Device(d
, configRom
);
165 case FW_VENDORID_YAMAHA
:
169 return new Yamaha::GoDevice(d
, configRom
);
170 default: // return a plain BeBoB device
171 return new Device(d
, configRom
);
174 return new Device(d
, configRom
);
179 #define BEBOB_CHECK_AND_ADD_SR(v, x) \
180 { if(supportsSamplingFrequency(x)) \
185 unsigned int vendorId
= getConfigRom().getNodeVendorId();
186 unsigned int modelId
= getConfigRom().getModelId();
188 Util::Configuration
&c
= getDeviceManager().getConfiguration();
189 Util::Configuration::VendorModelEntry vme
= c
.findDeviceVME( vendorId
, modelId
);
191 if (c
.isValid(vme
) && vme
.driver
== Util::Configuration::eD_BeBoB
) {
192 debugOutput( DEBUG_LEVEL_VERBOSE
, "found %s %s\n",
193 vme
.vendor_name
.c_str(),
194 vme
.model_name
.c_str());
196 debugWarning("Using generic BeBoB support for unsupported device '%s %s'\n",
197 getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
200 if ( !Unit::discover() ) {
201 debugError( "Could not discover unit\n" );
205 if((getAudioSubunit( 0 ) == NULL
)) {
206 debugError( "Unit doesn't have an Audio subunit.\n");
209 if((getMusicSubunit( 0 ) == NULL
)) {
210 debugError( "Unit doesn't have a Music subunit.\n");
215 debugWarning("Could not build mixer\n");
218 // keep track of the config id of this discovery
219 m_last_discovery_config_id
= getConfigurationId();
227 debugOutput(DEBUG_LEVEL_VERBOSE
, "Building a generic BeBoB mixer...\n");
229 // this removes the mixer if it already exists
230 // note: a mixer self-registers to it's parent
233 // create the mixer & register it
234 if(getAudioSubunit(0) == NULL
) {
235 debugWarning("Could not find audio subunit, mixer not available.\n");
238 m_Mixer
= new Mixer(*this);
240 if (m_Mixer
) m_Mixer
->setVerboseLevel(getDebugLevel());
241 return m_Mixer
!= NULL
;
245 Device::destroyMixer()
252 Device::setSelectorFBValue(int id
, int value
) {
253 FunctionBlockCmd
fbCmd( get1394Service(),
254 FunctionBlockCmd::eFBT_Selector
,
256 FunctionBlockCmd::eCA_Current
);
257 fbCmd
.setNodeId( getNodeId() );
258 fbCmd
.setSubunitId( 0x00 );
259 fbCmd
.setCommandType( AVCCommand::eCT_Control
);
260 fbCmd
.m_pFBSelector
->m_inputFbPlugNumber
= (value
& 0xFF);
261 fbCmd
.setVerboseLevel( getDebugLevel() );
263 if ( !fbCmd
.fire() ) {
264 debugError( "cmd failed\n" );
268 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
269 // Util::Cmd::CoutSerializer se;
270 // fbCmd.serialize( se );
273 if((fbCmd
.getResponse() != AVCCommand::eR_Accepted
)) {
274 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
277 return (fbCmd
.getResponse() == AVCCommand::eR_Accepted
);
281 Device::getSelectorFBValue(int id
) {
283 FunctionBlockCmd
fbCmd( get1394Service(),
284 FunctionBlockCmd::eFBT_Selector
,
286 FunctionBlockCmd::eCA_Current
);
287 fbCmd
.setNodeId( getNodeId() );
288 fbCmd
.setSubunitId( 0x00 );
289 fbCmd
.setCommandType( AVCCommand::eCT_Status
);
290 fbCmd
.m_pFBSelector
->m_inputFbPlugNumber
= 0xFF;
291 fbCmd
.setVerboseLevel( getDebugLevel() );
293 if ( !fbCmd
.fire() ) {
294 debugError( "cmd failed\n" );
298 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
299 // Util::Cmd::CoutSerializer se;
300 // fbCmd.serialize( se );
303 if((fbCmd
.getResponse() != AVCCommand::eR_Implemented
)) {
304 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
307 return fbCmd
.m_pFBSelector
->m_inputFbPlugNumber
;
311 Device::setFeatureFBVolumeCurrent(int id
, int channel
, int v
) {
313 FunctionBlockCmd
fbCmd( get1394Service(),
314 FunctionBlockCmd::eFBT_Feature
,
316 FunctionBlockCmd::eCA_Current
);
317 fbCmd
.setNodeId( getNodeId() );
318 fbCmd
.setSubunitId( 0x00 );
319 fbCmd
.setCommandType( AVCCommand::eCT_Control
);
320 fbCmd
.m_pFBFeature
->m_audioChannelNumber
= channel
;
321 fbCmd
.m_pFBFeature
->m_controlSelector
= FunctionBlockFeature::eCSE_Feature_Volume
;
322 AVC::FunctionBlockFeatureVolume vl
;
323 fbCmd
.m_pFBFeature
->m_pVolume
= vl
.clone();
324 fbCmd
.m_pFBFeature
->m_pVolume
->m_volume
= v
;
325 fbCmd
.setVerboseLevel( getDebugLevel() );
327 if ( !fbCmd
.fire() ) {
328 debugError( "cmd failed\n" );
332 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
333 // Util::Cmd::CoutSerializer se;
334 // fbCmd.serialize( se );
337 if((fbCmd
.getResponse() != AVCCommand::eR_Accepted
)) {
338 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
341 return (fbCmd
.getResponse() == AVCCommand::eR_Accepted
);
345 Device::getFeatureFBVolumeValue(int id
, int channel
, FunctionBlockCmd::EControlAttribute controlAttribute
)
347 FunctionBlockCmd
fbCmd( get1394Service(),
348 FunctionBlockCmd::eFBT_Feature
,
351 fbCmd
.setNodeId( getNodeId() );
352 fbCmd
.setSubunitId( 0x00 );
353 fbCmd
.setCommandType( AVCCommand::eCT_Status
);
354 fbCmd
.m_pFBFeature
->m_audioChannelNumber
= channel
;
355 fbCmd
.m_pFBFeature
->m_controlSelector
= FunctionBlockFeature::eCSE_Feature_Volume
;
356 AVC::FunctionBlockFeatureVolume vl
;
357 fbCmd
.m_pFBFeature
->m_pVolume
= vl
.clone();
358 fbCmd
.m_pFBFeature
->m_pVolume
->m_volume
= 0;
359 fbCmd
.setVerboseLevel( getDebugLevel() );
361 if ( !fbCmd
.fire() ) {
362 debugError( "cmd failed\n" );
366 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
367 // Util::Cmd::CoutSerializer se;
368 // fbCmd.serialize( se );
371 if((fbCmd
.getResponse() != AVCCommand::eR_Implemented
)) {
372 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
375 int16_t volume
=(int16_t)(fbCmd
.m_pFBFeature
->m_pVolume
->m_volume
);
381 Device::getFeatureFBVolumeMinimum(int id
, int channel
)
383 return getFeatureFBVolumeValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Minimum
);
387 Device::getFeatureFBVolumeMaximum(int id
, int channel
)
389 return getFeatureFBVolumeValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Maximum
);
393 Device::getFeatureFBVolumeCurrent(int id
, int channel
)
395 return getFeatureFBVolumeValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Current
);
399 Device::setFeatureFBLRBalanceCurrent(int id
, int channel
, int v
) {
401 FunctionBlockCmd
fbCmd( get1394Service(),
402 FunctionBlockCmd::eFBT_Feature
,
404 FunctionBlockCmd::eCA_Current
);
405 fbCmd
.setNodeId( getNodeId() );
406 fbCmd
.setSubunitId( 0x00 );
407 fbCmd
.setCommandType( AVCCommand::eCT_Control
);
408 fbCmd
.m_pFBFeature
->m_audioChannelNumber
= channel
;
409 fbCmd
.m_pFBFeature
->m_controlSelector
= FunctionBlockFeature::eCSE_Feature_LRBalance
;
410 AVC::FunctionBlockFeatureLRBalance bl
;
411 fbCmd
.m_pFBFeature
->m_pLRBalance
= bl
.clone();
412 fbCmd
.m_pFBFeature
->m_pLRBalance
->m_lrBalance
= v
;
413 fbCmd
.setVerboseLevel( getDebugLevel() );
415 if ( !fbCmd
.fire() ) {
416 debugError( "cmd failed\n" );
420 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
421 // Util::Cmd::CoutSerializer se;
422 // fbCmd.serialize( se );
425 if((fbCmd
.getResponse() != AVCCommand::eR_Accepted
)) {
426 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
429 return (fbCmd
.getResponse() == AVCCommand::eR_Accepted
);
433 Device::getFeatureFBLRBalanceValue(int id
, int channel
, FunctionBlockCmd::EControlAttribute controlAttribute
)
435 FunctionBlockCmd
fbCmd( get1394Service(),
436 FunctionBlockCmd::eFBT_Feature
,
439 fbCmd
.setNodeId( getNodeId() );
440 fbCmd
.setSubunitId( 0x00 );
441 fbCmd
.setCommandType( AVCCommand::eCT_Status
);
442 fbCmd
.m_pFBFeature
->m_audioChannelNumber
= channel
;
443 fbCmd
.m_pFBFeature
->m_controlSelector
= FunctionBlockFeature::eCSE_Feature_LRBalance
;
444 AVC::FunctionBlockFeatureLRBalance bl
;
445 fbCmd
.m_pFBFeature
->m_pLRBalance
= bl
.clone();
446 fbCmd
.m_pFBFeature
->m_pLRBalance
->m_lrBalance
= 0;
447 fbCmd
.setVerboseLevel( getDebugLevel() );
449 if ( !fbCmd
.fire() ) {
450 debugError( "cmd failed\n" );
454 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
455 // Util::Cmd::CoutSerializer se;
456 // fbCmd.serialize( se );
459 if((fbCmd
.getResponse() != AVCCommand::eR_Implemented
)) {
460 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
463 int16_t balance
=(int16_t)(fbCmd
.m_pFBFeature
->m_pLRBalance
->m_lrBalance
);
469 Device::getFeatureFBLRBalanceMinimum(int id
, int channel
)
471 return getFeatureFBLRBalanceValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Minimum
);
475 Device::getFeatureFBLRBalanceMaximum(int id
, int channel
)
477 return getFeatureFBLRBalanceValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Maximum
);
481 Device::getFeatureFBLRBalanceCurrent(int id
, int channel
)
483 return getFeatureFBLRBalanceValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Current
);
487 Device::setProcessingFBMixerSingleCurrent(int id
, int iPlugNum
,
488 int iAChNum
, int oAChNum
,
491 AVC::FunctionBlockCmd
fbCmd(get1394Service(),
492 AVC::FunctionBlockCmd::eFBT_Processing
,
494 AVC::FunctionBlockCmd::eCA_Current
);
495 fbCmd
.setNodeId(getNodeId());
496 fbCmd
.setSubunitId(0x00);
497 fbCmd
.setCommandType(AVCCommand::eCT_Control
);
498 fbCmd
.setVerboseLevel( getDebugLevel() );
500 AVC::FunctionBlockProcessing
*fbp
= fbCmd
.m_pFBProcessing
;
501 fbp
->m_selectorLength
= 0x04;
502 fbp
->m_fbInputPlugNumber
= iPlugNum
;
503 fbp
->m_inputAudioChannelNumber
= iAChNum
;
504 fbp
->m_outputAudioChannelNumber
= oAChNum
;
506 // mixer object is not generated automatically
507 fbp
->m_pMixer
= new AVC::FunctionBlockProcessingMixer
;
508 fbp
->m_pMixer
->m_mixerSetting
= setting
;
510 if ( !fbCmd
.fire() ) {
511 debugError( "cmd failed\n" );
515 if((fbCmd
.getResponse() != AVCCommand::eR_Accepted
)) {
516 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
519 return (fbCmd
.getResponse() == AVCCommand::eR_Accepted
);
523 Device::getProcessingFBMixerSingleCurrent(int id
, int iPlugNum
,
524 int iAChNum
, int oAChNum
)
526 AVC::FunctionBlockCmd
fbCmd(get1394Service(),
527 AVC::FunctionBlockCmd::eFBT_Processing
,
529 AVC::FunctionBlockCmd::eCA_Current
);
530 fbCmd
.setNodeId(getNodeId());
531 fbCmd
.setSubunitId(0x00);
532 fbCmd
.setCommandType(AVCCommand::eCT_Status
);
533 fbCmd
.setVerboseLevel( getDebugLevel() );
535 AVC::FunctionBlockProcessing
*fbp
= fbCmd
.m_pFBProcessing
;
536 fbp
->m_selectorLength
= 0x04;
537 fbp
->m_fbInputPlugNumber
= iPlugNum
;
538 fbp
->m_inputAudioChannelNumber
= iAChNum
;
539 fbp
->m_outputAudioChannelNumber
= oAChNum
;
541 // mixer object is not generated automatically
542 fbp
->m_pMixer
= new AVC::FunctionBlockProcessingMixer
;
544 if ( !fbCmd
.fire() ) {
545 debugError( "cmd failed\n" );
549 if( (fbCmd
.getResponse() != AVCCommand::eR_Implemented
) ) {
550 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
553 int16_t setting
= (int16_t)(fbp
->m_pMixer
->m_mixerSetting
);
561 debugOutput(DEBUG_LEVEL_NORMAL
, "Device is a BeBoB device\n");
562 GenericAVC::Device::showDevice();
567 Device::setVerboseLevel(int l
)
569 if (m_Mixer
) m_Mixer
->setVerboseLevel( l
);
570 GenericAVC::Device::setVerboseLevel( l
);
571 debugOutput( DEBUG_LEVEL_VERBOSE
, "Setting verbose level to %d...\n", l
);
575 Device::createSubunit(AVC::Unit
& unit
,
576 AVC::ESubunitType type
,
579 AVC::Subunit
* s
=NULL
;
582 s
=new BeBoB::SubunitAudio(unit
, id
);
585 s
=new BeBoB::SubunitMusic(unit
, id
);
591 if(s
) s
->setVerboseLevel(getDebugLevel());
597 Device::createPlug( AVC::Unit
* unit
,
598 AVC::Subunit
* subunit
,
599 AVC::function_block_type_t functionBlockType
,
600 AVC::function_block_type_t functionBlockId
,
601 AVC::Plug::EPlugAddressType plugAddressType
,
602 AVC::Plug::EPlugDirection plugDirection
,
603 AVC::plug_id_t plugId
,
607 Plug
*p
= new BeBoB::Plug( unit
,
615 if (p
) p
->setVerboseLevel(getDebugLevel());
620 Device::propagatePlugInfo() {
621 // we don't have to propagate since we discover things
623 debugOutput(DEBUG_LEVEL_VERBOSE
, "Skip plug info propagation\n");
628 Device::getConfigurationIdSampleRate()
630 ExtendedStreamFormatCmd
extStreamFormatCmd( get1394Service() );
631 UnitPlugAddress
unitPlugAddress( UnitPlugAddress::ePT_PCR
, 0 );
632 extStreamFormatCmd
.setPlugAddress( PlugAddress( PlugAddress::ePD_Input
,
633 PlugAddress::ePAM_Unit
,
636 extStreamFormatCmd
.setNodeId( getNodeId() );
637 extStreamFormatCmd
.setCommandType( AVCCommand::eCT_Status
);
638 extStreamFormatCmd
.setVerbose( getDebugLevel() );
640 if ( !extStreamFormatCmd
.fire() ) {
641 debugError( "Stream format command failed\n" );
645 FormatInformation
* formatInfo
=
646 extStreamFormatCmd
.getFormatInformation();
647 FormatInformationStreamsCompound
* compoundStream
648 = dynamic_cast< FormatInformationStreamsCompound
* > (
649 formatInfo
->m_streams
);
650 if ( compoundStream
) {
651 debugOutput(DEBUG_LEVEL_VERBOSE
, "Sample rate 0x%02x\n",
652 compoundStream
->m_samplingFrequency
);
653 return compoundStream
->m_samplingFrequency
;
656 debugError( "Could not retrieve sample rate\n" );
661 Device::getConfigurationIdNumberOfChannel( PlugAddress::EPlugDirection ePlugDirection
)
663 ExtendedPlugInfoCmd
extPlugInfoCmd( get1394Service() );
664 UnitPlugAddress
unitPlugAddress( UnitPlugAddress::ePT_PCR
,
666 extPlugInfoCmd
.setPlugAddress( PlugAddress( ePlugDirection
,
667 PlugAddress::ePAM_Unit
,
669 extPlugInfoCmd
.setNodeId( getNodeId() );
670 extPlugInfoCmd
.setCommandType( AVCCommand::eCT_Status
);
671 extPlugInfoCmd
.setVerbose( getDebugLevel() );
672 ExtendedPlugInfoInfoType
extendedPlugInfoInfoType(
673 ExtendedPlugInfoInfoType::eIT_NoOfChannels
);
674 extendedPlugInfoInfoType
.initialize();
675 extPlugInfoCmd
.setInfoType( extendedPlugInfoInfoType
);
677 if ( !extPlugInfoCmd
.fire() ) {
678 debugError( "Number of channels command failed\n" );
682 ExtendedPlugInfoInfoType
* infoType
= extPlugInfoCmd
.getInfoType();
684 && infoType
->m_plugNrOfChns
)
686 debugOutput(DEBUG_LEVEL_VERBOSE
, "Number of channels 0x%02x\n",
687 infoType
->m_plugNrOfChns
->m_nrOfChannels
);
688 return infoType
->m_plugNrOfChns
->m_nrOfChannels
;
691 debugError( "Could not retrieve number of channels\n" );
696 Device::getConfigurationIdSyncMode()
698 SignalSourceCmd
signalSourceCmd( get1394Service() );
699 SignalUnitAddress signalUnitAddr
;
700 signalUnitAddr
.m_plugId
= 0x01;
701 signalSourceCmd
.setSignalDestination( signalUnitAddr
);
702 signalSourceCmd
.setNodeId( getNodeId() );
703 signalSourceCmd
.setSubunitType( eST_Unit
);
704 signalSourceCmd
.setSubunitId( 0xff );
705 signalSourceCmd
.setVerbose( getDebugLevel() );
707 signalSourceCmd
.setCommandType( AVCCommand::eCT_Status
);
709 if ( !signalSourceCmd
.fire() ) {
710 debugError( "Signal source command failed\n" );
714 SignalAddress
* pSyncPlugSignalAddress
= signalSourceCmd
.getSignalSource();
715 SignalSubunitAddress
* pSyncPlugSubunitAddress
716 = dynamic_cast<SignalSubunitAddress
*>( pSyncPlugSignalAddress
);
717 if ( pSyncPlugSubunitAddress
) {
718 debugOutput(DEBUG_LEVEL_VERBOSE
, "Sync mode 0x%02x\n",
719 ( pSyncPlugSubunitAddress
->m_subunitType
<< 3
720 | pSyncPlugSubunitAddress
->m_subunitId
) << 8
721 | pSyncPlugSubunitAddress
->m_plugId
);
723 return ( pSyncPlugSubunitAddress
->m_subunitType
<< 3
724 | pSyncPlugSubunitAddress
->m_subunitId
) << 8
725 | pSyncPlugSubunitAddress
->m_plugId
;
728 SignalUnitAddress
* pSyncPlugUnitAddress
729 = dynamic_cast<SignalUnitAddress
*>( pSyncPlugSignalAddress
);
730 if ( pSyncPlugUnitAddress
) {
731 debugOutput(DEBUG_LEVEL_VERBOSE
, "Sync mode 0x%02x\n",
732 0xff << 8 | pSyncPlugUnitAddress
->m_plugId
);
734 return ( 0xff << 8 | pSyncPlugUnitAddress
->m_plugId
);
737 debugError( "Could not retrieve sync mode\n" );
742 Device::needsRediscovery()
744 // require rediscovery if the config id differs from the one saved
745 // in the previous discovery
746 return getConfigurationId() != m_last_discovery_config_id
;
750 Device::getConfigurationId()
752 // create a unique configuration id.
754 id
= getConfigurationIdSampleRate();
755 id
|= getConfigurationIdNumberOfChannel( PlugAddress::ePD_Input
) << 8;
756 id
|= getConfigurationIdNumberOfChannel( PlugAddress::ePD_Output
) << 16;
757 id
|= ((uint64_t)getConfigurationIdSyncMode()) << 24;
762 Device::serialize( std::string basePath
,
763 Util::IOSerialize
& ser
) const
766 result
= GenericAVC::Device::serialize( basePath
, ser
);
771 Device::deserialize( std::string basePath
,
772 Util::IODeserialize
& deser
)
775 result
= GenericAVC::Device::deserialize( basePath
, deser
);
780 Device::getCachePath()
782 std::string cachePath
;
785 string path
= CACHEDIR
;
786 if ( path
.size() && path
[0] == '~' ) {
787 path
.erase( 0, 1 ); // remove ~
788 path
.insert( 0, getenv( "HOME" ) ); // prepend the home path
791 if ( asprintf( &pCachePath
, "%s/cache/", path
.c_str() ) < 0 ) {
792 debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
793 cachePath
= "/var/cache/libffado/";
795 cachePath
= pCachePath
;
802 Device::loadFromCache()
804 std::string sDevicePath
= getCachePath() + getConfigRom().getGuidString();
807 asprintf(&configId
, "%016"PRIx64
"", getConfigurationId() );
809 debugError( "could not create id string\n" );
813 std::string sFileName
= sDevicePath
+ "/" + configId
+ ".xml";
815 debugOutput( DEBUG_LEVEL_NORMAL
, "filename %s\n", sFileName
.c_str() );
818 if ( stat( sFileName
.c_str(), &buf
) != 0 ) {
819 debugOutput( DEBUG_LEVEL_NORMAL
, "\"%s\" does not exist\n", sFileName
.c_str() );
822 if ( !S_ISREG( buf
.st_mode
) ) {
823 debugOutput( DEBUG_LEVEL_NORMAL
, "\"%s\" is not a regular file\n", sFileName
.c_str() );
828 Util::XMLDeserialize
deser( sFileName
, getDebugLevel() );
830 if (!deser
.isValid()) {
831 debugOutput( DEBUG_LEVEL_NORMAL
, "cache not valid: %s\n",
836 bool result
= deserialize( "", deser
);
838 debugOutput( DEBUG_LEVEL_NORMAL
, "could create valid bebob driver from %s\n",
852 // the path looks like this:
853 // PATH_TO_CACHE + GUID + CONFIGURATION_ID
854 string tmp_path
= getCachePath() + getConfigRom().getGuidString();
856 // the following piece should do something like
857 // 'mkdir -p some/path/with/some/dirs/which/do/not/exist'
858 vector
<string
> tokens
;
859 tokenize( tmp_path
, tokens
, "/" );
861 for ( vector
<string
>::const_iterator it
= tokens
.begin();
868 if ( stat( path
.c_str(), &buf
) == 0 ) {
869 if ( !S_ISDIR( buf
.st_mode
) ) {
870 debugError( "\"%s\" is not a directory\n", path
.c_str() );
874 if ( mkdir( path
.c_str(), S_IRWXU
| S_IRWXG
) != 0 ) {
875 debugError( "Could not create \"%s\" directory\n", path
.c_str() );
881 // come up with an unique file name for the current settings
883 asprintf(&configId
, "%016"PRIx64
"", BeBoB::Device::getConfigurationId() );
885 debugError( "Could not create id string\n" );
888 string filename
= path
+ "/" + configId
+ ".xml";
890 debugOutput( DEBUG_LEVEL_NORMAL
, "filename %s\n", filename
.c_str() );
892 Util::XMLSerialize
ser( filename
);
893 return serialize( "", ser
);
896 } // end of namespace