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

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

split config.h into config/version/debug_config to allow for faster compilation (splits dependencies)

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, " copying %u bytes to internal buffer offset %u\n",readDescCmd.m_data_length, bytes_read);
257        
258         memcpy(m_data+bytes_read,readDescCmd.m_data, readDescCmd.m_data_length);
259         bytes_read += readDescCmd.m_data_length;
260        
261         if((readDescCmd.getStatus() != ReadDescriptorCmd::eMoreToRead)
262            && ( bytes_read<m_descriptor_length )) {
263             debugError(" Still bytes to read but device claims not.\n");
264             return false;
265         }
266        
267     }
268     //-------------
269    
270     debugOutput(DEBUG_LEVEL_VERBOSE, " Close descriptor\n");
271     openDescCmd.clear();
272     openDescCmd.setMode( OpenDescriptorCmd::eClose );
273     openDescCmd.m_specifier=&m_specifier;
274     openDescCmd.setNodeId( m_unit->getConfigRom().getNodeId() );
275     openDescCmd.setCommandType( AVCCommand::eCT_Control );
276     openDescCmd.setSubunitType( getSubunitType() );
277     openDescCmd.setSubunitId( getSubunitId() );
278     openDescCmd.setVerbose( getVerboseLevel() );
279    
280     result=openDescCmd.fire();
281
282     if (!result || (openDescCmd.getResponse() != AVCCommand::eR_Accepted)) {
283         debugOutput(DEBUG_LEVEL_VERBOSE, " Could not close descriptor\n");
284         return false;
285     }
286 #ifdef DEBUG
287     if(getDebugLevel() >= DEBUG_LEVEL_VERY_VERBOSE) {
288         debugOutput(DEBUG_LEVEL_VERBOSE, " Descriptor content:\n");
289         printBufferBytes( DEBUG_LEVEL_VERY_VERBOSE, m_descriptor_length, m_data );
290     }
291 #endif
292     debugOutput(DEBUG_LEVEL_VERBOSE, " Parse descriptor\n");
293     // parse the descriptor
294     Util::Cmd::BufferDeserialize de( m_data, m_descriptor_length );
295     result = deserialize( de );
296     if (!result) {
297         debugOutput(DEBUG_LEVEL_VERBOSE, " Could not parse descriptor\n");
298         return false;
299     }
300
301 #ifdef DEBUG
302     if(getDebugLevel() >= DEBUG_LEVEL_VERY_VERBOSE) {
303         Util::Cmd::StringSerializer se_dbg;
304         serialize( se_dbg );
305
306         // output the debug message in smaller chunks to avoid problems
307         // with a max message size
308         unsigned int chars_to_write=se_dbg.getString().size();
309         unsigned int chars_written=0;
310         while (chars_written<chars_to_write) {
311             debugOutputShort(DEBUG_LEVEL_VERBOSE, "%s\n",
312                             se_dbg.getString().substr(chars_written, DEBUG_MAX_MESSAGE_LENGTH).c_str());
313             chars_written += DEBUG_MAX_MESSAGE_LENGTH-1;
314         }
315     }
316 #endif
317     m_loaded=true;
318     return true;
319 }
320
321 bool
322 AVCDescriptor::serialize( Util::Cmd::IOSSerialize& se )
323 {
324     return true;
325 }
326
327 bool
328 AVCDescriptor::deserialize( Util::Cmd::IISDeserialize& de )
329 {
330     return true;
331 }
332
333 AVCDescriptor*
334 AVCDescriptor::clone() const
335 {
336     return new AVCDescriptor( *this );
337 }
338
339 ESubunitType
340 AVCDescriptor::getSubunitType() const
341 {
342     return (m_subunit==NULL?eST_Unit:m_subunit->getSubunitType());
343 }
344
345 subunit_id_t
346 AVCDescriptor::getSubunitId() const
347 {
348     return (m_subunit==NULL?0xFF:m_subunit->getSubunitId());
349 }
350
351 bool
352 AVCDescriptor::setVerboseLevel( int verboseLevel )
353 {
354     setDebugLevel(verboseLevel);
355     return true;
356 }
357
358 int
359 AVCDescriptor::getVerboseLevel()
360 {
361     return getDebugLevel();
362 }
363
364 void
365 AVCDescriptor::show()
366 {
367
368 }
369
370 void
371 AVCDescriptor::printBufferBytes( unsigned int level, size_t length, byte_t* buffer ) const
372 {
373
374     for ( unsigned int i=0; i < length; ++i ) {
375         if ( ( i % 16 ) == 0 ) {
376             if ( i > 0 ) {
377                 debugOutputShort(level,"\n");
378             }
379             debugOutputShort(level," %4d: ",i*16);
380         }
381         debugOutputShort(level,"%02X ",buffer[i]);
382     }
383     debugOutputShort(level,"\n");
384 }
385
386 // --- Info block
387 AVCInfoBlock::AVCInfoBlock( )
388     : IBusData()
389     , m_compound_length ( 0 )
390     , m_info_block_type ( 0 )
391     , m_primary_field_length ( 0 )
392     , m_supported_info_block_type ( 0xFFFF )
393 {}
394
395 AVCInfoBlock::AVCInfoBlock( uint16_t supported_type )
396     : IBusData()
397     , m_compound_length ( 0 )
398     , m_info_block_type ( 0 )
399     , m_primary_field_length ( 0 )
400     , m_supported_info_block_type ( supported_type )
401 {}
402
403 bool
404 AVCInfoBlock::serialize( Util::Cmd::IOSSerialize& se )
405 {
406     bool result=true;
407     if((m_supported_info_block_type != 0xFFFF)
408        && (m_info_block_type != m_supported_info_block_type)) {
409         debugError("%s: Incorrect block type: 0x%04X, should be 0x%04X\n",
410             getInfoBlockName(), m_info_block_type, m_supported_info_block_type);
411         return false;
412     }
413     result &= se.write( m_compound_length, "AVCInfoBlock m_compound_length" );
414     result &= se.write( m_info_block_type, "AVCInfoBlock m_info_block_type" );
415     result &= se.write( m_primary_field_length, "AVCInfoBlock m_primary_field_length" );
416     return result;
417 }
418
419 bool
420 AVCInfoBlock::deserialize( Util::Cmd::IISDeserialize& de )
421 {
422     bool result=true;
423     result &= de.read( &m_compound_length );
424     result &= de.read( &m_info_block_type );
425     result &= de.read( &m_primary_field_length );
426    
427     if((m_supported_info_block_type != 0xFFFF)
428        && (m_info_block_type != m_supported_info_block_type)) {
429         debugError("%s: Incorrect block type: 0x%04X, should be 0x%04X\n",
430             getInfoBlockName(), m_info_block_type, m_supported_info_block_type);
431         return false;
432     }
433    
434     debugOutput(DEBUG_LEVEL_VERBOSE, "%s length=0x%04X (%u), type=0x%04X, primary field length=0x%04X (%u)\n",
435         getInfoBlockName(), m_compound_length, m_compound_length,
436         m_info_block_type, m_primary_field_length, m_primary_field_length);
437
438     return result;
439 }
440
441 bool
442 AVCInfoBlock::peekBlockType( Util::Cmd::IISDeserialize& de, uint16_t *type )
443 {
444     return de.peek(type, 2);
445 }
446
447 bool
448 AVCInfoBlock::peekBlockLength( Util::Cmd::IISDeserialize& de, uint16_t *type )
449 {
450     return de.peek(type, 0);
451 }
452
453 AVCInfoBlock*
454 AVCInfoBlock::clone() const
455 {
456     return new AVCInfoBlock( *this );
457 }
458 bool
459 AVCInfoBlock::setVerbose( int verboseLevel )
460 {
461     setDebugLevel(verboseLevel);
462     return true;
463 }
464
465 int
466 AVCInfoBlock::getVerboseLevel()
467 {
468     return getDebugLevel();
469 }
470
471 void
472 AVCInfoBlock::show()
473 {
474
475 }
476
477 // ---------
478
479 //FIXME: find out the correct id for this
480 AVCRawTextInfoBlock::AVCRawTextInfoBlock( )
481     : AVCInfoBlock( 0x000A )
482 {}
483
484 AVCRawTextInfoBlock::~AVCRawTextInfoBlock( )
485 {
486     clear();
487 }
488
489 bool
490 AVCRawTextInfoBlock::clear()
491 {
492     return true;
493 }
494
495 bool
496 AVCRawTextInfoBlock::serialize( Util::Cmd::IOSSerialize& se )
497 {
498     bool result=true;
499     result &= AVCInfoBlock::serialize(se);
500     if (m_text.size()) {
501         se.write(m_text.c_str(),m_text.size(), "AVCRawTextInfoBlock text");
502     }
503     return result;
504 }
505
506 bool
507 AVCRawTextInfoBlock::deserialize( Util::Cmd::IISDeserialize& de )
508 {
509     bool result=true;
510     result &= AVCInfoBlock::deserialize(de);
511
512     // note that the pointer returned by de.read is not valid outside this function
513     // but since we add it to m_text it's not a problem
514     char *txt;
515     result &= de.read(&txt,m_compound_length-4);
516     m_text.clear();
517     m_text.append(txt);
518
519     debugOutput(DEBUG_LEVEL_VERBOSE, "Read AVCRawTextInfoBlock: '%s'\n", m_text.c_str());
520
521     return result;
522 }
523
524 // ---------
525
526 AVCNameInfoBlock::AVCNameInfoBlock( )
527     : AVCInfoBlock( 0x000B )
528 {}
529
530 AVCNameInfoBlock::~AVCNameInfoBlock( )
531 {
532     clear();
533 }
534
535 bool
536 AVCNameInfoBlock::clear()
537 {
538     return true;
539 }
540
541 bool
542 AVCNameInfoBlock::serialize( Util::Cmd::IOSSerialize& se )
543 {
544     bool result=true;
545     result &= AVCInfoBlock::serialize(se);
546    
547     if (m_text.size()) {
548         result &= se.write((uint16_t)0x0000, "AVCNameInfoBlock unknown");
549         result &= se.write((uint16_t)0x0000, "AVCNameInfoBlock unknown");
550         result &= se.write((uint16_t)0x0000, "AVCNameInfoBlock unknown length");
551         result &= se.write((uint16_t)0x0000, "AVCNameInfoBlock unknown");
552         result &= se.write((uint16_t)m_text.size(), "AVCNameInfoBlock text length");
553        
554         se.write(m_text.c_str(),m_text.size(), "AVCNameInfoBlock text");
555     }
556     return result;
557 }
558
559 bool
560 AVCNameInfoBlock::deserialize( Util::Cmd::IISDeserialize& de )
561 {
562     bool result=true;
563     result &= AVCInfoBlock::deserialize(de);
564
565     // FIXME: get the spec somewhere to do this correctly
566     uint16_t dummy16;
567     uint16_t length1;
568     uint16_t text_length;
569    
570     result &= de.read(&dummy16);
571     result &= de.read(&dummy16);
572     result &= de.read(&length1);
573     result &= de.read(&dummy16);
574     result &= de.read(&text_length);
575
576     // note that the pointer returned by de.read is not valid outside this function
577     // but since we add it to m_text it's not a problem
578     char *txt;
579     result &= de.read(&txt,text_length);
580     m_text.clear();
581     m_text.append(txt);
582
583     debugOutput(DEBUG_LEVEL_VERBOSE, "Read AVCNameInfoBlock: '%s'\n", m_text.c_str());
584
585     return result;
586 }
587
588 }
Note: See TracBrowser for help on using the browser.