root/trunk/libffado/src/libavc/general/avc_generic.cpp

Revision 783, 8.7 kB (checked in by ppalmers, 14 years ago)

cleanup time/wait/sleep code

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