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

Revision 560, 7.5 kB (checked in by ppalmers, 16 years ago)

- Sort the FFADODevice vector on GUID before assigning device id's

This results in the same device id for identical device setups,
independent of the way they are connected or the node numbers they
have been assigned.

- Sanitized debug message reporting a bit
- Cosmetic changes

Line 
1 /*
2  * Copyright (C)      2007 by Pieter Palmers
3  * Copyright (C) 2005-2007 by Daniel Wagner
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License version 2.1, as published by the Free Software Foundation;
13  *
14  * This library 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 GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22  * MA 02110-1301 USA
23  */
24
25
26 #include "avc_subunit.h"
27 #include "../general/avc_unit.h"
28 #include "../general/avc_plug.h"
29
30 #include "libieee1394/configrom.h"
31
32 #include "../general/avc_plug_info.h"
33 #include "../streamformat/avc_extended_stream_format.h"
34 #include "../util/avc_serialize.h"
35
36 #include <sstream>
37
38 namespace AVC {
39
40 IMPL_DEBUG_MODULE( Subunit, Subunit, DEBUG_LEVEL_NORMAL );
41
42 ////////////////////////////////////////////
43
44 Subunit::Subunit( Unit& unit,
45                   ESubunitType type,
46                   subunit_t id )
47     : m_unit( &unit )
48     , m_sbType( type )
49     , m_sbId( id )
50 {
51
52 }
53
54 Subunit::Subunit()
55 {
56 }
57
58 Subunit::~Subunit()
59 {
60     for ( PlugVector::iterator it = m_plugs.begin();
61           it != m_plugs.end();
62           ++it )
63     {
64         delete *it;
65     }
66 }
67
68 void
69 Subunit::setVerboseLevel(int l)
70 {
71     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
72     setDebugLevel(l);
73 }
74
75
76 Plug *
77 Subunit::createPlug( AVC::Unit* unit,
78                      AVC::Subunit* subunit,
79                      AVC::function_block_type_t functionBlockType,
80                      AVC::function_block_type_t functionBlockId,
81                      AVC::Plug::EPlugAddressType plugAddressType,
82                      AVC::Plug::EPlugDirection plugDirection,
83                      AVC::plug_id_t plugId )
84 {
85
86     return new Plug( unit,
87                      subunit,
88                      functionBlockType,
89                      functionBlockId,
90                      plugAddressType,
91                      plugDirection,
92                      plugId );
93 }
94
95 bool
96 Subunit::discover()
97 {
98     if ( !discoverPlugs() ) {
99         debugError( "plug discovery failed\n" );
100         return false;
101     }
102     return true;
103 }
104
105 bool
106 Subunit::discoverPlugs()
107 {
108     debugOutput(DEBUG_LEVEL_NORMAL, "Discovering plugs...\n");
109    
110     PlugInfoCmd plugInfoCmd( getUnit().get1394Service(),
111                              PlugInfoCmd::eSF_SerialBusIsochronousAndExternalPlug );
112     plugInfoCmd.setNodeId( getUnit().getConfigRom().getNodeId() );
113     plugInfoCmd.setCommandType( AVCCommand::eCT_Status );
114     plugInfoCmd.setSubunitType( getSubunitType() );
115     plugInfoCmd.setSubunitId( getSubunitId() );
116     plugInfoCmd.setVerbose( getDebugLevel() );
117
118     if ( !plugInfoCmd.fire() ) {
119         debugError( "plug info command failed\n" );
120         return false;
121     }
122
123     debugOutput( DEBUG_LEVEL_VERBOSE, "number of source plugs = %d\n",
124                  plugInfoCmd.m_sourcePlugs );
125     debugOutput( DEBUG_LEVEL_VERBOSE, "number of destination output "
126                  "plugs = %d\n", plugInfoCmd.m_destinationPlugs );
127
128     if ( !discoverPlugs( Plug::eAPD_Input,
129                          plugInfoCmd.m_destinationPlugs ) )
130     {
131         debugError( "destination plug discovering failed\n" );
132         return false;
133     }
134
135     if ( !discoverPlugs(  Plug::eAPD_Output,
136                           plugInfoCmd.m_sourcePlugs ) )
137     {
138         debugError( "source plug discovering failed\n" );
139         return false;
140     }
141
142     return true;
143 }
144
145 bool
146 Subunit::discoverConnections()
147 {
148     debugOutput(DEBUG_LEVEL_NORMAL, "Discovering connections...\n");
149    
150     for ( PlugVector::iterator it = getPlugs().begin();
151           it != getPlugs().end();
152           ++it )
153     {
154         Plug* plug = *it;
155         if ( !plug->discoverConnections() ) {
156             debugError( "plug connection discovering failed ('%s')\n",
157                         plug->getName() );
158             return false;
159         }
160     }
161
162     return true;
163 }
164
165 bool
166 Subunit::discoverPlugs(Plug::EPlugDirection plugDirection,
167                                       plug_id_t plugMaxId )
168 {
169     debugOutput(DEBUG_LEVEL_VERBOSE, "Discovering plugs for direction %d...\n", plugDirection);
170     for ( int plugIdx = 0;
171           plugIdx < plugMaxId;
172           ++plugIdx )
173     {
174         Plug* plug = createPlug(  &getUnit(),
175                                 &getSubunit(),
176                                 0xff,
177                                 0xff,
178                                 Plug::eAPA_SubunitPlug,
179                                 plugDirection,
180                                 plugIdx );
181         if ( !plug ) {
182             debugError( "plug creation failed\n" );
183             return false;
184         }
185        
186         plug->setVerboseLevel(getDebugLevel());
187        
188         if ( !plug->discover() ) {
189             debugError( "plug discover failed\n" );
190             return false;
191         }
192
193         debugOutput( DEBUG_LEVEL_VERBOSE, "plug '%s' found\n",
194                      plug->getName() );
195         getPlugs().push_back( plug );
196     }
197     return true;
198 }
199
200 bool
201 Subunit::addPlug( Plug& plug )
202 {
203     m_plugs.push_back( &plug );
204     return true;
205 }
206
207
208 Plug*
209 Subunit::getPlug(Plug::EPlugDirection direction, plug_id_t plugId)
210 {
211     for ( PlugVector::iterator it = m_plugs.begin();
212           it != m_plugs.end();
213           ++it )
214     {
215         Plug* plug = *it;
216         if ( ( plug->getPlugId() == plugId )
217             && ( plug->getDirection() == direction ) )
218         {
219             return plug;
220         }
221     }
222     return 0;
223 }
224
225 bool
226 Subunit::initPlugFromDescriptor( Plug& plug )
227 {
228     debugError("plug loading from descriptor not implemented\n");
229     return false;
230 }
231
232 bool
233 Subunit::serialize( Glib::ustring basePath,
234                                    Util::IOSerialize& ser ) const
235 {
236     bool result;
237
238     result  = ser.write( basePath + "m_sbType", m_sbType );
239     result &= ser.write( basePath + "m_sbId", m_sbId );
240     result &= ser.write( basePath + "m_verboseLevel", getDebugLevel() );
241     result &= serializeChild( basePath, ser );
242
243     return result;
244 }
245
246 Subunit*
247 Subunit::deserialize( Glib::ustring basePath,
248                       Util::IODeserialize& deser,
249                       Unit& unit )
250 {
251     bool result;
252     ESubunitType sbType;
253
254     if ( !deser.isExisting( basePath + "m_sbType" ) ) {
255         return 0;
256     }
257
258     result  = deser.read( basePath + "m_sbType", sbType );
259
260     Subunit* pSubunit = 0;
261    
262     #warning FIXME: The derived class should be creating these
263     // FIXME: The derived class should be creating these, such that discover() can become pure virtual
264     switch( sbType ) {
265     case eST_Audio:
266         pSubunit = new SubunitAudio;
267         break;
268     case eST_Music:
269         pSubunit = new SubunitMusic;
270         break;
271     default:
272         pSubunit = 0;
273     }
274
275     if ( !pSubunit ) {
276         return 0;
277     }
278
279     pSubunit->m_unit = &unit;
280     pSubunit->m_sbType = sbType;
281     result &= deser.read( basePath + "m_sbId", pSubunit->m_sbId );
282     int verboseLevel;
283     result &= deser.read( basePath + "m_verboseLevel", verboseLevel );
284     setDebugLevel(verboseLevel);
285     result &= pSubunit->deserializeChild( basePath, deser, unit );
286
287     if ( !result ) {
288         delete pSubunit;
289         return 0;
290     }
291
292     return pSubunit;
293 }
294
295 }
Note: See TracBrowser for help on using the browser.