root/trunk/libffado/src/bounce/bounce_avdevice.cpp

Revision 742, 18.5 kB (checked in by ppalmers, 13 years ago)

- Remove some obsolete support files and dirs

- Clean up the license statements in the source files. Everything is

GPL version 3 now.

- Add license and copyright notices to scons scripts

- Clean up some other text files

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 program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "bounce/bounce_avdevice.h"
26
27 #include "libieee1394/configrom.h"
28 #include "libieee1394/ieee1394service.h"
29
30 #include "libavc/general/avc_plug_info.h"
31 #include "libavc/general/avc_extended_plug_info.h"
32 #include "libavc/general/avc_subunit_info.h"
33 #include "libavc/streamformat/avc_extended_stream_format.h"
34 #include "libutil/cmd_serialize.h"
35 #include "libavc/avc_definitions.h"
36
37 #include "debugmodule/debugmodule.h"
38
39 #include <iostream>
40 #include <sstream>
41 #include <stdint.h>
42
43 #include <string>
44 #include <netinet/in.h>
45
46 namespace Bounce {
47
48 // to define the supported devices
49 static VendorModelEntry supportedDeviceList[] =
50 {
51     {FW_VENDORID_FFADO, 0x0B0001LU, 0x0B0001LU, "FFADO", "Bounce"},
52 };
53
54 BounceDevice::BounceDevice( Ieee1394Service& ieee1394Service,
55                             std::auto_ptr<ConfigRom>( configRom ))
56     : FFADODevice( ieee1394Service, configRom )
57     , m_samplerate (44100)
58     , m_model( NULL )
59     , m_Notifier ( NULL )
60 {
61     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Bounce::BounceDevice (NodeID %d)\n",
62                  getConfigRom().getNodeId() );
63     addOption(Util::OptionContainer::Option("snoopMode",false));
64 }
65
66 BounceDevice::~BounceDevice()
67 {
68
69 }
70
71 bool
72 BounceDevice::probe( ConfigRom& configRom )
73 {
74
75     debugOutput( DEBUG_LEVEL_VERBOSE, "probing BounceDevice\n");
76 //     unsigned int vendorId = configRom.getNodeVendorId();
77     unsigned int modelId = configRom.getModelId();
78     unsigned int unitSpecifierId = configRom.getUnitSpecifierId();
79     debugOutput( DEBUG_LEVEL_VERBOSE, "modelId = 0x%08X, specid = 0x%08X\n", modelId, unitSpecifierId);
80
81     for ( unsigned int i = 0;
82           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
83           ++i )
84     {
85         if (
86 //             ( supportedDeviceList[i].vendor_id == vendorId )
87              ( supportedDeviceList[i].model_id == modelId )
88              && ( supportedDeviceList[i].unit_specifier_id == unitSpecifierId )
89            )
90         {
91             return true;
92         }
93     }
94
95     return false;
96 }
97
98 FFADODevice *
99 BounceDevice::createDevice( Ieee1394Service& ieee1394Service,
100                             std::auto_ptr<ConfigRom>( configRom ))
101 {
102     return new BounceDevice(ieee1394Service, configRom );
103 }
104
105 bool
106 BounceDevice::discover()
107 {
108     debugOutput( DEBUG_LEVEL_VERBOSE, "discovering BounceDevice (NodeID %d)\n",
109                  getNodeId() );
110
111 //     unsigned int vendorId = m_pConfigRom->getNodeVendorId();
112     unsigned int modelId = m_pConfigRom->getModelId();
113     unsigned int unitSpecifierId = m_pConfigRom->getUnitSpecifierId();
114
115     for ( unsigned int i = 0;
116           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
117           ++i )
118     {
119         if ( //( supportedDeviceList[i].vendor_id == vendorId )
120              ( supportedDeviceList[i].model_id == modelId )
121              && ( supportedDeviceList[i].unit_specifier_id == unitSpecifierId )
122            )
123         {
124             m_model = &(supportedDeviceList[i]);
125         }
126     }
127
128     if (m_model != NULL) {
129         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
130                 m_model->vendor_name, m_model->model_name);
131         return true;
132     }
133     return false;
134 }
135
136 int BounceDevice::getSamplingFrequency( ) {
137     return m_samplerate;
138 }
139
140 bool BounceDevice::setSamplingFrequency( int s ) {
141     if (s) {
142         m_samplerate=s;
143         return true;
144     } else return false;
145 }
146
147 FFADODevice::ClockSourceVector
148 BounceDevice::getSupportedClockSources() {
149     FFADODevice::ClockSourceVector r;
150     return r;
151 }
152
153 bool
154 BounceDevice::setActiveClockSource(ClockSource s) {
155     return false;
156 }
157
158 FFADODevice::ClockSource
159 BounceDevice::getActiveClockSource() {
160     ClockSource s;
161     return s;
162 }
163
164 int BounceDevice::getConfigurationId( ) {
165     return 0;
166 }
167
168
169 bool
170 BounceDevice::lock() {
171
172     return true;
173 }
174
175
176 bool
177 BounceDevice::unlock() {
178
179     return true;
180 }
181
182 void
183 BounceDevice::showDevice()
184 {
185     debugOutput(DEBUG_LEVEL_NORMAL, "\nI am the bouncedevice, the bouncedevice I am...\n" );
186     debugOutput(DEBUG_LEVEL_NORMAL, "Vendor            :  %s\n", m_pConfigRom->getVendorName().c_str());
187     debugOutput(DEBUG_LEVEL_NORMAL, "Model             :  %s\n", m_pConfigRom->getModelName().c_str());
188     debugOutput(DEBUG_LEVEL_NORMAL, "Vendor Name       :  %s\n", m_model->vendor_name);
189     debugOutput(DEBUG_LEVEL_NORMAL, "Model Name        :  %s\n", m_model->model_name);
190     debugOutput(DEBUG_LEVEL_NORMAL, "Node              :  %d\n", getNodeId());
191     debugOutput(DEBUG_LEVEL_NORMAL, "GUID              :  0x%016llX\n", m_pConfigRom->getGuid());
192     debugOutput(DEBUG_LEVEL_NORMAL, "\n" );
193 }
194
195 bool
196 BounceDevice::addPortsToProcessor(
197     Streaming::StreamProcessor *processor,
198     Streaming::Port::E_Direction direction) {
199
200     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to processor\n");
201
202     std::string id=std::string("dev?");
203     if(!getOption("id", id)) {
204         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
205     }
206
207     int i=0;
208     for (i=0;i<BOUNCE_NB_AUDIO_CHANNELS;i++) {
209         char *buff;
210         asprintf(&buff,"%s%s_Port%d",id.c_str(),direction==Streaming::Port::E_Playback?"p":"c",i);
211
212         Streaming::Port *p=NULL;
213         p=new Streaming::AmdtpAudioPort(
214                 buff,
215                 direction,
216                 // \todo: streaming backend expects indexing starting from 0
217                 // but bebob reports it starting from 1. Decide where
218                 // and how to handle this (pp: here)
219                 i,
220                 0,
221                 Streaming::AmdtpPortInfo::E_MBLA
222         );
223
224         if (!p) {
225             debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
226         } else {
227
228             if (!processor->addPort(p)) {
229                 debugWarning("Could not register port with stream processor\n");
230                 free(buff);
231                 return false;
232             } else {
233                 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
234             }
235         }
236         free(buff);
237     }
238
239     for (i=0;i<BOUNCE_NB_MIDI_CHANNELS;i++) {
240         char *buff;
241         asprintf(&buff,"%s_Midi%s%d",id.c_str(),direction==Streaming::Port::E_Playback?"Out":"In",i);
242
243         Streaming::Port *p=NULL;
244         p=new Streaming::AmdtpMidiPort(
245                 buff,
246                 direction,
247                 // \todo: streaming backend expects indexing starting from 0
248                 // but bebob reports it starting from 1. Decide where
249                 // and how to handle this (pp: here)
250                 BOUNCE_NB_AUDIO_CHANNELS,
251                 i,
252                 Streaming::AmdtpPortInfo::E_Midi
253         );
254
255         if (!p) {
256             debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
257         } else {
258
259             if (!processor->addPort(p)) {
260                 debugWarning("Could not register port with stream processor\n");
261                 free(buff);
262                 return false;
263             } else {
264                 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
265             }
266         }
267         free(buff);
268      }
269
270     return true;
271 }
272
273 bool
274 BounceDevice::prepare() {
275     debugOutput(DEBUG_LEVEL_NORMAL, "Preparing BounceDevice...\n" );
276
277     bool snoopMode=false;
278     if(!getOption("snoopMode", snoopMode)) {
279         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
280     }
281
282     // create & add streamprocessors
283     Streaming::StreamProcessor *p;
284
285     p=new Streaming::AmdtpReceiveStreamProcessor(
286                              m_p1394Service->getPort(),
287                              m_samplerate,
288                              BOUNCE_NB_AUDIO_CHANNELS+(BOUNCE_NB_MIDI_CHANNELS?1:0));
289
290     if(!p->init()) {
291         debugFatal("Could not initialize receive processor!\n");
292         delete p;
293         return false;
294     }
295
296     if (!addPortsToProcessor(p,
297             Streaming::Port::E_Capture)) {
298         debugFatal("Could not add plug to processor!\n");
299         delete p;
300         return false;
301     }
302
303     m_receiveProcessors.push_back(p);
304
305     // do the transmit processor
306     if (snoopMode) {
307         // we are snooping, so this is receive too.
308         p=new Streaming::AmdtpReceiveStreamProcessor(
309                                 m_p1394Service->getPort(),
310                                 m_samplerate,
311                                 BOUNCE_NB_AUDIO_CHANNELS+(BOUNCE_NB_MIDI_CHANNELS?1:0));
312     } else {
313         p=new Streaming::AmdtpTransmitStreamProcessor(
314                                 m_p1394Service->getPort(),
315                                 m_samplerate,
316                                 BOUNCE_NB_AUDIO_CHANNELS+(BOUNCE_NB_MIDI_CHANNELS?1:0));
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 (!addPortsToProcessor(p,
328             Streaming::Port::E_Capture)) {
329             debugFatal("Could not add plug to processor!\n");
330             delete p;
331             return false;
332         }
333         m_receiveProcessors.push_back(p);
334     } else {
335         if (!addPortsToProcessor(p,
336             Streaming::Port::E_Playback)) {
337             debugFatal("Could not add plug to processor!\n");
338             delete p;
339             return false;
340         }
341         m_transmitProcessors.push_back(p);
342     }
343
344     return true;
345 }
346
347 int
348 BounceDevice::getStreamCount() {
349     return m_receiveProcessors.size() + m_transmitProcessors.size();
350 }
351
352 Streaming::StreamProcessor *
353 BounceDevice::getStreamProcessorByIndex(int i) {
354     if (i<(int)m_receiveProcessors.size()) {
355         return m_receiveProcessors.at(i);
356     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
357         return m_transmitProcessors.at(i-m_receiveProcessors.size());
358     }
359
360     return NULL;
361 }
362
363 bool
364 BounceDevice::startStreamByIndex(int i) {
365     if (i<(int)m_receiveProcessors.size()) {
366         int n=i;
367         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
368
369         // allocate ISO channel
370         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
371         if(isochannel<0) {
372             debugError("Could not allocate iso channel for SP %d\n",i);
373             return false;
374         }
375         p->setChannel(isochannel);
376
377         fb_quadlet_t reg_isoch;
378         // check value of ISO_CHANNEL register
379         if(!readReg(BOUNCE_REGISTER_TX_ISOCHANNEL, &reg_isoch)) {
380             debugError("Could not read ISO_CHANNEL register\n", n);
381             p->setChannel(-1);
382             deallocateIsoChannel(isochannel);
383             return false;
384         }
385         if(reg_isoch != 0xFFFFFFFFUL) {
386             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X)\n", reg_isoch);
387             p->setChannel(-1);
388             deallocateIsoChannel(isochannel);
389             return false;
390         }
391
392         // write value of ISO_CHANNEL register
393         reg_isoch=isochannel;
394         if(!writeReg(BOUNCE_REGISTER_TX_ISOCHANNEL, reg_isoch)) {
395             debugError("Could not write ISO_CHANNEL register\n");
396             p->setChannel(-1);
397             deallocateIsoChannel(isochannel);
398             return false;
399         }
400
401         return true;
402
403     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
404         int n=i-m_receiveProcessors.size();
405         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
406
407         // allocate ISO channel
408         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
409         if(isochannel<0) {
410             debugError("Could not allocate iso channel for SP %d\n",i);
411             return false;
412         }
413         p->setChannel(isochannel);
414
415         fb_quadlet_t reg_isoch;
416         // check value of ISO_CHANNEL register
417         if(!readReg(BOUNCE_REGISTER_RX_ISOCHANNEL, &reg_isoch)) {
418             debugError("Could not read ISO_CHANNEL register\n");
419             p->setChannel(-1);
420             deallocateIsoChannel(isochannel);
421             return false;
422         }
423         if(reg_isoch != 0xFFFFFFFFUL) {
424             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X)\n", reg_isoch);
425             p->setChannel(-1);
426             deallocateIsoChannel(isochannel);
427             return false;
428         }
429
430         // write value of ISO_CHANNEL register
431         reg_isoch=isochannel;
432         if(!writeReg(BOUNCE_REGISTER_RX_ISOCHANNEL, reg_isoch)) {
433             debugError("Could not write ISO_CHANNEL register\n");
434             p->setChannel(-1);
435             deallocateIsoChannel(isochannel);
436             return false;
437         }
438
439         return true;
440     }
441
442     debugError("SP index %d out of range!\n",i);
443
444     return false;
445 }
446
447 bool
448 BounceDevice::stopStreamByIndex(int i) {
449     if (i<(int)m_receiveProcessors.size()) {
450         int n=i;
451         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
452         unsigned int isochannel=p->getChannel();
453
454         fb_quadlet_t reg_isoch;
455         // check value of ISO_CHANNEL register
456         if(!readReg(BOUNCE_REGISTER_TX_ISOCHANNEL, &reg_isoch)) {
457             debugError("Could not read ISO_CHANNEL register\n");
458             return false;
459         }
460         if(reg_isoch != isochannel) {
461             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X)\n", isochannel, reg_isoch);
462             return false;
463         }
464
465         // write value of ISO_CHANNEL register
466         reg_isoch=0xFFFFFFFFUL;
467         if(!writeReg(BOUNCE_REGISTER_TX_ISOCHANNEL, reg_isoch)) {
468             debugError("Could not write ISO_CHANNEL register" );
469             return false;
470         }
471
472         // deallocate ISO channel
473         if(!deallocateIsoChannel(isochannel)) {
474             debugError("Could not deallocate iso channel for SP\n",i);
475             return false;
476         }
477
478         p->setChannel(-1);
479         return true;
480
481     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
482         int n=i-m_receiveProcessors.size();
483         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
484
485         unsigned int isochannel=p->getChannel();
486
487         fb_quadlet_t reg_isoch;
488         // check value of ISO_CHANNEL register
489         if(!readReg(BOUNCE_REGISTER_RX_ISOCHANNEL, &reg_isoch)) {
490             debugError("Could not read ISO_CHANNEL register\n");
491             return false;
492         }
493         if(reg_isoch != isochannel) {
494             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X)\n", isochannel, reg_isoch);
495             return false;
496         }
497
498         // write value of ISO_CHANNEL register
499         reg_isoch=0xFFFFFFFFUL;
500         if(!writeReg(BOUNCE_REGISTER_RX_ISOCHANNEL, reg_isoch)) {
501             debugError("Could not write ISO_CHANNEL register\n");
502             return false;
503         }
504
505         // deallocate ISO channel
506         if(!deallocateIsoChannel(isochannel)) {
507             debugError("Could not deallocate iso channel for SP (%d)\n",i);
508             return false;
509         }
510
511         p->setChannel(-1);
512         return true;
513     }
514
515     debugError("SP index %d out of range!\n",i);
516     return false;
517 }
518
519 // helper functions
520
521 // allocate ISO resources for the SP's
522 int BounceDevice::allocateIsoChannel(unsigned int packet_size) {
523     unsigned int bandwidth=8+packet_size;
524
525     int ch=m_p1394Service->allocateIsoChannelGeneric(bandwidth);
526
527     debugOutput(DEBUG_LEVEL_VERBOSE, "allocated channel %d, bandwidth %d\n",
528         ch, bandwidth);
529
530     return ch;
531 }
532 // deallocate ISO resources
533 bool BounceDevice::deallocateIsoChannel(int channel) {
534     debugOutput(DEBUG_LEVEL_VERBOSE, "freeing channel %d\n",channel);
535     return m_p1394Service->freeIsoChannel(channel);
536 }
537
538 // I/O functions
539
540 bool
541 BounceDevice::readReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
542     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX\n", offset);
543
544     if(offset >= BOUNCE_INVALID_OFFSET) {
545         debugError("invalid offset: 0x%016llX\n", offset);
546         return false;
547     }
548
549     fb_nodeaddr_t addr=BOUNCE_REGISTER_BASE + offset;
550     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
551
552     if(!m_p1394Service->read_quadlet( nodeId, addr, result ) ) {
553         debugError("Could not read from node 0x%04X addr 0x%012X\n", nodeId, addr);
554         return false;
555     }
556     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Read result: 0x%08X\n", *result);
557
558     return true;
559 }
560
561 bool
562 BounceDevice::writeReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
563     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, data: 0x%08X\n",
564         offset, data);
565
566     if(offset >= BOUNCE_INVALID_OFFSET) {
567         debugError("invalid offset: 0x%016llX\n", offset);
568         return false;
569     }
570
571     fb_nodeaddr_t addr=BOUNCE_REGISTER_BASE + offset;
572     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
573
574     if(!m_p1394Service->write_quadlet( nodeId, addr, data ) ) {
575         debugError("Could not write to node 0x%04X addr 0x%012X\n", nodeId, addr);
576         return false;
577     }
578     return true;
579 }
580
581 bool
582 BounceDevice::readRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
583     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
584         offset, length);
585
586     if(offset >= BOUNCE_INVALID_OFFSET) {
587         debugError("invalid offset: 0x%016llX\n", offset);
588         return false;
589     }
590
591     fb_nodeaddr_t addr=BOUNCE_REGISTER_BASE + offset;
592     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
593
594     if(!m_p1394Service->read( nodeId, addr, length, data ) ) {
595         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
596         return false;
597     }
598     return true;
599 }
600
601 bool
602 BounceDevice::writeRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
603     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n",
604         offset, length);
605
606     if(offset >= BOUNCE_INVALID_OFFSET) {
607         debugError("invalid offset: 0x%016llX\n", offset);
608         return false;
609     }
610
611     fb_nodeaddr_t addr=BOUNCE_REGISTER_BASE + offset;
612     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
613
614     if(!m_p1394Service->write( nodeId, addr, length, data ) ) {
615         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
616         return false;
617     }
618     return true;
619 }
620
621
622 } // namespace
Note: See TracBrowser for help on using the browser.