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

Revision 587, 17.5 kB (checked in by ppalmers, 16 years ago)

- moved all vendor id's to one include file
- introduced the framework for the ECHO FireWorks? platform

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