root/trunk/libffado/src/libavc/audiosubunit/avc_function_block.cpp

Revision 618, 20.2 kB (checked in by ppalmers, 13 years ago)

move serialization routines to libutil such that they can be used for non-AVC stuff too (fireworks EFC)

Line 
1 /*
2  * Copyright (C) 2005-2007 by Daniel Wagner
3  * Copyright (C) 2005-2007 by Pieter Palmers
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 library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License version 2.1, as published by the Free Software Foundation;
13  *
14  * This library 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 GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22  * MA 02110-1301 USA
23  */
24
25 #include "avc_function_block.h"
26 #include "libutil/cmd_serialize.h"
27 #include "libieee1394/ieee1394service.h"
28
29
30 namespace AVC {
31
32
33 /////////////////////////////////
34
35 FunctionBlockFeatureVolume::FunctionBlockFeatureVolume()
36     : IBusData()
37     , m_controlDataLength( 2 )
38     , m_volume( 0 )
39 {
40 }
41
42 FunctionBlockFeatureVolume::FunctionBlockFeatureVolume( const FunctionBlockFeatureVolume& rhs )
43     : m_controlDataLength( rhs.m_controlDataLength )
44     , m_volume( rhs.m_volume )
45 {
46 }
47
48 FunctionBlockFeatureVolume::~FunctionBlockFeatureVolume()
49 {
50 }
51
52 bool
53 FunctionBlockFeatureVolume::serialize( Util::IOSSerialize& se )
54 {
55     bool bStatus;
56     byte_t val;
57     bStatus = se.write( m_controlDataLength,  "FunctionBlockFeatureVolume controlDataLength" );
58     val = (byte_t)(m_volume >> 8);
59     bStatus &= se.write( val,                  "FunctionBlockFeatureVolume volume high" );
60     val = m_volume & 0xff;
61     bStatus &= se.write( val,                  "FunctionBlockFeatureVolume volume low" );
62
63     return bStatus;
64 }
65
66 bool
67 FunctionBlockFeatureVolume::deserialize( Util::IISDeserialize& de )
68 {
69     bool bStatus;
70     byte_t val;
71     bStatus = de.read( &m_controlDataLength );
72     bStatus &= de.read( &val );
73     m_volume = val << 8;
74     bStatus &= de.read( &val );
75     m_volume |= val;
76
77     return bStatus;
78 }
79
80 FunctionBlockFeatureVolume*
81 FunctionBlockFeatureVolume::clone() const
82 {
83     return new FunctionBlockFeatureVolume( *this );
84 }
85
86 /////////////////////////////////
87
88 FunctionBlockProcessingMixer::FunctionBlockProcessingMixer()
89     : IBusData()
90     , m_controlSelector( FunctionBlockProcessing::eCSE_Processing_Mixer )
91 {
92 }
93
94 FunctionBlockProcessingMixer::FunctionBlockProcessingMixer( const FunctionBlockProcessingMixer& rhs )
95     : m_controlSelector( rhs.m_controlSelector )
96 {
97 }
98
99 FunctionBlockProcessingMixer::~FunctionBlockProcessingMixer()
100 {
101 }
102
103 bool
104 FunctionBlockProcessingMixer::serialize( Util::IOSSerialize& se )
105 {
106     bool bStatus;
107     bStatus = se.write( m_controlSelector,    "FunctionBlockProcessingMixer controlSelector" );
108
109     return bStatus;
110 }
111
112 bool
113 FunctionBlockProcessingMixer::deserialize( Util::IISDeserialize& de )
114 {
115     bool bStatus;
116     bStatus = de.read( &m_controlSelector );
117
118     return bStatus;
119 }
120
121 FunctionBlockProcessingMixer*
122 FunctionBlockProcessingMixer::clone() const
123 {
124     return new FunctionBlockProcessingMixer( *this );
125 }
126
127 /////////////////////////////////
128
129 FunctionBlockProcessingEnhancedMixer::FunctionBlockProcessingEnhancedMixer()
130     : IBusData()
131     , m_controlSelector( FunctionBlockProcessing::eCSE_Processing_EnhancedMixer )
132     , m_statusSelector( eSS_ProgramableState )
133 {
134 }
135
136 FunctionBlockProcessingEnhancedMixer::FunctionBlockProcessingEnhancedMixer(
137     const FunctionBlockProcessingEnhancedMixer& rhs )
138     : m_controlSelector( rhs.m_controlSelector )
139     , m_statusSelector( rhs.m_statusSelector )
140 {
141 }
142
143 FunctionBlockProcessingEnhancedMixer::~FunctionBlockProcessingEnhancedMixer()
144 {
145 }
146
147 bool
148 FunctionBlockProcessingEnhancedMixer::serialize( Util::IOSSerialize& se )
149 {
150     int todo,done;
151     bool bStatus;
152     byte_t data_length_hi, data_length_lo;
153    
154     bStatus  = se.write( m_controlSelector, "FunctionBlockProcessingEnhancedMixer controlSelector" );
155     bStatus &= se.write( m_statusSelector,  "FunctionBlockProcessingEnhancedMixer statusSelector" );
156    
157     switch (m_statusSelector) {
158         case eSS_ProgramableState:
159             m_controlDataLength=m_LevelData.size();
160             data_length_hi=(m_controlDataLength >> 8);
161             data_length_lo=(m_controlDataLength & 0xFF);
162             bStatus &= se.write( data_length_hi,  "FunctionBlockProcessingEnhancedMixer controlDataLengthHi" );
163             bStatus &= se.write( data_length_lo,  "FunctionBlockProcessingEnhancedMixer controlDataLengthLo" );
164
165             for (int i=0;i<m_controlDataLength/8;i++) {
166                 byte_t value=0;
167                
168                 for (int j=0;j<8;j++) {
169                     control_data_ext_length_t bit_value=m_ProgramableStateData.at(i*8+j);
170                     value |= bit_value << (7-j);
171                 }
172                
173                 bStatus &= se.write( value,  "FunctionBlockProcessingEnhancedMixer data" );
174             }
175            
176             todo=m_controlDataLength%8;
177             done=m_controlDataLength-todo;
178             if (todo) {
179                 byte_t value=0;
180                 for (int j=0;j<todo;j++) {
181                     control_data_ext_length_t bit_value=m_ProgramableStateData.at(done*8+j);
182                     value |= bit_value << (7-j);
183                 }
184                 bStatus &= se.write( value,  "FunctionBlockProcessingEnhancedMixer data" );
185             }
186             break;
187         case eSS_Level:
188             m_controlDataLength=m_LevelData.size()/2;
189             data_length_hi=(m_controlDataLength >> 8);
190             data_length_lo=(m_controlDataLength & 0xFF);
191             bStatus &= se.write( data_length_hi,  "FunctionBlockProcessingEnhancedMixer controlDataLengthHi" );
192             bStatus &= se.write( data_length_lo,  "FunctionBlockProcessingEnhancedMixer controlDataLengthLo" );
193
194             for (int i=0;i<m_controlDataLength/2;i++) {
195                 mixer_level_t value=m_LevelData.at(i);
196                 byte_t value_hi=value >> 8;
197                 byte_t value_lo=value & 0xFF;
198                
199                 bStatus &= se.write( value_hi,  "FunctionBlockProcessingEnhancedMixer data" );
200                 bStatus &= se.write( value_lo,  "FunctionBlockProcessingEnhancedMixer data" );
201             }
202             break;
203     }
204     return bStatus;
205 }
206
207 bool
208 FunctionBlockProcessingEnhancedMixer::deserialize( Util::IISDeserialize& de )
209 {
210     int todo;
211     bool bStatus=true;
212     bStatus  = de.read( &m_controlSelector );
213
214     // NOTE: the returned value is currently bogus, so overwrite it
215     m_controlSelector=FunctionBlockProcessing::eCSE_Processing_EnhancedMixer;
216
217     bStatus &= de.read( &m_statusSelector );
218
219     byte_t data_length_hi;
220     byte_t data_length_lo;
221     bStatus &= de.read( &data_length_hi );
222     bStatus &= de.read( &data_length_lo );
223
224     m_controlDataLength = (data_length_hi << 8) + data_length_lo;
225     switch (m_statusSelector) {
226         case eSS_ProgramableState:
227             m_ProgramableStateData.clear();
228             for (int i=0;i<m_controlDataLength/8;i++) {
229                 byte_t value;
230                 bStatus &= de.read( &value);
231
232                 for (int j=7;j>=0;j--) {
233                     byte_t bit_value;
234                     bit_value=(((1<<j) & value) ? 1 : 0);
235                     m_ProgramableStateData.push_back(bit_value);
236                 }
237             }
238
239             todo=m_controlDataLength%8;
240             if (todo) {
241                 byte_t value;
242                 bStatus &= de.read( &value);
243
244                 for (int j=7;j>7-todo;j--) {
245                     byte_t bit_value;
246                     bit_value=(((1<<j) & value) ? 1 : 0);
247                     m_ProgramableStateData.push_back(bit_value);
248                 }
249             }
250             break;
251         case eSS_Level:
252             m_LevelData.clear();
253             for (int i=0;i<m_controlDataLength/2;i++) {
254                 byte_t mixer_value_hi=0, mixer_value_lo=0;
255                 bStatus &= de.read( &mixer_value_hi);
256                 bStatus &= de.read( &mixer_value_lo);
257                 mixer_level_t value = (mixer_value_hi << 8) + mixer_value_lo;
258                 m_LevelData.push_back(value);
259             }
260             break;
261     }
262
263     return bStatus;
264 }
265
266 FunctionBlockProcessingEnhancedMixer*
267 FunctionBlockProcessingEnhancedMixer::clone() const
268 {
269     return new FunctionBlockProcessingEnhancedMixer( *this );
270 }
271
272
273 /////////////////////////////////
274 /////////////////////////////////
275
276 FunctionBlockSelector::FunctionBlockSelector()
277     : IBusData()
278     , m_selectorLength( 0x02 )
279     , m_inputFbPlugNumber( 0x00 )
280     , m_controlSelector( eCSE_Selector_Selector )
281 {
282 }
283
284 FunctionBlockSelector::FunctionBlockSelector( const FunctionBlockSelector& rhs )
285     : IBusData()
286     , m_selectorLength( rhs.m_selectorLength )
287     , m_inputFbPlugNumber( rhs.m_inputFbPlugNumber )
288     , m_controlSelector( rhs.m_controlSelector )
289 {
290 }
291
292 FunctionBlockSelector::~FunctionBlockSelector()
293 {
294 }
295
296 bool
297 FunctionBlockSelector::serialize( Util::IOSSerialize& se )
298 {
299     bool bStatus;
300     bStatus  = se.write( m_selectorLength,    "FunctionBlockSelector selectorLength" );
301     bStatus &= se.write( m_inputFbPlugNumber, "FunctionBlockSelector inputFbPlugNumber" );
302     bStatus &= se.write( m_controlSelector,   "FunctionBlockSelector controlSelector" );
303
304     return bStatus;
305 }
306
307 bool
308 FunctionBlockSelector::deserialize( Util::IISDeserialize& de )
309 {
310     bool bStatus;
311     bStatus  = de.read( &m_selectorLength );
312     bStatus &= de.read( &m_inputFbPlugNumber );
313     bStatus &= de.read( &m_controlSelector );
314
315     return bStatus;
316 }
317
318 FunctionBlockSelector*
319 FunctionBlockSelector::clone() const
320 {
321     return new FunctionBlockSelector( *this );
322 }
323
324 /////////////////////////////////
325
326 FunctionBlockFeature::FunctionBlockFeature()
327     : IBusData()
328     , m_selectorLength( 0x02 )
329     , m_audioChannelNumber( 0x00 )
330     , m_controlSelector( eCSE_Feature_Unknown )
331     , m_pVolume( new FunctionBlockFeatureVolume )
332 {
333 }
334
335 FunctionBlockFeature::FunctionBlockFeature( const FunctionBlockFeature& rhs )
336     : IBusData()
337     , m_selectorLength( rhs.m_selectorLength )
338     , m_audioChannelNumber( rhs.m_audioChannelNumber )
339     , m_controlSelector( rhs.m_controlSelector )
340 {
341     if ( rhs.m_pVolume ) {
342         m_pVolume = new FunctionBlockFeatureVolume( *rhs.m_pVolume );
343     }
344 }
345
346 FunctionBlockFeature::~FunctionBlockFeature()
347 {
348     delete m_pVolume;
349     m_pVolume = NULL;
350 }
351
352 bool
353 FunctionBlockFeature::serialize( Util::IOSSerialize& se )
354 {
355     bool bStatus;
356     bStatus  = se.write( m_selectorLength,     "FunctionBlockFeature selectorLength" );
357     bStatus &= se.write( m_audioChannelNumber, "FunctionBlockFeature audioChannelNumber" );
358     bStatus &= se.write( m_controlSelector,    "FunctionBlockFeature controlSelector" );
359
360     if ( m_controlSelector == eCSE_Feature_Volume ) {
361         bStatus &= m_pVolume->serialize( se );
362     } else {
363         bStatus = false;
364     }
365
366     return bStatus;
367 }
368
369 bool
370 FunctionBlockFeature::deserialize( Util::IISDeserialize& de )
371 {
372     bool bStatus;
373     bStatus  = de.read( &m_selectorLength );
374     bStatus &= de.read( &m_audioChannelNumber );
375     bStatus &= de.read( &m_controlSelector );
376
377     switch( m_controlSelector ) {
378     case eCSE_Feature_Volume:
379         bStatus &= m_pVolume->deserialize( de );
380         break;
381     case eCSE_Feature_Mute:
382     case eCSE_Feature_LRBalance:
383     case eCSE_Feature_FRBalance:
384     case eCSE_Feature_Bass:
385     case eCSE_Feature_Mid:
386     case eCSE_Feature_Treble:
387     case eCSE_Feature_GEQ:
388     case eCSE_Feature_AGC:
389     case eCSE_Feature_Delay:
390     case eCSE_Feature_BassBoost:
391     case eCSE_Feature_Loudness:
392     default:
393         bStatus = false;
394     }
395
396     return bStatus;
397 }
398
399 FunctionBlockFeature*
400 FunctionBlockFeature::clone() const
401 {
402     return new FunctionBlockFeature( *this );
403 }
404
405 /////////////////////////////////
406
407 FunctionBlockProcessing::FunctionBlockProcessing()
408     : IBusData()
409     , m_selectorLength( 0x04 )
410     , m_fbInputPlugNumber( 0x00 )
411     , m_inputAudioChannelNumber( 0x00 )
412     , m_outputAudioChannelNumber( 0x00 )
413     , m_pMixer( 0 )
414     , m_pEnhancedMixer( 0 )
415 {
416 }
417
418 FunctionBlockProcessing::FunctionBlockProcessing( const FunctionBlockProcessing& rhs )
419     : m_selectorLength( rhs.m_selectorLength )
420     , m_fbInputPlugNumber( rhs.m_fbInputPlugNumber )
421     , m_inputAudioChannelNumber( rhs.m_inputAudioChannelNumber )
422     , m_outputAudioChannelNumber( rhs.m_outputAudioChannelNumber )
423 {
424     if ( rhs.m_pMixer ) {
425         m_pMixer = new FunctionBlockProcessingMixer( *rhs.m_pMixer );
426     } else if ( rhs.m_pEnhancedMixer ) {
427         m_pEnhancedMixer = new FunctionBlockProcessingEnhancedMixer( *rhs.m_pEnhancedMixer );
428     }
429 }
430
431 FunctionBlockProcessing::~FunctionBlockProcessing()
432 {
433     delete m_pMixer;
434     m_pMixer = 0;
435     delete m_pEnhancedMixer;
436     m_pEnhancedMixer = 0;
437 }
438
439 bool
440 FunctionBlockProcessing::serialize( Util::IOSSerialize& se )
441 {
442     bool bStatus;
443     bStatus  = se.write( m_selectorLength,     "FunctionBlockProcessing selectorLength" );
444     bStatus &= se.write( m_fbInputPlugNumber,  "FunctionBlockProcessing fbInputPlugNumber" );
445     bStatus &= se.write( m_inputAudioChannelNumber,  "FunctionBlockProcessing inputAudioChannelNumber" );
446     bStatus &= se.write( m_outputAudioChannelNumber, "FunctionBlockProcessing outputAudioChannelNumber" );
447
448     if ( m_pMixer ) {
449         bStatus &= m_pMixer->serialize( se );
450     } else if ( m_pEnhancedMixer ) {
451         bStatus &= m_pEnhancedMixer->serialize( se );
452     } else {
453         bStatus = false;
454     }
455
456     return bStatus;
457 }
458
459 bool
460 FunctionBlockProcessing::deserialize( Util::IISDeserialize& de )
461 {
462     // NOTE: apparently the fbCmd of the STATUS type,
463     // with EnhancedMixer controlSelector returns with this
464     // controlSelector type changed to Mixer, making it
465     // impossible to choose the correct response handler
466     // based upon the response only.
467    
468     // HACK: we assume that it is the same as the sent one
469     // we also look at our data structure to figure out what we sent
470     byte_t controlSelector=eCSE_Processing_Unknown;
471     if(m_pMixer) {
472         controlSelector=eCSE_Processing_Mixer;
473     } else if(m_pEnhancedMixer) {
474         controlSelector=eCSE_Processing_EnhancedMixer;
475     }
476    
477     bool bStatus;
478     bStatus  = de.read( &m_selectorLength );
479     bStatus &= de.read( &m_fbInputPlugNumber );
480     bStatus &= de.read( &m_inputAudioChannelNumber );
481     bStatus &= de.read( &m_outputAudioChannelNumber );
482
483     byte_t controlSelector_response;
484     bStatus &= de.peek( &controlSelector_response );
485 /*    debugOutput(DEBUG_LEVEL_VERBOSE,"ctrlsel: orig = %02X, resp = %02X\n",
486         controlSelector, controlSelector_response);*/
487    
488     switch( controlSelector ) {
489     case eCSE_Processing_Mixer:
490         if ( !m_pMixer ) {
491             m_pMixer = new FunctionBlockProcessingMixer;
492         }
493         bStatus &= m_pMixer->deserialize( de );
494         break;
495     case eCSE_Processing_EnhancedMixer:
496         if ( !m_pEnhancedMixer ) {
497             m_pEnhancedMixer = new FunctionBlockProcessingEnhancedMixer;
498         }
499         bStatus &= m_pEnhancedMixer->deserialize( de );
500         break;
501     case eCSE_Processing_Enable:
502     case eCSE_Processing_Mode:
503     default:
504         bStatus = false;
505     }
506
507     byte_t tmp;
508     if (de.peek(&tmp)) {
509         debugOutput(DEBUG_LEVEL_VERBOSE,"Unprocessed bytes:\n");
510         while (de.read(&tmp)) {
511             debugOutput(DEBUG_LEVEL_VERBOSE," %02X\n",tmp);
512         }
513     }
514
515     return bStatus;
516 }
517
518 FunctionBlockProcessing*
519 FunctionBlockProcessing::clone() const
520 {
521     return new FunctionBlockProcessing( *this );
522 }
523
524 /////////////////////////////////
525
526 FunctionBlockCodec::FunctionBlockCodec()
527     : IBusData()
528 {
529 }
530
531 FunctionBlockCodec::FunctionBlockCodec( const FunctionBlockCodec& rhs )
532     : IBusData()
533 {
534 }
535
536 FunctionBlockCodec::~FunctionBlockCodec()
537 {
538 }
539
540 bool
541 FunctionBlockCodec::serialize( Util::IOSSerialize& se )
542 {
543     return false;
544 }
545
546 bool
547 FunctionBlockCodec::deserialize( Util::IISDeserialize& de )
548 {
549     return false;
550 }
551
552 FunctionBlockCodec*
553 FunctionBlockCodec::clone() const
554 {
555     return new FunctionBlockCodec( *this );
556 }
557
558 /////////////////////////////////
559 /////////////////////////////////
560
561 FunctionBlockCmd::FunctionBlockCmd( Ieee1394Service& ieee1394service,
562                                     EFunctionBlockType eType,
563                                     function_block_id_t id,
564                                     EControlAttribute eCtrlAttrib )
565     : AVCCommand( ieee1394service, AVC1394_FUNCTION_BLOCK_CMD )
566     , m_functionBlockType( eType )
567     , m_functionBlockId( id )
568     , m_controlAttribute( eCtrlAttrib )
569     , m_pFBSelector( 0 )
570     , m_pFBFeature( 0 )
571     , m_pFBProcessing( 0 )
572     , m_pFBCodec( 0 )
573 {
574     setSubunitType( eST_Audio );
575
576     switch( m_functionBlockType ) {
577         case eFBT_Selector:
578             m_pFBSelector = new FunctionBlockSelector;
579             break;
580         case eFBT_Feature:
581             m_pFBFeature = new FunctionBlockFeature;
582             break;
583         case eFBT_Processing:
584             m_pFBProcessing = new FunctionBlockProcessing;
585             break;
586         case eFBT_Codec:
587             m_pFBCodec = new FunctionBlockCodec;
588             break;
589     }
590 }
591
592 FunctionBlockCmd::FunctionBlockCmd( const FunctionBlockCmd& rhs )
593     : AVCCommand( rhs )
594     , m_functionBlockType( rhs.m_functionBlockType )
595     , m_functionBlockId( rhs.m_functionBlockId )
596     , m_controlAttribute( rhs.m_controlAttribute )
597     , m_pFBSelector( new FunctionBlockSelector( *rhs.m_pFBSelector ) )
598     , m_pFBFeature( new FunctionBlockFeature( *rhs.m_pFBFeature ) )
599     , m_pFBProcessing( new FunctionBlockProcessing( *rhs.m_pFBProcessing ) )
600     , m_pFBCodec( new FunctionBlockCodec( *rhs.m_pFBCodec ) )
601 {
602 }
603
604 FunctionBlockCmd::~FunctionBlockCmd()
605 {
606     delete m_pFBSelector;
607     m_pFBSelector = 0;
608     delete m_pFBFeature;
609     m_pFBFeature = 0;
610     delete m_pFBProcessing;
611     m_pFBProcessing = 0;
612     delete m_pFBCodec;
613     m_pFBCodec = 0;
614 }
615
616 bool
617 FunctionBlockCmd::serialize( Util::IOSSerialize& se )
618 {
619     bool bStatus;
620     bStatus  = AVCCommand::serialize( se );
621     bStatus &= se.write( m_functionBlockType, "FunctionBlockCmd functionBlockType" );
622     bStatus &= se.write( m_functionBlockId,   "FunctionBlockCmd functionBlockId" );
623     bStatus &= se.write( m_controlAttribute,  "FunctionBlockCmd controlAttribute" );
624
625     switch( m_functionBlockType ) {
626         case eFBT_Selector:
627             if ( m_pFBSelector ) {
628                 bStatus &= m_pFBSelector->serialize( se );
629             } else {
630                 bStatus = false;
631             }
632             break;
633         case eFBT_Feature:
634             if ( m_pFBFeature ) {
635                 bStatus &= m_pFBFeature->serialize( se );
636             } else {
637                 bStatus = false;
638             }
639             break;
640         case eFBT_Processing:
641             if ( m_pFBProcessing ) {
642                 bStatus &= m_pFBProcessing->serialize( se );
643             } else {
644                 bStatus = false;
645             }
646             break;
647         case eFBT_Codec:
648             if ( m_pFBCodec ) {
649                 bStatus &= m_pFBCodec->serialize( se );
650             } else {
651                 bStatus = false;
652             }
653             break;
654         default:
655             bStatus = false;
656     }
657
658     return bStatus;
659 }
660
661 bool
662 FunctionBlockCmd::deserialize( Util::IISDeserialize& de )
663 {
664     bool bStatus;
665     bStatus  = AVCCommand::deserialize( de );
666
667     bStatus &= de.read( &m_functionBlockType );
668     bStatus &= de.read( &m_functionBlockId );
669     bStatus &= de.read( &m_controlAttribute );
670
671     switch( m_functionBlockType ) {
672         case eFBT_Selector:
673             if ( !m_pFBSelector ) {
674                 m_pFBSelector = new FunctionBlockSelector;
675             }
676             bStatus &= m_pFBSelector->deserialize( de );
677             break;
678         case eFBT_Feature:
679             if ( !m_pFBFeature ) {
680                 m_pFBFeature = new FunctionBlockFeature;
681             }
682             bStatus &= m_pFBFeature->deserialize( de );
683             break;
684         case eFBT_Processing:
685             if ( !m_pFBProcessing ) {
686                 m_pFBProcessing = new FunctionBlockProcessing;
687             }
688             bStatus &= m_pFBProcessing->deserialize( de );
689             break;
690         case eFBT_Codec:
691             if ( !m_pFBCodec ) {
692                 m_pFBCodec = new FunctionBlockCodec;
693             }
694             bStatus &= m_pFBCodec->deserialize( de );
695             break;
696         default:
697             bStatus = false;
698     }
699
700     return bStatus;
701 }
702
703 FunctionBlockCmd*
704 FunctionBlockCmd::clone() const
705 {
706     return new FunctionBlockCmd( *this );
707 }
708
709 }
Note: See TracBrowser for help on using the browser.