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"
39 #include "bebob/maudio/maudio_normal_avdevice.h"
40 #include "bebob/presonus/firebox_avdevice.h"
41 #include "bebob/presonus/inspire1394_avdevice.h"
43 #include "libieee1394/configrom.h"
44 #include "libieee1394/ieee1394service.h"
46 #include "libavc/general/avc_plug_info.h"
47 #include "libavc/general/avc_extended_plug_info.h"
48 #include "libavc/general/avc_subunit_info.h"
49 #include "libavc/streamformat/avc_extended_stream_format.h"
50 #include "libutil/cmd_serialize.h"
51 #include "libavc/avc_definitions.h"
53 #include "debugmodule/debugmodule.h"
66 Device::Device( DeviceManager
& d
, std::auto_ptr
< ConfigRom
>( configRom
) )
67 : GenericAVC::Device( d
, configRom
)
68 , m_last_discovery_config_id ( 0xFFFFFFFFFFFFFFFFLLU
)
71 debugOutput( DEBUG_LEVEL_VERBOSE
, "Created BeBoB::Device (NodeID %d)\n",
72 getConfigRom().getNodeId() );
81 Device::probe( Util::Configuration
& c
, ConfigRom
& configRom
, bool generic
)
84 // try a bebob-specific command to check for the firmware
85 ExtendedPlugInfoCmd
extPlugInfoCmd( configRom
.get1394Service() );
86 UnitPlugAddress
unitPlugAddress( UnitPlugAddress::ePT_PCR
,
87 configRom
.getNodeId() );
88 extPlugInfoCmd
.setPlugAddress( PlugAddress( PlugAddress::ePD_Input
,
89 PlugAddress::ePAM_Unit
,
91 extPlugInfoCmd
.setNodeId( configRom
.getNodeId() );
92 extPlugInfoCmd
.setCommandType( AVCCommand::eCT_Status
);
93 extPlugInfoCmd
.setVerbose( configRom
.getVerboseLevel() );
94 ExtendedPlugInfoInfoType
extendedPlugInfoInfoType(
95 ExtendedPlugInfoInfoType::eIT_NoOfChannels
);
96 extendedPlugInfoInfoType
.initialize();
97 extPlugInfoCmd
.setInfoType( extendedPlugInfoInfoType
);
99 if ( !extPlugInfoCmd
.fire() ) {
100 debugError( "Number of channels command failed\n" );
104 if((extPlugInfoCmd
.getResponse() != AVCCommand::eR_Implemented
)) {
105 // command not supported
109 ExtendedPlugInfoInfoType
* infoType
= extPlugInfoCmd
.getInfoType();
111 && infoType
->m_plugNrOfChns
)
117 // check if device is in supported devices list
118 unsigned int vendorId
= configRom
.getNodeVendorId();
119 unsigned int modelId
= configRom
.getModelId();
121 Util::Configuration::VendorModelEntry vme
= c
.findDeviceVME( vendorId
, modelId
);
122 return c
.isValid(vme
) && vme
.driver
== Util::Configuration::eD_BeBoB
;
127 Device::createDevice(DeviceManager
& d
, std::auto_ptr
<ConfigRom
>( configRom
))
129 unsigned int vendorId
= configRom
->getNodeVendorId();
130 unsigned int modelId
= configRom
->getModelId();
133 case FW_VENDORID_MACKIE
:
134 if (modelId
== 0x00010065 ) {
135 return new Mackie::OnyxMixerDevice(d
, configRom
);
137 case FW_VENDORID_EDIROL
:
140 return new Edirol::EdirolFa101Device(d
, configRom
);
142 return new Edirol::EdirolFa66Device(d
, configRom
);
144 return new Device(d
, configRom
);
146 case FW_VENDORID_ESI
:
147 if (modelId
== 0x00010064) {
148 return new ESI::QuataFireDevice(d
, configRom
);
151 case FW_VENDORID_TERRATEC
:
154 return new Terratec::Phase88Device(d
, configRom
);
155 default: // return a plain BeBoB device
156 return new Device(d
, configRom
);
158 case FW_VENDORID_FOCUSRITE
:
162 return new Focusrite::SaffireProDevice(d
, configRom
);
164 return new Focusrite::SaffireDevice(d
, configRom
);
165 default: // return a plain BeBoB device
166 return new Device(d
, configRom
);
168 case FW_VENDORID_YAMAHA
:
172 return new Yamaha::GoDevice(d
, configRom
);
173 default: // return a plain BeBoB device
174 return new Device(d
, configRom
);
176 case FW_VENDORID_MAUDIO
:
178 case 0x0000000a: // Ozonic
179 case 0x00010046: // fw410
180 case 0x00010060: // Audiophile
181 case 0x00010062: // Solo
182 return new MAudio::NormalDevice(d
, configRom
, modelId
);
184 return new Device(d
, configRom
);
186 case FW_VENDORID_PRESONUS
:
189 return new Presonus::FireboxDevice(d
, configRom
);
191 return new Presonus::Inspire1394Device(d
, configRom
);
193 return new Device(d
, configRom
);
196 return new Device(d
, configRom
);
201 #define BEBOB_CHECK_AND_ADD_SR(v, x) \
202 { if(supportsSamplingFrequency(x)) \
207 unsigned int vendorId
= getConfigRom().getNodeVendorId();
208 unsigned int modelId
= getConfigRom().getModelId();
210 Util::Configuration
&c
= getDeviceManager().getConfiguration();
211 Util::Configuration::VendorModelEntry vme
= c
.findDeviceVME( vendorId
, modelId
);
213 if (c
.isValid(vme
) && vme
.driver
== Util::Configuration::eD_BeBoB
) {
214 debugOutput( DEBUG_LEVEL_VERBOSE
, "found %s %s\n",
215 vme
.vendor_name
.c_str(),
216 vme
.model_name
.c_str());
218 debugWarning("Using generic BeBoB support for unsupported device '%s %s'\n",
219 getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
222 if ( !Unit::discover() ) {
223 debugError( "Could not discover unit\n" );
227 if((getAudioSubunit( 0 ) == NULL
)) {
228 debugError( "Unit doesn't have an Audio subunit.\n");
231 if((getMusicSubunit( 0 ) == NULL
)) {
232 debugError( "Unit doesn't have a Music subunit.\n");
237 debugWarning("Could not build mixer\n");
240 // keep track of the config id of this discovery
241 m_last_discovery_config_id
= getConfigurationId();
249 debugOutput(DEBUG_LEVEL_VERBOSE
, "Building a generic BeBoB mixer...\n");
251 // this removes the mixer if it already exists
252 // note: a mixer self-registers to it's parent
255 // create the mixer & register it
256 if(getAudioSubunit(0) == NULL
) {
257 debugWarning("Could not find audio subunit, mixer not available.\n");
260 m_Mixer
= new Mixer(*this);
262 if (m_Mixer
) m_Mixer
->setVerboseLevel(getDebugLevel());
263 return m_Mixer
!= NULL
;
267 Device::destroyMixer()
274 Device::setSelectorFBValue(int id
, int value
) {
275 FunctionBlockCmd
fbCmd( get1394Service(),
276 FunctionBlockCmd::eFBT_Selector
,
278 FunctionBlockCmd::eCA_Current
);
279 fbCmd
.setNodeId( getNodeId() );
280 fbCmd
.setSubunitId( 0x00 );
281 fbCmd
.setCommandType( AVCCommand::eCT_Control
);
282 fbCmd
.m_pFBSelector
->m_inputFbPlugNumber
= (value
& 0xFF);
283 fbCmd
.setVerboseLevel( getDebugLevel() );
285 if ( !fbCmd
.fire() ) {
286 debugError( "cmd failed\n" );
290 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
291 // Util::Cmd::CoutSerializer se;
292 // fbCmd.serialize( se );
295 if((fbCmd
.getResponse() != AVCCommand::eR_Accepted
)) {
296 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
299 return (fbCmd
.getResponse() == AVCCommand::eR_Accepted
);
303 Device::getSelectorFBValue(int id
) {
305 FunctionBlockCmd
fbCmd( get1394Service(),
306 FunctionBlockCmd::eFBT_Selector
,
308 FunctionBlockCmd::eCA_Current
);
309 fbCmd
.setNodeId( getNodeId() );
310 fbCmd
.setSubunitId( 0x00 );
311 fbCmd
.setCommandType( AVCCommand::eCT_Status
);
312 fbCmd
.m_pFBSelector
->m_inputFbPlugNumber
= 0xFF;
313 fbCmd
.setVerboseLevel( getDebugLevel() );
315 if ( !fbCmd
.fire() ) {
316 debugError( "cmd failed\n" );
320 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
321 // Util::Cmd::CoutSerializer se;
322 // fbCmd.serialize( se );
325 if((fbCmd
.getResponse() != AVCCommand::eR_Implemented
)) {
326 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
329 return fbCmd
.m_pFBSelector
->m_inputFbPlugNumber
;
333 Device::setFeatureFBVolumeCurrent(int id
, int channel
, int v
) {
335 FunctionBlockCmd
fbCmd( get1394Service(),
336 FunctionBlockCmd::eFBT_Feature
,
338 FunctionBlockCmd::eCA_Current
);
339 fbCmd
.setNodeId( getNodeId() );
340 fbCmd
.setSubunitId( 0x00 );
341 fbCmd
.setCommandType( AVCCommand::eCT_Control
);
342 fbCmd
.m_pFBFeature
->m_audioChannelNumber
= channel
;
343 fbCmd
.m_pFBFeature
->m_controlSelector
= FunctionBlockFeature::eCSE_Feature_Volume
;
344 AVC::FunctionBlockFeatureVolume vl
;
345 fbCmd
.m_pFBFeature
->m_pVolume
= vl
.clone();
346 fbCmd
.m_pFBFeature
->m_pVolume
->m_volume
= v
;
347 fbCmd
.setVerboseLevel( getDebugLevel() );
349 if ( !fbCmd
.fire() ) {
350 debugError( "cmd failed\n" );
354 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
355 // Util::Cmd::CoutSerializer se;
356 // fbCmd.serialize( se );
359 if((fbCmd
.getResponse() != AVCCommand::eR_Accepted
)) {
360 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
363 return (fbCmd
.getResponse() == AVCCommand::eR_Accepted
);
367 Device::getFeatureFBVolumeValue(int id
, int channel
, FunctionBlockCmd::EControlAttribute controlAttribute
)
369 FunctionBlockCmd
fbCmd( get1394Service(),
370 FunctionBlockCmd::eFBT_Feature
,
373 fbCmd
.setNodeId( getNodeId() );
374 fbCmd
.setSubunitId( 0x00 );
375 fbCmd
.setCommandType( AVCCommand::eCT_Status
);
376 fbCmd
.m_pFBFeature
->m_audioChannelNumber
= channel
;
377 fbCmd
.m_pFBFeature
->m_controlSelector
= FunctionBlockFeature::eCSE_Feature_Volume
;
378 AVC::FunctionBlockFeatureVolume vl
;
379 fbCmd
.m_pFBFeature
->m_pVolume
= vl
.clone();
380 fbCmd
.m_pFBFeature
->m_pVolume
->m_volume
= 0;
381 fbCmd
.setVerboseLevel( getDebugLevel() );
383 if ( !fbCmd
.fire() ) {
384 debugError( "cmd failed\n" );
388 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
389 // Util::Cmd::CoutSerializer se;
390 // fbCmd.serialize( se );
393 if((fbCmd
.getResponse() != AVCCommand::eR_Implemented
)) {
394 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
397 int16_t volume
=(int16_t)(fbCmd
.m_pFBFeature
->m_pVolume
->m_volume
);
403 Device::getFeatureFBVolumeMinimum(int id
, int channel
)
405 return getFeatureFBVolumeValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Minimum
);
409 Device::getFeatureFBVolumeMaximum(int id
, int channel
)
411 return getFeatureFBVolumeValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Maximum
);
415 Device::getFeatureFBVolumeCurrent(int id
, int channel
)
417 return getFeatureFBVolumeValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Current
);
421 Device::setFeatureFBLRBalanceCurrent(int id
, int channel
, int v
) {
423 FunctionBlockCmd
fbCmd( get1394Service(),
424 FunctionBlockCmd::eFBT_Feature
,
426 FunctionBlockCmd::eCA_Current
);
427 fbCmd
.setNodeId( getNodeId() );
428 fbCmd
.setSubunitId( 0x00 );
429 fbCmd
.setCommandType( AVCCommand::eCT_Control
);
430 fbCmd
.m_pFBFeature
->m_audioChannelNumber
= channel
;
431 fbCmd
.m_pFBFeature
->m_controlSelector
= FunctionBlockFeature::eCSE_Feature_LRBalance
;
432 AVC::FunctionBlockFeatureLRBalance bl
;
433 fbCmd
.m_pFBFeature
->m_pLRBalance
= bl
.clone();
434 fbCmd
.m_pFBFeature
->m_pLRBalance
->m_lrBalance
= v
;
435 fbCmd
.setVerboseLevel( getDebugLevel() );
437 if ( !fbCmd
.fire() ) {
438 debugError( "cmd failed\n" );
442 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
443 // Util::Cmd::CoutSerializer se;
444 // fbCmd.serialize( se );
447 if((fbCmd
.getResponse() != AVCCommand::eR_Accepted
)) {
448 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
451 return (fbCmd
.getResponse() == AVCCommand::eR_Accepted
);
455 Device::getFeatureFBLRBalanceValue(int id
, int channel
, FunctionBlockCmd::EControlAttribute controlAttribute
)
457 FunctionBlockCmd
fbCmd( get1394Service(),
458 FunctionBlockCmd::eFBT_Feature
,
461 fbCmd
.setNodeId( getNodeId() );
462 fbCmd
.setSubunitId( 0x00 );
463 fbCmd
.setCommandType( AVCCommand::eCT_Status
);
464 fbCmd
.m_pFBFeature
->m_audioChannelNumber
= channel
;
465 fbCmd
.m_pFBFeature
->m_controlSelector
= FunctionBlockFeature::eCSE_Feature_LRBalance
;
466 AVC::FunctionBlockFeatureLRBalance bl
;
467 fbCmd
.m_pFBFeature
->m_pLRBalance
= bl
.clone();
468 fbCmd
.m_pFBFeature
->m_pLRBalance
->m_lrBalance
= 0;
469 fbCmd
.setVerboseLevel( getDebugLevel() );
471 if ( !fbCmd
.fire() ) {
472 debugError( "cmd failed\n" );
476 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
477 // Util::Cmd::CoutSerializer se;
478 // fbCmd.serialize( se );
481 if((fbCmd
.getResponse() != AVCCommand::eR_Implemented
)) {
482 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
485 int16_t balance
=(int16_t)(fbCmd
.m_pFBFeature
->m_pLRBalance
->m_lrBalance
);
491 Device::getFeatureFBLRBalanceMinimum(int id
, int channel
)
493 return getFeatureFBLRBalanceValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Minimum
);
497 Device::getFeatureFBLRBalanceMaximum(int id
, int channel
)
499 return getFeatureFBLRBalanceValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Maximum
);
503 Device::getFeatureFBLRBalanceCurrent(int id
, int channel
)
505 return getFeatureFBLRBalanceValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Current
);
509 Device::setProcessingFBMixerSingleCurrent(int id
, int iPlugNum
,
510 int iAChNum
, int oAChNum
,
513 AVC::FunctionBlockCmd
fbCmd(get1394Service(),
514 AVC::FunctionBlockCmd::eFBT_Processing
,
516 AVC::FunctionBlockCmd::eCA_Current
);
517 fbCmd
.setNodeId(getNodeId());
518 fbCmd
.setSubunitId(0x00);
519 fbCmd
.setCommandType(AVCCommand::eCT_Control
);
520 fbCmd
.setVerboseLevel( getDebugLevel() );
522 AVC::FunctionBlockProcessing
*fbp
= fbCmd
.m_pFBProcessing
;
523 fbp
->m_selectorLength
= 0x04;
524 fbp
->m_fbInputPlugNumber
= iPlugNum
;
525 fbp
->m_inputAudioChannelNumber
= iAChNum
;
526 fbp
->m_outputAudioChannelNumber
= oAChNum
;
528 // mixer object is not generated automatically
529 fbp
->m_pMixer
= new AVC::FunctionBlockProcessingMixer
;
530 fbp
->m_pMixer
->m_mixerSetting
= setting
;
532 if ( !fbCmd
.fire() ) {
533 debugError( "cmd failed\n" );
537 if((fbCmd
.getResponse() != AVCCommand::eR_Accepted
)) {
538 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
541 return (fbCmd
.getResponse() == AVCCommand::eR_Accepted
);
545 Device::getProcessingFBMixerSingleCurrent(int id
, int iPlugNum
,
546 int iAChNum
, int oAChNum
)
548 AVC::FunctionBlockCmd
fbCmd(get1394Service(),
549 AVC::FunctionBlockCmd::eFBT_Processing
,
551 AVC::FunctionBlockCmd::eCA_Current
);
552 fbCmd
.setNodeId(getNodeId());
553 fbCmd
.setSubunitId(0x00);
554 fbCmd
.setCommandType(AVCCommand::eCT_Status
);
555 fbCmd
.setVerboseLevel( getDebugLevel() );
557 AVC::FunctionBlockProcessing
*fbp
= fbCmd
.m_pFBProcessing
;
558 fbp
->m_selectorLength
= 0x04;
559 fbp
->m_fbInputPlugNumber
= iPlugNum
;
560 fbp
->m_inputAudioChannelNumber
= iAChNum
;
561 fbp
->m_outputAudioChannelNumber
= oAChNum
;
563 // mixer object is not generated automatically
564 fbp
->m_pMixer
= new AVC::FunctionBlockProcessingMixer
;
566 if ( !fbCmd
.fire() ) {
567 debugError( "cmd failed\n" );
571 if( (fbCmd
.getResponse() != AVCCommand::eR_Implemented
) ) {
572 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
575 int16_t setting
= (int16_t)(fbp
->m_pMixer
->m_mixerSetting
);
583 debugOutput(DEBUG_LEVEL_NORMAL
, "Device is a BeBoB device\n");
584 GenericAVC::Device::showDevice();
589 Device::setVerboseLevel(int l
)
591 if (m_Mixer
) m_Mixer
->setVerboseLevel( l
);
592 GenericAVC::Device::setVerboseLevel( l
);
593 debugOutput( DEBUG_LEVEL_VERBOSE
, "Setting verbose level to %d...\n", l
);
597 Device::createSubunit(AVC::Unit
& unit
,
598 AVC::ESubunitType type
,
601 AVC::Subunit
* s
=NULL
;
604 s
=new BeBoB::SubunitAudio(unit
, id
);
607 s
=new BeBoB::SubunitMusic(unit
, id
);
613 if(s
) s
->setVerboseLevel(getDebugLevel());
619 Device::createPlug( AVC::Unit
* unit
,
620 AVC::Subunit
* subunit
,
621 AVC::function_block_type_t functionBlockType
,
622 AVC::function_block_type_t functionBlockId
,
623 AVC::Plug::EPlugAddressType plugAddressType
,
624 AVC::Plug::EPlugDirection plugDirection
,
625 AVC::plug_id_t plugId
,
629 Plug
*p
= new BeBoB::Plug( unit
,
637 if (p
) p
->setVerboseLevel(getDebugLevel());
642 Device::propagatePlugInfo() {
643 // we don't have to propagate since we discover things
645 debugOutput(DEBUG_LEVEL_VERBOSE
, "Skip plug info propagation\n");
650 Device::getConfigurationIdSampleRate()
652 ExtendedStreamFormatCmd
extStreamFormatCmd( get1394Service() );
653 UnitPlugAddress
unitPlugAddress( UnitPlugAddress::ePT_PCR
, 0 );
654 extStreamFormatCmd
.setPlugAddress( PlugAddress( PlugAddress::ePD_Input
,
655 PlugAddress::ePAM_Unit
,
658 extStreamFormatCmd
.setNodeId( getNodeId() );
659 extStreamFormatCmd
.setCommandType( AVCCommand::eCT_Status
);
660 extStreamFormatCmd
.setVerbose( getDebugLevel() );
662 if ( !extStreamFormatCmd
.fire() ) {
663 debugError( "Stream format command failed\n" );
667 FormatInformation
* formatInfo
=
668 extStreamFormatCmd
.getFormatInformation();
669 FormatInformationStreamsCompound
* compoundStream
670 = dynamic_cast< FormatInformationStreamsCompound
* > (
671 formatInfo
->m_streams
);
672 if ( compoundStream
) {
673 debugOutput(DEBUG_LEVEL_VERBOSE
, "Sample rate 0x%02x\n",
674 compoundStream
->m_samplingFrequency
);
675 return compoundStream
->m_samplingFrequency
;
678 debugError( "Could not retrieve sample rate\n" );
683 Device::getConfigurationIdNumberOfChannel( PlugAddress::EPlugDirection ePlugDirection
)
685 ExtendedPlugInfoCmd
extPlugInfoCmd( get1394Service() );
686 UnitPlugAddress
unitPlugAddress( UnitPlugAddress::ePT_PCR
,
688 extPlugInfoCmd
.setPlugAddress( PlugAddress( ePlugDirection
,
689 PlugAddress::ePAM_Unit
,
691 extPlugInfoCmd
.setNodeId( getNodeId() );
692 extPlugInfoCmd
.setCommandType( AVCCommand::eCT_Status
);
693 extPlugInfoCmd
.setVerbose( getDebugLevel() );
694 ExtendedPlugInfoInfoType
extendedPlugInfoInfoType(
695 ExtendedPlugInfoInfoType::eIT_NoOfChannels
);
696 extendedPlugInfoInfoType
.initialize();
697 extPlugInfoCmd
.setInfoType( extendedPlugInfoInfoType
);
699 if ( !extPlugInfoCmd
.fire() ) {
700 debugError( "Number of channels command failed\n" );
704 ExtendedPlugInfoInfoType
* infoType
= extPlugInfoCmd
.getInfoType();
706 && infoType
->m_plugNrOfChns
)
708 debugOutput(DEBUG_LEVEL_VERBOSE
, "Number of channels 0x%02x\n",
709 infoType
->m_plugNrOfChns
->m_nrOfChannels
);
710 return infoType
->m_plugNrOfChns
->m_nrOfChannels
;
713 debugError( "Could not retrieve number of channels\n" );
718 Device::getConfigurationIdSyncMode()
720 SignalSourceCmd
signalSourceCmd( get1394Service() );
721 SignalUnitAddress signalUnitAddr
;
722 signalUnitAddr
.m_plugId
= 0x01;
723 signalSourceCmd
.setSignalDestination( signalUnitAddr
);
724 signalSourceCmd
.setNodeId( getNodeId() );
725 signalSourceCmd
.setSubunitType( eST_Unit
);
726 signalSourceCmd
.setSubunitId( 0xff );
727 signalSourceCmd
.setVerbose( getDebugLevel() );
729 signalSourceCmd
.setCommandType( AVCCommand::eCT_Status
);
731 if ( !signalSourceCmd
.fire() ) {
732 debugError( "Signal source command failed\n" );
736 SignalAddress
* pSyncPlugSignalAddress
= signalSourceCmd
.getSignalSource();
737 SignalSubunitAddress
* pSyncPlugSubunitAddress
738 = dynamic_cast<SignalSubunitAddress
*>( pSyncPlugSignalAddress
);
739 if ( pSyncPlugSubunitAddress
) {
740 debugOutput(DEBUG_LEVEL_VERBOSE
, "Sync mode 0x%02x\n",
741 ( pSyncPlugSubunitAddress
->m_subunitType
<< 3
742 | pSyncPlugSubunitAddress
->m_subunitId
) << 8
743 | pSyncPlugSubunitAddress
->m_plugId
);
745 return ( pSyncPlugSubunitAddress
->m_subunitType
<< 3
746 | pSyncPlugSubunitAddress
->m_subunitId
) << 8
747 | pSyncPlugSubunitAddress
->m_plugId
;
750 SignalUnitAddress
* pSyncPlugUnitAddress
751 = dynamic_cast<SignalUnitAddress
*>( pSyncPlugSignalAddress
);
752 if ( pSyncPlugUnitAddress
) {
753 debugOutput(DEBUG_LEVEL_VERBOSE
, "Sync mode 0x%02x\n",
754 0xff << 8 | pSyncPlugUnitAddress
->m_plugId
);
756 return ( 0xff << 8 | pSyncPlugUnitAddress
->m_plugId
);
759 debugError( "Could not retrieve sync mode\n" );
764 Device::needsRediscovery()
766 // require rediscovery if the config id differs from the one saved
767 // in the previous discovery
768 return getConfigurationId() != m_last_discovery_config_id
;
772 Device::getConfigurationId()
774 // create a unique configuration id.
776 id
= getConfigurationIdSampleRate();
777 id
|= getConfigurationIdNumberOfChannel( PlugAddress::ePD_Input
) << 8;
778 id
|= getConfigurationIdNumberOfChannel( PlugAddress::ePD_Output
) << 16;
779 id
|= ((uint64_t)getConfigurationIdSyncMode()) << 24;
784 Device::serialize( std::string basePath
,
785 Util::IOSerialize
& ser
) const
788 result
= GenericAVC::Device::serialize( basePath
, ser
);
793 Device::deserialize( std::string basePath
,
794 Util::IODeserialize
& deser
)
797 result
= GenericAVC::Device::deserialize( basePath
, deser
);
802 Device::getCachePath()
804 std::string cachePath
;
807 string path
= CACHEDIR
;
808 if ( path
.size() && path
[0] == '~' ) {
809 path
.erase( 0, 1 ); // remove ~
810 path
.insert( 0, getenv( "HOME" ) ); // prepend the home path
813 if ( asprintf( &pCachePath
, "%s/cache/", path
.c_str() ) < 0 ) {
814 debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
815 cachePath
= "/var/cache/libffado/";
817 cachePath
= pCachePath
;
824 Device::loadFromCache()
826 std::string sDevicePath
= getCachePath() + getConfigRom().getGuidString();
829 asprintf(&configId
, "%016"PRIx64
"", getConfigurationId() );
831 debugError( "could not create id string\n" );
835 std::string sFileName
= sDevicePath
+ "/" + configId
+ ".xml";
837 debugOutput( DEBUG_LEVEL_NORMAL
, "filename %s\n", sFileName
.c_str() );
840 if ( stat( sFileName
.c_str(), &buf
) != 0 ) {
841 debugOutput( DEBUG_LEVEL_NORMAL
, "\"%s\" does not exist\n", sFileName
.c_str() );
844 if ( !S_ISREG( buf
.st_mode
) ) {
845 debugOutput( DEBUG_LEVEL_NORMAL
, "\"%s\" is not a regular file\n", sFileName
.c_str() );
850 Util::XMLDeserialize
deser( sFileName
, getDebugLevel() );
852 if (!deser
.isValid()) {
853 debugOutput( DEBUG_LEVEL_NORMAL
, "cache not valid: %s\n",
858 bool result
= deserialize( "", deser
);
860 debugOutput( DEBUG_LEVEL_NORMAL
, "could create valid bebob driver from %s\n",
874 // the path looks like this:
875 // PATH_TO_CACHE + GUID + CONFIGURATION_ID
876 string tmp_path
= getCachePath() + getConfigRom().getGuidString();
878 // the following piece should do something like
879 // 'mkdir -p some/path/with/some/dirs/which/do/not/exist'
880 vector
<string
> tokens
;
881 tokenize( tmp_path
, tokens
, "/" );
883 for ( vector
<string
>::const_iterator it
= tokens
.begin();
890 if ( stat( path
.c_str(), &buf
) == 0 ) {
891 if ( !S_ISDIR( buf
.st_mode
) ) {
892 debugError( "\"%s\" is not a directory\n", path
.c_str() );
896 if ( mkdir( path
.c_str(), S_IRWXU
| S_IRWXG
) != 0 ) {
897 debugError( "Could not create \"%s\" directory\n", path
.c_str() );
903 // come up with an unique file name for the current settings
905 asprintf(&configId
, "%016"PRIx64
"", BeBoB::Device::getConfigurationId() );
907 debugError( "Could not create id string\n" );
910 string filename
= path
+ "/" + configId
+ ".xml";
912 debugOutput( DEBUG_LEVEL_NORMAL
, "filename %s\n", filename
.c_str() );
914 Util::XMLSerialize
ser( filename
);
915 return serialize( "", ser
);
918 } // end of namespace