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

Revision 599, 17.5 kB (checked in by wagi, 13 years ago)

Instead of static compiled in vendor/model table use configuration files.

Maybe needs some more cleanup but I wanted to check in this baby before
someone else screws me up with some majors changes in the repos :)

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