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

Revision 2440, 25.8 kB (checked in by mocchi, 6 years ago)

[BeBoB/Yamaha?] assign Yamaha's GO series to specific class

Yamaha devices based on BeBoB chipset has device specific operation to control its clock source. Currently 'GO 44' and 'GO 46' is confirmed to be such a device.

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