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

Revision 589, 17.7 kB (checked in by ppalmers, 16 years ago)

small discovery fix

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