root/trunk/libffado/src/libavc/descriptors/avc_descriptor.cpp

Revision 824, 16.0 kB (checked in by wagi, 16 years ago)

- moved cmd_serialize.h Util:: namespace to Util::Cmd:: in order to avoid ambiguities with serialize.h
- bebob: enhanced mixer stuff added (not finished)

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
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 3 of the License, or
12  * (at your option) any later version.
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 "avc_descriptor.h"
25 #include "avc_descriptor_cmd.h"
26
27 #include "../general/avc_unit.h"
28 #include "../general/avc_subunit.h"
29
30 #include "libutil/cmd_serialize.h"
31 #include "libieee1394/ieee1394service.h"
32 #include "libieee1394/configrom.h"
33
34 namespace AVC {
35
36 AVCDescriptorSpecifier::AVCDescriptorSpecifier( enum EType type )
37     : m_type ( type )
38     , m_listid_size ( 0 )
39     , m_objectid_size ( 0 )
40     , m_entrypos_size ( 0 )
41     , m_info_block_type ( 0 )
42     , m_info_block_instance ( 0 )
43     , m_info_block_position ( 0 )
44 {
45
46 }
47
48 bool
49 AVCDescriptorSpecifier::serialize( Util::Cmd::IOSSerialize& se )
50 {
51     se.write( (byte_t)m_type, "AVCDescriptorSpecifier descriptor_specifier_type" );
52     switch ( m_type ) {
53         case eIndentifier:
54             // nothing to serialize
55             return true;
56         case eInfoBlockByType:
57             se.write( m_info_block_type, "AVCDescriptorSpecifier info_block_type" );
58             se.write( m_info_block_instance, "AVCDescriptorSpecifier instance_count" );
59             return true;
60         case eInfoBlockByPosition:
61             se.write( m_info_block_position, "AVCDescriptorSpecifier info_block_position" );
62             return true;
63         case eSubunit0x80:
64             // nothing to serialize
65             return true;
66         case eInvalid:
67         default:
68             debugError("Unsupported Descriptor Specifier type: 0x%02X\n",m_type);
69             return false;
70     }
71 }
72
73 bool
74 AVCDescriptorSpecifier::deserialize( Util::Cmd::IISDeserialize& de )
75 {
76     de.read( (byte_t *)&m_type );
77     switch ( m_type ) {
78         case eIndentifier:
79             // nothing to deserialize
80             return true;
81         case eInfoBlockByType:
82             de.read( &m_info_block_type);
83             de.read( &m_info_block_instance );
84         case eInfoBlockByPosition:
85             de.read( &m_info_block_position);
86            
87             return true;
88         case eSubunit0x80:
89             // nothing to deserialize
90             return true;
91         case eInvalid:
92         default:
93             debugError("Unsupported Descriptor Specifier type: 0x%02X\n",m_type);
94             return false;
95     }
96
97     return true;
98 }
99
100 AVCDescriptorSpecifier*
101 AVCDescriptorSpecifier::clone() const
102 {
103     return new AVCDescriptorSpecifier( *this );
104 }
105
106 //----------------------
107 AVCDescriptor::AVCDescriptor( Unit* unit )
108     : IBusData()
109     , m_unit( unit )
110     , m_subunit ( NULL )
111     , m_specifier ( AVCDescriptorSpecifier::eInvalid )
112     , m_data ( NULL )
113     , m_descriptor_length(0)
114     , m_loaded ( false )
115 {
116 }
117
118 AVCDescriptor::AVCDescriptor( Unit* unit, Subunit* subunit )
119     : IBusData()
120     , m_unit( unit )
121     , m_subunit ( subunit )
122     , m_specifier ( AVCDescriptorSpecifier::eInvalid )
123     , m_data ( NULL )
124     , m_descriptor_length(0)
125     , m_loaded ( false )
126 {
127 }
128
129 AVCDescriptor::AVCDescriptor( Unit* unit, Subunit* subunit,
130                               AVCDescriptorSpecifier s )
131     : IBusData()
132     , m_unit( unit )
133     , m_subunit ( subunit )
134     , m_specifier ( s )
135     , m_data ( NULL )
136     , m_descriptor_length(0)
137     , m_loaded ( false )
138 {
139 }
140
141 AVCDescriptor::~AVCDescriptor()
142 {
143     if (m_data != NULL) free(m_data);
144 }
145 bool
146 AVCDescriptor::reload()
147 {
148     m_loaded = false;
149     return load();
150 }
151
152 bool
153 AVCDescriptor::load()
154 {
155     bool result;
156    
157     if (m_loaded) {
158         debugOutput(DEBUG_LEVEL_VERBOSE, "Descriptor already loaded, not re-loading...\n" );
159         return true;
160     }
161    
162     OpenDescriptorCmd openDescCmd(m_unit->get1394Service());
163
164     debugOutput(DEBUG_LEVEL_VERBOSE, " Open descriptor (%s)\n",getDescriptorName());
165     openDescCmd.setMode( OpenDescriptorCmd::eRead );
166     openDescCmd.m_specifier=&m_specifier;
167     openDescCmd.setNodeId( m_unit->getConfigRom().getNodeId() );
168     openDescCmd.setCommandType( AVCCommand::eCT_Control );
169     openDescCmd.setSubunitType( getSubunitType() );
170     openDescCmd.setSubunitId( getSubunitId() );
171     openDescCmd.setVerbose( getVerboseLevel() );
172    
173     result=openDescCmd.fire();
174
175     if (!result || (openDescCmd.getResponse() != AVCCommand::eR_Accepted)) {
176         debugOutput(DEBUG_LEVEL_VERBOSE, " Could not open descriptor\n");
177         return false;
178     }
179    
180     debugOutput(DEBUG_LEVEL_VERBOSE, " Read descriptor\n");
181     ReadDescriptorCmd readDescCmd(m_unit->get1394Service());
182     readDescCmd.m_specifier=&m_specifier;
183     readDescCmd.setNodeId( m_unit->getConfigRom().getNodeId() );
184     readDescCmd.setCommandType( AVCCommand::eCT_Control );
185     readDescCmd.setSubunitType( getSubunitType() );
186     readDescCmd.setSubunitId( getSubunitId() );
187     readDescCmd.setVerbose( getVerboseLevel() );
188     readDescCmd.m_data_length=2;
189     readDescCmd.m_address=0;
190    
191     result=readDescCmd.fire();
192    
193     if (!result || (readDescCmd.getResponse() != AVCCommand::eR_Accepted)) {
194         debugOutput(DEBUG_LEVEL_VERBOSE, " Could not read descriptor\n");
195         return false;
196     }
197    
198     size_t bytes_read=readDescCmd.m_data_length;
199     if (bytes_read < 2) {
200         debugOutput(DEBUG_LEVEL_VERBOSE, " Descriptor length field not present\n");
201         return false;
202     }
203
204 #ifdef DEBUG
205     if(getDebugLevel() >= DEBUG_LEVEL_VERY_VERBOSE) {
206         debugOutput(DEBUG_LEVEL_VERBOSE, " Read result:\n");
207         printBufferBytes( DEBUG_LEVEL_VERY_VERBOSE, bytes_read, readDescCmd.m_data );
208     }
209 #endif
210
211     // obtain descriptor length
212     m_descriptor_length=(readDescCmd.m_data[0]<<8) + (readDescCmd.m_data[1]);
213     debugOutput(DEBUG_LEVEL_VERBOSE, " Descriptor length: %u\n", m_descriptor_length);
214    
215     if (m_data != NULL) free(m_data);
216    
217     m_data=(byte_t *)calloc(m_descriptor_length, 1);
218     if (m_data == NULL) {
219         debugError("Could not allocate memory for descriptor\n");
220         return false;
221     }
222    
223     // we reread everything from here
224     bytes_read=0;
225     while(bytes_read<m_descriptor_length) {
226    
227         // read the full descriptor
228         readDescCmd.clear();
229         readDescCmd.m_specifier=&m_specifier;
230         readDescCmd.setNodeId( m_unit->getConfigRom().getNodeId() );
231         readDescCmd.setCommandType( AVCCommand::eCT_Control );
232         readDescCmd.setSubunitType( getSubunitType() );
233         readDescCmd.setSubunitId( getSubunitId() );
234         readDescCmd.setVerbose( getVerboseLevel() );
235         readDescCmd.m_data_length=m_descriptor_length-bytes_read;
236         // account for the length field
237         readDescCmd.m_address=bytes_read+2;
238        
239         result=readDescCmd.fire();
240        
241         if (!result || (readDescCmd.getResponse() != AVCCommand::eR_Accepted)) {
242             debugOutput(DEBUG_LEVEL_VERBOSE, " Could not read descriptor data\n");
243             return false;
244         }
245        
246         // copy the payload
247        
248         if (bytes_read+readDescCmd.m_data_length>m_descriptor_length) {
249             debugWarning("Device returned too much data, truncating\n");
250             readDescCmd.m_data_length=m_descriptor_length-bytes_read;
251         }
252        
253         debugOutput(DEBUG_LEVEL_VERBOSE, " copying %u bytes to internal buffer offset %u\n",readDescCmd.m_data_length, bytes_read);
254        
255         memcpy(m_data+bytes_read,readDescCmd.m_data, readDescCmd.m_data_length);
256         bytes_read += readDescCmd.m_data_length;
257        
258         if((readDescCmd.getStatus() != ReadDescriptorCmd::eMoreToRead)
259            && ( bytes_read<m_descriptor_length )) {
260             debugError(" Still bytes to read but device claims not.\n");
261             return false;
262         }
263        
264     }
265     //-------------
266    
267     debugOutput(DEBUG_LEVEL_VERBOSE, " Close descriptor\n");
268     openDescCmd.clear();
269     openDescCmd.setMode( OpenDescriptorCmd::eClose );
270     openDescCmd.m_specifier=&m_specifier;
271     openDescCmd.setNodeId( m_unit->getConfigRom().getNodeId() );
272     openDescCmd.setCommandType( AVCCommand::eCT_Control );
273     openDescCmd.setSubunitType( getSubunitType() );
274     openDescCmd.setSubunitId( getSubunitId() );
275     openDescCmd.setVerbose( getVerboseLevel() );
276    
277     result=openDescCmd.fire();
278
279     if (!result || (openDescCmd.getResponse() != AVCCommand::eR_Accepted)) {
280         debugOutput(DEBUG_LEVEL_VERBOSE, " Could not close descriptor\n");
281         return false;
282     }
283 #ifdef DEBUG
284     if(getDebugLevel() >= DEBUG_LEVEL_VERY_VERBOSE) {
285         debugOutput(DEBUG_LEVEL_VERBOSE, " Descriptor content:\n");
286         printBufferBytes( DEBUG_LEVEL_VERY_VERBOSE, m_descriptor_length, m_data );
287     }
288 #endif
289     debugOutput(DEBUG_LEVEL_VERBOSE, " Parse descriptor\n");
290     // parse the descriptor
291     Util::Cmd::BufferDeserialize de( m_data, m_descriptor_length );
292     result = deserialize( de );
293     if (!result) {
294         debugOutput(DEBUG_LEVEL_VERBOSE, " Could not parse descriptor\n");
295         return false;
296     }
297    
298 #ifdef DEBUG
299     if(getDebugLevel() >= DEBUG_LEVEL_VERY_VERBOSE) {
300         Util::Cmd::StringSerializer se_dbg;
301         serialize( se_dbg );
302        
303         // output the debug message in smaller chunks to avoid problems
304         // with a max message size
305         unsigned int chars_to_write=se_dbg.getString().size();
306         unsigned int chars_written=0;
307         while (chars_written<chars_to_write) {
308             debugOutputShort(DEBUG_LEVEL_VERBOSE, "%s\n",
309                             se_dbg.getString().substr(chars_written, DEBUG_MAX_MESSAGE_LENGTH).c_str());
310             chars_written += DEBUG_MAX_MESSAGE_LENGTH-1;
311         }
312     }
313 #endif
314     m_loaded=true;
315     return true;
316 }
317
318 bool
319 AVCDescriptor::serialize( Util::Cmd::IOSSerialize& se )
320 {
321     return true;
322 }
323
324 bool
325 AVCDescriptor::deserialize( Util::Cmd::IISDeserialize& de )
326 {
327     return true;
328 }
329
330 AVCDescriptor*
331 AVCDescriptor::clone() const
332 {
333     return new AVCDescriptor( *this );
334 }
335
336 ESubunitType
337 AVCDescriptor::getSubunitType() const
338 {
339     return (m_subunit==NULL?eST_Unit:m_subunit->getSubunitType());
340 }
341
342 subunit_id_t
343 AVCDescriptor::getSubunitId() const
344 {
345     return (m_subunit==NULL?0xFF:m_subunit->getSubunitId());
346 }
347
348 bool
349 AVCDescriptor::setVerboseLevel( int verboseLevel )
350 {
351     setDebugLevel(verboseLevel);
352     return true;
353 }
354
355 int
356 AVCDescriptor::getVerboseLevel()
357 {
358     return getDebugLevel();
359 }
360
361 void
362 AVCDescriptor::printBufferBytes( unsigned int level, size_t length, byte_t* buffer ) const
363 {
364
365     for ( unsigned int i=0; i < length; ++i ) {
366         if ( ( i % 16 ) == 0 ) {
367             if ( i > 0 ) {
368                 debugOutputShort(level,"\n");
369             }
370             debugOutputShort(level," %4d: ",i*16);
371         }
372         debugOutputShort(level,"%02X ",buffer[i]);
373     }
374     debugOutputShort(level,"\n");
375 }
376
377 // --- Info block
378 AVCInfoBlock::AVCInfoBlock( )
379     : IBusData()
380     , m_compound_length ( 0 )
381     , m_info_block_type ( 0 )
382     , m_primary_field_length ( 0 )
383     , m_supported_info_block_type ( 0xFFFF )
384 {}
385
386 AVCInfoBlock::AVCInfoBlock( uint16_t supported_type )
387     : IBusData()
388     , m_compound_length ( 0 )
389     , m_info_block_type ( 0 )
390     , m_primary_field_length ( 0 )
391     , m_supported_info_block_type ( supported_type )
392 {}
393
394 bool
395 AVCInfoBlock::serialize( Util::Cmd::IOSSerialize& se )
396 {
397     bool result=true;
398     if((m_supported_info_block_type != 0xFFFF)
399        && (m_info_block_type != m_supported_info_block_type)) {
400         debugError("%s: Incorrect block type: 0x%04X, should be 0x%04X\n",
401             getInfoBlockName(), m_info_block_type, m_supported_info_block_type);
402         return false;
403     }
404     result &= se.write( m_compound_length, "AVCInfoBlock m_compound_length" );
405     result &= se.write( m_info_block_type, "AVCInfoBlock m_info_block_type" );
406     result &= se.write( m_primary_field_length, "AVCInfoBlock m_primary_field_length" );
407     return result;
408 }
409
410 bool
411 AVCInfoBlock::deserialize( Util::Cmd::IISDeserialize& de )
412 {
413     bool result=true;
414     result &= de.read( &m_compound_length );
415     result &= de.read( &m_info_block_type );
416     result &= de.read( &m_primary_field_length );
417    
418     if((m_supported_info_block_type != 0xFFFF)
419        && (m_info_block_type != m_supported_info_block_type)) {
420         debugError("%s: Incorrect block type: 0x%04X, should be 0x%04X\n",
421             getInfoBlockName(), m_info_block_type, m_supported_info_block_type);
422         return false;
423     }
424    
425     debugOutput(DEBUG_LEVEL_VERBOSE, "%s length=0x%04X (%u), type=0x%04X, primary field length=0x%04X (%u)\n",
426         getInfoBlockName(), m_compound_length, m_compound_length,
427         m_info_block_type, m_primary_field_length, m_primary_field_length);
428
429     return result;
430 }
431
432 bool
433 AVCInfoBlock::peekBlockType( Util::Cmd::IISDeserialize& de, uint16_t *type )
434 {
435     return de.peek(type, 2);
436 }
437
438 bool
439 AVCInfoBlock::peekBlockLength( Util::Cmd::IISDeserialize& de, uint16_t *type )
440 {
441     return de.peek(type, 0);
442 }
443
444 AVCInfoBlock*
445 AVCInfoBlock::clone() const
446 {
447     return new AVCInfoBlock( *this );
448 }
449 bool
450 AVCInfoBlock::setVerbose( int verboseLevel )
451 {
452     setDebugLevel(verboseLevel);
453     return true;
454 }
455
456 int
457 AVCInfoBlock::getVerboseLevel()
458 {
459     return getDebugLevel();
460 }
461
462 // ---------
463
464 //FIXME: find out the correct id for this
465 AVCRawTextInfoBlock::AVCRawTextInfoBlock( )
466     : AVCInfoBlock( 0x000A )
467 {}
468
469 AVCRawTextInfoBlock::~AVCRawTextInfoBlock( )
470 {
471     clear();
472 }
473
474 bool
475 AVCRawTextInfoBlock::clear()
476 {
477     return true;
478 }
479
480 bool
481 AVCRawTextInfoBlock::serialize( Util::Cmd::IOSSerialize& se )
482 {
483     bool result=true;
484     result &= AVCInfoBlock::serialize(se);
485     if (m_text.size()) {
486         se.write(m_text.c_str(),m_text.size(), "AVCRawTextInfoBlock text");
487     }
488     return result;
489 }
490
491 bool
492 AVCRawTextInfoBlock::deserialize( Util::Cmd::IISDeserialize& de )
493 {
494     bool result=true;
495     result &= AVCInfoBlock::deserialize(de);
496
497     // note that the pointer returned by de.read is not valid outside this function
498     // but since we add it to m_text it's not a problem
499     char *txt;
500     result &= de.read(&txt,m_compound_length-4);
501     m_text.clear();
502     m_text.append(txt);
503
504     debugOutput(DEBUG_LEVEL_VERBOSE, "Read AVCRawTextInfoBlock: '%s'\n", m_text.c_str());
505
506     return result;
507 }
508
509 // ---------
510
511 AVCNameInfoBlock::AVCNameInfoBlock( )
512     : AVCInfoBlock( 0x000B )
513 {}
514
515 AVCNameInfoBlock::~AVCNameInfoBlock( )
516 {
517     clear();
518 }
519
520 bool
521 AVCNameInfoBlock::clear()
522 {
523     return true;
524 }
525
526 bool
527 AVCNameInfoBlock::serialize( Util::Cmd::IOSSerialize& se )
528 {
529     bool result=true;
530     result &= AVCInfoBlock::serialize(se);
531    
532     if (m_text.size()) {
533         result &= se.write((uint16_t)0x0000, "AVCNameInfoBlock unknown");
534         result &= se.write((uint16_t)0x0000, "AVCNameInfoBlock unknown");
535         result &= se.write((uint16_t)0x0000, "AVCNameInfoBlock unknown length");
536         result &= se.write((uint16_t)0x0000, "AVCNameInfoBlock unknown");
537         result &= se.write((uint16_t)m_text.size(), "AVCNameInfoBlock text length");
538        
539         se.write(m_text.c_str(),m_text.size(), "AVCNameInfoBlock text");
540     }
541     return result;
542 }
543
544 bool
545 AVCNameInfoBlock::deserialize( Util::Cmd::IISDeserialize& de )
546 {
547     bool result=true;
548     result &= AVCInfoBlock::deserialize(de);
549
550     // FIXME: get the spec somewhere to do this correctly
551     uint16_t dummy16;
552     uint16_t length1;
553     uint16_t text_length;
554    
555     result &= de.read(&dummy16);
556     result &= de.read(&dummy16);
557     result &= de.read(&length1);
558     result &= de.read(&dummy16);
559     result &= de.read(&text_length);
560
561     // note that the pointer returned by de.read is not valid outside this function
562     // but since we add it to m_text it's not a problem
563     char *txt;
564     result &= de.read(&txt,text_length);
565     m_text.clear();
566     m_text.append(txt);
567
568     debugOutput(DEBUG_LEVEL_VERBOSE, "Read AVCNameInfoBlock: '%s'\n", m_text.c_str());
569
570     return result;
571 }
572
573 }
Note: See TracBrowser for help on using the browser.