root/branches/libffado-2.0/src/libavc/descriptors/avc_descriptor.cpp

Revision 1721, 16.1 kB (checked in by ppalmers, 14 years ago)

fix all format string warnings

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