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

Revision 455, 20.1 kB (checked in by ppalmers, 17 years ago)

- test-mixer volume control works (tested on phase88 only)
- volume control is exposed to the outside

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