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

Revision 2803, 16.6 kB (checked in by jwoithe, 1 year ago)

Cosmetic: capitalise "L" in "Linux".

"Linux" is a proper noun so it should start with a capital letter. These
changes are almost all within comments.

This patch was originally proposed by pander on the ffado-devel mailing
list. It has been expanded to cover all similar cases to maintain
consistency throughout the source tree.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  * Copyright (C) 2005-2008 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 2 of the License, or
13  * (at your option) version 3 of the License.
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 "libutil/Configuration.h"
31
32 #include "debugmodule/debugmodule.h"
33
34 #include "devicemanager.h"
35
36 #include <iostream>
37 #include <sstream>
38 #include <stdint.h>
39
40 #include <string>
41 #include "libutil/ByteSwap.h"
42
43 namespace Bounce {
44
45 Device::Device( DeviceManager& d, ffado_smartptr< ConfigRom >( configRom ) )
46     : FFADODevice( d, configRom )
47     , m_samplerate (44100)
48     , m_Notifier ( NULL )
49 {
50     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Bounce::Device (NodeID %d)\n",
51                  getConfigRom().getNodeId() );
52     addOption(Util::OptionContainer::Option("snoopMode",false));
53 }
54
55 Device::~Device()
56 {
57
58 }
59
60 bool
61 Device::probe( Util::Configuration& c, ConfigRom& configRom, bool generic )
62 {
63     if(generic) {
64         return false;
65     } else {
66         // check if device is in supported devices list
67         unsigned int vendorId = configRom.getNodeVendorId();
68         unsigned int modelId = configRom.getModelId();
69
70         Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
71         return c.isValid(vme) && vme.driver == Util::Configuration::eD_Bounce;
72     }
73     return false;
74 }
75
76 FFADODevice *
77 Device::createDevice(DeviceManager& d, ffado_smartptr<ConfigRom>( configRom ))
78 {
79     return new Device(d, configRom );
80 }
81
82 bool
83 Device::discover()
84 {
85     debugOutput( DEBUG_LEVEL_VERBOSE, "discovering Device (NodeID %d)\n",
86                  getNodeId() );
87
88     unsigned int vendorId = getConfigRom().getNodeVendorId();
89     unsigned int modelId = getConfigRom().getModelId();
90
91     Util::Configuration &c = getDeviceManager().getConfiguration();
92     Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
93
94     if (c.isValid(vme) && vme.driver == Util::Configuration::eD_Bounce) {
95         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
96                      vme.vendor_name.c_str(),
97                      vme.model_name.c_str());
98     } else {
99         debugWarning("Using generic Bounce support for unsupported device '%s %s'\n",
100                      getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
101     }
102     return true;
103 }
104
105 int Device::getSamplingFrequency( ) {
106     return m_samplerate;
107 }
108
109 bool Device::setSamplingFrequency( int s ) {
110     if (s) {
111         m_samplerate=s;
112         return true;
113     } else return false;
114 }
115
116 FFADODevice::ClockSourceVector
117 Device::getSupportedClockSources() {
118     FFADODevice::ClockSourceVector r;
119     return r;
120 }
121
122 bool
123 Device::setActiveClockSource(ClockSource s) {
124     return false;
125 }
126
127 FFADODevice::ClockSource
128 Device::getActiveClockSource() {
129     ClockSource s;
130     return s;
131 }
132
133 std::vector<int>
134 Device::getSupportedSamplingFrequencies()
135 {
136     std::vector<int> frequencies;
137     return frequencies;
138 }
139
140
141 bool
142 Device::lock() {
143
144     return true;
145 }
146
147
148 bool
149 Device::unlock() {
150
151     return true;
152 }
153
154 void
155 Device::showDevice()
156 {
157
158     debugOutput(DEBUG_LEVEL_NORMAL, "\nI am the bouncedevice, the bouncedevice I am...\n" );
159     debugOutput(DEBUG_LEVEL_NORMAL, "Vendor            :  %s\n", getConfigRom().getVendorName().c_str());
160     debugOutput(DEBUG_LEVEL_NORMAL, "Model             :  %s\n", getConfigRom().getModelName().c_str());
161     debugOutput(DEBUG_LEVEL_NORMAL, "Node              :  %d\n", getNodeId());
162     debugOutput(DEBUG_LEVEL_NORMAL, "GUID              :  0x%016llX\n", getConfigRom().getGuid());
163     debugOutput(DEBUG_LEVEL_NORMAL, "\n" );
164 }
165
166 bool
167 Device::addPortsToProcessor(
168     Streaming::StreamProcessor *processor,
169     Streaming::Port::E_Direction direction) {
170
171     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to processor\n");
172
173     std::string id=std::string("dev?");
174     if(!getOption("id", id)) {
175         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
176     }
177
178     int i=0;
179     for (i=0;i<BOUNCE_NB_AUDIO_CHANNELS;i++) {
180         char *buff;
181         asprintf(&buff,"%s%s_Port%d",id.c_str(),direction==Streaming::Port::E_Playback?"p":"c",i);
182
183         Streaming::Port *p=NULL;
184         p=new Streaming::AmdtpAudioPort(
185                 *processor,
186                 buff,
187                 direction,
188                 // \todo: streaming backend expects indexing starting from 0
189                 // but bebob reports it starting from 1. Decide where
190                 // and how to handle this (pp: here)
191                 i,
192                 0,
193                 Streaming::AmdtpPortInfo::E_MBLA
194         );
195
196         if (!p) {
197             debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
198         }
199         free(buff);
200     }
201
202     for (i=0;i<BOUNCE_NB_MIDI_CHANNELS;i++) {
203         char *buff;
204         asprintf(&buff,"%s_Midi%s%d",id.c_str(),direction==Streaming::Port::E_Playback?"Out":"In",i);
205
206         Streaming::Port *p=NULL;
207         p=new Streaming::AmdtpMidiPort(
208                 *processor,
209                 buff,
210                 direction,
211                 // \todo: streaming backend expects indexing starting from 0
212                 // but bebob reports it starting from 1. Decide where
213                 // and how to handle this (pp: here)
214                 BOUNCE_NB_AUDIO_CHANNELS,
215                 i,
216                 Streaming::AmdtpPortInfo::E_Midi
217         );
218
219         if (!p) {
220             debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
221         }
222         free(buff);
223      }
224
225     return true;
226 }
227
228 bool
229 Device::prepare() {
230     debugOutput(DEBUG_LEVEL_NORMAL, "Preparing Device...\n" );
231
232     bool snoopMode=false;
233     if(!getOption("snoopMode", snoopMode)) {
234         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
235     }
236
237     // create & add streamprocessors
238     Streaming::StreamProcessor *p;
239
240     p=new Streaming::AmdtpReceiveStreamProcessor(*this,
241                              BOUNCE_NB_AUDIO_CHANNELS+(BOUNCE_NB_MIDI_CHANNELS?1:0));
242
243     if(!p->init()) {
244         debugFatal("Could not initialize receive processor!\n");
245         delete p;
246         return false;
247     }
248
249     if (!addPortsToProcessor(p,
250             Streaming::Port::E_Capture)) {
251         debugFatal("Could not add plug to processor!\n");
252         delete p;
253         return false;
254     }
255
256     m_receiveProcessors.push_back(p);
257
258     // do the transmit processor
259     if (snoopMode) {
260         // we are snooping, so this is receive too.
261         p=new Streaming::AmdtpReceiveStreamProcessor(*this,
262                                 BOUNCE_NB_AUDIO_CHANNELS+(BOUNCE_NB_MIDI_CHANNELS?1:0));
263     } else {
264         p=new Streaming::AmdtpTransmitStreamProcessor(*this,
265                                 BOUNCE_NB_AUDIO_CHANNELS+(BOUNCE_NB_MIDI_CHANNELS?1:0));
266     }
267
268     if(!p->init()) {
269         debugFatal("Could not initialize transmit processor %s!\n",
270             (snoopMode?" in snoop mode":""));
271         delete p;
272         return false;
273     }
274
275     if (snoopMode) {
276         if (!addPortsToProcessor(p,
277             Streaming::Port::E_Capture)) {
278             debugFatal("Could not add plug to processor!\n");
279             delete p;
280             return false;
281         }
282         m_receiveProcessors.push_back(p);
283     } else {
284         if (!addPortsToProcessor(p,
285             Streaming::Port::E_Playback)) {
286             debugFatal("Could not add plug to processor!\n");
287             delete p;
288             return false;
289         }
290         m_transmitProcessors.push_back(p);
291     }
292
293     return true;
294 }
295
296 int
297 Device::getStreamCount() {
298     return m_receiveProcessors.size() + m_transmitProcessors.size();
299 }
300
301 Streaming::StreamProcessor *
302 Device::getStreamProcessorByIndex(int i) {
303     if (i<(int)m_receiveProcessors.size()) {
304         return m_receiveProcessors.at(i);
305     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
306         return m_transmitProcessors.at(i-m_receiveProcessors.size());
307     }
308
309     return NULL;
310 }
311
312 bool
313 Device::startStreamByIndex(int i) {
314     if (i<(int)m_receiveProcessors.size()) {
315         int n=i;
316         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
317
318         // allocate ISO channel
319         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
320         if(isochannel<0) {
321             debugError("Could not allocate iso channel for SP %d\n",i);
322             return false;
323         }
324         p->setChannel(isochannel);
325
326         fb_quadlet_t reg_isoch;
327         // check value of ISO_CHANNEL register
328         if(!readReg(BOUNCE_REGISTER_TX_ISOCHANNEL, &reg_isoch)) {
329             debugError("Could not read ISO_CHANNEL register\n");
330             p->setChannel(-1);
331             deallocateIsoChannel(isochannel);
332             return false;
333         }
334         if(reg_isoch != 0xFFFFFFFFUL) {
335             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X)\n", reg_isoch);
336             p->setChannel(-1);
337             deallocateIsoChannel(isochannel);
338             return false;
339         }
340
341         // write value of ISO_CHANNEL register
342         reg_isoch=isochannel;
343         if(!writeReg(BOUNCE_REGISTER_TX_ISOCHANNEL, reg_isoch)) {
344             debugError("Could not write ISO_CHANNEL register\n");
345             p->setChannel(-1);
346             deallocateIsoChannel(isochannel);
347             return false;
348         }
349
350         return true;
351
352     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
353         int n=i-m_receiveProcessors.size();
354         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
355
356         // allocate ISO channel
357         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
358         if(isochannel<0) {
359             debugError("Could not allocate iso channel for SP %d\n",i);
360             return false;
361         }
362         p->setChannel(isochannel);
363
364         fb_quadlet_t reg_isoch;
365         // check value of ISO_CHANNEL register
366         if(!readReg(BOUNCE_REGISTER_RX_ISOCHANNEL, &reg_isoch)) {
367             debugError("Could not read ISO_CHANNEL register\n");
368             p->setChannel(-1);
369             deallocateIsoChannel(isochannel);
370             return false;
371         }
372         if(reg_isoch != 0xFFFFFFFFUL) {
373             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X)\n", reg_isoch);
374             p->setChannel(-1);
375             deallocateIsoChannel(isochannel);
376             return false;
377         }
378
379         // write value of ISO_CHANNEL register
380         reg_isoch=isochannel;
381         if(!writeReg(BOUNCE_REGISTER_RX_ISOCHANNEL, reg_isoch)) {
382             debugError("Could not write ISO_CHANNEL register\n");
383             p->setChannel(-1);
384             deallocateIsoChannel(isochannel);
385             return false;
386         }
387
388         return true;
389     }
390
391     debugError("SP index %d out of range!\n",i);
392
393     return false;
394 }
395
396 bool
397 Device::stopStreamByIndex(int i) {
398     if (i<(int)m_receiveProcessors.size()) {
399         int n=i;
400         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
401         unsigned int isochannel=p->getChannel();
402
403         fb_quadlet_t reg_isoch;
404         // check value of ISO_CHANNEL register
405         if(!readReg(BOUNCE_REGISTER_TX_ISOCHANNEL, &reg_isoch)) {
406             debugError("Could not read ISO_CHANNEL register\n");
407             return false;
408         }
409         if(reg_isoch != isochannel) {
410             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X)\n", isochannel, reg_isoch);
411             return false;
412         }
413
414         // write value of ISO_CHANNEL register
415         reg_isoch=0xFFFFFFFFUL;
416         if(!writeReg(BOUNCE_REGISTER_TX_ISOCHANNEL, reg_isoch)) {
417             debugError("Could not write ISO_CHANNEL register\n" );
418             return false;
419         }
420
421         // deallocate ISO channel
422         if(!deallocateIsoChannel(isochannel)) {
423             debugError("Could not deallocate iso channel for SP\n");
424             return false;
425         }
426
427         p->setChannel(-1);
428         return true;
429
430     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
431         int n=i-m_receiveProcessors.size();
432         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
433
434         unsigned int isochannel=p->getChannel();
435
436         fb_quadlet_t reg_isoch;
437         // check value of ISO_CHANNEL register
438         if(!readReg(BOUNCE_REGISTER_RX_ISOCHANNEL, &reg_isoch)) {
439             debugError("Could not read ISO_CHANNEL register\n");
440             return false;
441         }
442         if(reg_isoch != isochannel) {
443             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X)\n", isochannel, reg_isoch);
444             return false;
445         }
446
447         // write value of ISO_CHANNEL register
448         reg_isoch=0xFFFFFFFFUL;
449         if(!writeReg(BOUNCE_REGISTER_RX_ISOCHANNEL, reg_isoch)) {
450             debugError("Could not write ISO_CHANNEL register\n");
451             return false;
452         }
453
454         // deallocate ISO channel
455         if(!deallocateIsoChannel(isochannel)) {
456             debugError("Could not deallocate iso channel for SP (%d)\n",i);
457             return false;
458         }
459
460         p->setChannel(-1);
461         return true;
462     }
463
464     debugError("SP index %d out of range!\n",i);
465     return false;
466 }
467
468 // helper functions
469
470 // allocate ISO resources for the SP's
471 int Device::allocateIsoChannel(unsigned int packet_size) {
472     unsigned int bandwidth=8+packet_size;
473
474     int ch=get1394Service().allocateIsoChannelGeneric(bandwidth);
475
476     debugOutput(DEBUG_LEVEL_VERBOSE, "allocated channel %d, bandwidth %d\n",
477         ch, bandwidth);
478
479     return ch;
480 }
481 // deallocate ISO resources
482 bool Device::deallocateIsoChannel(int channel) {
483     debugOutput(DEBUG_LEVEL_VERBOSE, "freeing channel %d\n",channel);
484     return get1394Service().freeIsoChannel(channel);
485 }
486
487 // I/O functions
488
489 bool
490 Device::readReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
491     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX\n", offset);
492
493     if(offset >= BOUNCE_INVALID_OFFSET) {
494         debugError("invalid offset: 0x%016llX\n", offset);
495         return false;
496     }
497
498     fb_nodeaddr_t addr=BOUNCE_REGISTER_BASE + offset;
499     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
500
501     if(!get1394Service().read_quadlet( nodeId, addr, result ) ) {
502         debugError("Could not read from node 0x%04X addr 0x%012X\n", nodeId, (unsigned int)addr);
503         return false;
504     }
505     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Read result: 0x%08X\n", *result);
506
507     return true;
508 }
509
510 bool
511 Device::writeReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
512     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, data: 0x%08X\n",
513         offset, data);
514
515     if(offset >= BOUNCE_INVALID_OFFSET) {
516         debugError("invalid offset: 0x%016llX\n", offset);
517         return false;
518     }
519
520     fb_nodeaddr_t addr=BOUNCE_REGISTER_BASE + offset;
521     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
522
523     if(!get1394Service().write_quadlet( nodeId, addr, data ) ) {
524         debugError("Could not write to node 0x%04X addr 0x%012X\n", nodeId, (unsigned int)addr);
525         return false;
526     }
527     return true;
528 }
529
530 bool
531 Device::readRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
532     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
533         offset, length);
534
535     if(offset >= BOUNCE_INVALID_OFFSET) {
536         debugError("invalid offset: 0x%016llX\n", offset);
537         return false;
538     }
539
540     fb_nodeaddr_t addr=BOUNCE_REGISTER_BASE + offset;
541     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
542
543     if(!get1394Service().read( nodeId, addr, length, data ) ) {
544         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
545         return false;
546     }
547     return true;
548 }
549
550 bool
551 Device::writeRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
552     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n",
553         offset, length);
554
555     if(offset >= BOUNCE_INVALID_OFFSET) {
556         debugError("invalid offset: 0x%016llX\n", offset);
557         return false;
558     }
559
560     fb_nodeaddr_t addr=BOUNCE_REGISTER_BASE + offset;
561     fb_nodeid_t nodeId=getNodeId() | 0xFFC0;
562
563     if(!get1394Service().write( nodeId, addr, length, data ) ) {
564         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
565         return false;
566     }
567     return true;
568 }
569
570
571 } // namespace
Note: See TracBrowser for help on using the browser.