root/branches/streaming-rework/src/bounce/bounce_avdevice.cpp

Revision 426, 17.2 kB (checked in by pieterpalmers, 17 years ago)

- changed the IAvDevice from an interface to a base class,

since there is some code duplication starting to
appear.

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() const
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 #define BOUNCE_NR_OF_CHANNELS 2
165
166 bool
167 BounceDevice::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_NR_OF_CHANNELS;i++) {
180         char *buff;
181         asprintf(&buff,"%s%s_Port%d",id.c_str(),direction==Streaming::AmdtpAudioPort::E_Playback?"p":"c",i);
182
183         Streaming::Port *p=NULL;
184         p=new Streaming::AmdtpAudioPort(
185                 buff,
186                 direction,
187                 // \todo: streaming backend expects indexing starting from 0
188                 // but bebob reports it starting from 1. Decide where
189                 // and how to handle this (pp: here)
190                 i,
191                 0,
192                 Streaming::AmdtpPortInfo::E_MBLA
193         );
194
195         if (!p) {
196             debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
197         } else {
198
199             if (!processor->addPort(p)) {
200                 debugWarning("Could not register port with stream processor\n");
201                 free(buff);
202                 return false;
203             } else {
204                 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
205             }
206         }
207
208         free(buff);
209
210      }
211
212         return true;
213 }
214
215 bool
216 BounceDevice::prepare() {
217     debugOutput(DEBUG_LEVEL_NORMAL, "Preparing BounceDevice...\n" );
218    
219     bool snoopMode=false;
220     if(!getOption("snoopMode", snoopMode)) {
221         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
222     }
223
224     // create & add streamprocessors
225     Streaming::StreamProcessor *p;
226    
227     p=new Streaming::AmdtpReceiveStreamProcessor(
228                              m_p1394Service->getPort(),
229                              m_samplerate,
230                              BOUNCE_NR_OF_CHANNELS);
231
232     if(!p->init()) {
233         debugFatal("Could not initialize receive processor!\n");
234         delete p;
235         return false;
236     }
237
238     if (!addPortsToProcessor(p,
239             Streaming::Port::E_Capture)) {
240         debugFatal("Could not add plug to processor!\n");
241         delete p;
242         return false;
243     }
244
245     m_receiveProcessors.push_back(p);
246
247     // do the transmit processor
248     if (snoopMode) {
249         // we are snooping, so this is receive too.
250         p=new Streaming::AmdtpReceiveStreamProcessor(
251                                   m_p1394Service->getPort(),
252                                   m_samplerate,
253                                   BOUNCE_NR_OF_CHANNELS);
254     } else {
255         p=new Streaming::AmdtpTransmitStreamProcessor(
256                                 m_p1394Service->getPort(),
257                                 m_samplerate,
258                                 BOUNCE_NR_OF_CHANNELS);
259     }
260    
261     if(!p->init()) {
262         debugFatal("Could not initialize transmit processor %s!\n",
263             (snoopMode?" in snoop mode":""));
264         delete p;
265         return false;
266     }
267
268     if (snoopMode) {
269         if (!addPortsToProcessor(p,
270             Streaming::Port::E_Capture)) {
271             debugFatal("Could not add plug to processor!\n");
272             delete p;
273             return false;
274         }
275         m_receiveProcessors.push_back(p);
276     } else {
277         if (!addPortsToProcessor(p,
278             Streaming::Port::E_Playback)) {
279             debugFatal("Could not add plug to processor!\n");
280             delete p;
281             return false;
282         }
283         m_transmitProcessors.push_back(p);
284     }
285
286     return true;
287 }
288
289 int
290 BounceDevice::getStreamCount() {
291     return m_receiveProcessors.size() + m_transmitProcessors.size();
292 }
293
294 Streaming::StreamProcessor *
295 BounceDevice::getStreamProcessorByIndex(int i) {
296     if (i<(int)m_receiveProcessors.size()) {
297         return m_receiveProcessors.at(i);
298     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
299         return m_transmitProcessors.at(i-m_receiveProcessors.size());
300     }
301
302     return NULL;
303 }
304
305 bool
306 BounceDevice::startStreamByIndex(int i) {
307     if (i<(int)m_receiveProcessors.size()) {
308         int n=i;
309         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
310        
311         // allocate ISO channel
312         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
313         if(isochannel<0) {
314             debugError("Could not allocate iso channel for SP %d\n",i);
315             return false;
316         }
317         p->setChannel(isochannel);
318        
319         fb_quadlet_t reg_isoch;
320         // check value of ISO_CHANNEL register
321         if(!readReg(BOUNCE_REGISTER_TX_ISOCHANNEL, &reg_isoch)) {
322             debugError("Could not read ISO_CHANNEL register\n", n);
323             p->setChannel(-1);
324             deallocateIsoChannel(isochannel);
325             return false;
326         }
327         if(reg_isoch != 0xFFFFFFFFUL) {
328             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X)\n", reg_isoch);
329             p->setChannel(-1);
330             deallocateIsoChannel(isochannel);
331             return false;
332         }
333        
334         // write value of ISO_CHANNEL register
335         reg_isoch=isochannel;
336         if(!writeReg(BOUNCE_REGISTER_TX_ISOCHANNEL, reg_isoch)) {
337             debugError("Could not write ISO_CHANNEL register\n");
338             p->setChannel(-1);
339             deallocateIsoChannel(isochannel);
340             return false;
341         }
342        
343         return true;
344        
345     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
346         int n=i-m_receiveProcessors.size();
347         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
348        
349         // allocate ISO channel
350         int isochannel=allocateIsoChannel(p->getMaxPacketSize());
351         if(isochannel<0) {
352             debugError("Could not allocate iso channel for SP %d\n",i);
353             return false;
354         }
355         p->setChannel(isochannel);
356        
357         fb_quadlet_t reg_isoch;
358         // check value of ISO_CHANNEL register
359         if(!readReg(BOUNCE_REGISTER_RX_ISOCHANNEL, &reg_isoch)) {
360             debugError("Could not read ISO_CHANNEL register\n");
361             p->setChannel(-1);
362             deallocateIsoChannel(isochannel);
363             return false;
364         }
365         if(reg_isoch != 0xFFFFFFFFUL) {
366             debugError("ISO_CHANNEL register != 0xFFFFFFFF (=0x%08X)\n", reg_isoch);
367             p->setChannel(-1);
368             deallocateIsoChannel(isochannel);
369             return false;
370         }
371        
372         // write value of ISO_CHANNEL register
373         reg_isoch=isochannel;
374         if(!writeReg(BOUNCE_REGISTER_RX_ISOCHANNEL, reg_isoch)) {
375             debugError("Could not write ISO_CHANNEL register\n");
376             p->setChannel(-1);
377             deallocateIsoChannel(isochannel);
378             return false;
379         }
380        
381         return true;
382     }
383    
384     debugError("SP index %d out of range!\n",i);
385    
386     return false;
387 }
388
389 bool
390 BounceDevice::stopStreamByIndex(int i) {
391     if (i<(int)m_receiveProcessors.size()) {
392         int n=i;
393         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
394         unsigned int isochannel=p->getChannel();
395        
396         fb_quadlet_t reg_isoch;
397         // check value of ISO_CHANNEL register
398         if(!readReg(BOUNCE_REGISTER_TX_ISOCHANNEL, &reg_isoch)) {
399             debugError("Could not read ISO_CHANNEL register\n");
400             return false;
401         }
402         if(reg_isoch != isochannel) {
403             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X)\n", isochannel, reg_isoch);
404             return false;
405         }
406        
407         // write value of ISO_CHANNEL register
408         reg_isoch=0xFFFFFFFFUL;
409         if(!writeReg(BOUNCE_REGISTER_TX_ISOCHANNEL, reg_isoch)) {
410             debugError("Could not write ISO_CHANNEL register" );
411             return false;
412         }
413        
414         // deallocate ISO channel
415         if(!deallocateIsoChannel(isochannel)) {
416             debugError("Could not deallocate iso channel for SP\n",i);
417             return false;
418         }
419        
420         p->setChannel(-1);
421         return true;
422        
423     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
424         int n=i-m_receiveProcessors.size();
425         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
426        
427         unsigned int isochannel=p->getChannel();
428        
429         fb_quadlet_t reg_isoch;
430         // check value of ISO_CHANNEL register
431         if(!readReg(BOUNCE_REGISTER_RX_ISOCHANNEL, &reg_isoch)) {
432             debugError("Could not read ISO_CHANNEL register\n");
433             return false;
434         }
435         if(reg_isoch != isochannel) {
436             debugError("ISO_CHANNEL register != 0x%08X (=0x%08X)\n", isochannel, reg_isoch);
437             return false;
438         }
439        
440         // write value of ISO_CHANNEL register
441         reg_isoch=0xFFFFFFFFUL;
442         if(!writeReg(BOUNCE_REGISTER_RX_ISOCHANNEL, reg_isoch)) {
443             debugError("Could not write ISO_CHANNEL register\n");
444             return false;
445         }
446        
447         // deallocate ISO channel
448         if(!deallocateIsoChannel(isochannel)) {
449             debugError("Could not deallocate iso channel for SP (%d)\n",i);
450             return false;
451         }
452        
453         p->setChannel(-1);
454         return true;
455     }
456    
457     debugError("SP index %d out of range!\n",i);
458     return false;
459 }
460
461 // helper functions
462
463 // allocate ISO resources for the SP's
464 int BounceDevice::allocateIsoChannel(unsigned int packet_size) {
465     unsigned int bandwidth=8+packet_size;
466    
467     int ch=m_p1394Service->allocateIsoChannelGeneric(bandwidth);
468        
469     debugOutput(DEBUG_LEVEL_VERBOSE, "allocated channel %d, bandwidth %d\n",
470         ch, bandwidth);
471    
472     return ch;
473 }
474 // deallocate ISO resources
475 bool BounceDevice::deallocateIsoChannel(int channel) {
476     debugOutput(DEBUG_LEVEL_VERBOSE, "freeing channel %d\n",channel);
477     return m_p1394Service->freeIsoChannel(channel);
478 }
479
480 // I/O functions
481
482 bool
483 BounceDevice::readReg(fb_nodeaddr_t offset, fb_quadlet_t *result) {
484     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX\n", offset);
485    
486     if(offset >= BOUNCE_INVALID_OFFSET) {
487         debugError("invalid offset: 0x%016llX\n", offset);
488         return false;
489     }
490    
491     fb_nodeaddr_t addr=BOUNCE_REGISTER_BASE + offset;
492     fb_nodeid_t nodeId=m_nodeId | 0xFFC0;
493    
494     if(!m_p1394Service->read_quadlet( nodeId, addr, result ) ) {
495         debugError("Could not read from node 0x%04X addr 0x%012X\n", nodeId, addr);
496         return false;
497     }
498     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Read result: 0x%08X\n", *result);
499    
500     return true;
501 }
502
503 bool
504 BounceDevice::writeReg(fb_nodeaddr_t offset, fb_quadlet_t data) {
505     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, data: 0x%08X\n", 
506         offset, data);
507    
508     if(offset >= BOUNCE_INVALID_OFFSET) {
509         debugError("invalid offset: 0x%016llX\n", offset);
510         return false;
511     }
512    
513     fb_nodeaddr_t addr=BOUNCE_REGISTER_BASE + offset;
514     fb_nodeid_t nodeId=m_nodeId | 0xFFC0;
515    
516     if(!m_p1394Service->write_quadlet( nodeId, addr, data ) ) {
517         debugError("Could not write to node 0x%04X addr 0x%012X\n", nodeId, addr);
518         return false;
519     }
520     return true;
521 }
522
523 bool
524 BounceDevice::readRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
525     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Reading base register offset 0x%08llX, length %u\n",
526         offset, length);
527    
528     if(offset >= BOUNCE_INVALID_OFFSET) {
529         debugError("invalid offset: 0x%016llX\n", offset);
530         return false;
531     }
532    
533     fb_nodeaddr_t addr=BOUNCE_REGISTER_BASE + offset;
534     fb_nodeid_t nodeId=m_nodeId | 0xFFC0;
535    
536     if(!m_p1394Service->read( nodeId, addr, length, data ) ) {
537         debugError("Could not read from node 0x%04X addr 0x%012llX\n", nodeId, addr);
538         return false;
539     }
540     return true;
541 }
542
543 bool
544 BounceDevice::writeRegBlock(fb_nodeaddr_t offset, fb_quadlet_t *data, size_t length) {
545     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Writing base register offset 0x%08llX, length: %u\n", 
546         offset, length);
547    
548     if(offset >= BOUNCE_INVALID_OFFSET) {
549         debugError("invalid offset: 0x%016llX\n", offset);
550         return false;
551     }
552    
553     fb_nodeaddr_t addr=BOUNCE_REGISTER_BASE + offset;
554     fb_nodeid_t nodeId=m_nodeId | 0xFFC0;
555
556     if(!m_p1394Service->write( nodeId, addr, length, data ) ) {
557         debugError("Could not write to node 0x%04X addr 0x%012llX\n", nodeId, addr);
558         return false;
559     }
560     return true;
561 }
562
563
564 } // namespace
Note: See TracBrowser for help on using the browser.