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

Revision 436, 18.3 kB (checked in by pieterpalmers, 17 years ago)

- fixed verbose level setting
- debugged DICE code, works with EVM

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