root/branches/echoaudio/src/libavc/general/avc_generic.cpp

Revision 502, 8.6 kB (checked in by ppalmers, 17 years ago)

Restructure the libavc directory in order to improve maintainability when
extending the implemented AV/C standards. The new directory structure is
a reflection of the specifications: the files in each directory (roughly)
correspond to the same specification.

The breakdown is:

general : AV/C Digital Interface Command Set General Specification
audiosubunit : Audio Subunit Specification
musicsubunit : Music Subunit Specification
ccm : Connection and Compatibility Management Specification
descriptors : AV/C Descriptor Mechanism Specification

util : Various utility classes (not from specs)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2007 by Daniel Wagner
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_generic.h"
25 #include "../util/avc_serialize.h"
26 #include "libieee1394/ieee1394service.h"
27
28 #include "debugmodule/debugmodule.h"
29
30 #include <netinet/in.h>
31
32 #define DEBUG_EXTRA_VERBOSE 5
33
34 IMPL_DEBUG_MODULE( AVCCommand, AVCCommand, DEBUG_LEVEL_NORMAL );
35 IMPL_DEBUG_MODULE( IBusData, IBusData, DEBUG_LEVEL_VERBOSE );
36
37 int AVCCommand::m_time = 0;
38
39 AVCCommand::AVCCommand( Ieee1394Service& ieee1394service,
40                         opcode_t opcode )
41     : m_p1394Service( &ieee1394service )
42     , m_nodeId( 0 )
43     , m_ctype( eCT_Unknown )
44     , m_subunit( 0xff )
45     , m_opcode( opcode )
46     , m_eResponse( eR_Unknown )
47 {
48
49 }
50
51 bool
52 AVCCommand::serialize( IOSSerialize& se )
53 {
54     // XXX \todo improve IOSSerialize::write interface
55     char* buf;
56     asprintf( &buf, "AVCCommand ctype ('%s')",
57               responseToString( static_cast<AVCCommand::EResponse>( m_ctype ) ) );
58     se.write( m_ctype, buf );
59     free( buf );
60
61     asprintf( &buf, "AVCCommand subunit (subunit_type = %d, subunit_id = %d)",
62               getSubunitType(), getSubunitId() );
63     se.write( m_subunit, buf );
64     free( buf );
65
66     se.write( m_opcode, "AVCCommand opcode" );
67     return true;
68 }
69
70 bool
71 AVCCommand::deserialize( IISDeserialize& de )
72 {
73     de.read( &m_ctype );
74     de.read( &m_subunit );
75     de.read( &m_opcode );
76     return true;
77 }
78
79 bool
80 AVCCommand::setCommandType( ECommandType commandType )
81 {
82     m_ctype = commandType;
83     m_commandType = commandType;
84     return true;
85 }
86
87 AVCCommand::ECommandType
88 AVCCommand::getCommandType()
89 {
90     return m_commandType;
91 }
92
93 AVCCommand::EResponse
94 AVCCommand::getResponse()
95 {
96     return m_eResponse;
97 }
98
99 bool
100 AVCCommand::setSubunitType(ESubunitType subunitType)
101 {
102     byte_t subT = subunitType;
103
104     m_subunit = ( subT << 3 ) | ( m_subunit & 0x7 );
105     return true;
106 }
107
108 bool
109 AVCCommand::setNodeId( fb_nodeid_t nodeId )
110 {
111     m_nodeId = nodeId;
112     return true;
113 }
114
115 bool
116 AVCCommand::setSubunitId(subunit_id_t subunitId)
117 {
118     m_subunit = ( subunitId & 0x7 ) | ( m_subunit & 0xf8 );
119     return true;
120 }
121
122 ESubunitType
123 AVCCommand::getSubunitType()
124 {
125     return static_cast<ESubunitType>( ( m_subunit >> 3 ) );
126 }
127
128 subunit_id_t
129 AVCCommand::getSubunitId()
130 {
131     return m_subunit & 0x7;
132 }
133
134 bool
135 AVCCommand::setVerbose( int verboseLevel )
136 {
137     setDebugLevel(verboseLevel);
138     return true;
139 }
140
141 int
142 AVCCommand::getVerboseLevel()
143 {
144     return getDebugLevel();
145 }
146
147
148 void
149 AVCCommand::showFcpFrame( const unsigned char* buf,
150                           unsigned short frameSize ) const
151 {
152     // use an intermediate buffer to avoid a load of very small print's that cause the
153     // message ringbuffer to overflow
154     char msg[DEBUG_MAX_MESSAGE_LENGTH];
155     int chars_written=0;
156     for ( int i = 0; i < frameSize; ++i ) {
157         if ( ( i % 16 ) == 0 ) {
158             if ( i > 0 ) {
159                 debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, "%s\n", msg);
160                 chars_written=0;
161             }
162             chars_written+=snprintf(msg+chars_written,DEBUG_MAX_MESSAGE_LENGTH-chars_written,"  %3d:\t", i );;
163         } else if ( ( i % 4 ) == 0 ) {
164             chars_written+=snprintf(msg+chars_written,DEBUG_MAX_MESSAGE_LENGTH-chars_written," ");
165         }
166         chars_written+=snprintf(msg+chars_written,DEBUG_MAX_MESSAGE_LENGTH-chars_written, "%02x ", buf[i] );
167     }
168     if (chars_written != 0) {
169         debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, "%s\n", msg );
170     } else {
171         debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, "\n" );
172     }
173 }
174
175 bool
176 AVCCommand::fire()
177 {
178     memset( &m_fcpFrame,  0x0,  sizeof( m_fcpFrame ) );
179
180     BufferSerialize se( m_fcpFrame, sizeof( m_fcpFrame ) );
181     if ( !serialize( se ) ) {
182         debugFatal(  "fire: Could not serialize\n" );
183         return false;
184     }
185
186     unsigned short fcpFrameSize = se.getNrOfProducesBytes();
187
188     if (getDebugLevel() >= DEBUG_LEVEL_VERY_VERBOSE) {
189         debugOutputShort( DEBUG_LEVEL_VERY_VERBOSE, "%s:\n", getCmdName() );
190         debugOutputShort( DEBUG_LEVEL_VERY_VERBOSE,  "  Request:\n");
191         showFcpFrame( m_fcpFrame, fcpFrameSize );
192
193         StringSerializer se_dbg;
194         serialize( se_dbg );
195        
196         // output the debug message in smaller chunks to avoid problems
197         // with a max message size
198         unsigned int chars_to_write=se_dbg.getString().size();
199         unsigned int chars_written=0;
200         while (chars_written<chars_to_write) {
201             debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, "%s\n",
202                          se_dbg.getString().substr(chars_written, DEBUG_MAX_MESSAGE_LENGTH).c_str());
203             chars_written += DEBUG_MAX_MESSAGE_LENGTH-1;
204         }
205     }
206
207     unsigned int resp_len;
208     quadlet_t* resp = m_p1394Service->transactionBlock( m_nodeId,
209                                                         (quadlet_t*)m_fcpFrame,
210                                                         ( fcpFrameSize+3 ) / 4,
211                                                         &resp_len );
212     bool result = false;
213     if ( resp ) {
214         resp_len *= 4;
215         unsigned char* buf = ( unsigned char* ) resp;
216
217         m_eResponse = ( EResponse )( *buf );
218         switch ( m_eResponse )
219         {
220         case eR_Accepted:
221         case eR_Implemented:
222         case eR_Rejected:
223         case eR_NotImplemented:
224         {
225             BufferDeserialize de( buf, resp_len );
226             result = deserialize( de );
227
228             debugOutputShort( DEBUG_LEVEL_VERY_VERBOSE,"  Response:\n");
229             showFcpFrame( buf, de.getNrOfConsumedBytes() );
230
231             StringSerializer se_dbg;
232             serialize( se_dbg );
233
234             // output the debug message in smaller chunks to avoid problems
235             // with a max message size
236             unsigned int chars_to_write=se_dbg.getString().size();
237             unsigned int chars_written=0;
238             while (chars_written<chars_to_write) {
239                 debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, "%s\n",
240                             se_dbg.getString().substr(chars_written, DEBUG_MAX_MESSAGE_LENGTH).c_str());
241                 chars_written += DEBUG_MAX_MESSAGE_LENGTH-1;
242             }
243
244         }
245         break;
246         default:
247             debugWarning( "unexpected response received (0x%x)\n", m_eResponse );
248             debugOutputShort( DEBUG_LEVEL_VERY_VERBOSE,"  Response:\n");
249
250             BufferDeserialize de( buf, resp_len );
251             deserialize( de );
252
253             showFcpFrame( buf, de.getNrOfConsumedBytes() );
254
255         }
256     } else {
257        debugWarning( "no response\n" );
258     }
259
260     debugOutputShort( DEBUG_LEVEL_VERY_VERBOSE, "\n" );
261
262     m_p1394Service->transactionBlockClose();
263
264     usleep( m_time );
265
266     return result;
267 }
268
269 void
270 AVCCommand::setSleepAfterAVCCommand( int time )
271 {
272     m_time = time;
273 }
274
275 const char* subunitTypeStrings[] =
276 {
277     "Monitor",
278     "Audio",
279     "Printer",
280     "Disc recorder",
281     "Tape recorder/VCR",
282     "Tuner",
283     "CA",
284     "Video camera",
285     "unknown",
286     "Panel",
287     "Bulletin board",
288     "Camera storage",
289     "Music",
290 };
291
292 const char*
293 subunitTypeToString( subunit_type_t subunitType )
294 {
295     if ( subunitType == eST_Unit ) {
296         return "Unit";
297     }
298     if ( subunitType > ( int ) ( sizeof( subunitTypeStrings )
299              / sizeof( subunitTypeStrings[0] ) ) ) {
300         return "unknown";
301     } else {
302         return subunitTypeStrings[subunitType];
303     }
304 }
305
306 const char* responseToStrings[] =
307 {
308     "control",
309     "status",
310     "specific inquiry",
311     "notify",
312     "general inquiry",
313     "reserved for future specification",
314     "reserved for future specification",
315     "reserved for future specification",
316     "not implemented",
317     "accepted",
318     "rejected",
319     "in transition",
320     "implemented/stable",
321     "changed"
322     "reserved for future specification",
323     "interim",
324 };
325
326 const char*
327 responseToString( AVCCommand::EResponse eResponse )
328 {
329     if ( eResponse > ( int )( sizeof( responseToStrings ) / sizeof( responseToStrings[0] ) ) ) {
330         return "unknown";
331     }
332     return responseToStrings[eResponse];
333 }
Note: See TracBrowser for help on using the browser.