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

Revision 864, 16.0 kB (checked in by ppalmers, 15 years ago)

update license to GPLv2 or GPLv3 instead of GPLv2 or any later version. Update copyrights to reflect the new year

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 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.