root/trunk/libffado/src/genericavc/avc_avdevice.cpp

Revision 607, 18.2 kB (checked in by ppalmers, 13 years ago)

- Fix file-based discovery. The previous code used a pointer to a

vendormodel entry. This pointer however pointed to a VendorModel?
object that was created on the stack of the discover function.
Hence the pointer becomes invalid when the discover function is
exited.

The changes incorporate using a VendorModelEntry? struct instead
of a pointer to it. So now the FFADODevice has it's own copy of
this struct, instead of a pointer to it.

Line 
1 /*
2  * Copyright (C) 2005-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 #warning Generic AV/C support is currently useless
26
27 #include "genericavc/avc_avdevice.h"
28
29 #include "libieee1394/configrom.h"
30 #include "libieee1394/ieee1394service.h"
31
32 #include "libavc/avc_definitions.h"
33 #include "libavc/general/avc_plug_info.h"
34
35 #include "debugmodule/debugmodule.h"
36
37 #include "config.h"
38
39 #include <string>
40 #include <stdint.h>
41 #include <assert.h>
42 #include <netinet/in.h>
43 #include <iostream>
44 #include <sstream>
45
46 #include <libraw1394/csr.h>
47
48 using namespace AVC;
49
50 namespace GenericAVC {
51
52 IMPL_DEBUG_MODULE( AvDevice, AvDevice, DEBUG_LEVEL_VERBOSE );
53
54
55 AvDevice::AvDevice( Ieee1394Service& ieee1394Service,
56                     std::auto_ptr<ConfigRom>( configRom ))
57     : FFADODevice( ieee1394Service, configRom )
58 {
59     debugOutput( DEBUG_LEVEL_VERBOSE, "Created GenericAVC::AvDevice (NodeID %d)\n",
60                  getConfigRom().getNodeId() );
61     addOption(Util::OptionContainer::Option("snoopMode",false));
62 }
63
64 AvDevice::~AvDevice()
65 {
66
67 }
68
69 bool
70 AvDevice::probe( ConfigRom& configRom )
71 {
72     unsigned int vendorId = configRom.getNodeVendorId();
73     unsigned int modelId = configRom.getModelId();
74
75     GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_genericavc.txt" );
76     if ( vendorModel.parse() ) {
77         vendorModel.printTable();
78         return vendorModel.isPresent( vendorId, modelId );
79     }
80
81     return false;
82 }
83
84 FFADODevice *
85 AvDevice::createDevice( Ieee1394Service& ieee1394Service,
86                         std::auto_ptr<ConfigRom>( configRom ))
87 {
88     return new AvDevice(ieee1394Service, configRom );
89 }
90
91 bool
92 AvDevice::discover()
93 {
94     // check if we already have a valid VendorModel entry
95     // e.g. because a subclass called this function
96     if (!GenericAVC::VendorModel::isValid(m_model)) {
97         unsigned int vendorId = m_pConfigRom->getNodeVendorId();
98         unsigned int modelId = m_pConfigRom->getModelId();
99    
100         GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_genericavc.txt" );
101         if ( vendorModel.parse() ) {
102             m_model = vendorModel.find( vendorId, modelId );
103         }
104    
105         if (!GenericAVC::VendorModel::isValid(m_model)) {
106             return false;
107         }
108         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
109                 m_model.vendor_name.c_str(), m_model.model_name.c_str());
110     }
111
112     if ( !Unit::discover() ) {
113         debugError( "Could not discover unit\n" );
114         return false;
115     }
116
117     if((getAudioSubunit( 0 ) == NULL)) {
118         debugError( "Unit doesn't have an Audio subunit.\n");
119         return false;
120     }
121     if((getMusicSubunit( 0 ) == NULL)) {
122         debugError( "Unit doesn't have a Music subunit.\n");
123         return false;
124     }
125
126     return true;
127 }
128
129 void
130 AvDevice::setVerboseLevel(int l)
131 {
132     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
133
134     m_pPlugManager->setVerboseLevel(l);
135
136     FFADODevice::setVerboseLevel(l);
137     AVC::Unit::setVerboseLevel(l);
138 }
139
140 int
141 AvDevice::getSamplingFrequency( ) {
142     AVC::Plug* inputPlug = getPlugById( m_pcrPlugs, Plug::eAPD_Input, 0 );
143     if ( !inputPlug ) {
144         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
145         return false;
146     }
147     AVC::Plug* outputPlug = getPlugById( m_pcrPlugs, Plug::eAPD_Output, 0 );
148     if ( !outputPlug ) {
149         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
150         return false;
151     }
152
153     int samplerate_playback=inputPlug->getSampleRate();
154     int samplerate_capture=outputPlug->getSampleRate();
155
156     if (samplerate_playback != samplerate_capture) {
157         debugWarning("Samplerates for capture and playback differ!\n");
158     }
159     return samplerate_capture;
160 }
161
162 bool
163 AvDevice::setSamplingFrequency( int s )
164 {
165     bool snoopMode=false;
166     if(!getOption("snoopMode", snoopMode)) {
167         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
168     }
169
170     if(snoopMode) {
171         int current_sr=getSamplingFrequency();
172         if (current_sr != s ) {
173             debugError("In snoop mode it is impossible to set the sample rate.\n");
174             debugError("Please start the client with the correct setting.\n");
175             return false;
176         }
177         return true;
178     } else {
179         AVC::Plug* plug = getPlugById( m_pcrPlugs, Plug::eAPD_Input, 0 );
180         if ( !plug ) {
181             debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
182             return false;
183         }
184
185         if ( !plug->setSampleRate( s ) )
186         {
187             debugError( "setSampleRate: Setting sample rate failed\n" );
188             return false;
189         }
190
191         plug = getPlugById( m_pcrPlugs, Plug::eAPD_Output,  0 );
192         if ( !plug ) {
193             debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
194             return false;
195         }
196
197         if ( !plug->setSampleRate( s ) )
198         {
199             debugError( "setSampleRate: Setting sample rate failed\n" );
200             return false;
201         }
202
203         debugOutput( DEBUG_LEVEL_VERBOSE,
204                      "setSampleRate: Set sample rate to %d\n",
205                      s );
206         return true;
207     }
208     // not executable
209     return false;
210
211 }
212
213 bool
214 AvDevice::lock() {
215     bool snoopMode=false;
216     if(!getOption("snoopMode", snoopMode)) {
217         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
218     }
219
220     if (snoopMode) {
221         // don't lock
222     } else {
223 //         return Unit::reserve(4);
224     }
225
226     return true;
227 }
228
229 bool
230 AvDevice::unlock() {
231     bool snoopMode=false;
232     if(!getOption("snoopMode", snoopMode)) {
233         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
234     }
235
236     if (snoopMode) {
237         // don't unlock
238     } else {
239 //         return Unit::reserve(0);
240     }
241     return true;
242 }
243
244 void
245 AvDevice::showDevice()
246 {
247     FFADODevice::showDevice();
248
249     debugOutput(DEBUG_LEVEL_NORMAL,
250         "%s %s\n", m_model.vendor_name.c_str(), m_model.model_name.c_str());
251
252     AVC::Unit::show();
253     flushDebugOutput();
254 }
255
256 bool
257 AvDevice::prepare() {
258     bool snoopMode=false;
259     if(!getOption("snoopMode", snoopMode)) {
260         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
261     }
262
263     ///////////
264     // get plugs
265
266     AVC::Plug* inputPlug = getPlugById( m_pcrPlugs, Plug::eAPD_Input, 0 );
267     if ( !inputPlug ) {
268         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
269         return false;
270     }
271     AVC::Plug* outputPlug = getPlugById( m_pcrPlugs, Plug::eAPD_Output, 0 );
272     if ( !outputPlug ) {
273         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
274         return false;
275     }
276
277     int samplerate=outputPlug->getSampleRate();
278
279     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing receive processor...\n");
280     // create & add streamprocessors
281     Streaming::StreamProcessor *p;
282
283     p=new Streaming::AmdtpReceiveStreamProcessor(
284                              get1394Service().getPort(),
285                              samplerate,
286                              outputPlug->getNrOfChannels());
287
288     if(!p->init()) {
289         debugFatal("Could not initialize receive processor!\n");
290         delete p;
291         return false;
292     }
293
294     if (!addPlugToProcessor(*outputPlug,p,
295         Streaming::Port::E_Capture)) {
296         debugFatal("Could not add plug to processor!\n");
297         delete p;
298         return false;
299     }
300
301     m_receiveProcessors.push_back(p);
302
303     // do the transmit processor
304     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing transmit processor%s...\n",
305             (snoopMode?" in snoop mode":""));
306     if (snoopMode) {
307         // we are snooping, so this is receive too.
308         p=new Streaming::AmdtpReceiveStreamProcessor(
309                                   get1394Service().getPort(),
310                                   samplerate,
311                                   inputPlug->getNrOfChannels());
312     } else {
313         p=new Streaming::AmdtpTransmitStreamProcessor(
314                                 get1394Service().getPort(),
315                                 samplerate,
316                                 inputPlug->getNrOfChannels());
317     }
318
319     if(!p->init()) {
320         debugFatal("Could not initialize transmit processor %s!\n",
321             (snoopMode?" in snoop mode":""));
322         delete p;
323         return false;
324     }
325
326     if (snoopMode) {
327         if (!addPlugToProcessor(*inputPlug,p,
328             Streaming::Port::E_Capture)) {
329             debugFatal("Could not add plug to processor!\n");
330             return false;
331         }
332     } else {
333         if (!addPlugToProcessor(*inputPlug,p,
334             Streaming::Port::E_Playback)) {
335             debugFatal("Could not add plug to processor!\n");
336             return false;
337         }
338     }
339
340     // we put this SP into the transmit SP vector,
341     // no matter if we are in snoop mode or not
342     // this allows us to find out what direction
343     // a certain stream should have.
344     m_transmitProcessors.push_back(p);
345
346     return true;
347 }
348
349 bool
350 AvDevice::addPlugToProcessor(
351     AVC::Plug& plug,
352     Streaming::StreamProcessor *processor,
353     Streaming::AmdtpAudioPort::E_Direction direction) {
354
355     std::string id=std::string("dev?");
356     if(!getOption("id", id)) {
357         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
358     }
359
360     Plug::ClusterInfoVector& clusterInfos = plug.getClusterInfos();
361     for ( Plug::ClusterInfoVector::const_iterator it = clusterInfos.begin();
362           it != clusterInfos.end();
363           ++it )
364     {
365         const Plug::ClusterInfo* clusterInfo = &( *it );
366
367         Plug::ChannelInfoVector channelInfos = clusterInfo->m_channelInfos;
368         for ( Plug::ChannelInfoVector::const_iterator it = channelInfos.begin();
369               it != channelInfos.end();
370               ++it )
371         {
372             const Plug::ChannelInfo* channelInfo = &( *it );
373             std::ostringstream portname;
374
375             portname << id << "_" << channelInfo->m_name;
376
377             Streaming::Port *p=NULL;
378             switch(clusterInfo->m_portType) {
379             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Speaker:
380             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Headphone:
381             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Microphone:
382             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Line:
383             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Analog:
384                 debugOutput(DEBUG_LEVEL_VERBOSE, " Adding audio channel %s (pos=0x%02X, loc=0x%02X)\n",
385                     channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location);
386                 p=new Streaming::AmdtpAudioPort(
387                         portname.str(),
388                         direction,
389                         channelInfo->m_streamPosition,
390                         channelInfo->m_location,
391                         Streaming::AmdtpPortInfo::E_MBLA
392                 );
393                 break;
394
395             case ExtendedPlugInfoClusterInfoSpecificData::ePT_MIDI:
396                 debugOutput(DEBUG_LEVEL_VERBOSE, " Adding MIDI channel %s (pos=0x%02X, loc=0x%02X)\n",
397                     channelInfo->m_name.c_str(), channelInfo->m_streamPosition, processor->getPortCount(Streaming::Port::E_Midi));
398                 p=new Streaming::AmdtpMidiPort(
399                         portname.str(),
400                         direction,
401                         channelInfo->m_streamPosition,
402                         // Workaround for out-of-spec hardware
403                         // should be:
404                         // channelInfo->m_location,
405                         // but now we renumber the midi channels' location as they
406                         // are discovered
407                         processor->getPortCount(Streaming::Port::E_Midi),
408                         Streaming::AmdtpPortInfo::E_Midi
409                 );
410
411                 break;
412             case ExtendedPlugInfoClusterInfoSpecificData::ePT_SPDIF:
413             case ExtendedPlugInfoClusterInfoSpecificData::ePT_ADAT:
414             case ExtendedPlugInfoClusterInfoSpecificData::ePT_TDIF:
415             case ExtendedPlugInfoClusterInfoSpecificData::ePT_MADI:
416             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Digital:
417                 debugOutput(DEBUG_LEVEL_VERBOSE, " Adding digital audio channel %s (pos=0x%02X, loc=0x%02X)\n",
418                     channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location);
419                 p=new Streaming::AmdtpAudioPort(
420                         portname.str(),
421                         direction,
422                         channelInfo->m_streamPosition,
423                         channelInfo->m_location,
424                         Streaming::AmdtpPortInfo::E_MBLA
425                 );
426                 break;
427
428             case ExtendedPlugInfoClusterInfoSpecificData::ePT_NoType:
429             default:
430             // unsupported
431                 break;
432             }
433
434             if (!p) {
435                 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->m_name.c_str());
436             } else {
437
438                 if (!processor->addPort(p)) {
439                     debugWarning("Could not register port with stream processor\n");
440                     return false;
441                 }
442             }
443          }
444     }
445     return true;
446 }
447
448 int
449 AvDevice::getStreamCount() {
450     return m_receiveProcessors.size() + m_transmitProcessors.size();
451 }
452
453 Streaming::StreamProcessor *
454 AvDevice::getStreamProcessorByIndex(int i) {
455
456     if (i<(int)m_receiveProcessors.size()) {
457         return m_receiveProcessors.at(i);
458     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
459         return m_transmitProcessors.at(i-m_receiveProcessors.size());
460     }
461
462     return NULL;
463 }
464
465 bool
466 AvDevice::startStreamByIndex(int i) {
467     int iso_channel=-1;
468     bool snoopMode=false;
469     if(!getOption("snoopMode", snoopMode)) {
470         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
471     }
472
473     if (i<(int)m_receiveProcessors.size()) {
474         int n=i;
475         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
476
477         if(snoopMode) { // a stream from the device to another host
478             // FIXME: put this into a decent framework!
479             // we should check the oPCR[n] on the device
480             struct iec61883_oPCR opcr;
481             if (iec61883_get_oPCRX(
482                     get1394Service().getHandle(),
483                     m_pConfigRom->getNodeId() | 0xffc0,
484                     (quadlet_t *)&opcr,
485                     n)) {
486
487                 debugWarning("Error getting the channel for SP %d\n",i);
488                 return false;
489             }
490
491             iso_channel=opcr.channel;
492         } else {
493             iso_channel=get1394Service().allocateIsoChannelCMP(
494                 m_pConfigRom->getNodeId() | 0xffc0, n,
495                 get1394Service().getLocalNodeId()| 0xffc0, -1);
496         }
497         if (iso_channel<0) {
498             debugError("Could not allocate ISO channel for SP %d\n",i);
499             return false;
500         }
501
502         debugOutput(DEBUG_LEVEL_VERBOSE, "Started SP %d on channel %d\n",i,iso_channel);
503
504         p->setChannel(iso_channel);
505         return true;
506
507     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
508         int n=i-m_receiveProcessors.size();
509         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
510
511         if(snoopMode) { // a stream from another host to the device
512             // FIXME: put this into a decent framework!
513             // we should check the iPCR[n] on the device
514             struct iec61883_iPCR ipcr;
515             if (iec61883_get_iPCRX(
516                     get1394Service().getHandle(),
517                     m_pConfigRom->getNodeId() | 0xffc0,
518                     (quadlet_t *)&ipcr,
519                     n)) {
520
521                 debugWarning("Error getting the channel for SP %d\n",i);
522                 return false;
523             }
524
525             iso_channel=ipcr.channel;
526
527         } else {
528             iso_channel=get1394Service().allocateIsoChannelCMP(
529                 get1394Service().getLocalNodeId()| 0xffc0, -1,
530                 m_pConfigRom->getNodeId() | 0xffc0, n);
531         }
532
533         if (iso_channel<0) {
534             debugError("Could not allocate ISO channel for SP %d\n",i);
535             return false;
536         }
537
538         debugOutput(DEBUG_LEVEL_VERBOSE, "Started SP %d on channel %d\n",i,iso_channel);
539
540         p->setChannel(iso_channel);
541         return true;
542     }
543
544     debugError("SP index %d out of range!\n",i);
545     return false;
546 }
547
548 bool
549 AvDevice::stopStreamByIndex(int i) {
550     bool snoopMode=false;
551     if(!getOption("snoopMode", snoopMode)) {
552         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
553     }
554
555     if (i<(int)m_receiveProcessors.size()) {
556         int n=i;
557         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
558
559         if(snoopMode) {
560
561         } else {
562             // deallocate ISO channel
563             if(!get1394Service().freeIsoChannel(p->getChannel())) {
564                 debugError("Could not deallocate iso channel for SP %d\n",i);
565                 return false;
566             }
567         }
568         p->setChannel(-1);
569
570         return true;
571
572     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
573         int n=i-m_receiveProcessors.size();
574         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
575
576         if(snoopMode) {
577
578         } else {
579             // deallocate ISO channel
580             if(!get1394Service().freeIsoChannel(p->getChannel())) {
581                 debugError("Could not deallocate iso channel for SP %d\n",i);
582                 return false;
583             }
584         }
585         p->setChannel(-1);
586
587         return true;
588     }
589
590     debugError("SP index %d out of range!\n",i);
591     return false;
592 }
593
594 }
Note: See TracBrowser for help on using the browser.