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

Revision 583, 18.4 kB (checked in by ppalmers, 17 years ago)

- Clean up the FFADODevice constructor to remove the nodeid that

can be retrieved from the configrom.

- Implement new method of creating devices: a device is supposed

to implement the createDevice static method that should return
an instance of itself or a subclass of itself. This should ease
support for manufacturer specific customizations since we don't
have to put them into the device manager class.

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