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

Revision 554, 7.2 kB (checked in by ppalmers, 14 years ago)

Merge echoaudio branch into trunk.

This adds support for the Echo Audiofire devices to FFADO. Possibly also other devices working with the Apple Class Driver will work with this code. It is not fully complete yet, but the main rework is
done.

First of all the IAvDevice class/interface is renamed to FFADODevice, in order to separate the AV/C code from the FFADO API code. A device supported by FFADO implements a FFADODevice.

The BeBoB device has been split up into three groups:
- libavc/* : all code and commands that are specified by AV/C specs. Note that a lot of the code that used to be in BeBoB::AvDevice? now resides in AVC::Unit
- genericavc/* : a FFADODevice that uses AV/C descriptors & commands for discovery and config
- bebob/* : the bebob FFADODevice that inherits from GenericAVC::AvDevice? but that uses BridgeCo? commands for discovery

Everything has been moved as high as possible in the class hierarchy. If necessary, a subclass that uses device specific commands is introduced (e.g. BeBoB::Plug inherits from AVC::Plug and uses the
BridgeCo? extended plug info command to discover it's properties).

There are some other fixes along the way that have been done too.

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_VERBOSE );
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 Plug *
69 Subunit::createPlug( AVC::Unit* unit,
70                      AVC::Subunit* subunit,
71                      AVC::function_block_type_t functionBlockType,
72                      AVC::function_block_type_t functionBlockId,
73                      AVC::Plug::EPlugAddressType plugAddressType,
74                      AVC::Plug::EPlugDirection plugDirection,
75                      AVC::plug_id_t plugId )
76 {
77
78     return new Plug( unit,
79                      subunit,
80                      functionBlockType,
81                      functionBlockId,
82                      plugAddressType,
83                      plugDirection,
84                      plugId );
85 }
86
87 bool
88 Subunit::discover()
89 {
90     if ( !discoverPlugs() ) {
91         debugError( "plug discovery failed\n" );
92         return false;
93     }
94
95     return true;
96 }
97
98 bool
99 Subunit::discoverPlugs()
100 {
101     PlugInfoCmd plugInfoCmd( getUnit().get1394Service(),
102                              PlugInfoCmd::eSF_SerialBusIsochronousAndExternalPlug );
103     plugInfoCmd.setNodeId( getUnit().getConfigRom().getNodeId() );
104     plugInfoCmd.setCommandType( AVCCommand::eCT_Status );
105     plugInfoCmd.setSubunitType( getSubunitType() );
106     plugInfoCmd.setSubunitId( getSubunitId() );
107     plugInfoCmd.setVerbose( getDebugLevel() );
108
109     if ( !plugInfoCmd.fire() ) {
110         debugError( "plug info command failed\n" );
111         return false;
112     }
113
114     debugOutput( DEBUG_LEVEL_NORMAL, "number of source plugs = %d\n",
115                  plugInfoCmd.m_sourcePlugs );
116     debugOutput( DEBUG_LEVEL_NORMAL, "number of destination output "
117                  "plugs = %d\n", plugInfoCmd.m_destinationPlugs );
118
119     if ( !discoverPlugs( Plug::eAPD_Input,
120                          plugInfoCmd.m_destinationPlugs ) )
121     {
122         debugError( "destination plug discovering failed\n" );
123         return false;
124     }
125
126     if ( !discoverPlugs(  Plug::eAPD_Output,
127                           plugInfoCmd.m_sourcePlugs ) )
128     {
129         debugError( "source plug discovering failed\n" );
130         return false;
131     }
132
133     return true;
134 }
135
136 bool
137 Subunit::discoverConnections()
138 {
139     debugOutput(DEBUG_LEVEL_NORMAL, "Discovering connections...\n");
140    
141     for ( PlugVector::iterator it = getPlugs().begin();
142           it != getPlugs().end();
143           ++it )
144     {
145         Plug* plug = *it;
146         if ( !plug->discoverConnections() ) {
147             debugError( "plug connection discovering failed ('%s')\n",
148                         plug->getName() );
149             return false;
150         }
151     }
152
153     return true;
154 }
155
156 bool
157 Subunit::discoverPlugs(Plug::EPlugDirection plugDirection,
158                                       plug_id_t plugMaxId )
159 {
160     debugOutput(DEBUG_LEVEL_NORMAL, "Discovering plugs...\n");
161     for ( int plugIdx = 0;
162           plugIdx < plugMaxId;
163           ++plugIdx )
164     {
165         Plug* plug = createPlug(  &getUnit(),
166                                 &getSubunit(),
167                                 0xff,
168                                 0xff,
169                                 Plug::eAPA_SubunitPlug,
170                                 plugDirection,
171                                 plugIdx );
172         if ( !plug ) {
173             debugError( "plug creation failed\n" );
174             return false;
175         }
176        
177         plug->setVerboseLevel(getDebugLevel());
178        
179         if ( !plug->discover() ) {
180             debugError( "plug discover failed\n" );
181             return false;
182         }
183
184         debugOutput( DEBUG_LEVEL_NORMAL, "plug '%s' found\n",
185                      plug->getName() );
186         getPlugs().push_back( plug );
187     }
188     return true;
189 }
190
191 bool
192 Subunit::addPlug( Plug& plug )
193 {
194     m_plugs.push_back( &plug );
195     return true;
196 }
197
198
199 Plug*
200 Subunit::getPlug(Plug::EPlugDirection direction, plug_id_t plugId)
201 {
202     for ( PlugVector::iterator it = m_plugs.begin();
203           it != m_plugs.end();
204           ++it )
205     {
206         Plug* plug = *it;
207         if ( ( plug->getPlugId() == plugId )
208             && ( plug->getDirection() == direction ) )
209         {
210             return plug;
211         }
212     }
213     return 0;
214 }
215
216 bool
217 Subunit::initPlugFromDescriptor( Plug& plug )
218 {
219     debugError("plug loading from descriptor not implemented\n");
220     return false;
221 }
222
223 bool
224 Subunit::serialize( Glib::ustring basePath,
225                                    Util::IOSerialize& ser ) const
226 {
227     bool result;
228
229     result  = ser.write( basePath + "m_sbType", m_sbType );
230     result &= ser.write( basePath + "m_sbId", m_sbId );
231     result &= ser.write( basePath + "m_verboseLevel", getDebugLevel() );
232     result &= serializeChild( basePath, ser );
233
234     return result;
235 }
236
237 Subunit*
238 Subunit::deserialize( Glib::ustring basePath,
239                       Util::IODeserialize& deser,
240                       Unit& unit )
241 {
242     bool result;
243     ESubunitType sbType;
244
245     if ( !deser.isExisting( basePath + "m_sbType" ) ) {
246         return 0;
247     }
248
249     result  = deser.read( basePath + "m_sbType", sbType );
250
251     Subunit* pSubunit = 0;
252    
253     #warning FIXME: The derived class should be creating these
254     // FIXME: The derived class should be creating these, such that discover() can become pure virtual
255     switch( sbType ) {
256     case eST_Audio:
257         pSubunit = new SubunitAudio;
258         break;
259     case eST_Music:
260         pSubunit = new SubunitMusic;
261         break;
262     default:
263         pSubunit = 0;
264     }
265
266     if ( !pSubunit ) {
267         return 0;
268     }
269
270     pSubunit->m_unit = &unit;
271     pSubunit->m_sbType = sbType;
272     result &= deser.read( basePath + "m_sbId", pSubunit->m_sbId );
273     int verboseLevel;
274     result &= deser.read( basePath + "m_verboseLevel", verboseLevel );
275     setDebugLevel(verboseLevel);
276     result &= pSubunit->deserializeChild( basePath, deser, unit );
277
278     if ( !result ) {
279         delete pSubunit;
280         return 0;
281     }
282
283     return pSubunit;
284 }
285
286 }
Note: See TracBrowser for help on using the browser.