root/branches/libfreebob-2.0/src/devicemanager.cpp

Revision 262, 11.0 kB (checked in by jwoithe, 18 years ago)

Make skeleton MOTU device discovery work. Proof-of-concept MOTU sample rate
control in place.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* devicemanager.cpp
2  * Copyright (C) 2005,06 by Daniel Wagner
3  *
4  * This file is part of FreeBob.
5  *
6  * FreeBob is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * FreeBob is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with FreeBob; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20
21 #include "fbtypes.h"
22
23 #include "devicemanager.h"
24 #include "iavdevice.h"
25 #include "configrom.h"
26
27 #include "libfreebobavc/ieee1394service.h"
28 #include "debugmodule/debugmodule.h"
29 #include "bebob/bebob_avdevice.h"
30 #include "bebob_light/bebob_light_avdevice.h"
31 #include "bounce/bounce_avdevice.h"
32 #include "motu/motu_avdevice.h"
33
34 #include <iostream>
35 #include <unistd.h>
36
37 // Unit directory SpecifierID/Version identifying a true Bebob AVC device
38 #define BEBOB_AVCDEVICE_UNIT_SPECIFIER   0x0000a02d
39 #define BEBOB_AVCDEVICE_UNIT_VERSION     0x10001
40
41 using namespace std;
42
43 IMPL_DEBUG_MODULE( DeviceManager, DeviceManager, DEBUG_LEVEL_NORMAL );
44
45 DeviceManager::DeviceManager()
46     : m_1394Service( 0 )
47 {
48     m_probeList.push_back( probeBeBoB );
49     m_probeList.push_back( probeMotu );
50     m_probeList.push_back( probeBounce );
51 }
52
53 DeviceManager::~DeviceManager()
54 {
55     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
56           it != m_avDevices.end();
57           ++it )
58     {
59         delete *it;
60     }
61
62     delete m_1394Service;
63 }
64
65 bool
66 DeviceManager::initialize( int port )
67 {
68     m_1394Service = new Ieee1394Service();
69     if ( !m_1394Service ) {
70         debugFatal( "Could not create Ieee1349Service object\n" );
71         return false;
72     }
73
74     if ( !m_1394Service->initialize( port ) ) {
75         debugFatal( "Could not initialize Ieee1349Service object\n" );
76         delete m_1394Service;
77         m_1394Service = 0;
78         return false;
79     }
80
81     return true;
82 }
83
84 bool
85 DeviceManager::discover( int verboseLevel )
86 {
87     if ( verboseLevel ) {
88         setDebugLevel( DEBUG_LEVEL_VERBOSE );
89     }
90     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
91           it != m_avDevices.end();
92           ++it )
93     {
94         delete *it;
95     }
96     m_avDevices.clear();
97
98     for ( fb_nodeid_t nodeId = 0;
99           nodeId < m_1394Service->getNodeCount();
100           ++nodeId )
101     {
102         ConfigRom configRom( m_1394Service, nodeId );
103         if ( !configRom.initialize() ) {
104             // \todo If a PHY on the bus in power safe mode than
105             // the config rom is missing. So this might be just
106             // such a case and we can safely skip it. But it might
107             // be there is a real software problem on our side.
108             // This should be handled more carefuly.
109             debugOutput( DEBUG_LEVEL_NORMAL,
110                          "Could not read config rom from device (node id %d). "
111                          "Skip device discovering for this node\n",
112                          nodeId );
113             continue;
114         }
115
116         for ( ProbeFunctionVector::iterator it = m_probeList.begin();
117               it != m_probeList.end();
118               ++it )
119         {
120             ProbeFunction func = *it;
121             IAvDevice* avDevice = func(*m_1394Service, configRom, nodeId, verboseLevel);
122             if ( avDevice ) {
123                 m_avDevices.push_back( avDevice );
124                 if (!avDevice->setId(m_avDevices.size())) {
125                     debugError("Could not set Id of AvDevice\n");
126                 }
127                 if ( verboseLevel ) {
128                     avDevice->showDevice();
129                 }
130                 break;
131             }
132         }
133
134     }
135
136     return true;
137 }
138
139
140 IAvDevice*
141 DeviceManager::probeBeBoB(Ieee1394Service& service, ConfigRom& configRom, int id, int level)
142 {
143     IAvDevice* avDevice;
144
145     // All BeBob devices have predictable unit specifier/version fields
146     if (configRom.getUnitSpecifierId() != BEBOB_AVCDEVICE_UNIT_SPECIFIER ||
147         configRom.getUnitVersion() == BEBOB_AVCDEVICE_UNIT_VERSION) {
148         debugOutput( DEBUG_LEVEL_VERBOSE, "Not a BeBoB device...\n" );
149         return NULL;
150     }
151
152     avDevice = new BeBoB_Light::AvDevice( service, id, level );
153     if ( !avDevice ) {
154         return NULL;
155     }
156
157     if ( !avDevice->discover() ) {
158         delete avDevice;
159         debugOutput( DEBUG_LEVEL_VERBOSE, "Not a BeBoB device...\n" );
160         return NULL;
161     }
162     debugOutput( DEBUG_LEVEL_VERBOSE, "BeBoB device discovered...\n" );
163     return avDevice;
164 }
165
166 IAvDevice*
167 DeviceManager::probeBounce(Ieee1394Service& service, ConfigRom& configRom, int id, int level)
168 {
169     IAvDevice* avDevice;
170
171     // All Bounce devices have predictable unit specifier/version fields
172     if (configRom.getUnitSpecifierId() != BEBOB_AVCDEVICE_UNIT_SPECIFIER ||
173         configRom.getUnitVersion() == BEBOB_AVCDEVICE_UNIT_VERSION) {
174         debugOutput( DEBUG_LEVEL_VERBOSE, "Not a Bounce device...\n" );
175         return NULL;
176     }
177
178     avDevice = new Bounce::BounceDevice( service, id, level );
179     if ( !avDevice ) {
180         return NULL;
181     }
182
183     if ( !avDevice->discover() ) {
184         debugOutput( DEBUG_LEVEL_VERBOSE, "Not a Bounce device...\n");
185         delete avDevice;
186         return NULL;
187     }
188     debugOutput( DEBUG_LEVEL_VERBOSE, "Bounce device discovered...\n");
189    
190     return avDevice;
191 }
192
193 IAvDevice*
194 DeviceManager::probeMotu(Ieee1394Service& service, ConfigRom& configRom, int id, int level)
195 {
196     IAvDevice* avDevice = new Motu::MotuDevice( service, id, level );
197     if ( !avDevice ) {
198         return NULL;
199     }
200
201     // MOTU's discover() needs to differentiate between different models,
202     // so for now keep all probing code in there since it's very intermingled.
203     // The code is robust in the event that the device isn't a MOTU, so
204     // at this stage there seems no reason to do otherwise.
205     if ( !avDevice->discover() ) {
206         debugOutput( DEBUG_LEVEL_VERBOSE, "Not a MOTU device...\n");
207         delete avDevice;
208         return NULL;
209     }
210     debugOutput( DEBUG_LEVEL_VERBOSE, "MOTU device discovered...\n");
211
212     return avDevice;
213 }
214
215 bool
216 DeviceManager::isValidNode(int node)
217 {
218     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
219           it != m_avDevices.end();
220           ++it )
221     {
222         IAvDevice* avDevice = *it;
223
224         if (avDevice->getConfigRom().getNodeId() == node) {
225                 return true;
226         }
227     }
228     return false;
229 }
230
231 int
232 DeviceManager::getNbDevices()
233 {
234     return m_avDevices.size();
235 }
236
237 int
238 DeviceManager::getDeviceNodeId( int deviceNr )
239 {
240     if ( ! ( deviceNr < getNbDevices() ) ) {
241         debugError( "Device number out of range (%d)\n", deviceNr );
242         return -1;
243     }
244
245     IAvDevice* avDevice = m_avDevices.at( deviceNr );
246
247     if ( !avDevice ) {
248         debugError( "Could not get device at position (%d)\n",  deviceNr );
249     }
250
251     return avDevice->getConfigRom().getNodeId();
252 }
253
254 IAvDevice*
255 DeviceManager::getAvDevice( int nodeId )
256 {
257     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
258           it != m_avDevices.end();
259           ++it )
260     {
261         IAvDevice* avDevice = *it;
262         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
263             return avDevice;
264         }
265     }
266
267     return 0;
268 }
269
270 IAvDevice*
271 DeviceManager::getAvDeviceByIndex( int idx )
272 {
273         return m_avDevices.at(idx);
274 }
275
276 unsigned int
277 DeviceManager::getAvDeviceCount( )
278 {
279         return m_avDevices.size();
280 }
281
282 xmlDocPtr
283 DeviceManager::getXmlDescription()
284 {
285     xmlDocPtr doc = xmlNewDoc( BAD_CAST "1.0" );
286     if ( !doc ) {
287         debugError( "Couldn't create new xml doc\n" );
288         return 0;
289     }
290
291     xmlNodePtr rootNode = xmlNewNode( 0,  BAD_CAST "FreeBobConnectionInfo" );
292     if ( !rootNode ) {
293         debugError( "Couldn't create root node\n" );
294         xmlFreeDoc( doc );
295         xmlCleanupParser();
296         return 0;
297     }
298     xmlDocSetRootElement( doc, rootNode );
299
300     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
301           it != m_avDevices.end();
302           ++it )
303     {
304         IAvDevice* avDevice = *it;
305
306         xmlNodePtr deviceNode = xmlNewChild( rootNode, 0,
307                                              BAD_CAST "Device", 0 );
308         if ( !deviceNode ) {
309             debugError( "Couldn't create device node\n" );
310             xmlFreeDoc( doc );
311             xmlCleanupParser();
312             return 0;
313         }
314
315         char* result;
316         asprintf( &result, "%d", avDevice->getConfigRom().getNodeId() );
317         if ( !xmlNewChild( deviceNode,  0,
318                            BAD_CAST "NodeId",  BAD_CAST result ) )
319         {
320             debugError( "Couldn't create 'NodeId' node" );
321             free(result);
322             return false;
323         }
324
325         std::string res = "Connection Information for "
326                           + avDevice->getConfigRom().getVendorName()
327                           +", "
328                           + avDevice->getConfigRom().getModelName()
329                           + " configuration";
330         if ( !xmlNewChild( deviceNode,
331                            0,
332                            BAD_CAST "Comment",
333                            BAD_CAST res.c_str() ) ) {
334             debugError( "Couldn't create comment node\n" );
335             xmlFreeDoc( doc );
336             xmlCleanupParser();
337             free(result);
338             return 0;
339         }
340
341         res = avDevice->getConfigRom().getVendorName();
342
343         if ( !xmlNewChild( deviceNode,
344                            0,
345                            BAD_CAST "Vendor",
346                            BAD_CAST res.c_str() ) ) {
347             debugError( "Couldn't create vendor node\n" );
348             xmlFreeDoc( doc );
349             xmlCleanupParser();
350             free(result);
351             return 0;
352         }
353
354         res = avDevice->getConfigRom().getModelName();
355
356         if ( !xmlNewChild( deviceNode,
357                            0,
358                            BAD_CAST "Model",
359                            BAD_CAST res.c_str() ) ) {
360             debugError( "Couldn't create model node\n" );
361             xmlFreeDoc( doc );
362             xmlCleanupParser();
363             free(result);
364             return 0;
365         }
366
367         asprintf( &result, "%08x%08x",
368                   ( quadlet_t )( avDevice->getConfigRom().getGuid() >> 32 ),
369                   ( quadlet_t )( avDevice->getConfigRom().getGuid() & 0xfffffff ) );
370         if ( !xmlNewChild( deviceNode,  0,
371                            BAD_CAST "GUID",  BAD_CAST result ) ) {
372             debugError( "Couldn't create 'GUID' node\n" );
373             xmlFreeDoc( doc );
374             xmlCleanupParser();
375             free(result);
376             return false;
377         }
378
379         if ( !avDevice->addXmlDescription( deviceNode ) ) {
380             debugError( "Adding XML description failed\n" );
381             xmlFreeDoc( doc );
382             xmlCleanupParser();
383             free(result);
384             return 0;
385         }
386        
387         free(result);
388     }
389
390     return doc;
391 }
392
393 bool
394 DeviceManager::deinitialize()
395 {
396     return true;
397 }
398
Note: See TracBrowser for help on using the browser.