root/trunk/libffado/src/bebob/bebob_avdevice.cpp

Revision 580, 16.4 kB (checked in by ppalmers, 16 years ago)

move vendor specific stuff to vendor directory

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 "config.h"
25
26 #include "bebob/bebob_avdevice.h"
27 #include "bebob/bebob_avdevice_subunit.h"
28 #include "bebob/bebob_mixer.h"
29
30 #include "bebob/focusrite/focusrite.h"
31 #include "bebob/terratec/terratec.h"
32
33 #include "libieee1394/configrom.h"
34 #include "libieee1394/ieee1394service.h"
35
36 #include "genericavc/avc_vendormodel.h"
37
38 #include "libavc/general/avc_plug_info.h"
39 #include "libavc/general/avc_extended_plug_info.h"
40 #include "libavc/general/avc_subunit_info.h"
41 #include "libavc/streamformat/avc_extended_stream_format.h"
42 #include "libavc/util/avc_serialize.h"
43 #include "libavc/avc_definitions.h"
44
45 #include "debugmodule/debugmodule.h"
46
47 #include <iostream>
48 #include <sstream>
49 #include <unistd.h>
50 #include <sys/stat.h>
51
52 using namespace AVC;
53
54 namespace BeBoB {
55
56 static GenericAVC::VendorModelEntry supportedDeviceList[] =
57 {
58     {0x00000f, 0x00010065, "Mackie", "Onyx Firewire"},
59
60     {0x0003db, 0x00010048, "Apogee Electronics", "Rosetta 200"},
61
62     {0x0007f5, 0x00010048, "BridgeCo", "RD Audio1"},
63
64     {0x000a92, 0x00010000, "PreSonus", "FIREBOX"},
65     {0x000a92, 0x00010066, "PreSonus", "FirePOD"},
66
67     {0x000aac, 0x00000003, "TerraTec Electronic GmbH", "Phase 88 FW"},
68     {0x000aac, 0x00000004, "TerraTec Electronic GmbH", "Phase X24 FW (model version 4)"},
69     {0x000aac, 0x00000007, "TerraTec Electronic GmbH", "Phase X24 FW (model version 7)"},
70
71     {0x000f1b, 0x00010064, "ESI", "Quatafire 610"},
72
73     {0x00130e, 0x00000000, "Focusrite", "Saffire (LE)"},
74     {0x00130e, 0x00000003, "Focusrite", "Saffire Pro26IO"},
75     {0x00130e, 0x00000006, "Focusrite", "Saffire Pro10IO"},
76
77     {0x0040ab, 0x00010048, "EDIROL", "FA-101"},
78     {0x0040ab, 0x00010049, "EDIROL", "FA-66"},
79
80     {0x000d6c, 0x00010062, "M-Audio", "FW Solo"},
81     {0x000d6c, 0x00010081, "M-Audio", "NRV10"},
82 };
83
84 AvDevice::AvDevice( std::auto_ptr< ConfigRom >( configRom ),
85                     Ieee1394Service& ieee1394service,
86                     int nodeId )
87     : GenericAVC::AvDevice( configRom, ieee1394service, nodeId )
88     , m_Mixer ( NULL )
89 {
90     debugOutput( DEBUG_LEVEL_VERBOSE, "Created BeBoB::AvDevice (NodeID %d)\n",
91                  nodeId );
92 }
93
94 AvDevice::~AvDevice()
95 {
96     if(m_Mixer != NULL) {
97         delete m_Mixer;
98     }
99 }
100
101 void
102 AvDevice::showDevice()
103 {
104     debugOutput(DEBUG_LEVEL_NORMAL, "Device is a BeBoB device\n");
105     GenericAVC::AvDevice::showDevice();
106     flushDebugOutput();
107 }
108
109 AVC::Subunit*
110 AvDevice::createSubunit(AVC::Unit& unit,
111                         AVC::ESubunitType type,
112                         AVC::subunit_t id )
113 {
114     AVC::Subunit* s=NULL;
115     switch (type) {
116         case eST_Audio:
117             s=new BeBoB::SubunitAudio(unit, id );
118             break;
119         case eST_Music:
120             s=new BeBoB::SubunitMusic(unit, id );
121             break;
122         default:
123             s=NULL;
124             break;
125     }
126     if(s) s->setVerboseLevel(getDebugLevel());
127     return s;
128 }
129
130
131 AVC::Plug *
132 AvDevice::createPlug( AVC::Unit* unit,
133                       AVC::Subunit* subunit,
134                       AVC::function_block_type_t functionBlockType,
135                       AVC::function_block_type_t functionBlockId,
136                       AVC::Plug::EPlugAddressType plugAddressType,
137                       AVC::Plug::EPlugDirection plugDirection,
138                       AVC::plug_id_t plugId )
139 {
140
141     Plug *p= new BeBoB::Plug( unit,
142                               subunit,
143                               functionBlockType,
144                               functionBlockId,
145                               plugAddressType,
146                               plugDirection,
147                               plugId );
148     if (p) p->setVerboseLevel(getDebugLevel());
149     return p;
150 }
151
152 bool
153 AvDevice::probe( ConfigRom& configRom )
154 {
155     unsigned int vendorId = configRom.getNodeVendorId();
156     unsigned int modelId = configRom.getModelId();
157
158     //GenericAVC::VendorModel vendorModel( "/home/wagi/src/libffado/src/bebob/ffado_driver_bebob.txt" );
159
160     for ( unsigned int i = 0;
161           i < ( sizeof( supportedDeviceList )/sizeof( GenericAVC::VendorModelEntry ) );
162           ++i )
163     {
164         if ( ( supportedDeviceList[i].vendor_id == vendorId )
165              && ( supportedDeviceList[i].model_id == modelId ) )
166         {
167             return true;
168         }
169     }
170     return false;
171 }
172
173 bool
174 AvDevice::discover()
175 {
176     unsigned int vendorId = m_pConfigRom->getNodeVendorId();
177     unsigned int modelId = m_pConfigRom->getModelId();
178
179     for ( unsigned int i = 0;
180           i < ( sizeof( supportedDeviceList )/sizeof( GenericAVC::VendorModelEntry ) );
181           ++i )
182     {
183         if ( ( supportedDeviceList[i].vendor_id == vendorId )
184              && ( supportedDeviceList[i].model_id == modelId )
185            )
186         {
187             m_model = &(supportedDeviceList[i]);
188             break;
189         }
190     }
191
192     if (m_model != NULL) {
193         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
194                 m_model->vendor_name, m_model->model_name);
195     } else return false;
196
197     if ( !Unit::discover() ) {
198         debugError( "Could not discover unit\n" );
199         return false;
200     }
201
202     if((getAudioSubunit( 0 ) == NULL)) {
203         debugError( "Unit doesn't have an Audio subunit.\n");
204         return false;
205     }
206     if((getMusicSubunit( 0 ) == NULL)) {
207         debugError( "Unit doesn't have a Music subunit.\n");
208         return false;
209     }
210
211     // create a Mixer
212     // this removes the mixer if it already exists
213     // note: a mixer self-registers to it's parent
214     if(m_Mixer != NULL) {
215         delete m_Mixer;
216     }
217
218 //      create the mixer & register it
219     if(getAudioSubunit(0) == NULL) {
220         debugWarning("Could not find audio subunit, mixer not available.\n");
221         m_Mixer = NULL;
222     } else {
223         m_Mixer = new Mixer(*this);
224     }
225     return true;
226 }
227
228 bool
229 AvDevice::propagatePlugInfo() {
230     // we don't have to propagate since we discover things
231     // another way
232     debugOutput(DEBUG_LEVEL_VERBOSE, "Skip plug info propagation\n");
233     return true;
234 }
235
236
237 int
238 AvDevice::getConfigurationIdSampleRate()
239 {
240     ExtendedStreamFormatCmd extStreamFormatCmd( *m_p1394Service );
241     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
242                                      m_nodeId );
243     extStreamFormatCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
244                                                     PlugAddress::ePAM_Unit,
245                                                     unitPlugAddress ) );
246
247     extStreamFormatCmd.setNodeId( m_nodeId );
248     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
249     extStreamFormatCmd.setVerbose( true );
250
251     if ( !extStreamFormatCmd.fire() ) {
252         debugError( "Stream format command failed\n" );
253         return false;
254     }
255
256     FormatInformation* formatInfo =
257         extStreamFormatCmd.getFormatInformation();
258     FormatInformationStreamsCompound* compoundStream
259         = dynamic_cast< FormatInformationStreamsCompound* > (
260             formatInfo->m_streams );
261     if ( compoundStream ) {
262         debugOutput(DEBUG_LEVEL_VERBOSE, "Sample rate 0x%02x\n",
263                     compoundStream->m_samplingFrequency );
264         return compoundStream->m_samplingFrequency;
265     }
266
267     debugError( "Could not retrieve sample rate\n" );
268     return 0;
269 }
270
271 int
272 AvDevice::getConfigurationIdNumberOfChannel( PlugAddress::EPlugDirection ePlugDirection )
273 {
274     ExtendedPlugInfoCmd extPlugInfoCmd( *m_p1394Service );
275     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
276                                      m_nodeId );
277     extPlugInfoCmd.setPlugAddress( PlugAddress( ePlugDirection,
278                                                 PlugAddress::ePAM_Unit,
279                                                 unitPlugAddress ) );
280     extPlugInfoCmd.setNodeId( m_nodeId );
281     extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
282     extPlugInfoCmd.setVerbose( true );
283     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
284         ExtendedPlugInfoInfoType::eIT_NoOfChannels );
285     extendedPlugInfoInfoType.initialize();
286     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
287
288     if ( !extPlugInfoCmd.fire() ) {
289         debugError( "Number of channels command failed\n" );
290         return false;
291     }
292
293     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
294     if ( infoType
295          && infoType->m_plugNrOfChns )
296     {
297         debugOutput(DEBUG_LEVEL_VERBOSE, "Number of channels 0x%02x\n",
298                     infoType->m_plugNrOfChns->m_nrOfChannels );
299         return infoType->m_plugNrOfChns->m_nrOfChannels;
300     }
301
302     debugError( "Could not retrieve number of channels\n" );
303     return 0;
304 }
305
306 int
307 AvDevice::getConfigurationIdSyncMode()
308 {
309     SignalSourceCmd signalSourceCmd( *m_p1394Service );
310     SignalUnitAddress signalUnitAddr;
311     signalUnitAddr.m_plugId = 0x01;
312     signalSourceCmd.setSignalDestination( signalUnitAddr );
313     signalSourceCmd.setNodeId( m_nodeId );
314     signalSourceCmd.setSubunitType( eST_Unit  );
315     signalSourceCmd.setSubunitId( 0xff );
316
317     signalSourceCmd.setCommandType( AVCCommand::eCT_Status );
318
319     if ( !signalSourceCmd.fire() ) {
320         debugError( "Number of channels command failed\n" );
321         return false;
322     }
323
324     SignalAddress* pSyncPlugSignalAddress = signalSourceCmd.getSignalSource();
325     SignalSubunitAddress* pSyncPlugSubunitAddress
326         = dynamic_cast<SignalSubunitAddress*>( pSyncPlugSignalAddress );
327     if ( pSyncPlugSubunitAddress ) {
328         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
329                     ( pSyncPlugSubunitAddress->m_subunitType << 3
330                       | pSyncPlugSubunitAddress->m_subunitId ) << 8
331                     | pSyncPlugSubunitAddress->m_plugId );
332
333         return ( pSyncPlugSubunitAddress->m_subunitType << 3
334                  | pSyncPlugSubunitAddress->m_subunitId ) << 8
335             | pSyncPlugSubunitAddress->m_plugId;
336     }
337
338     debugError( "Could not retrieve sync mode\n" );
339     return 0;
340 }
341
342 int
343 AvDevice::getConfigurationId()
344 {
345     // create a unique configuration id.
346     int id = 0;
347     id = getConfigurationIdSampleRate();
348     id |= ( getConfigurationIdNumberOfChannel( PlugAddress::ePD_Input )
349             + getConfigurationIdNumberOfChannel( PlugAddress::ePD_Output ) ) << 8;
350     id |= getConfigurationIdSyncMode() << 16;
351
352     return id;
353 }
354
355
356 template <typename T> bool serializeVector( Glib::ustring path,
357                                             Util::IOSerialize& ser,
358                                             const T& vec )
359 {
360     bool result = true; // if vec.size() == 0
361     int i = 0;
362     for ( typename T::const_iterator it = vec.begin(); it != vec.end(); ++it ) {
363         std::ostringstream strstrm;
364         strstrm << path << i;
365         result &= ( *it )->serialize( strstrm.str() + "/", ser );
366         i++;
367     }
368     return result;
369 }
370
371 template <typename T, typename VT> bool deserializeVector( Glib::ustring path,
372                                                            Util::IODeserialize& deser,
373                                                            Unit& avDevice,
374                                                            VT& vec )
375 {
376     int i = 0;
377     bool bFinished = false;
378     do {
379         std::ostringstream strstrm;
380         strstrm << path << i << "/";
381         T* ptr = T::deserialize( strstrm.str(),
382                                  deser,
383                                  avDevice );
384         if ( ptr ) {
385             vec.push_back( ptr );
386             i++;
387         } else {
388             bFinished = true;
389         }
390     } while ( !bFinished );
391
392     return true;
393 }
394
395 bool
396 AvDevice::serialize( Glib::ustring basePath,
397                      Util::IOSerialize& ser ) const
398 {
399
400     bool result;
401     result  = m_pConfigRom->serialize( basePath + "m_pConfigRom/", ser );
402     result &= ser.write( basePath + "m_verboseLevel", getDebugLevel() );
403     result &= m_pPlugManager->serialize( basePath + "Plug", ser ); // serialize all av plugs
404     result &= serializeVector( basePath + "PlugConnection", ser, m_plugConnections );
405     result &= serializeVector( basePath + "Subunit", ser, m_subunits );
406     #warning broken at echoaudio merge
407     //result &= serializeSyncInfoVector( basePath + "SyncInfo", ser, m_syncInfos );
408
409     int i = 0;
410     for ( SyncInfoVector::const_iterator it = m_syncInfos.begin();
411           it != m_syncInfos.end();
412           ++it )
413     {
414         const SyncInfo& info = *it;
415         if ( m_activeSyncInfo == &info ) {
416             result &= ser.write( basePath + "m_activeSyncInfo",  i );
417             break;
418         }
419         i++;
420     }
421
422     result &= serializeOptions( basePath + "Options", ser );
423
424 //     result &= ser.write( basePath + "m_id", id );
425
426     return result;
427 }
428
429 AvDevice*
430 AvDevice::deserialize( Glib::ustring basePath,
431                        Util::IODeserialize& deser,
432                        Ieee1394Service& ieee1394Service )
433 {
434
435 //     ConfigRom *configRom =
436 //         ConfigRom::deserialize( basePath + "m_pConfigRom/", deser, ieee1394Service );
437 //
438 //     if ( !configRom ) {
439 //         return NULL;
440 //     }
441 //
442 //     AvDevice* pDev = new AvDevice(
443 //         std::auto_ptr<ConfigRom>(configRom),
444 //         ieee1394Service, configRom->getNodeId());
445 //
446 //     if ( pDev ) {
447 //         bool result;
448 //         int verboseLevel;
449 //         result  = deser.read( basePath + "m_verboseLevel", verboseLevel );
450 //         setDebugLevel( verboseLevel );
451 //
452 //         result &= AVC::Unit::deserialize(basePath, pDev, deser, ieee1394Service);
453 //
454 //         result &= deserializeOptions( basePath + "Options", deser, *pDev );
455 //     }
456 //
457 //     return pDev;
458     return NULL;
459 }
460
461 Glib::ustring
462 AvDevice::getCachePath()
463 {
464     Glib::ustring cachePath;
465     char* pCachePath;
466     if ( asprintf( &pCachePath, "%s/cache/libffado/",  CACHEDIR ) < 0 ) {
467         debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
468         cachePath == "/var/cache/libffado/";
469     } else {
470         cachePath = pCachePath;
471         free( pCachePath );
472     }
473     return cachePath;
474 }
475
476 bool
477 AvDevice::loadFromCache()
478 {
479 /*    Glib::ustring sDevicePath = getCachePath() + m_pConfigRom->getGuidString();
480
481     char* configId;
482     asprintf(&configId, "%08x", getConfigurationId() );
483     if ( !configId ) {
484         debugError( "could not create id string\n" );
485         return false;
486     }
487
488     Glib::ustring sFileName = sDevicePath + "/" + configId + ".xml";
489     free( configId );
490     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
491
492     Util::XMLDeserialize deser( sFileName, m_verboseLevel );
493
494     bool result = deserialize( "", deser );
495     if ( result ) {
496         debugOutput( DEBUG_LEVEL_NORMAL, "could create valid bebob driver from %s\n",
497                      sFileName.c_str() );
498     }
499
500     return result;*/
501     return false;
502 }
503
504 bool
505 AvDevice::saveCache()
506 {
507 //     // the path looks like this:
508 //     // PATH_TO_CACHE + GUID + CONFIGURATION_ID
509 //
510 //     Glib::ustring sDevicePath = getCachePath() + m_pConfigRom->getGuidString();
511 //     struct stat buf;
512 //     if ( stat( sDevicePath.c_str(), &buf ) == 0 ) {
513 //         if ( !S_ISDIR( buf.st_mode ) ) {
514 //             debugError( "\"%s\" is not a directory\n",  sDevicePath.c_str() );
515 //             return false;
516 //         }
517 //     } else {
518 //         if (  mkdir( sDevicePath.c_str(), S_IRWXU | S_IRWXG ) != 0 ) {
519 //             debugError( "Could not create \"%s\" directory\n", sDevicePath.c_str() );
520 //             return false;
521 //         }
522 //     }
523 //
524 //     char* configId;
525 //     asprintf(&configId, "%08x", BeBoB::AvDevice::getConfigurationId() );
526 //     if ( !configId ) {
527 //         debugError( "Could not create id string\n" );
528 //         return false;
529 //     }
530 //     Glib::ustring sFileName = sDevicePath + "/" + configId + ".xml";
531 //     free( configId );
532 //     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
533 //
534 //     Util::XMLSerialize ser( sFileName );
535 //     return serialize( "", ser );
536     return false;
537 }
538
539 } // end of namespace
Note: See TracBrowser for help on using the browser.