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/normal_avdevice.h"
40 #include "bebob/maudio/special_avdevice.h"
41 #include "bebob/presonus/firebox_avdevice.h"
42 #include "bebob/presonus/inspire1394_avdevice.h"
44 #include "libieee1394/configrom.h"
45 #include "libieee1394/ieee1394service.h"
47 #include "libavc/general/avc_plug_info.h"
48 #include "libavc/general/avc_extended_plug_info.h"
49 #include "libavc/general/avc_subunit_info.h"
50 #include "libavc/streamformat/avc_extended_stream_format.h"
51 #include "libutil/cmd_serialize.h"
52 #include "libavc/avc_definitions.h"
54 #include "debugmodule/debugmodule.h"
67 Device::Device( DeviceManager
& d
, std::auto_ptr
< ConfigRom
>( configRom
) )
68 : GenericAVC::Device( d
, configRom
)
69 , m_last_discovery_config_id ( 0xFFFFFFFFFFFFFFFFLLU
)
72 debugOutput( DEBUG_LEVEL_VERBOSE
, "Created BeBoB::Device (NodeID %d)\n",
73 getConfigRom().getNodeId() );
82 Device::probe( Util::Configuration
& c
, ConfigRom
& configRom
, bool generic
)
84 unsigned int vendorId
= configRom
.getNodeVendorId();
85 unsigned int modelId
= configRom
.getModelId();
88 /* M-Audio Special Devices don't support followed commands */
89 if ((vendorId
== FW_VENDORID_MAUDIO
) &&
90 ((modelId
== 0x00010071) || (modelId
== 0x00010091)))
93 // try a bebob-specific command to check for the firmware
94 ExtendedPlugInfoCmd
extPlugInfoCmd( configRom
.get1394Service() );
95 UnitPlugAddress
unitPlugAddress( UnitPlugAddress::ePT_PCR
,
96 configRom
.getNodeId() );
97 extPlugInfoCmd
.setPlugAddress( PlugAddress( PlugAddress::ePD_Input
,
98 PlugAddress::ePAM_Unit
,
100 extPlugInfoCmd
.setNodeId( configRom
.getNodeId() );
101 extPlugInfoCmd
.setCommandType( AVCCommand::eCT_Status
);
102 extPlugInfoCmd
.setVerbose( configRom
.getVerboseLevel() );
103 ExtendedPlugInfoInfoType
extendedPlugInfoInfoType(
104 ExtendedPlugInfoInfoType::eIT_NoOfChannels
);
105 extendedPlugInfoInfoType
.initialize();
106 extPlugInfoCmd
.setInfoType( extendedPlugInfoInfoType
);
108 if ( !extPlugInfoCmd
.fire() ) {
109 debugError( "Number of channels command failed\n" );
113 if((extPlugInfoCmd
.getResponse() != AVCCommand::eR_Implemented
)) {
114 // command not supported
118 ExtendedPlugInfoInfoType
* infoType
= extPlugInfoCmd
.getInfoType();
120 && infoType
->m_plugNrOfChns
)
126 // check if device is in supported devices list
127 Util::Configuration::VendorModelEntry vme
= c
.findDeviceVME( vendorId
, modelId
);
128 return c
.isValid(vme
) && vme
.driver
== Util::Configuration::eD_BeBoB
;
133 Device::createDevice(DeviceManager
& d
, std::auto_ptr
<ConfigRom
>( configRom
))
135 unsigned int vendorId
= configRom
->getNodeVendorId();
136 unsigned int modelId
= configRom
->getModelId();
139 case FW_VENDORID_MACKIE
:
140 if (modelId
== 0x00010065 ) {
141 return new Mackie::OnyxMixerDevice(d
, configRom
);
143 case FW_VENDORID_EDIROL
:
146 return new Edirol::EdirolFa101Device(d
, configRom
);
148 return new Edirol::EdirolFa66Device(d
, configRom
);
150 return new Device(d
, configRom
);
152 case FW_VENDORID_ESI
:
153 if (modelId
== 0x00010064) {
154 return new ESI::QuataFireDevice(d
, configRom
);
157 case FW_VENDORID_TERRATEC
:
160 return new Terratec::Phase88Device(d
, configRom
);
161 default: // return a plain BeBoB device
162 return new Device(d
, configRom
);
164 case FW_VENDORID_FOCUSRITE
:
168 return new Focusrite::SaffireProDevice(d
, configRom
);
170 return new Focusrite::SaffireDevice(d
, configRom
);
171 default: // return a plain BeBoB device
172 return new Device(d
, configRom
);
174 case FW_VENDORID_YAMAHA
:
178 return new Yamaha::GoDevice(d
, configRom
);
179 default: // return a plain BeBoB device
180 return new Device(d
, configRom
);
182 case FW_VENDORID_MAUDIO
:
184 case 0x0000000a: // Ozonic
185 case 0x00010046: // fw410
186 case 0x00010060: // Audiophile
187 case 0x00010062: // Solo
188 return new MAudio::Normal::Device(d
, configRom
, modelId
);
189 case 0x00010071: // Firewire 1814
190 case 0x00010091: // ProjectMix I/O
191 return new MAudio::Special::Device(d
, configRom
);
193 return new Device(d
, configRom
);
195 case FW_VENDORID_PRESONUS
:
198 return new Presonus::Firebox::Device(d
, configRom
);
200 return new Presonus::Inspire1394::Device(d
, configRom
);
202 return new Device(d
, configRom
);
205 return new Device(d
, configRom
);
210 #define BEBOB_CHECK_AND_ADD_SR(v, x) \
211 { if(supportsSamplingFrequency(x)) \
216 unsigned int vendorId
= getConfigRom().getNodeVendorId();
217 unsigned int modelId
= getConfigRom().getModelId();
219 Util::Configuration
&c
= getDeviceManager().getConfiguration();
220 Util::Configuration::VendorModelEntry vme
= c
.findDeviceVME( vendorId
, modelId
);
222 if (c
.isValid(vme
) && vme
.driver
== Util::Configuration::eD_BeBoB
) {
223 debugOutput( DEBUG_LEVEL_VERBOSE
, "found %s %s\n",
224 vme
.vendor_name
.c_str(),
225 vme
.model_name
.c_str());
227 debugWarning("Using generic BeBoB support for unsupported device '%s %s'\n",
228 getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
231 if ( !Unit::discover() ) {
232 debugError( "Could not discover unit\n" );
236 if((getAudioSubunit( 0 ) == NULL
)) {
237 debugError( "Unit doesn't have an Audio subunit.\n");
240 if((getMusicSubunit( 0 ) == NULL
)) {
241 debugError( "Unit doesn't have a Music subunit.\n");
246 debugWarning("Could not build mixer\n");
249 // keep track of the config id of this discovery
250 m_last_discovery_config_id
= getConfigurationId();
258 debugOutput(DEBUG_LEVEL_VERBOSE
, "Building a generic BeBoB mixer...\n");
260 // this removes the mixer if it already exists
261 // note: a mixer self-registers to it's parent
264 // create the mixer & register it
265 if(getAudioSubunit(0) == NULL
) {
266 debugWarning("Could not find audio subunit, mixer not available.\n");
269 m_Mixer
= new Mixer(*this);
271 if (m_Mixer
) m_Mixer
->setVerboseLevel(getDebugLevel());
272 return m_Mixer
!= NULL
;
276 Device::destroyMixer()
283 Device::setSelectorFBValue(int id
, int value
) {
284 FunctionBlockCmd
fbCmd( get1394Service(),
285 FunctionBlockCmd::eFBT_Selector
,
287 FunctionBlockCmd::eCA_Current
);
288 fbCmd
.setNodeId( getNodeId() );
289 fbCmd
.setSubunitId( 0x00 );
290 fbCmd
.setCommandType( AVCCommand::eCT_Control
);
291 fbCmd
.m_pFBSelector
->m_inputFbPlugNumber
= (value
& 0xFF);
292 fbCmd
.setVerboseLevel( getDebugLevel() );
294 if ( !fbCmd
.fire() ) {
295 debugError( "cmd failed\n" );
299 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
300 // Util::Cmd::CoutSerializer se;
301 // fbCmd.serialize( se );
304 if((fbCmd
.getResponse() != AVCCommand::eR_Accepted
)) {
305 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
308 return (fbCmd
.getResponse() == AVCCommand::eR_Accepted
);
312 Device::getSelectorFBValue(int id
) {
314 FunctionBlockCmd
fbCmd( get1394Service(),
315 FunctionBlockCmd::eFBT_Selector
,
317 FunctionBlockCmd::eCA_Current
);
318 fbCmd
.setNodeId( getNodeId() );
319 fbCmd
.setSubunitId( 0x00 );
320 fbCmd
.setCommandType( AVCCommand::eCT_Status
);
321 fbCmd
.m_pFBSelector
->m_inputFbPlugNumber
= 0xFF;
322 fbCmd
.setVerboseLevel( getDebugLevel() );
324 if ( !fbCmd
.fire() ) {
325 debugError( "cmd failed\n" );
329 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
330 // Util::Cmd::CoutSerializer se;
331 // fbCmd.serialize( se );
334 if((fbCmd
.getResponse() != AVCCommand::eR_Implemented
)) {
335 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
338 return fbCmd
.m_pFBSelector
->m_inputFbPlugNumber
;
342 Device::setFeatureFBVolumeCurrent(int id
, int channel
, int v
) {
344 FunctionBlockCmd
fbCmd( get1394Service(),
345 FunctionBlockCmd::eFBT_Feature
,
347 FunctionBlockCmd::eCA_Current
);
348 fbCmd
.setNodeId( getNodeId() );
349 fbCmd
.setSubunitId( 0x00 );
350 fbCmd
.setCommandType( AVCCommand::eCT_Control
);
351 fbCmd
.m_pFBFeature
->m_audioChannelNumber
= channel
;
352 fbCmd
.m_pFBFeature
->m_controlSelector
= FunctionBlockFeature::eCSE_Feature_Volume
;
353 AVC::FunctionBlockFeatureVolume vl
;
354 fbCmd
.m_pFBFeature
->m_pVolume
= vl
.clone();
355 fbCmd
.m_pFBFeature
->m_pVolume
->m_volume
= v
;
356 fbCmd
.setVerboseLevel( getDebugLevel() );
358 if ( !fbCmd
.fire() ) {
359 debugError( "cmd failed\n" );
363 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
364 // Util::Cmd::CoutSerializer se;
365 // fbCmd.serialize( se );
368 if((fbCmd
.getResponse() != AVCCommand::eR_Accepted
)) {
369 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
372 return (fbCmd
.getResponse() == AVCCommand::eR_Accepted
);
376 Device::getFeatureFBVolumeValue(int id
, int channel
, FunctionBlockCmd::EControlAttribute controlAttribute
)
378 FunctionBlockCmd
fbCmd( get1394Service(),
379 FunctionBlockCmd::eFBT_Feature
,
382 fbCmd
.setNodeId( getNodeId() );
383 fbCmd
.setSubunitId( 0x00 );
384 fbCmd
.setCommandType( AVCCommand::eCT_Status
);
385 fbCmd
.m_pFBFeature
->m_audioChannelNumber
= channel
;
386 fbCmd
.m_pFBFeature
->m_controlSelector
= FunctionBlockFeature::eCSE_Feature_Volume
;
387 AVC::FunctionBlockFeatureVolume vl
;
388 fbCmd
.m_pFBFeature
->m_pVolume
= vl
.clone();
389 fbCmd
.m_pFBFeature
->m_pVolume
->m_volume
= 0;
390 fbCmd
.setVerboseLevel( getDebugLevel() );
392 if ( !fbCmd
.fire() ) {
393 debugError( "cmd failed\n" );
397 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
398 // Util::Cmd::CoutSerializer se;
399 // fbCmd.serialize( se );
402 if((fbCmd
.getResponse() != AVCCommand::eR_Implemented
)) {
403 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
406 int16_t volume
=(int16_t)(fbCmd
.m_pFBFeature
->m_pVolume
->m_volume
);
412 Device::getFeatureFBVolumeMinimum(int id
, int channel
)
414 return getFeatureFBVolumeValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Minimum
);
418 Device::getFeatureFBVolumeMaximum(int id
, int channel
)
420 return getFeatureFBVolumeValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Maximum
);
424 Device::getFeatureFBVolumeCurrent(int id
, int channel
)
426 return getFeatureFBVolumeValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Current
);
430 Device::setFeatureFBLRBalanceCurrent(int id
, int channel
, int v
) {
432 FunctionBlockCmd
fbCmd( get1394Service(),
433 FunctionBlockCmd::eFBT_Feature
,
435 FunctionBlockCmd::eCA_Current
);
436 fbCmd
.setNodeId( getNodeId() );
437 fbCmd
.setSubunitId( 0x00 );
438 fbCmd
.setCommandType( AVCCommand::eCT_Control
);
439 fbCmd
.m_pFBFeature
->m_audioChannelNumber
= channel
;
440 fbCmd
.m_pFBFeature
->m_controlSelector
= FunctionBlockFeature::eCSE_Feature_LRBalance
;
441 AVC::FunctionBlockFeatureLRBalance bl
;
442 fbCmd
.m_pFBFeature
->m_pLRBalance
= bl
.clone();
443 fbCmd
.m_pFBFeature
->m_pLRBalance
->m_lrBalance
= v
;
444 fbCmd
.setVerboseLevel( getDebugLevel() );
446 if ( !fbCmd
.fire() ) {
447 debugError( "cmd failed\n" );
451 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
452 // Util::Cmd::CoutSerializer se;
453 // fbCmd.serialize( se );
456 if((fbCmd
.getResponse() != AVCCommand::eR_Accepted
)) {
457 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
460 return (fbCmd
.getResponse() == AVCCommand::eR_Accepted
);
464 Device::getFeatureFBLRBalanceValue(int id
, int channel
, FunctionBlockCmd::EControlAttribute controlAttribute
)
466 FunctionBlockCmd
fbCmd( get1394Service(),
467 FunctionBlockCmd::eFBT_Feature
,
470 fbCmd
.setNodeId( getNodeId() );
471 fbCmd
.setSubunitId( 0x00 );
472 fbCmd
.setCommandType( AVCCommand::eCT_Status
);
473 fbCmd
.m_pFBFeature
->m_audioChannelNumber
= channel
;
474 fbCmd
.m_pFBFeature
->m_controlSelector
= FunctionBlockFeature::eCSE_Feature_LRBalance
;
475 AVC::FunctionBlockFeatureLRBalance bl
;
476 fbCmd
.m_pFBFeature
->m_pLRBalance
= bl
.clone();
477 fbCmd
.m_pFBFeature
->m_pLRBalance
->m_lrBalance
= 0;
478 fbCmd
.setVerboseLevel( getDebugLevel() );
480 if ( !fbCmd
.fire() ) {
481 debugError( "cmd failed\n" );
485 // if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
486 // Util::Cmd::CoutSerializer se;
487 // fbCmd.serialize( se );
490 if((fbCmd
.getResponse() != AVCCommand::eR_Implemented
)) {
491 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
494 int16_t balance
=(int16_t)(fbCmd
.m_pFBFeature
->m_pLRBalance
->m_lrBalance
);
500 Device::getFeatureFBLRBalanceMinimum(int id
, int channel
)
502 return getFeatureFBLRBalanceValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Minimum
);
506 Device::getFeatureFBLRBalanceMaximum(int id
, int channel
)
508 return getFeatureFBLRBalanceValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Maximum
);
512 Device::getFeatureFBLRBalanceCurrent(int id
, int channel
)
514 return getFeatureFBLRBalanceValue(id
, channel
, AVC::FunctionBlockCmd::eCA_Current
);
518 Device::setProcessingFBMixerSingleCurrent(int id
, int iPlugNum
,
519 int iAChNum
, int oAChNum
,
522 AVC::FunctionBlockCmd
fbCmd(get1394Service(),
523 AVC::FunctionBlockCmd::eFBT_Processing
,
525 AVC::FunctionBlockCmd::eCA_Current
);
526 fbCmd
.setNodeId(getNodeId());
527 fbCmd
.setSubunitId(0x00);
528 fbCmd
.setCommandType(AVCCommand::eCT_Control
);
529 fbCmd
.setVerboseLevel( getDebugLevel() );
531 AVC::FunctionBlockProcessing
*fbp
= fbCmd
.m_pFBProcessing
;
532 fbp
->m_selectorLength
= 0x04;
533 fbp
->m_fbInputPlugNumber
= iPlugNum
;
534 fbp
->m_inputAudioChannelNumber
= iAChNum
;
535 fbp
->m_outputAudioChannelNumber
= oAChNum
;
537 // mixer object is not generated automatically
538 fbp
->m_pMixer
= new AVC::FunctionBlockProcessingMixer
;
539 fbp
->m_pMixer
->m_mixerSetting
= setting
;
541 if ( !fbCmd
.fire() ) {
542 debugError( "cmd failed\n" );
546 if((fbCmd
.getResponse() != AVCCommand::eR_Accepted
)) {
547 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
550 return (fbCmd
.getResponse() == AVCCommand::eR_Accepted
);
554 Device::getProcessingFBMixerSingleCurrent(int id
, int iPlugNum
,
555 int iAChNum
, int oAChNum
)
557 AVC::FunctionBlockCmd
fbCmd(get1394Service(),
558 AVC::FunctionBlockCmd::eFBT_Processing
,
560 AVC::FunctionBlockCmd::eCA_Current
);
561 fbCmd
.setNodeId(getNodeId());
562 fbCmd
.setSubunitId(0x00);
563 fbCmd
.setCommandType(AVCCommand::eCT_Status
);
564 fbCmd
.setVerboseLevel( getDebugLevel() );
566 AVC::FunctionBlockProcessing
*fbp
= fbCmd
.m_pFBProcessing
;
567 fbp
->m_selectorLength
= 0x04;
568 fbp
->m_fbInputPlugNumber
= iPlugNum
;
569 fbp
->m_inputAudioChannelNumber
= iAChNum
;
570 fbp
->m_outputAudioChannelNumber
= oAChNum
;
572 // mixer object is not generated automatically
573 fbp
->m_pMixer
= new AVC::FunctionBlockProcessingMixer
;
575 if ( !fbCmd
.fire() ) {
576 debugError( "cmd failed\n" );
580 if( (fbCmd
.getResponse() != AVCCommand::eR_Implemented
) ) {
581 debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
584 int16_t setting
= (int16_t)(fbp
->m_pMixer
->m_mixerSetting
);
592 debugOutput(DEBUG_LEVEL_NORMAL
, "Device is a BeBoB device\n");
593 GenericAVC::Device::showDevice();
598 Device::setVerboseLevel(int l
)
600 if (m_Mixer
) m_Mixer
->setVerboseLevel( l
);
601 GenericAVC::Device::setVerboseLevel( l
);
602 debugOutput( DEBUG_LEVEL_VERBOSE
, "Setting verbose level to %d...\n", l
);
606 Device::createSubunit(AVC::Unit
& unit
,
607 AVC::ESubunitType type
,
610 AVC::Subunit
* s
=NULL
;
613 s
=new BeBoB::SubunitAudio(unit
, id
);
616 s
=new BeBoB::SubunitMusic(unit
, id
);
622 if(s
) s
->setVerboseLevel(getDebugLevel());
628 Device::createPlug( AVC::Unit
* unit
,
629 AVC::Subunit
* subunit
,
630 AVC::function_block_type_t functionBlockType
,
631 AVC::function_block_type_t functionBlockId
,
632 AVC::Plug::EPlugAddressType plugAddressType
,
633 AVC::Plug::EPlugDirection plugDirection
,
634 AVC::plug_id_t plugId
,
638 Plug
*p
= new BeBoB::Plug( unit
,
646 if (p
) p
->setVerboseLevel(getDebugLevel());
651 Device::propagatePlugInfo() {
652 // we don't have to propagate since we discover things
654 debugOutput(DEBUG_LEVEL_VERBOSE
, "Skip plug info propagation\n");
659 Device::getConfigurationIdSampleRate()
661 ExtendedStreamFormatCmd
extStreamFormatCmd( get1394Service() );
662 UnitPlugAddress
unitPlugAddress( UnitPlugAddress::ePT_PCR
, 0 );
663 extStreamFormatCmd
.setPlugAddress( PlugAddress( PlugAddress::ePD_Input
,
664 PlugAddress::ePAM_Unit
,
667 extStreamFormatCmd
.setNodeId( getNodeId() );
668 extStreamFormatCmd
.setCommandType( AVCCommand::eCT_Status
);
669 extStreamFormatCmd
.setVerbose( getDebugLevel() );
671 if ( !extStreamFormatCmd
.fire() ) {
672 debugError( "Stream format command failed\n" );
676 FormatInformation
* formatInfo
=
677 extStreamFormatCmd
.getFormatInformation();
678 FormatInformationStreamsCompound
* compoundStream
679 = dynamic_cast< FormatInformationStreamsCompound
* > (
680 formatInfo
->m_streams
);
681 if ( compoundStream
) {
682 debugOutput(DEBUG_LEVEL_VERBOSE
, "Sample rate 0x%02x\n",
683 compoundStream
->m_samplingFrequency
);
684 return compoundStream
->m_samplingFrequency
;
687 debugError( "Could not retrieve sample rate\n" );
692 Device::getConfigurationIdNumberOfChannel( PlugAddress::EPlugDirection ePlugDirection
)
694 ExtendedPlugInfoCmd
extPlugInfoCmd( get1394Service() );
695 UnitPlugAddress
unitPlugAddress( UnitPlugAddress::ePT_PCR
,
697 extPlugInfoCmd
.setPlugAddress( PlugAddress( ePlugDirection
,
698 PlugAddress::ePAM_Unit
,
700 extPlugInfoCmd
.setNodeId( getNodeId() );
701 extPlugInfoCmd
.setCommandType( AVCCommand::eCT_Status
);
702 extPlugInfoCmd
.setVerbose( getDebugLevel() );
703 ExtendedPlugInfoInfoType
extendedPlugInfoInfoType(
704 ExtendedPlugInfoInfoType::eIT_NoOfChannels
);
705 extendedPlugInfoInfoType
.initialize();
706 extPlugInfoCmd
.setInfoType( extendedPlugInfoInfoType
);
708 if ( !extPlugInfoCmd
.fire() ) {
709 debugError( "Number of channels command failed\n" );
713 ExtendedPlugInfoInfoType
* infoType
= extPlugInfoCmd
.getInfoType();
715 && infoType
->m_plugNrOfChns
)
717 debugOutput(DEBUG_LEVEL_VERBOSE
, "Number of channels 0x%02x\n",
718 infoType
->m_plugNrOfChns
->m_nrOfChannels
);
719 return infoType
->m_plugNrOfChns
->m_nrOfChannels
;
722 debugError( "Could not retrieve number of channels\n" );
727 Device::getConfigurationIdSyncMode()
729 SignalSourceCmd
signalSourceCmd( get1394Service() );
730 SignalUnitAddress signalUnitAddr
;
731 signalUnitAddr
.m_plugId
= 0x01;
732 signalSourceCmd
.setSignalDestination( signalUnitAddr
);
733 signalSourceCmd
.setNodeId( getNodeId() );
734 signalSourceCmd
.setSubunitType( eST_Unit
);
735 signalSourceCmd
.setSubunitId( 0xff );
736 signalSourceCmd
.setVerbose( getDebugLevel() );
738 signalSourceCmd
.setCommandType( AVCCommand::eCT_Status
);
740 if ( !signalSourceCmd
.fire() ) {
741 debugError( "Signal source command failed\n" );
745 SignalAddress
* pSyncPlugSignalAddress
= signalSourceCmd
.getSignalSource();
746 SignalSubunitAddress
* pSyncPlugSubunitAddress
747 = dynamic_cast<SignalSubunitAddress
*>( pSyncPlugSignalAddress
);
748 if ( pSyncPlugSubunitAddress
) {
749 debugOutput(DEBUG_LEVEL_VERBOSE
, "Sync mode 0x%02x\n",
750 ( pSyncPlugSubunitAddress
->m_subunitType
<< 3
751 | pSyncPlugSubunitAddress
->m_subunitId
) << 8
752 | pSyncPlugSubunitAddress
->m_plugId
);
754 return ( pSyncPlugSubunitAddress
->m_subunitType
<< 3
755 | pSyncPlugSubunitAddress
->m_subunitId
) << 8
756 | pSyncPlugSubunitAddress
->m_plugId
;
759 SignalUnitAddress
* pSyncPlugUnitAddress
760 = dynamic_cast<SignalUnitAddress
*>( pSyncPlugSignalAddress
);
761 if ( pSyncPlugUnitAddress
) {
762 debugOutput(DEBUG_LEVEL_VERBOSE
, "Sync mode 0x%02x\n",
763 0xff << 8 | pSyncPlugUnitAddress
->m_plugId
);
765 return ( 0xff << 8 | pSyncPlugUnitAddress
->m_plugId
);
768 debugError( "Could not retrieve sync mode\n" );
773 Device::needsRediscovery()
775 // require rediscovery if the config id differs from the one saved
776 // in the previous discovery
777 return getConfigurationId() != m_last_discovery_config_id
;
781 Device::getConfigurationId()
783 // create a unique configuration id.
785 id
= getConfigurationIdSampleRate();
786 id
|= getConfigurationIdNumberOfChannel( PlugAddress::ePD_Input
) << 8;
787 id
|= getConfigurationIdNumberOfChannel( PlugAddress::ePD_Output
) << 16;
788 id
|= ((uint64_t)getConfigurationIdSyncMode()) << 24;
793 Device::serialize( std::string basePath
,
794 Util::IOSerialize
& ser
) const
797 result
= GenericAVC::Device::serialize( basePath
, ser
);
802 Device::deserialize( std::string basePath
,
803 Util::IODeserialize
& deser
)
806 result
= GenericAVC::Device::deserialize( basePath
, deser
);
811 Device::getCachePath()
813 std::string cachePath
;
816 string path
= CACHEDIR
;
817 if ( path
.size() && path
[0] == '~' ) {
818 path
.erase( 0, 1 ); // remove ~
819 path
.insert( 0, getenv( "HOME" ) ); // prepend the home path
822 if ( asprintf( &pCachePath
, "%s/cache/", path
.c_str() ) < 0 ) {
823 debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
824 cachePath
= "/var/cache/libffado/";
826 cachePath
= pCachePath
;
833 Device::loadFromCache()
835 std::string sDevicePath
= getCachePath() + getConfigRom().getGuidString();
838 asprintf(&configId
, "%016"PRIx64
"", getConfigurationId() );
840 debugError( "could not create id string\n" );
844 std::string sFileName
= sDevicePath
+ "/" + configId
+ ".xml";
846 debugOutput( DEBUG_LEVEL_NORMAL
, "filename %s\n", sFileName
.c_str() );
849 if ( stat( sFileName
.c_str(), &buf
) != 0 ) {
850 debugOutput( DEBUG_LEVEL_NORMAL
, "\"%s\" does not exist\n", sFileName
.c_str() );
853 if ( !S_ISREG( buf
.st_mode
) ) {
854 debugOutput( DEBUG_LEVEL_NORMAL
, "\"%s\" is not a regular file\n", sFileName
.c_str() );
859 Util::XMLDeserialize
deser( sFileName
, getDebugLevel() );
861 if (!deser
.isValid()) {
862 debugOutput( DEBUG_LEVEL_NORMAL
, "cache not valid: %s\n",
867 bool result
= deserialize( "", deser
);
869 debugOutput( DEBUG_LEVEL_NORMAL
, "could create valid bebob driver from %s\n",
883 // the path looks like this:
884 // PATH_TO_CACHE + GUID + CONFIGURATION_ID
885 string tmp_path
= getCachePath() + getConfigRom().getGuidString();
887 // the following piece should do something like
888 // 'mkdir -p some/path/with/some/dirs/which/do/not/exist'
889 vector
<string
> tokens
;
890 tokenize( tmp_path
, tokens
, "/" );
892 for ( vector
<string
>::const_iterator it
= tokens
.begin();
899 if ( stat( path
.c_str(), &buf
) == 0 ) {
900 if ( !S_ISDIR( buf
.st_mode
) ) {
901 debugError( "\"%s\" is not a directory\n", path
.c_str() );
905 if ( mkdir( path
.c_str(), S_IRWXU
| S_IRWXG
) != 0 ) {
906 debugError( "Could not create \"%s\" directory\n", path
.c_str() );
912 // come up with an unique file name for the current settings
914 asprintf(&configId
, "%016"PRIx64
"", BeBoB::Device::getConfigurationId() );
916 debugError( "Could not create id string\n" );
919 string filename
= path
+ "/" + configId
+ ".xml";
921 debugOutput( DEBUG_LEVEL_NORMAL
, "filename %s\n", filename
.c_str() );
923 Util::XMLSerialize
ser( filename
);
924 return serialize( "", ser
);
927 } // end of namespace