root/trunk/libffado/src/genericavc/avc_avdevice.cpp

Revision 745, 22.7 kB (checked in by ppalmers, 13 years ago)

implement clock source selection for DICE EVM

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  * Copyright (C) 2005-2007 by Daniel Wagner
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "genericavc/avc_avdevice.h"
26
27 #include "libieee1394/configrom.h"
28 #include "libieee1394/ieee1394service.h"
29
30 #include "libavc/avc_definitions.h"
31 #include "libavc/general/avc_plug_info.h"
32 #include "libavc/general/avc_extended_plug_info.h"
33
34 #include "debugmodule/debugmodule.h"
35
36 #include "config.h"
37
38 #include <string>
39 #include <stdint.h>
40 #include <assert.h>
41 #include <netinet/in.h>
42 #include <iostream>
43 #include <sstream>
44
45 #include <libraw1394/csr.h>
46
47 using namespace AVC;
48
49 namespace GenericAVC {
50
51 IMPL_DEBUG_MODULE( AvDevice, AvDevice, DEBUG_LEVEL_NORMAL );
52
53 AvDevice::AvDevice(std::auto_ptr<ConfigRom>( configRom ))
54     : FFADODevice( configRom )
55 {
56     debugOutput( DEBUG_LEVEL_VERBOSE, "Created GenericAVC::AvDevice (NodeID %d)\n",
57                  getConfigRom().getNodeId() );
58     addOption(Util::OptionContainer::Option("snoopMode",false));
59 }
60
61 bool
62 AvDevice::probe( ConfigRom& configRom )
63 {
64     unsigned int vendorId = configRom.getNodeVendorId();
65     unsigned int modelId = configRom.getModelId();
66
67     GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_genericavc.txt" );
68     if ( vendorModel.parse() ) {
69         return vendorModel.isPresent( vendorId, modelId );
70     }
71
72     return false;
73 }
74
75 FFADODevice *
76 AvDevice::createDevice(std::auto_ptr<ConfigRom>( configRom ))
77 {
78     return new AvDevice(configRom );
79 }
80
81 bool
82 AvDevice::discover()
83 {
84     // check if we already have a valid VendorModel entry
85     // e.g. because a subclass called this function
86     if (!GenericAVC::VendorModel::isValid(m_model)) {
87         unsigned int vendorId = getConfigRom().getNodeVendorId();
88         unsigned int modelId = getConfigRom().getModelId();
89
90         GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_genericavc.txt" );
91         if ( vendorModel.parse() ) {
92             m_model = vendorModel.find( vendorId, modelId );
93         }
94
95         if (!GenericAVC::VendorModel::isValid(m_model)) {
96             return false;
97         }
98         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
99                 m_model.vendor_name.c_str(), m_model.model_name.c_str());
100     }
101
102     if ( !Unit::discover() ) {
103         debugError( "Could not discover unit\n" );
104         return false;
105     }
106
107     if((getAudioSubunit( 0 ) == NULL)) {
108         debugError( "Unit doesn't have an Audio subunit.\n");
109         return false;
110     }
111     if((getMusicSubunit( 0 ) == NULL)) {
112         debugError( "Unit doesn't have a Music subunit.\n");
113         return false;
114     }
115
116     return true;
117 }
118
119 void
120 AvDevice::setVerboseLevel(int l)
121 {
122     setDebugLevel(l);
123     m_pPlugManager->setVerboseLevel(l);
124     FFADODevice::setVerboseLevel(l);
125     AVC::Unit::setVerboseLevel(l);
126     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
127 }
128
129 int
130 AvDevice::getSamplingFrequency( ) {
131     AVC::Plug* inputPlug = getPlugById( m_pcrPlugs, Plug::eAPD_Input, 0 );
132     if ( !inputPlug ) {
133         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
134         return false;
135     }
136     AVC::Plug* outputPlug = getPlugById( m_pcrPlugs, Plug::eAPD_Output, 0 );
137     if ( !outputPlug ) {
138         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
139         return false;
140     }
141
142     int samplerate_playback=inputPlug->getSampleRate();
143     int samplerate_capture=outputPlug->getSampleRate();
144
145     if (samplerate_playback != samplerate_capture) {
146         debugWarning("Samplerates for capture and playback differ!\n");
147     }
148     return samplerate_capture;
149 }
150
151 bool
152 AvDevice::setSamplingFrequency( int s )
153 {
154     bool snoopMode=false;
155     if(!getOption("snoopMode", snoopMode)) {
156         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
157     }
158
159     if(snoopMode) {
160         int current_sr=getSamplingFrequency();
161         if (current_sr != s ) {
162             debugError("In snoop mode it is impossible to set the sample rate.\n");
163             debugError("Please start the client with the correct setting.\n");
164             return false;
165         }
166         return true;
167     } else {
168         AVC::Plug* plug = getPlugById( m_pcrPlugs, Plug::eAPD_Input, 0 );
169         if ( !plug ) {
170             debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
171             return false;
172         }
173
174         if ( !plug->setSampleRate( s ) )
175         {
176             debugError( "setSampleRate: Setting sample rate failed\n" );
177             return false;
178         }
179
180         plug = getPlugById( m_pcrPlugs, Plug::eAPD_Output,  0 );
181         if ( !plug ) {
182             debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
183             return false;
184         }
185
186         if ( !plug->setSampleRate( s ) )
187         {
188             debugError( "setSampleRate: Setting sample rate failed\n" );
189             return false;
190         }
191
192         debugOutput( DEBUG_LEVEL_VERBOSE,
193                      "setSampleRate: Set sample rate to %d\n",
194                      s );
195         return true;
196     }
197     // not executable
198     return false;
199
200 }
201
202 FFADODevice::ClockSourceVector
203 AvDevice::getSupportedClockSources() {
204     FFADODevice::ClockSourceVector r;
205
206     PlugVector syncMSUInputPlugs = m_pPlugManager->getPlugsByType(
207         eST_Music,
208         0,
209         0xff,
210         0xff,
211         Plug::eAPA_SubunitPlug,
212         Plug::eAPD_Input,
213         Plug::eAPT_Sync );
214     if ( !syncMSUInputPlugs.size() ) {
215         debugWarning( "No sync input plug for MSU subunit found\n" );
216         return r;
217     }
218
219     for ( SyncInfoVector::const_iterator it
220               = getSyncInfos().begin();
221           it != getSyncInfos().end();
222           ++it )
223     {
224         const SyncInfo si=*it;
225
226         // check if the destination is a MSU input plug
227         bool found=false;
228         for ( PlugVector::const_iterator it2 = syncMSUInputPlugs.begin();
229               it2 != syncMSUInputPlugs.end();
230               ++it2 )
231         {
232             AVC::Plug* msuPlug = *it2;
233             found |= (msuPlug == si.m_destination);
234         }
235
236         if (found) {
237             ClockSource s=syncInfoToClockSource(*it);
238             r.push_back(s);
239         }
240     }
241
242     return r;
243 }
244
245 bool
246 AvDevice::setActiveClockSource(ClockSource s) {
247     Plug *src=m_pPlugManager->getPlug( s.id );
248     if (!src) {
249         debugError("Could not find plug with id %d\n", s.id);
250         return false;
251     }
252
253     for ( SyncInfoVector::const_iterator it
254               = getSyncInfos().begin();
255           it != getSyncInfos().end();
256           ++it )
257     {
258         const SyncInfo si=*it;
259
260         if (si.m_source==src) {
261             return setActiveSync(si);
262         }
263     }
264
265     return false;
266 }
267
268 FFADODevice::ClockSource
269 AvDevice::getActiveClockSource() {
270     const SyncInfo* si=getActiveSyncInfo();
271     if ( !si ) {
272         debugError( "Could not retrieve active sync information\n" );
273         ClockSource s;
274         s.type=eCT_Invalid;
275         return s;
276     }
277     debugOutput(DEBUG_LEVEL_VERBOSE, "Active Sync mode:  %s\n", si->m_description.c_str() );
278
279     return syncInfoToClockSource(*si);
280 }
281
282 FFADODevice::ClockSource
283 AvDevice::syncInfoToClockSource(const SyncInfo& si) {
284     ClockSource s;
285
286     // the description is easy
287     // it can be that we overwrite it later
288     s.description=si.m_description;
289
290     // FIXME: always valid at the moment
291     s.valid=true;
292
293     assert(si.m_source);
294     s.id=si.m_source->getGlobalId();
295
296     // now figure out what type this is
297     switch(si.m_source->getPlugType()) {
298         case Plug::eAPT_IsoStream:
299             s.type=eCT_SytMatch;
300             break;
301         case Plug::eAPT_Sync:
302             if(si.m_source->getPlugAddressType() == Plug::eAPA_PCR) {
303                 s.type=eCT_SytStream; // this is logical
304             } else if(si.m_source->getPlugAddressType() == Plug::eAPA_SubunitPlug) {
305                 s.type=eCT_Internal; // this assumes some stuff
306             } else if(si.m_source->getPlugAddressType() == Plug::eAPA_ExternalPlug) {
307                 std::string plugname=si.m_source->getName();
308                 s.description=plugname;
309                 // this is basically due to Focusrites interpretation
310                 if(plugname.find( "SPDIF", 0 ) != string::npos) {
311                     s.type=eCT_SPDIF; // this assumes the name will tell us
312                 } else {
313                     s.type=eCT_WordClock; // this assumes a whole lot more
314                 }
315             } else {
316                 s.type=eCT_Invalid;
317             }
318             break;
319         case Plug::eAPT_Digital:
320             if(si.m_source->getPlugAddressType() == Plug::eAPA_ExternalPlug) {
321                 std::string plugname=si.m_source->getName();
322                 s.description=plugname;
323                 // this is basically due to Focusrites interpretation
324                 if(plugname.find( "ADAT", 0 ) != string::npos) {
325                     s.type=eCT_ADAT; // this assumes the name will tell us
326                 } else if(plugname.find( "SPDIF", 0 ) != string::npos) {
327                     s.type=eCT_SPDIF; // this assumes the name will tell us
328                 } else {
329                     s.type=eCT_WordClock; // this assumes a whole lot more
330                 }
331             } else {
332                 s.type=eCT_Invalid;
333             }
334             break;
335         default:
336             s.type=eCT_Invalid; break;
337     }
338
339     // is it active?
340     const SyncInfo* active=getActiveSyncInfo();
341     if (active) {
342         if ((active->m_source == si.m_source)
343            && (active->m_destination == si.m_destination))
344            s.active=true;
345         else s.active=false;
346     } else s.active=false;
347
348     return s;
349 }
350
351 bool
352 AvDevice::lock() {
353     bool snoopMode=false;
354     if(!getOption("snoopMode", snoopMode)) {
355         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
356     }
357
358     if (snoopMode) {
359         // don't lock
360     } else {
361 //         return Unit::reserve(4);
362     }
363
364     return true;
365 }
366
367 bool
368 AvDevice::unlock() {
369     bool snoopMode=false;
370     if(!getOption("snoopMode", snoopMode)) {
371         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
372     }
373
374     if (snoopMode) {
375         // don't unlock
376     } else {
377 //         return Unit::reserve(0);
378     }
379     return true;
380 }
381
382 void
383 AvDevice::showDevice()
384 {
385     FFADODevice::showDevice();
386
387     AVC::Unit::show();
388     flushDebugOutput();
389 }
390
391 bool
392 AvDevice::prepare() {
393     bool snoopMode=false;
394     if(!getOption("snoopMode", snoopMode)) {
395         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
396     }
397
398     ///////////
399     // get plugs
400
401     AVC::Plug* inputPlug = getPlugById( m_pcrPlugs, Plug::eAPD_Input, 0 );
402     if ( !inputPlug ) {
403         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
404         return false;
405     }
406     AVC::Plug* outputPlug = getPlugById( m_pcrPlugs, Plug::eAPD_Output, 0 );
407     if ( !outputPlug ) {
408         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
409         return false;
410     }
411
412     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing receive processor...\n");
413     // create & add streamprocessors
414     Streaming::StreamProcessor *p;
415
416     if ( outputPlug->getNrOfChannels() == 0 ) {
417         debugError("Receive plug has no channels\n");
418         return false;
419     }
420     p=new Streaming::AmdtpReceiveStreamProcessor(
421                              get1394Service().getPort(),
422                              outputPlug->getNrOfChannels());
423
424     if(!p->init()) {
425         debugFatal("Could not initialize receive processor!\n");
426         delete p;
427         return false;
428     }
429
430     if (!addPlugToProcessor(*outputPlug,p,
431         Streaming::Port::E_Capture)) {
432         debugFatal("Could not add plug to processor!\n");
433         delete p;
434         return false;
435     }
436
437     m_receiveProcessors.push_back(p);
438
439     // do the transmit processor
440     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing transmit processor%s...\n",
441             (snoopMode?" in snoop mode":""));
442     if (snoopMode) {
443         // we are snooping, so this is receive too.
444         p=new Streaming::AmdtpReceiveStreamProcessor(
445                                   get1394Service().getPort(),
446                                   inputPlug->getNrOfChannels());
447     } else {
448         p=new Streaming::AmdtpTransmitStreamProcessor(
449                                 get1394Service().getPort(),
450                                 inputPlug->getNrOfChannels());
451     }
452
453     if(!p->init()) {
454         debugFatal("Could not initialize transmit processor %s!\n",
455             (snoopMode?" in snoop mode":""));
456         delete p;
457         return false;
458     }
459
460     if (snoopMode) {
461         if (!addPlugToProcessor(*inputPlug,p,
462             Streaming::Port::E_Capture)) {
463             debugFatal("Could not add plug to processor!\n");
464             return false;
465         }
466     } else {
467         if (!addPlugToProcessor(*inputPlug,p,
468             Streaming::Port::E_Playback)) {
469             debugFatal("Could not add plug to processor!\n");
470             return false;
471         }
472     }
473
474     // we put this SP into the transmit SP vector,
475     // no matter if we are in snoop mode or not
476     // this allows us to find out what direction
477     // a certain stream should have.
478     m_transmitProcessors.push_back(p);
479
480     return true;
481 }
482
483 bool
484 AvDevice::addPlugToProcessor(
485     AVC::Plug& plug,
486     Streaming::StreamProcessor *processor,
487     Streaming::AmdtpAudioPort::E_Direction direction) {
488
489     std::string id=std::string("dev?");
490     if(!getOption("id", id)) {
491         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
492     }
493
494     Plug::ClusterInfoVector& clusterInfos = plug.getClusterInfos();
495     for ( Plug::ClusterInfoVector::const_iterator it = clusterInfos.begin();
496           it != clusterInfos.end();
497           ++it )
498     {
499         const Plug::ClusterInfo* clusterInfo = &( *it );
500
501         Plug::ChannelInfoVector channelInfos = clusterInfo->m_channelInfos;
502         for ( Plug::ChannelInfoVector::const_iterator it = channelInfos.begin();
503               it != channelInfos.end();
504               ++it )
505         {
506             const Plug::ChannelInfo* channelInfo = &( *it );
507             std::ostringstream portname;
508
509             portname << id << "_" << channelInfo->m_name;
510
511             Streaming::Port *p=NULL;
512             switch(clusterInfo->m_portType) {
513             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Speaker:
514             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Headphone:
515             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Microphone:
516             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Line:
517             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Analog:
518                 debugOutput(DEBUG_LEVEL_VERBOSE, " Adding audio channel %s (pos=0x%02X, loc=0x%02X)\n",
519                     channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location);
520                 p=new Streaming::AmdtpAudioPort(
521                         portname.str(),
522                         direction,
523                         channelInfo->m_streamPosition,
524                         channelInfo->m_location,
525                         Streaming::AmdtpPortInfo::E_MBLA
526                 );
527                 break;
528
529             case ExtendedPlugInfoClusterInfoSpecificData::ePT_MIDI:
530                 debugOutput(DEBUG_LEVEL_VERBOSE, " Adding MIDI channel %s (pos=0x%02X, loc=0x%02X)\n",
531                     channelInfo->m_name.c_str(), channelInfo->m_streamPosition, processor->getPortCount(Streaming::Port::E_Midi));
532                 p=new Streaming::AmdtpMidiPort(
533                         portname.str(),
534                         direction,
535                         channelInfo->m_streamPosition,
536                         // Workaround for out-of-spec hardware
537                         // should be:
538                         // channelInfo->m_location,
539                         // but now we renumber the midi channels' location as they
540                         // are discovered
541                         processor->getPortCount(Streaming::Port::E_Midi),
542                         Streaming::AmdtpPortInfo::E_Midi
543                 );
544
545                 break;
546             case ExtendedPlugInfoClusterInfoSpecificData::ePT_SPDIF:
547             case ExtendedPlugInfoClusterInfoSpecificData::ePT_ADAT:
548             case ExtendedPlugInfoClusterInfoSpecificData::ePT_TDIF:
549             case ExtendedPlugInfoClusterInfoSpecificData::ePT_MADI:
550             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Digital:
551                 debugOutput(DEBUG_LEVEL_VERBOSE, " Adding digital audio channel %s (pos=0x%02X, loc=0x%02X)\n",
552                     channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location);
553                 p=new Streaming::AmdtpAudioPort(
554                         portname.str(),
555                         direction,
556                         channelInfo->m_streamPosition,
557                         channelInfo->m_location,
558                         Streaming::AmdtpPortInfo::E_MBLA
559                 );
560                 break;
561
562             case ExtendedPlugInfoClusterInfoSpecificData::ePT_NoType:
563             default:
564             // unsupported
565                 break;
566             }
567
568             if (!p) {
569                 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->m_name.c_str());
570             } else {
571
572                 if (!processor->addPort(p)) {
573                     debugWarning("Could not register port with stream processor\n");
574                     return false;
575                 }
576             }
577          }
578     }
579     return true;
580 }
581
582 int
583 AvDevice::getStreamCount() {
584     return m_receiveProcessors.size() + m_transmitProcessors.size();
585     //return 1;
586 }
587
588 Streaming::StreamProcessor *
589 AvDevice::getStreamProcessorByIndex(int i) {
590
591     if (i<(int)m_receiveProcessors.size()) {
592         return m_receiveProcessors.at(i);
593     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
594         return m_transmitProcessors.at(i-m_receiveProcessors.size());
595     }
596
597     return NULL;
598 }
599
600 bool
601 AvDevice::startStreamByIndex(int i) {
602     int iso_channel=-1;
603     bool snoopMode=false;
604     if(!getOption("snoopMode", snoopMode)) {
605         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
606     }
607
608     if (i<(int)m_receiveProcessors.size()) {
609         int n=i;
610         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
611
612         if(snoopMode) { // a stream from the device to another host
613             // FIXME: put this into a decent framework!
614             // we should check the oPCR[n] on the device
615             struct iec61883_oPCR opcr;
616             if (iec61883_get_oPCRX(
617                     get1394Service().getHandle(),
618                     getConfigRom().getNodeId() | 0xffc0,
619                     (quadlet_t *)&opcr,
620                     n)) {
621
622                 debugWarning("Error getting the channel for SP %d\n",i);
623                 return false;
624             }
625
626             iso_channel=opcr.channel;
627         } else {
628             iso_channel=get1394Service().allocateIsoChannelCMP(
629                 getConfigRom().getNodeId() | 0xffc0, n,
630                 get1394Service().getLocalNodeId()| 0xffc0, -1);
631         }
632         if (iso_channel<0) {
633             debugError("Could not allocate ISO channel for SP %d\n",i);
634             return false;
635         }
636
637         debugOutput(DEBUG_LEVEL_VERBOSE, "Started SP %d on channel %d\n",i,iso_channel);
638
639         p->setChannel(iso_channel);
640         return true;
641
642     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
643         int n=i-m_receiveProcessors.size();
644         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
645
646         if(snoopMode) { // a stream from another host to the device
647             // FIXME: put this into a decent framework!
648             // we should check the iPCR[n] on the device
649             struct iec61883_iPCR ipcr;
650             if (iec61883_get_iPCRX(
651                     get1394Service().getHandle(),
652                     getConfigRom().getNodeId() | 0xffc0,
653                     (quadlet_t *)&ipcr,
654                     n)) {
655
656                 debugWarning("Error getting the channel for SP %d\n",i);
657                 return false;
658             }
659
660             iso_channel=ipcr.channel;
661
662         } else {
663             iso_channel=get1394Service().allocateIsoChannelCMP(
664                 get1394Service().getLocalNodeId()| 0xffc0, -1,
665                 getConfigRom().getNodeId() | 0xffc0, n);
666         }
667
668         if (iso_channel<0) {
669             debugError("Could not allocate ISO channel for SP %d\n",i);
670             return false;
671         }
672
673         debugOutput(DEBUG_LEVEL_VERBOSE, "Started SP %d on channel %d\n",i,iso_channel);
674
675         p->setChannel(iso_channel);
676         return true;
677     }
678
679     debugError("SP index %d out of range!\n",i);
680     return false;
681 }
682
683 bool
684 AvDevice::stopStreamByIndex(int i) {
685     bool snoopMode=false;
686     if(!getOption("snoopMode", snoopMode)) {
687         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
688     }
689
690     if (i<(int)m_receiveProcessors.size()) {
691         int n=i;
692         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
693
694         if(snoopMode) {
695
696         } else {
697             // deallocate ISO channel
698             if(!get1394Service().freeIsoChannel(p->getChannel())) {
699                 debugError("Could not deallocate iso channel for SP %d\n",i);
700                 return false;
701             }
702         }
703         p->setChannel(-1);
704
705         return true;
706
707     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
708         int n=i-m_receiveProcessors.size();
709         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
710
711         if(snoopMode) {
712
713         } else {
714             // deallocate ISO channel
715             if(!get1394Service().freeIsoChannel(p->getChannel())) {
716                 debugError("Could not deallocate iso channel for SP %d\n",i);
717                 return false;
718             }
719         }
720         p->setChannel(-1);
721
722         return true;
723     }
724
725     debugError("SP index %d out of range!\n",i);
726     return false;
727 }
728
729 bool
730 AvDevice::serialize( Glib::ustring basePath, Util::IOSerialize& ser ) const
731 {
732     bool result;
733     result  = AVC::Unit::serialize( basePath, ser );
734     result &= serializeOptions( basePath + "Options", ser );
735     return result;
736 }
737
738 bool
739 AvDevice::deserialize( Glib::ustring basePath, Util::IODeserialize& deser )
740 {
741     bool result;
742     result = AVC::Unit::deserialize( basePath, deser );
743     return result;
744 }
745
746 }
Note: See TracBrowser for help on using the browser.