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

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

- Sort the FFADODevice vector on GUID before assigning device id's

This results in the same device id for identical device setups,
independent of the way they are connected or the node numbers they
have been assigned.

- Sanitized debug message reporting a bit
- Cosmetic changes

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