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

Revision 626, 14.8 kB (checked in by ppalmers, 16 years ago)

minor things

Line 
1 /*
2  * Copyright (C) 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 library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
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::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::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 status 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     // obtain descriptor length
205     m_descriptor_length=(readDescCmd.m_data[0]<<8) + (readDescCmd.m_data[1]);
206     debugOutput(DEBUG_LEVEL_VERBOSE, " Descriptor length: %u\n", m_descriptor_length);
207    
208     if (m_data != NULL) free(m_data);
209    
210     m_data=(byte_t *)calloc(m_descriptor_length, 1);
211     if (m_data == NULL) {
212         debugError("Could not allocate memory for descriptor\n");
213         return false;
214     }
215    
216     // we reread everything from here
217     bytes_read=0;
218     while(bytes_read<m_descriptor_length) {
219    
220         // read the full descriptor
221         readDescCmd.clear();
222         readDescCmd.m_specifier=&m_specifier;
223         readDescCmd.setNodeId( m_unit->getConfigRom().getNodeId() );
224         readDescCmd.setCommandType( AVCCommand::eCT_Control );
225         readDescCmd.setSubunitType( getSubunitType() );
226         readDescCmd.setSubunitId( getSubunitId() );
227         readDescCmd.setVerbose( getVerboseLevel() );
228         readDescCmd.m_data_length=m_descriptor_length-bytes_read;
229         // account for the length field
230         readDescCmd.m_address=bytes_read+2;
231        
232         result=readDescCmd.fire();
233        
234         if (!result || (readDescCmd.getResponse() != AVCCommand::eR_Accepted)) {
235             debugOutput(DEBUG_LEVEL_VERBOSE, " Could not read descriptor data\n");
236             return false;
237         }
238        
239         // copy the payload
240        
241         if (bytes_read+readDescCmd.m_data_length>m_descriptor_length) {
242             debugWarning("Device returned too much data, truncating\n");
243             readDescCmd.m_data_length=m_descriptor_length-bytes_read;
244         }
245        
246         debugOutput(DEBUG_LEVEL_VERBOSE, " copying %u bytes to internal buffer offset %u\n",readDescCmd.m_data_length, bytes_read);
247        
248         memcpy(m_data+bytes_read,readDescCmd.m_data, readDescCmd.m_data_length);
249         bytes_read += readDescCmd.m_data_length;
250        
251         if((readDescCmd.getStatus() != ReadDescriptorCmd::eMoreToRead)
252            && ( bytes_read<m_descriptor_length )) {
253             debugError(" Still bytes to read but device claims not.\n");
254             return false;
255         }
256        
257     }
258     //-------------
259    
260     debugOutput(DEBUG_LEVEL_VERBOSE, " Close descriptor\n");
261     openDescCmd.clear();
262     openDescCmd.setMode( OpenDescriptorCmd::eClose );
263     openDescCmd.m_specifier=&m_specifier;
264     openDescCmd.setNodeId( m_unit->getConfigRom().getNodeId() );
265     openDescCmd.setCommandType( AVCCommand::eCT_Control );
266     openDescCmd.setSubunitType( getSubunitType() );
267     openDescCmd.setSubunitId( getSubunitId() );
268     openDescCmd.setVerbose( getVerboseLevel() );
269    
270     result=openDescCmd.fire();
271
272     if (!result || (openDescCmd.getResponse() != AVCCommand::eR_Accepted)) {
273         debugOutput(DEBUG_LEVEL_VERBOSE, " Could not close descriptor\n");
274         return false;
275     }
276
277     debugOutput(DEBUG_LEVEL_VERBOSE, " Parse descriptor\n");
278     // parse the descriptor
279     Util::BufferDeserialize de( m_data, m_descriptor_length );
280     result = deserialize( de );
281     if (!result) {
282         debugOutput(DEBUG_LEVEL_VERBOSE, " Could not parse descriptor\n");
283         return false;
284     }
285    
286 #ifdef DEBUG
287     if(getDebugLevel() >= DEBUG_LEVEL_VERY_VERBOSE) {
288         Util::StringSerializer se_dbg;
289         serialize( se_dbg );
290        
291         // output the debug message in smaller chunks to avoid problems
292         // with a max message size
293         unsigned int chars_to_write=se_dbg.getString().size();
294         unsigned int chars_written=0;
295         while (chars_written<chars_to_write) {
296             debugOutputShort(DEBUG_LEVEL_VERBOSE, "%s\n",
297                             se_dbg.getString().substr(chars_written, DEBUG_MAX_MESSAGE_LENGTH).c_str());
298             chars_written += DEBUG_MAX_MESSAGE_LENGTH-1;
299         }
300     }
301 #endif
302     m_loaded=true;
303     return true;
304 }
305
306 bool
307 AVCDescriptor::serialize( Util::IOSSerialize& se )
308 {
309     return true;
310 }
311
312 bool
313 AVCDescriptor::deserialize( Util::IISDeserialize& de )
314 {
315     return true;
316 }
317
318 AVCDescriptor*
319 AVCDescriptor::clone() const
320 {
321     return new AVCDescriptor( *this );
322 }
323
324 ESubunitType
325 AVCDescriptor::getSubunitType() const
326 {
327     return (m_subunit==NULL?eST_Unit:m_subunit->getSubunitType());
328 }
329
330 subunit_id_t
331 AVCDescriptor::getSubunitId() const
332 {
333     return (m_subunit==NULL?0xFF:m_subunit->getSubunitId());
334 }
335
336 bool
337 AVCDescriptor::setVerboseLevel( int verboseLevel )
338 {
339     setDebugLevel(verboseLevel);
340     return true;
341 }
342
343 int
344 AVCDescriptor::getVerboseLevel()
345 {
346     return getDebugLevel();
347 }
348
349 // --- Info block
350 AVCInfoBlock::AVCInfoBlock( )
351     : IBusData()
352     , m_compound_length ( 0 )
353     , m_info_block_type ( 0 )
354     , m_primary_field_length ( 0 )
355     , m_supported_info_block_type ( 0xFFFF )
356 {}
357
358 AVCInfoBlock::AVCInfoBlock( uint16_t supported_type )
359     : IBusData()
360     , m_compound_length ( 0 )
361     , m_info_block_type ( 0 )
362     , m_primary_field_length ( 0 )
363     , m_supported_info_block_type ( supported_type )
364 {}
365
366 bool
367 AVCInfoBlock::serialize( Util::IOSSerialize& se )
368 {
369     bool result=true;
370     if((m_supported_info_block_type != 0xFFFF)
371        && (m_info_block_type != m_supported_info_block_type)) {
372         debugError("%s: Incorrect block type: 0x%04X, should be 0x%04X\n",
373             getInfoBlockName(), m_info_block_type, m_supported_info_block_type);
374         return false;
375     }
376     result &= se.write( m_compound_length, "AVCInfoBlock m_compound_length" );
377     result &= se.write( m_info_block_type, "AVCInfoBlock m_info_block_type" );
378     result &= se.write( m_primary_field_length, "AVCInfoBlock m_primary_field_length" );
379     return result;
380 }
381
382 bool
383 AVCInfoBlock::deserialize( Util::IISDeserialize& de )
384 {
385     bool result=true;
386     result &= de.read( &m_compound_length );
387     result &= de.read( &m_info_block_type );
388     result &= de.read( &m_primary_field_length );
389    
390     if((m_supported_info_block_type != 0xFFFF)
391        && (m_info_block_type != m_supported_info_block_type)) {
392         debugError("%s: Incorrect block type: 0x%04X, should be 0x%04X\n",
393             getInfoBlockName(), m_info_block_type, m_supported_info_block_type);
394         return false;
395     }
396    
397     debugOutput(DEBUG_LEVEL_VERBOSE, "%s length=0x%04X (%u), type=0x%04X, primary field length=0x%04X (%u)\n",
398         getInfoBlockName(), m_compound_length, m_compound_length,
399         m_info_block_type, m_primary_field_length, m_primary_field_length);
400
401     return result;
402 }
403
404 bool
405 AVCInfoBlock::peekBlockType( Util::IISDeserialize& de, uint16_t *type )
406 {
407     return de.peek(type, 2);
408 }
409
410 bool
411 AVCInfoBlock::peekBlockLength( Util::IISDeserialize& de, uint16_t *type )
412 {
413     return de.peek(type, 0);
414 }
415
416 AVCInfoBlock*
417 AVCInfoBlock::clone() const
418 {
419     return new AVCInfoBlock( *this );
420 }
421 bool
422 AVCInfoBlock::setVerbose( int verboseLevel )
423 {
424     setDebugLevel(verboseLevel);
425     return true;
426 }
427
428 int
429 AVCInfoBlock::getVerboseLevel()
430 {
431     return getDebugLevel();
432 }
433
434 // ---------
435
436 //FIXME: find out the correct id for this
437 AVCRawTextInfoBlock::AVCRawTextInfoBlock( )
438     : AVCInfoBlock( 0x000A )
439 {}
440
441 AVCRawTextInfoBlock::~AVCRawTextInfoBlock( )
442 {
443     clear();
444 }
445
446 bool
447 AVCRawTextInfoBlock::clear()
448 {
449     return true;
450 }
451
452 bool
453 AVCRawTextInfoBlock::serialize( Util::IOSSerialize& se )
454 {
455     bool result=true;
456     result &= AVCInfoBlock::serialize(se);
457     if (m_text.size()) {
458         se.write(m_text.c_str(),m_text.size(), "AVCRawTextInfoBlock text");
459     }
460     return result;
461 }
462
463 bool
464 AVCRawTextInfoBlock::deserialize( Util::IISDeserialize& de )
465 {
466     bool result=true;
467     result &= AVCInfoBlock::deserialize(de);
468
469     char *txt;
470     result &= de.read(&txt,m_compound_length-4);
471     m_text.clear();
472     m_text.append(txt);
473
474     debugOutput(DEBUG_LEVEL_VERBOSE, "Read AVCRawTextInfoBlock: '%s'\n", m_text.c_str());
475
476     return result;
477 }
478
479 // ---------
480
481 AVCNameInfoBlock::AVCNameInfoBlock( )
482     : AVCInfoBlock( 0x000B )
483 {}
484
485 AVCNameInfoBlock::~AVCNameInfoBlock( )
486 {
487     clear();
488 }
489
490 bool
491 AVCNameInfoBlock::clear()
492 {
493     return true;
494 }
495
496 bool
497 AVCNameInfoBlock::serialize( Util::IOSSerialize& se )
498 {
499     bool result=true;
500     result &= AVCInfoBlock::serialize(se);
501    
502     if (m_text.size()) {
503         result &= se.write((uint16_t)0x0000, "AVCNameInfoBlock unknown");
504         result &= se.write((uint16_t)0x0000, "AVCNameInfoBlock unknown");
505         result &= se.write((uint16_t)0x0000, "AVCNameInfoBlock unknown length");
506         result &= se.write((uint16_t)0x0000, "AVCNameInfoBlock unknown");
507         result &= se.write((uint16_t)m_text.size(), "AVCNameInfoBlock text length");
508        
509         se.write(m_text.c_str(),m_text.size(), "AVCNameInfoBlock text");
510     }
511     return result;
512 }
513
514 bool
515 AVCNameInfoBlock::deserialize( Util::IISDeserialize& de )
516 {
517     bool result=true;
518     result &= AVCInfoBlock::deserialize(de);
519
520     // FIXME: get the spec somewhere to do this correctly
521     uint16_t dummy16;
522     uint16_t length1;
523     uint16_t text_length;
524    
525     result &= de.read(&dummy16);
526     result &= de.read(&dummy16);
527     result &= de.read(&length1);
528     result &= de.read(&dummy16);
529     result &= de.read(&text_length);
530
531     char *txt;
532     result &= de.read(&txt,text_length);
533     m_text.clear();
534     m_text.append(txt);
535
536     debugOutput(DEBUG_LEVEL_VERBOSE, "Read AVCNameInfoBlock: '%s'\n", m_text.c_str());
537
538     return result;
539 }
540
541 }
Note: See TracBrowser for help on using the browser.