Index: /branches/streaming-rework/src/libieee1394/ieee1394service.h =================================================================== --- /branches/streaming-rework/src/libieee1394/ieee1394service.h (revision 415) +++ /branches/streaming-rework/src/libieee1394/ieee1394service.h (revision 424) @@ -28,4 +28,6 @@ #include "debugmodule/debugmodule.h" +#include "IEC61883.h" + #include #include @@ -35,5 +37,5 @@ class ARMHandler; -class Ieee1394Service{ +class Ieee1394Service : public IEC61883 { public: Ieee1394Service(); Index: /branches/streaming-rework/src/libieee1394/IEC61883.h =================================================================== --- /branches/streaming-rework/src/libieee1394/IEC61883.h (revision 424) +++ /branches/streaming-rework/src/libieee1394/IEC61883.h (revision 424) @@ -0,0 +1,208 @@ +/* $Id$ */ + +/* + * FreeBob Streaming API + * FreeBob = Firewire (pro-)audio for linux + * + * http://freebob.sf.net + * + * Copyright (C) 2007 Pieter Palmers + * + * This program is free software {} you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation {} either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY {} without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program {} if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * + */ +#ifndef __FREEBOB_IEC61883__ +#define __FREEBOB_IEC61883__ + +#include "../debugmodule/debugmodule.h" + +/* + * This is shamelessly stolen from iec61883-private, + * but I need these functions! + * FIXME: this will only work until somebody decides to change + * these in libiec61883. + */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Plug Control Registers + **/ + +/* maximum number of PCRs allowed within the standard + * MPR/PCR addresses defined in IEC-61883. + * This refers to the number of output or input PCRs-- + * not the MPRs and not the combined total. + */ +#define IEC61883_PCR_MAX 31 + +/* standard CSR offsets for plugs */ +#define CSR_O_MPR 0x900 +#define CSR_O_PCR_0 0x904 + +#define CSR_I_MPR 0x980 +#define CSR_I_PCR_0 0x984 + +#if ( __BYTE_ORDER == __BIG_ENDIAN ) + +struct iec61883_oMPR { + unsigned int data_rate:2; + unsigned int bcast_channel:6; + unsigned int non_persist_ext:8; + unsigned int persist_ext:8; + unsigned int reserved:3; + unsigned int n_plugs:5; +}; + +struct iec61883_iMPR { + unsigned int data_rate:2; + unsigned int reserved:6; + unsigned int non_persist_ext:8; + unsigned int persist_ext:8; + unsigned int reserved2:3; + unsigned int n_plugs:5; +}; + +struct iec61883_oPCR { + unsigned int online:1; + unsigned int bcast_connection:1; + unsigned int n_p2p_connections:6; + unsigned int reserved:2; + unsigned int channel:6; + unsigned int data_rate:2; + unsigned int overhead_id:4; + unsigned int payload:10; +}; + +struct iec61883_iPCR { + unsigned int online:1; + unsigned int bcast_connection:1; + unsigned int n_p2p_connections:6; + unsigned int reserved:2; + unsigned int channel:6; + unsigned int reserved2:16; +}; + +#else + +struct iec61883_oMPR { + unsigned int n_plugs:5; + unsigned int reserved:3; + unsigned int persist_ext:8; + unsigned int non_persist_ext:8; + unsigned int bcast_channel:6; + unsigned int data_rate:2; +}; + +struct iec61883_iMPR { + unsigned int n_plugs:5; + unsigned int reserved2:3; + unsigned int persist_ext:8; + unsigned int non_persist_ext:8; + unsigned int reserved:6; + unsigned int data_rate:2; +}; + +struct iec61883_oPCR { + unsigned int payload:10; + unsigned int overhead_id:4; + unsigned int data_rate:2; + unsigned int channel:6; + unsigned int reserved:2; + unsigned int n_p2p_connections:6; + unsigned int bcast_connection:1; + unsigned int online:1; +}; + +struct iec61883_iPCR { + unsigned int reserved2:16; + unsigned int channel:6; + unsigned int reserved:2; + unsigned int n_p2p_connections:6; + unsigned int bcast_connection:1; + unsigned int online:1; +}; + +#endif + +/** + * iec61883_plug_get - Read a node's plug register. + * @h: A raw1394 handle. + * @n: The node id of the node to read + * @a: The CSR offset address (relative to base) of the register to read. + * @value: A pointer to a quadlet where the plug register's value will be stored. + * + * This function handles bus to host endian conversion. It returns 0 for + * suceess or -1 for error (errno available). + **/ +int +iec61883_plug_get(raw1394handle_t h, nodeid_t n, nodeaddr_t a, quadlet_t *value); + + +/** + * iec61883_plug_set - Write a node's plug register. + * @h: A raw1394 handle. + * @n: The node id of the node to read + * @a: The CSR offset address (relative to CSR base) of the register to write. + * @value: A quadlet containing the new register value. + * + * This uses a compare/swap lock operation to safely write the + * new register value, as required by IEC 61883-1. + * This function handles host to bus endian conversion. It returns 0 for success + * or -1 for error (errno available). + **/ +int +iec61883_plug_set(raw1394handle_t h, nodeid_t n, nodeaddr_t a, quadlet_t value); + +/** + * High level plug access macros + */ + +#define iec61883_get_oMPR(h,n,v) iec61883_plug_get((h), (n), CSR_O_MPR, (quadlet_t *)(v)) +#define iec61883_set_oMPR(h,n,v) iec61883_plug_set((h), (n), CSR_O_MPR, *((quadlet_t *)&(v))) +#define iec61883_get_oPCR0(h,n,v) iec61883_plug_get((h), (n), CSR_O_PCR_0, (quadlet_t *)(v)) +#define iec61883_set_oPCR0(h,n,v) iec61883_plug_set((h), (n), CSR_O_PCR_0, *((quadlet_t *)&(v))) +#define iec61883_get_oPCRX(h,n,v,x) iec61883_plug_get((h), (n), CSR_O_PCR_0+(4*(x)), (quadlet_t *)(v)) +#define iec61883_set_oPCRX(h,n,v,x) iec61883_plug_set((h), (n), CSR_O_PCR_0+(4*(x)), *((quadlet_t *)&(v))) +#define iec61883_get_iMPR(h,n,v) iec61883_plug_get((h), (n), CSR_I_MPR, (quadlet_t *)(v)) +#define iec61883_set_iMPR(h,n,v) iec61883_plug_set((h), (n), CSR_I_MPR, *((quadlet_t *)&(v))) +#define iec61883_get_iPCR0(h,n,v) iec61883_plug_get((h), (n), CSR_I_PCR_0, (quadlet_t *)(v)) +#define iec61883_set_iPCR0(h,n,v) iec61883_plug_set((h), (n), CSR_I_PCR_0, *((quadlet_t *)&(v))) +#define iec61883_get_iPCRX(h,n,v,x) iec61883_plug_get((h), (n), CSR_I_PCR_0+(4*(x)), (quadlet_t *)(v)) +#define iec61883_set_iPCRX(h,n,v,x) iec61883_plug_set((h), (n), CSR_I_PCR_0+(4*(x)), *((quadlet_t *)&(v))) + + +#ifdef __cplusplus +} +#endif + +class IEC61883 { + +public: + + IEC61883(); + virtual ~IEC61883(); + +protected: + DECLARE_DEBUG_MODULE; + +}; + +#endif /* __FREEBOB_IEC61883__ */ + + Index: /branches/streaming-rework/src/libieee1394/ieee1394service.cpp =================================================================== --- /branches/streaming-rework/src/libieee1394/ieee1394service.cpp (revision 415) +++ /branches/streaming-rework/src/libieee1394/ieee1394service.cpp (revision 424) @@ -117,4 +117,5 @@ m_default_arm_handler = raw1394_set_arm_tag_handler( m_resetHandle, this->armHandlerLowLevel ); + startRHThread(); Index: /branches/streaming-rework/src/libieee1394/IEC61883.cpp =================================================================== --- /branches/streaming-rework/src/libieee1394/IEC61883.cpp (revision 424) +++ /branches/streaming-rework/src/libieee1394/IEC61883.cpp (revision 424) @@ -0,0 +1,38 @@ +/* $Id$ */ + +/* + * FreeBob Streaming API + * FreeBob = Firewire (pro-)audio for linux + * + * http://freebob.sf.net + * + * Copyright (C) 2007 Pieter Palmers + * + * This program is free software {} you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation {} either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY {} without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program {} if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#include "IEC61883.h" + +IMPL_DEBUG_MODULE( IEC61883, IEC61883, DEBUG_LEVEL_NORMAL ); + +IEC61883::IEC61883() { + +} + +IEC61883::~IEC61883() { + +} Index: /branches/streaming-rework/src/libstreaming/StreamProcessor.h =================================================================== --- /branches/streaming-rework/src/libstreaming/StreamProcessor.h (revision 419) +++ /branches/streaming-rework/src/libstreaming/StreamProcessor.h (revision 424) @@ -37,6 +37,6 @@ #include "libutil/StreamStatistics.h" - #include "libutil/TimestampedBuffer.h" +#include "libutil/OptionContainer.h" namespace Streaming { @@ -54,5 +54,6 @@ class StreamProcessor : public IsoStream, public PortManager, - public Util::TimestampedBufferClient { + public Util::TimestampedBufferClient, + public Util::OptionContainer { friend class StreamProcessorManager; @@ -112,9 +113,9 @@ Util::TimestampedBuffer *m_data_buffer; -protected: - +protected: // SPM related void setManager(StreamProcessorManager *manager) {m_manager=manager;}; void clearManager() {m_manager=0;}; - + +protected: unsigned int m_nb_buffers; ///< cached from manager->getNbBuffers(), the number of periods to buffer unsigned int m_period; ///< cached from manager->getPeriod(), the period size Index: /branches/streaming-rework/src/libstreaming/AmdtpStreamProcessor.cpp =================================================================== --- /branches/streaming-rework/src/libstreaming/AmdtpStreamProcessor.cpp (revision 419) +++ /branches/streaming-rework/src/libstreaming/AmdtpStreamProcessor.cpp (revision 424) @@ -1211,13 +1211,13 @@ } - - debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n"); - debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, DBS: %d, SYT: %d\n", - m_framerate,m_dimension,m_syt_interval); - debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n", - m_period,m_nb_buffers); - debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n", - m_port,m_channel); - return true; + debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n"); + debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, DBS: %d, SYT: %d\n", + m_framerate,m_dimension,m_syt_interval); + debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n", + m_period,m_nb_buffers); + debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n", + m_port,m_channel); + + return true; } Index: /branches/streaming-rework/src/libstreaming/AmdtpStreamProcessor.h =================================================================== --- /branches/streaming-rework/src/libstreaming/AmdtpStreamProcessor.h (revision 419) +++ /branches/streaming-rework/src/libstreaming/AmdtpStreamProcessor.h (revision 424) @@ -145,5 +145,6 @@ int encodeSilencePortToMBLAEvents(AmdtpAudioPort *, quadlet_t *data, unsigned int offset, unsigned int nevents); - + void updatePreparedState(); + unsigned long m_last_timestamp; @@ -216,4 +217,5 @@ int decodeMBLAEventsToPort(AmdtpAudioPort *, quadlet_t *data, unsigned int offset, unsigned int nevents); + void updatePreparedState(); int m_dimension; Index: /branches/streaming-rework/src/libstreaming/StreamProcessorManager.cpp =================================================================== --- /branches/streaming-rework/src/libstreaming/StreamProcessorManager.cpp (revision 419) +++ /branches/streaming-rework/src/libstreaming/StreamProcessorManager.cpp (revision 424) @@ -48,7 +48,13 @@ StreamProcessorManager::StreamProcessorManager(unsigned int period, unsigned int nb_buffers) - : m_SyncSource(NULL), m_nb_buffers(nb_buffers), m_period(period), m_xruns(0), - m_isoManager(0), m_nbperiods(0) { - + : m_is_slave( false ) + , m_SyncSource(NULL) + , m_nb_buffers(nb_buffers) + , m_period(period) + , m_xruns(0) + , m_isoManager(0) + , m_nbperiods(0) +{ + addOption(Util::OptionContainer::Option("slaveMode",false)); } @@ -195,56 +201,69 @@ debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n"); - // if no sync source is set, select one here - if(m_SyncSource == NULL) { - debugWarning("Sync Source is not set. Defaulting to first StreamProcessor.\n"); - } - - for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); - it != m_ReceiveProcessors.end(); - ++it ) { - if(m_SyncSource == NULL) { - debugWarning(" => Sync Source is %p.\n", *it); - m_SyncSource = *it; - } - } - - for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); - it != m_TransmitProcessors.end(); - ++it ) { - if(m_SyncSource == NULL) { - debugWarning(" => Sync Source is %p.\n", *it); - m_SyncSource = *it; - } - } - - // now do the actual preparation - debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare Receive processors...\n"); - for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); - it != m_ReceiveProcessors.end(); - ++it ) { - if(!(*it)->setSyncSource(m_SyncSource)) { - debugFatal( " could not set sync source (%p)...\n",(*it)); - return false; - } - - if(!(*it)->prepare()) { - debugFatal( " could not prepare (%p)...\n",(*it)); - return false; - } - } - - debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare Transmit processors...\n"); - for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); - it != m_TransmitProcessors.end(); - ++it ) { - if(!(*it)->setSyncSource(m_SyncSource)) { - debugFatal( " could not set sync source (%p)...\n",(*it)); - return false; - } - if(!(*it)->prepare()) { - debugFatal( " could not prepare (%p)...\n",(*it)); - return false; - } - } + m_is_slave=false; + if(!getOption("snoopMode", m_is_slave)) { + debugWarning("Could not retrieve slaveMode parameter, defauling to false\n"); + } + + // if no sync source is set, select one here + if(m_SyncSource == NULL) { + debugWarning("Sync Source is not set. Defaulting to first StreamProcessor.\n"); + } + + for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); + it != m_ReceiveProcessors.end(); + ++it ) { + if(m_SyncSource == NULL) { + debugWarning(" => Sync Source is %p.\n", *it); + m_SyncSource = *it; + } + } + + for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); + it != m_TransmitProcessors.end(); + ++it ) { + if(m_SyncSource == NULL) { + debugWarning(" => Sync Source is %p.\n", *it); + m_SyncSource = *it; + } + } + + // now do the actual preparation + debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare Receive processors...\n"); + for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); + it != m_ReceiveProcessors.end(); + ++it ) { + + if(!(*it)->setSyncSource(m_SyncSource)) { + debugFatal( " could not set sync source (%p)...\n",(*it)); + return false; + } + + if(!(*it)->setOption("slaveMode", m_is_slave)) { + debugOutput(DEBUG_LEVEL_VERBOSE, " note: could not set slaveMode option for (%p)...\n",(*it)); + } + + if(!(*it)->prepare()) { + debugFatal( " could not prepare (%p)...\n",(*it)); + return false; + } + } + + debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare Transmit processors...\n"); + for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); + it != m_TransmitProcessors.end(); + ++it ) { + if(!(*it)->setSyncSource(m_SyncSource)) { + debugFatal( " could not set sync source (%p)...\n",(*it)); + return false; + } + if(!(*it)->setOption("slaveMode", m_is_slave)) { + debugOutput(DEBUG_LEVEL_VERBOSE, " note: could not set slaveMode option for (%p)...\n",(*it)); + } + if(!(*it)->prepare()) { + debugFatal( " could not prepare (%p)...\n",(*it)); + return false; + } + } // if there are no stream processors registered, @@ -818,5 +837,5 @@ xmt_bf = (*it)->getBufferFill(); } - debugOutput( DEBUG_LEVEL_VERBOSE, "XF at %011llu ticks, RBF=%d, XBF=%d, SUM=%d...\n", + debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "XF at %011llu ticks, RBF=%d, XBF=%d, SUM=%d...\n", m_time_of_transfer,rcv_bf,xmt_bf,rcv_bf+xmt_bf); Index: /branches/streaming-rework/src/libstreaming/StreamProcessor.cpp =================================================================== --- /branches/streaming-rework/src/libstreaming/StreamProcessor.cpp (revision 419) +++ /branches/streaming-rework/src/libstreaming/StreamProcessor.cpp (revision 424) @@ -185,5 +185,5 @@ bool StreamProcessor::isRunning() { - return m_running; + return m_running; } @@ -215,14 +215,10 @@ m_disabled=false; - return true; } bool StreamProcessor::disable() { - m_disabled=true; - - return true; - + return true; } Index: /branches/streaming-rework/src/libstreaming/StreamProcessorManager.h =================================================================== --- /branches/streaming-rework/src/libstreaming/StreamProcessorManager.h (revision 419) +++ /branches/streaming-rework/src/libstreaming/StreamProcessorManager.h (revision 424) @@ -29,6 +29,7 @@ #define __FREEBOB_STREAMPROCESSORMANAGER__ -#include "../debugmodule/debugmodule.h" -#include "../libutil/Thread.h" +#include "debugmodule/debugmodule.h" +#include "libutil/Thread.h" +#include "libutil/OptionContainer.h" #include #include "Port.h" @@ -50,6 +51,7 @@ */ -class StreamProcessorManager { - +class StreamProcessorManager : public Util::OptionContainer { + friend class StreamProcessor; + public: @@ -108,5 +110,7 @@ virtual void setVerboseLevel(int l); void dumpInfo(); - + +private: // slaving support + bool m_is_slave; // the sync source stuff @@ -118,6 +122,6 @@ StreamProcessor * getSyncSource(); - protected: + // thread sync primitives bool m_xrun_happened; Index: /branches/streaming-rework/src/devicemanager.h =================================================================== --- /branches/streaming-rework/src/devicemanager.h (revision 419) +++ /branches/streaming-rework/src/devicemanager.h (revision 424) @@ -25,4 +25,5 @@ #include "libfreebob/xmlparser.h" +#include "libutil/OptionContainer.h" #include @@ -42,5 +43,5 @@ -class DeviceManager{ +class DeviceManager : public Util::OptionContainer { public: DeviceManager(); @@ -71,4 +72,6 @@ int id, int level ); + IAvDevice* getSlaveDriver( std::auto_ptr( configRom ), + int level ); protected: Index: /branches/streaming-rework/src/iavdevice.h =================================================================== --- /branches/streaming-rework/src/iavdevice.h (revision 420) +++ /branches/streaming-rework/src/iavdevice.h (revision 424) @@ -216,4 +216,8 @@ virtual bool stopStreamByIndex(int i) = 0; + /** + * set verbosity level + */ + virtual void setVerboseLevel(int l) {setDebugLevel(l);}; }; Index: /branches/streaming-rework/src/freebob_streaming.cpp =================================================================== --- /branches/streaming-rework/src/freebob_streaming.cpp (revision 419) +++ /branches/streaming-rework/src/freebob_streaming.cpp (revision 424) @@ -109,8 +109,30 @@ return 0; } - + + // set slave mode option + bool slaveMode=(dev->options.slave_mode != 0); + debugOutput(DEBUG_LEVEL_VERBOSE, "setting slave mode to %d\n", slaveMode); + if(!dev->m_deviceManager->setOption("slaveMode", slaveMode)) { + debugWarning("Failed to set slave mode option\n"); + } + // set snoop mode option + bool snoopMode=(dev->options.snoop_mode != 0); + debugOutput(DEBUG_LEVEL_VERBOSE, "setting snoop mode to %d\n", snoopMode); + if(!dev->m_deviceManager->setOption("snoopMode", snoopMode)) { + debugWarning("Failed to set snoop mode option\n"); + } + // discover the devices on the bus if(!dev->m_deviceManager->discover(DEBUG_LEVEL_NORMAL)) { debugFatal("Could not discover devices\n"); + delete dev->processorManager; + delete dev->m_deviceManager; + delete dev; + return 0; + } + + // are there devices on the bus? + if(dev->m_deviceManager->getAvDeviceCount()==0) { + debugFatal("There are no devices on the bus\n"); delete dev->processorManager; delete dev->m_deviceManager; @@ -177,12 +199,12 @@ int freebob_streaming_prepare(freebob_device_t *dev) { - debugOutput(DEBUG_LEVEL_VERBOSE, "Preparing...\n"); - - if (!dev->processorManager->prepare()) { + debugOutput(DEBUG_LEVEL_VERBOSE, "Preparing...\n"); + + if (!dev->processorManager->prepare()) { debugFatal("Could not prepare streaming...\n"); return false; - } - - return true; + } + + return true; } Index: /branches/streaming-rework/src/bebob/bebob_avdevice.cpp =================================================================== --- /branches/streaming-rework/src/bebob/bebob_avdevice.cpp (revision 420) +++ /branches/streaming-rework/src/bebob/bebob_avdevice.cpp (revision 424) @@ -725,38 +725,53 @@ AvDevice::setSamplingFrequency( ESamplingFrequency samplingFrequency ) { - - AvPlug* plug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Input, 0 ); - if ( !plug ) { - debugError( "setSampleRate: Could not retrieve iso input plug 0\n" ); - return false; - } - - if ( !setSamplingFrequencyPlug( *plug, - AvPlug::eAPD_Input, - samplingFrequency ) ) - { - debugError( "setSampleRate: Setting sample rate failed\n" ); - return false; - } - - plug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Output, 0 ); - if ( !plug ) { - debugError( "setSampleRate: Could not retrieve iso output plug 0\n" ); - return false; - } - - if ( !setSamplingFrequencyPlug( *plug, - AvPlug::eAPD_Output, - samplingFrequency ) ) - { - debugError( "setSampleRate: Setting sample rate failed\n" ); - return false; - } - - - debugOutput( DEBUG_LEVEL_VERBOSE, - "setSampleRate: Set sample rate to %d\n", - convertESamplingFrequency( samplingFrequency ) ); - return true; + bool snoopMode=false; + if(!getOption("snoopMode", snoopMode)) { + debugWarning("Could not retrieve snoopMode parameter, defauling to false\n"); + } + + if(snoopMode) { + int current_sr=getSamplingFrequency(); + if (current_sr != convertESamplingFrequency( samplingFrequency ) ) { + debugError("In snoop mode it is impossible to set the sample rate.\n"); + debugError("Please start the client with the correct setting.\n"); + return false; + } + return true; + } else { + AvPlug* plug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Input, 0 ); + if ( !plug ) { + debugError( "setSampleRate: Could not retrieve iso input plug 0\n" ); + return false; + } + + if ( !setSamplingFrequencyPlug( *plug, + AvPlug::eAPD_Input, + samplingFrequency ) ) + { + debugError( "setSampleRate: Setting sample rate failed\n" ); + return false; + } + + plug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Output, 0 ); + if ( !plug ) { + debugError( "setSampleRate: Could not retrieve iso output plug 0\n" ); + return false; + } + + if ( !setSamplingFrequencyPlug( *plug, + AvPlug::eAPD_Output, + samplingFrequency ) ) + { + debugError( "setSampleRate: Setting sample rate failed\n" ); + return false; + } + + debugOutput( DEBUG_LEVEL_VERBOSE, + "setSampleRate: Set sample rate to %d\n", + convertESamplingFrequency( samplingFrequency ) ); + return true; + } + // not executable + return false; } @@ -955,12 +970,30 @@ bool AvDevice::lock() { + bool snoopMode=false; + if(!getOption("snoopMode", snoopMode)) { + debugWarning("Could not retrieve snoopMode parameter, defauling to false\n"); + } + + if (snoopMode) { + // don't lock + } else { + + } return true; } - bool AvDevice::unlock() { - + bool snoopMode=false; + if(!getOption("snoopMode", snoopMode)) { + debugWarning("Could not retrieve snoopMode parameter, defauling to false\n"); + } + + if (snoopMode) { + // don't unlock + } else { + + } return true; } @@ -972,5 +1005,5 @@ debugWarning("Could not retrieve snoopMode parameter, defauling to false\n"); } - + /////////// // get plugs @@ -989,4 +1022,5 @@ int samplerate=outputPlug->getSampleRate(); + debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing receive processor...\n"); // create & add streamprocessors Streaming::StreamProcessor *p; @@ -1013,4 +1047,6 @@ // do the transmit processor + debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing transmit processor%s...\n", + (snoopMode?" in snoop mode":"")); if (snoopMode) { // we are snooping, so this is receive too. @@ -1039,5 +1075,4 @@ return false; } - m_receiveProcessors.push_back(p); } else { if (!addPlugToProcessor(*inputPlug,p, @@ -1046,6 +1081,11 @@ return false; } - m_transmitProcessors.push_back(p); - } + } + + // we put this SP into the transmit SP vector, + // no matter if we are in snoop mode or not + // this allows us to find out what direction + // a certain stream should have. + m_transmitProcessors.push_back(p); return true; @@ -1157,17 +1197,39 @@ AvDevice::startStreamByIndex(int i) { int iso_channel=-1; - + bool snoopMode=false; + if(!getOption("snoopMode", snoopMode)) { + debugWarning("Could not retrieve snoopMode parameter, defauling to false\n"); + } + if (i<(int)m_receiveProcessors.size()) { int n=i; Streaming::StreamProcessor *p=m_receiveProcessors.at(n); - iso_channel=m_p1394Service->allocateIsoChannelCMP( - m_pConfigRom->getNodeId() | 0xffc0, 0, - m_p1394Service->getLocalNodeId()| 0xffc0, -1); - + if(snoopMode) { // a stream from the device to another host + // FIXME: put this into a decent framework! + // we should check the oPCR[n] on the device + struct iec61883_oPCR opcr; + if (iec61883_get_oPCRX( + m_p1394Service->getHandle(), + m_pConfigRom->getNodeId() | 0xffc0, + (quadlet_t *)&opcr, + n)) { + + debugWarning("Error getting the channel for SP %d\n",i); + return false; + } + + iso_channel=opcr.channel; + } else { + iso_channel=m_p1394Service->allocateIsoChannelCMP( + m_pConfigRom->getNodeId() | 0xffc0, n, + m_p1394Service->getLocalNodeId()| 0xffc0, -1); + } if (iso_channel<0) { debugError("Could not allocate ISO channel for SP %d\n",i); return false; } + + debugOutput(DEBUG_LEVEL_VERBOSE, "Started SP %d on channel %d\n",i,iso_channel); p->setChannel(iso_channel); @@ -1178,7 +1240,25 @@ Streaming::StreamProcessor *p=m_transmitProcessors.at(n); - iso_channel=m_p1394Service->allocateIsoChannelCMP( - m_p1394Service->getLocalNodeId()| 0xffc0, -1, - m_pConfigRom->getNodeId() | 0xffc0, 0); + if(snoopMode) { // a stream from another host to the device + // FIXME: put this into a decent framework! + // we should check the iPCR[n] on the device + struct iec61883_iPCR ipcr; + if (iec61883_get_iPCRX( + m_p1394Service->getHandle(), + m_pConfigRom->getNodeId() | 0xffc0, + (quadlet_t *)&ipcr, + n)) { + + debugWarning("Error getting the channel for SP %d\n",i); + return false; + } + + iso_channel=ipcr.channel; + + } else { + iso_channel=m_p1394Service->allocateIsoChannelCMP( + m_p1394Service->getLocalNodeId()| 0xffc0, -1, + m_pConfigRom->getNodeId() | 0xffc0, n); + } if (iso_channel<0) { @@ -1187,4 +1267,6 @@ } + debugOutput(DEBUG_LEVEL_VERBOSE, "Started SP %d on channel %d\n",i,iso_channel); + p->setChannel(iso_channel); return true; @@ -1197,12 +1279,21 @@ bool AvDevice::stopStreamByIndex(int i) { - if (i<(int)m_receiveProcessors.size()) { + bool snoopMode=false; + if(!getOption("snoopMode", snoopMode)) { + debugWarning("Could not retrieve snoopMode parameter, defauling to false\n"); + } + + if (i<(int)m_receiveProcessors.size()) { int n=i; Streaming::StreamProcessor *p=m_receiveProcessors.at(n); - // deallocate ISO channel - if(!m_p1394Service->freeIsoChannel(p->getChannel())) { - debugError("Could not deallocate iso channel for SP %d\n",i); - return false; + if(snoopMode) { + + } else { + // deallocate ISO channel + if(!m_p1394Service->freeIsoChannel(p->getChannel())) { + debugError("Could not deallocate iso channel for SP %d\n",i); + return false; + } } p->setChannel(-1); @@ -1214,8 +1305,12 @@ Streaming::StreamProcessor *p=m_transmitProcessors.at(n); - // deallocate ISO channel - if(!m_p1394Service->freeIsoChannel(p->getChannel())) { - debugError("Could not deallocate iso channel for SP %d\n",i); - return false; + if(snoopMode) { + + } else { + // deallocate ISO channel + if(!m_p1394Service->freeIsoChannel(p->getChannel())) { + debugError("Could not deallocate iso channel for SP %d\n",i); + return false; + } } p->setChannel(-1); Index: /branches/streaming-rework/src/Makefile.am =================================================================== --- /branches/streaming-rework/src/Makefile.am (revision 420) +++ /branches/streaming-rework/src/Makefile.am (revision 424) @@ -35,8 +35,9 @@ libieee1394/configrom.h libieee1394/csr1212.h \ libieee1394/ieee1394service.h libieee1394/ARMHandler.h \ + libieee1394/IEC61883.h \ debugmodule/debugmodule.h \ devicemanager.h fbtypes.h iavdevice.h threads.h bebob/bebob_avdevice.h \ bebob/bebob_avdevice_subunit.h bebob/bebob_avplug.h bebob/bebob_dl_bcd.h bebob/bebob_dl_codes.h \ - bebob/bebob_dl_mgr.h bebob/bebob_functionblock.h bounce/bounce_avdevice.h \ + bebob/bebob_dl_mgr.h bebob/bebob_functionblock.h bounce/bounce_avdevice.h bounce/bounce_slave_avdevice.h \ maudio/maudio_avdevice.h motu/motu_avdevice.h rme/rme_avdevice.h \ metrichalo/mh_avdevice.h dice/dice_avdevice.h \ @@ -83,4 +84,5 @@ libieee1394/csr1212.c \ libieee1394/ieee1394service.cpp \ + libieee1394/IEC61883.cpp \ libstreaming/cip.c \ libstreaming/IsoHandler.cpp \ @@ -126,5 +128,6 @@ bounce_src = \ - bounce/bounce_avdevice.cpp + bounce/bounce_avdevice.cpp \ + bounce/bounce_slave_avdevice.cpp metric_halo_src = \ Index: /branches/streaming-rework/src/devicemanager.cpp =================================================================== --- /branches/streaming-rework/src/devicemanager.cpp (revision 419) +++ /branches/streaming-rework/src/devicemanager.cpp (revision 424) @@ -43,4 +43,5 @@ #ifdef ENABLE_BOUNCE #include "bounce/bounce_avdevice.h" + #include "bounce/bounce_slave_avdevice.h" #endif @@ -68,5 +69,6 @@ : m_1394Service( 0 ) { - + addOption(Util::OptionContainer::Option("slaveMode",false)); + addOption(Util::OptionContainer::Option("snoopMode",false)); } @@ -105,4 +107,12 @@ DeviceManager::discover( int verboseLevel ) { + bool slaveMode=false; + if(!getOption("slaveMode", slaveMode)) { + debugWarning("Could not retrieve slaveMode parameter, defauling to false\n"); + } + bool snoopMode=false; + if(!getOption("snoopMode", snoopMode)) { + debugWarning("Could not retrieve snoopMode parameter, defauling to false\n"); + } setDebugLevel( verboseLevel ); @@ -117,14 +127,75 @@ m_avDevices.clear(); - for ( fb_nodeid_t nodeId = 0; - nodeId < m_1394Service->getNodeCount(); - ++nodeId ) - { - debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId ); - - if (nodeId == m_1394Service->getLocalNodeId()) { - debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId ); - continue; - } + if (!slaveMode) { + for ( fb_nodeid_t nodeId = 0; + nodeId < m_1394Service->getNodeCount(); + ++nodeId ) + { + debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId ); + + if (nodeId == m_1394Service->getLocalNodeId()) { + debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId ); + continue; + } + + std::auto_ptr configRom = + std::auto_ptr( new ConfigRom( *m_1394Service, + nodeId ) ); + if ( !configRom->initialize() ) { + // \todo If a PHY on the bus is in power safe mode then + // the config rom is missing. So this might be just + // such this case and we can safely skip it. But it might + // be there is a real software problem on our side. + // This should be handled more carefuly. + debugOutput( DEBUG_LEVEL_NORMAL, + "Could not read config rom from device (node id %d). " + "Skip device discovering for this node\n", + nodeId ); + continue; + } + + IAvDevice* avDevice = getDriverForDevice( configRom, + nodeId, + verboseLevel ); + if ( avDevice ) { + debugOutput( DEBUG_LEVEL_NORMAL, + "discover: driver found for device %d\n", + nodeId ); + + if ( !avDevice->discover() ) { + debugError( "discover: could not discover device\n" ); + delete avDevice; + continue; + } + + if ( !avDevice->setId( m_avDevices.size() ) ) { + debugError( "setting Id failed\n" ); + } + + if (snoopMode) { + debugOutput( DEBUG_LEVEL_VERBOSE, + "Enabling snoop mode on node %d...\n", nodeId ); + + if(!avDevice->setOption("snoopMode", snoopMode)) { + debugWarning("Could not set snoop mode for device on node %d\n",nodeId); + delete avDevice; + continue; + } + } + + avDevice->setVerboseLevel( verboseLevel ); + + if ( verboseLevel ) { + avDevice->showDevice(); + } + + m_avDevices.push_back( avDevice ); + } + } + return true; + + } else { // slave mode + fb_nodeid_t nodeId = m_1394Service->getLocalNodeId(); + debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId ); std::auto_ptr configRom = @@ -141,10 +212,8 @@ "Skip device discovering for this node\n", nodeId ); - continue; - } - - IAvDevice* avDevice = getDriverForDevice( configRom, - nodeId, - verboseLevel ); + return false; + } + + IAvDevice* avDevice = getSlaveDriver( configRom, verboseLevel ); if ( avDevice ) { debugOutput( DEBUG_LEVEL_NORMAL, @@ -155,5 +224,5 @@ debugError( "discover: could not discover device\n" ); delete avDevice; - continue; + return false; } @@ -167,7 +236,7 @@ m_avDevices.push_back( avDevice ); } - } - - return true; + + return true; + } } @@ -178,4 +247,5 @@ { #ifdef ENABLE_BEBOB + debugOutput( DEBUG_LEVEL_VERBOSE, "Trying BeBoB...\n" ); if ( BeBoB::AvDevice::probe( *configRom.get() ) ) { return new BeBoB::AvDevice( configRom, *m_1394Service, id, level ); @@ -184,4 +254,5 @@ #ifdef ENABLE_BEBOB + debugOutput( DEBUG_LEVEL_VERBOSE, "Trying M-Audio...\n" ); if ( MAudio::AvDevice::probe( *configRom.get() ) ) { return new MAudio::AvDevice( configRom, *m_1394Service, id, level ); @@ -190,4 +261,5 @@ #ifdef ENABLE_MOTU + debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Motu...\n" ); if ( Motu::MotuDevice::probe( *configRom.get() ) ) { return new Motu::MotuDevice( configRom, *m_1394Service, id, level ); @@ -196,4 +268,5 @@ #ifdef ENABLE_DICE + debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Dice...\n" ); if ( Dice::DiceAvDevice::probe( *configRom.get() ) ) { return new Dice::DiceAvDevice( configRom, *m_1394Service, id, level ); @@ -202,4 +275,5 @@ #ifdef ENABLE_METRIC_HALO + debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Metric Halo...\n" ); if ( MetricHalo::MHAvDevice::probe( *configRom.get() ) ) { return new MetricHalo::MHAvDevice( configRom, *m_1394Service, id, level ); @@ -208,4 +282,5 @@ #ifdef ENABLE_RME + debugOutput( DEBUG_LEVEL_VERBOSE, "Trying RME...\n" ); if ( Rme::RmeDevice::probe( *configRom.get() ) ) { return new Rme::RmeDevice( configRom, *m_1394Service, id, level ); @@ -214,6 +289,20 @@ #ifdef ENABLE_BOUNCE + debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Bounce...\n" ); if ( Bounce::BounceDevice::probe( *configRom.get() ) ) { return new Bounce::BounceDevice( configRom, *m_1394Service, id, level ); + } +#endif + + return 0; +} + +IAvDevice* +DeviceManager::getSlaveDriver( std::auto_ptr( configRom ), int level ) +{ + +#ifdef ENABLE_BOUNCE + if ( Bounce::BounceSlaveDevice::probe( *configRom.get() ) ) { + return new Bounce::BounceSlaveDevice( configRom, *m_1394Service, level ); } #endif @@ -300,11 +389,16 @@ DeviceManager::getSyncSource() { IAvDevice* device = getAvDeviceByIndex(0); - return device->getStreamProcessorByIndex(0); - + + bool slaveMode=false; + if(!getOption("slaveMode", slaveMode)) { + debugWarning("Could not retrieve slaveMode parameter, defauling to false\n"); + } + #warning TEST CODE FOR BOUNCE DEVICE !! - if (device->getConfigRom().getNodeId()==0) { + // this makes the bounce slave use the xmit SP as sync source + if (slaveMode) { + return device->getStreamProcessorByIndex(1); + } else { return device->getStreamProcessorByIndex(0); - } else { - return device->getStreamProcessorByIndex(1); } Index: /branches/streaming-rework/src/bounce/bounce_slave_avdevice.h =================================================================== --- /branches/streaming-rework/src/bounce/bounce_slave_avdevice.h (revision 422) +++ /branches/streaming-rework/src/bounce/bounce_slave_avdevice.h (revision 424) @@ -29,18 +29,64 @@ #define __FREEBOB_BOUNCESLAVEDEVICE__ -#include "../debugmodule/debugmodule.h" +#include "debugmodule/debugmodule.h" +#include "bounce_avdevice.h" namespace Bounce { -class BounceSlaveDevice { - +class BounceSlaveDevice : public BounceDevice { + class BounceSlaveNotifier; public: - BounceSlaveDevice(); - virtual ~BounceSlaveDevice(); + BounceSlaveDevice( std::auto_ptr( configRom ), + Ieee1394Service& ieee1394Service, + int verboseLevel ); + virtual ~BounceSlaveDevice(); + + static bool probe( ConfigRom& configRom ); + bool discover(); + bool prepare(); + bool lock(); + bool unlock(); + + bool startStreamByIndex(int i); + bool stopStreamByIndex(int i); + protected: DECLARE_DEBUG_MODULE; +private: + bool waitForRegisterNotEqualTo(nodeaddr_t offset, fb_quadlet_t v); + bool initMemSpace(); + bool restoreMemSpace(); + +private: // configrom shit + struct configrom_backup { + quadlet_t rom[0x100]; + size_t rom_size; + unsigned char rom_version; + }; + struct configrom_backup m_original_config_rom; + + struct configrom_backup + save_config_rom(raw1394handle_t handle); + int restore_config_rom(raw1394handle_t handle, struct configrom_backup old); + int init_config_rom(raw1394handle_t handle); + +private: + BounceSlaveNotifier *m_Notifier; + /** + * this class reacts on the ohter side writing to the + * hosts address space + */ + class BounceSlaveNotifier : public ARMHandler + { + public: + BounceSlaveNotifier(BounceSlaveDevice *, nodeaddr_t start); + virtual ~BounceSlaveNotifier(); + + private: + BounceSlaveDevice *m_bounceslavedevice; + }; }; Index: /branches/streaming-rework/src/bounce/bounce_avdevice.cpp =================================================================== --- /branches/streaming-rework/src/bounce/bounce_avdevice.cpp (revision 420) +++ /branches/streaming-rework/src/bounce/bounce_avdevice.cpp (revision 424) @@ -45,5 +45,5 @@ static VendorModelEntry supportedDeviceList[] = { - {0x0B0001, 0x0B0001, 0x0B0001, "FreeBoB", "Bounce"}, + {0x0B0001LU, 0x0B0001LU, 0x0B0001LU, "FreeBoB", "Bounce"}, }; @@ -58,5 +58,6 @@ , m_p1394Service( &ieee1394service ) , m_nodeId( nodeId ) - , m_verboseLevel( verboseLevel ) +// , m_verboseLevel( verboseLevel ) + , m_verboseLevel( DEBUG_LEVEL_VERBOSE ) , m_samplerate (44100) , m_model( NULL ) @@ -85,7 +86,10 @@ BounceDevice::probe( ConfigRom& configRom ) { + + debugOutput( DEBUG_LEVEL_VERBOSE, "probing BounceDevice\n"); // unsigned int vendorId = configRom.getNodeVendorId(); unsigned int modelId = configRom.getModelId(); unsigned int unitSpecifierId = configRom.getUnitSpecifierId(); + debugOutput( DEBUG_LEVEL_VERBOSE, "modelId = 0x%08X, specid = 0x%08X\n", modelId, unitSpecifierId); for ( unsigned int i = 0; @@ -109,8 +113,7 @@ BounceDevice::discover() { -// unsigned int resp_len=0; -// quadlet_t request[6]; -// quadlet_t *resp; - + debugOutput( DEBUG_LEVEL_VERBOSE, "discovering BounceDevice (NodeID %d)\n", + m_nodeId ); + // unsigned int vendorId = m_configRom->getNodeVendorId(); unsigned int modelId = m_configRom->getModelId(); @@ -135,33 +138,5 @@ return true; } - - debugOutput( DEBUG_LEVEL_VERBOSE, "Discovering...\n" ); - - std::string vendor=std::string(FREEBOB_BOUNCE_SERVER_VENDORNAME); - std::string model=std::string(FREEBOB_BOUNCE_SERVER_MODELNAME); - - if (!(m_configRom->getVendorName().compare(0,vendor.length(),vendor,0,vendor.length())==0) - || !(m_configRom->getModelName().compare(0,model.length(),model,0,model.length())==0)) { - return false; - } -/* -// AVC1394_COMMAND_INPUT_PLUG_SIGNAL_FORMAT - request[0] = htonl( AVC1394_CTYPE_STATUS | (AVC1394_SUBUNIT_TYPE_FREEBOB_BOUNCE_SERVER << 19) | (0 << 16) - | AVC1394_COMMAND_INPUT_PLUG_SIGNAL_FORMAT | 0x00); - - request[1] = 0xFFFFFFFF; - resp = m_p1394Service->transactionBlock( m_nodeId, - request, - 2, - &resp_len ); -// hexDump((unsigned char *)request,6*4); - if(resp) { - char *buffer=(char *)&resp[1]; - resp[resp_len-1]=0; - xmlDescription=buffer; -// hexDump((unsigned char *)resp,6*4); - } -*/ - return true; + return false; } @@ -212,5 +187,4 @@ debugOutput(DEBUG_LEVEL_NORMAL, "Node : %d\n", m_nodeId); debugOutput(DEBUG_LEVEL_NORMAL, "GUID : 0x%016llX\n", m_configRom->getGuid()); - debugOutput(DEBUG_LEVEL_NORMAL, "AVC test response : %s\n", xmlDescription.c_str()); debugOutput(DEBUG_LEVEL_NORMAL, "\n" ); } @@ -434,5 +408,5 @@ // write value of ISO_CHANNEL register reg_isoch=isochannel; - if(!writeReg(BOUNCE_REGISTER_TX_ISOCHANNEL, reg_isoch)) { + if(!writeReg(BOUNCE_REGISTER_RX_ISOCHANNEL, reg_isoch)) { debugError("Could not write ISO_CHANNEL register\n"); p->setChannel(-1); @@ -451,6 +425,72 @@ bool BounceDevice::stopStreamByIndex(int i) { - - return false; + if (i<(int)m_receiveProcessors.size()) { + int n=i; + Streaming::StreamProcessor *p=m_receiveProcessors.at(n); + unsigned int isochannel=p->getChannel(); + + fb_quadlet_t reg_isoch; + // check value of ISO_CHANNEL register + if(!readReg(BOUNCE_REGISTER_TX_ISOCHANNEL, ®_isoch)) { + debugError("Could not read ISO_CHANNEL register\n"); + return false; + } + if(reg_isoch != isochannel) { + debugError("ISO_CHANNEL register != 0x%08X (=0x%08X)\n", isochannel, reg_isoch); + return false; + } + + // write value of ISO_CHANNEL register + reg_isoch=0xFFFFFFFFUL; + if(!writeReg(BOUNCE_REGISTER_TX_ISOCHANNEL, reg_isoch)) { + debugError("Could not write ISO_CHANNEL register" ); + return false; + } + + // deallocate ISO channel + if(!deallocateIsoChannel(isochannel)) { + debugError("Could not deallocate iso channel for SP\n",i); + return false; + } + + p->setChannel(-1); + return true; + + } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) { + int n=i-m_receiveProcessors.size(); + Streaming::StreamProcessor *p=m_transmitProcessors.at(n); + + unsigned int isochannel=p->getChannel(); + + fb_quadlet_t reg_isoch; + // check value of ISO_CHANNEL register + if(!readReg(BOUNCE_REGISTER_RX_ISOCHANNEL, ®_isoch)) { + debugError("Could not read ISO_CHANNEL register\n"); + return false; + } + if(reg_isoch != isochannel) { + debugError("ISO_CHANNEL register != 0x%08X (=0x%08X)\n", isochannel, reg_isoch); + return false; + } + + // write value of ISO_CHANNEL register + reg_isoch=0xFFFFFFFFUL; + if(!writeReg(BOUNCE_REGISTER_RX_ISOCHANNEL, reg_isoch)) { + debugError("Could not write ISO_CHANNEL register\n"); + return false; + } + + // deallocate ISO channel + if(!deallocateIsoChannel(isochannel)) { + debugError("Could not deallocate iso channel for SP (%d)\n",i); + return false; + } + + p->setChannel(-1); + return true; + } + + debugError("SP index %d out of range!\n",i); + return false; } Index: /branches/streaming-rework/src/bounce/bounce_avdevice.h =================================================================== --- /branches/streaming-rework/src/bounce/bounce_avdevice.h (revision 420) +++ /branches/streaming-rework/src/bounce/bounce_avdevice.h (revision 424) @@ -51,7 +51,7 @@ // struct to define the supported devices struct VendorModelEntry { - unsigned int vendor_id; - unsigned int model_id; - unsigned int unit_specifier_id; + uint32_t vendor_id; + uint32_t model_id; + uint32_t unit_specifier_id; char *vendor_name; char *model_name; @@ -69,25 +69,25 @@ static bool probe( ConfigRom& configRom ); - virtual bool discover(); - virtual ConfigRom& getConfigRom() const; + bool discover(); + ConfigRom& getConfigRom() const; - virtual bool addXmlDescription( xmlNodePtr deviceNode ); + bool addXmlDescription( xmlNodePtr deviceNode ); - virtual bool setSamplingFrequency( ESamplingFrequency samplingFrequency ); - virtual int getSamplingFrequency( ); + bool setSamplingFrequency( ESamplingFrequency samplingFrequency ); + int getSamplingFrequency( ); - virtual bool prepare(); + bool prepare(); bool lock(); bool unlock(); - - virtual int getStreamCount(); - - virtual Streaming::StreamProcessor *getStreamProcessorByIndex(int i); - + + int getStreamCount(); + + Streaming::StreamProcessor *getStreamProcessorByIndex(int i); + bool startStreamByIndex(int i); bool stopStreamByIndex(int i); - virtual void showDevice() const; - virtual bool setId(unsigned int id); + void showDevice() const; + bool setId(unsigned int id); protected: @@ -97,5 +97,4 @@ int m_verboseLevel; -private: std::string xmlDescription; @@ -117,6 +116,6 @@ int allocateIsoChannel(unsigned int packet_size); bool deallocateIsoChannel(int channel); - -private: // I/O helpers + +protected: // I/O helpers // quadlet read/write routines bool readReg(fb_nodeaddr_t, fb_quadlet_t *); Index: /branches/streaming-rework/src/bounce/bounce_slave_avdevice.cpp =================================================================== --- /branches/streaming-rework/src/bounce/bounce_slave_avdevice.cpp (revision 422) +++ /branches/streaming-rework/src/bounce/bounce_slave_avdevice.cpp (revision 424) @@ -26,13 +26,33 @@ * */ - -#include "BounceSlaveDevice.h" +#include "libieee1394/configrom.h" +#include "libieee1394/ieee1394service.h" + +#include "bounce_slave_avdevice.h" +#include "libfreebob/freebob_bounce.h" + +#include +#include namespace Bounce { -IMPL_DEBUG_MODULE( BounceSlaveDevice, BounceSlaveDevice, DEBUG_LEVEL_NORMAL ); - -BounceSlaveDevice::BounceSlaveDevice() { - +static VendorModelEntry supportedDeviceList[] = +{ + //{vendor_id, model_id, unit_specifier_id, vendor_name, model_name}, + {0x0B0001, 0x0B0001, 0x0B0001, "FreeBoB", "Bounce Slave"}, +}; + +IMPL_DEBUG_MODULE( BounceSlaveDevice, BounceSlaveDevice, DEBUG_LEVEL_VERBOSE ); + +BounceSlaveDevice::BounceSlaveDevice( std::auto_ptr< ConfigRom >( configRom ), + Ieee1394Service& ieee1394service, + int verboseLevel ) + : BounceDevice( configRom, + ieee1394service, + ieee1394service.getLocalNodeId(), +// verboseLevel ) + DEBUG_LEVEL_VERBOSE ) +{ + addOption(Util::OptionContainer::Option("isoTimeoutSecs",(int64_t)120)); } @@ -41,3 +61,386 @@ } +bool +BounceSlaveDevice::probe( ConfigRom& configRom ) +{ + // we are always capable of constructing a slave device + return true; +} + +bool +BounceSlaveDevice::discover() +{ + m_model = &(supportedDeviceList[0]); + if (m_model != NULL) { + debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n", + m_model->vendor_name, m_model->model_name); + return true; + } + return false; +} + +bool BounceSlaveDevice::initMemSpace() { + debugOutput(DEBUG_LEVEL_VERBOSE, "Initializing memory space...\n"); + fb_quadlet_t result=0xFFFFFFFFLU; + + // initialize the ISO channel registers + // this will write to our own registers + if (!writeReg(BOUNCE_REGISTER_TX_ISOCHANNEL, result)) { + debugError("Could not initalize ISO channel register for TX\n"); + return false; + } + if (!writeReg(BOUNCE_REGISTER_RX_ISOCHANNEL, result)) { + debugError("Could not initalize ISO channel register for TX\n"); + return false; + } + + // set everything such that we can be discovered + m_original_config_rom=save_config_rom( m_p1394Service->getHandle() ); + + if ( init_config_rom( m_p1394Service->getHandle() ) < 0 ) { + debugError("Could not initalize local config rom\n"); + return false; + } + + // refresh our config rom cache + if ( !m_configRom->initialize() ) { + // \todo If a PHY on the bus is in power safe mode then + // the config rom is missing. So this might be just + // such this case and we can safely skip it. But it might + // be there is a real software problem on our side. + // This should be handled more carefuly. + debugError( "Could not reread config rom from device (node id %d).\n", + m_nodeId ); + return false; + } + return true; +} + +bool BounceSlaveDevice::restoreMemSpace() { + debugOutput(DEBUG_LEVEL_VERBOSE, "Restoring memory space...\n"); + restore_config_rom( m_p1394Service->getHandle(), m_original_config_rom); + return true; +} + +bool +BounceSlaveDevice::lock() { + debugOutput(DEBUG_LEVEL_VERBOSE, "Locking %s %s at node %d\n", + m_model->vendor_name, m_model->model_name, m_nodeId); + + // get a notifier to handle device notifications + nodeaddr_t notify_address; + notify_address = m_p1394Service->findFreeARMBlock( + BOUNCE_REGISTER_BASE, + BOUNCE_REGISTER_LENGTH, + BOUNCE_REGISTER_LENGTH); + + if (notify_address == 0xFFFFFFFFFFFFFFFFLLU) { + debugError("Could not find free ARM block for notification\n"); + return false; + } + + m_Notifier=new BounceSlaveDevice::BounceSlaveNotifier(this, notify_address); + + if(!m_Notifier) { + debugError("Could not allocate notifier\n"); + return false; + } + + if (!m_p1394Service->registerARMHandler(m_Notifier)) { + debugError("Could not register notifier\n"); + delete m_Notifier; + m_Notifier=NULL; + return false; + } + + // (re)initialize the memory space + if (!initMemSpace()) { + debugError("Could not initialize memory space\n"); + return false; + } + + return true; +} + +bool +BounceSlaveDevice::unlock() { + // (re)initialize the memory space + if (!restoreMemSpace()) { + debugError("Could not restore memory space\n"); + return false; + } + m_p1394Service->unregisterARMHandler(m_Notifier); + delete m_Notifier; + m_Notifier=NULL; + + return true; +} + +bool +BounceSlaveDevice::prepare() { + // snooping does not make sense for a slave device + setOption("snoopMode", false); + + // prepare the base class + // FIXME: when doing proper discovery this won't work anymore + // as it relies on a completely symmetric transmit/receive + if(!BounceDevice::prepare()) { + debugError("Base class preparation failed\n"); + return false; + } + + // do any customisations here + + return true; +} + +// this has to wait until the ISO channel numbers are written +bool +BounceSlaveDevice::startStreamByIndex(int i) { + + if (i<(int)m_receiveProcessors.size()) { + int n=i; + Streaming::StreamProcessor *p=m_receiveProcessors.at(n); + + // the other side sends on this channel + nodeaddr_t iso_channel_offset = BOUNCE_REGISTER_RX_ISOCHANNEL; + iso_channel_offset += ((unsigned)n)*4; + + if (!waitForRegisterNotEqualTo(iso_channel_offset, 0xFFFFFFFFLU)) { + debugError("Timeout waiting for stream %d to get an ISO channel\n",i); + return false; + } + + fb_quadlet_t result; + // this will read from our own registers + if (!readReg(iso_channel_offset, &result)) { + debugError("Could not read ISO channel register for stream %d\n",i); + return false; + } + + // set ISO channel + p->setChannel(result); + + return true; + + } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) { + int n=i-m_receiveProcessors.size(); + Streaming::StreamProcessor *p=m_transmitProcessors.at(n); + + // the other side sends on this channel + nodeaddr_t iso_channel_offset = BOUNCE_REGISTER_TX_ISOCHANNEL; + iso_channel_offset += ((unsigned)n)*4; + + if (!waitForRegisterNotEqualTo(iso_channel_offset, 0xFFFFFFFF)) { + debugError("Timeout waiting for stream %d to get an ISO channel\n",i); + return false; + } + + fb_quadlet_t result; + // this will read from our own registers + if (!readReg(iso_channel_offset, &result)) { + debugError("Could not read ISO channel register for stream %d\n",i); + return false; + } + + // set ISO channel + p->setChannel(result); + + return true; + + } + + debugError("SP index %d out of range!\n",i); + + return false; +} + +bool +BounceSlaveDevice::stopStreamByIndex(int i) { + // nothing special to do I guess... + return false; +} + +// helpers +bool +BounceSlaveDevice::waitForRegisterNotEqualTo(nodeaddr_t offset, fb_quadlet_t v) { + debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for StreamProcessor streams to start running...\n"); + // we have to wait until all streamprocessors indicate that they are running + // i.e. that there is actually some data stream flowing + int timeoutSecs=120; + if(!getOption("isoTimeoutSecs", timeoutSecs)) { + debugWarning("Could not retrieve isoTimeoutSecs parameter, defauling to 120secs\n"); + } + + int wait_cycles=timeoutSecs*10; // two seconds + + fb_quadlet_t reg=v; + + while ((v == reg) && wait_cycles) { + wait_cycles--; + if (!readReg(offset,®)) { + debugError("Could not read register\n"); + return false; + } + usleep(100000); + } + + if(!wait_cycles) { // timout has occurred + return false; + } + + return true; +} + +// configrom helpers +// FIXME: should be changed into a better framework + + +struct BounceSlaveDevice::configrom_backup +BounceSlaveDevice::save_config_rom(raw1394handle_t handle) +{ + int retval; + struct configrom_backup tmp; + /* get the current rom image */ + retval=raw1394_get_config_rom(handle, tmp.rom, 0x100, &tmp.rom_size, &tmp.rom_version); +// tmp.rom_size=rom1394_get_size(tmp.rom); +// printf("save_config_rom get_config_rom returned %d, romsize %d, rom_version %d:\n",retval,tmp.rom_size,tmp.rom_version); + + return tmp; +} + +int +BounceSlaveDevice::restore_config_rom(raw1394handle_t handle, struct BounceSlaveDevice::configrom_backup old) +{ + int retval; +// int i; + + quadlet_t current_rom[0x100]; + size_t current_rom_size; + unsigned char current_rom_version; + + retval=raw1394_get_config_rom(handle, current_rom, 0x100, ¤t_rom_size, ¤t_rom_version); +// printf("restore_config_rom get_config_rom returned %d, romsize %d, rom_version %d:\n",retval,current_rom_size,current_rom_version); + +// printf("restore_config_rom restoring to romsize %d, rom_version %d:\n",old.rom_size,old.rom_version); + + retval = raw1394_update_config_rom(handle, old.rom, old.rom_size, current_rom_version); +// printf("restore_config_rom update_config_rom returned %d\n",retval); + + /* get the current rom image */ + retval=raw1394_get_config_rom(handle, current_rom, 0x100, ¤t_rom_size, ¤t_rom_version); + current_rom_size = rom1394_get_size(current_rom); +// printf("get_config_rom returned %d, romsize %d, rom_version %d:",retval,current_rom_size,current_rom_version); +// for (i = 0; i < current_rom_size; i++) +// { +// if (i % 4 == 0) printf("\n0x%04x:", CSR_CONFIG_ROM+i*4); +// printf(" %08x", ntohl(current_rom[i])); +// } +// printf("\n"); + + return retval; +} + +int +BounceSlaveDevice::init_config_rom(raw1394handle_t handle) +{ + int retval, i; + quadlet_t rom[0x100]; + size_t rom_size; + unsigned char rom_version; + rom1394_directory dir; + char *leaf; + + /* get the current rom image */ + retval=raw1394_get_config_rom(handle, rom, 0x100, &rom_size, &rom_version); + rom_size = rom1394_get_size(rom); +// printf("get_config_rom returned %d, romsize %d, rom_version %d:",retval,rom_size,rom_version); +// for (i = 0; i < rom_size; i++) +// { +// if (i % 4 == 0) printf("\n0x%04x:", CSR_CONFIG_ROM+i*4); +// printf(" %08x", ntohl(rom[i])); +// } +// printf("\n"); + + /* get the local directory */ + rom1394_get_directory( handle, raw1394_get_local_id(handle) & 0x3f, &dir); + + /* change the vendor description for kicks */ + i = strlen(dir.textual_leafs[0]); + strncpy(dir.textual_leafs[0], FREEBOB_BOUNCE_SERVER_VENDORNAME " ", i); + + dir.vendor_id=FREEBOB_BOUNCE_SERVER_VENDORID; + dir.model_id=FREEBOB_BOUNCE_SERVER_MODELID; + + /* update the rom */ + retval = rom1394_set_directory(rom, &dir); +// printf("rom1394_set_directory returned %d, romsize %d:",retval,rom_size); +// for (i = 0; i < rom_size; i++) +// { +// if (i % 4 == 0) printf("\n0x%04x:", CSR_CONFIG_ROM+i*4); +// printf(" %08x", ntohl(rom[i])); +// } +// printf("\n"); + + /* free the allocated mem for the textual leaves */ + rom1394_free_directory( &dir); + + /* add an AV/C unit directory */ + dir.unit_spec_id = FREEBOB_BOUNCE_SERVER_SPECID; + dir.unit_sw_version = 0x00010001; + leaf = FREEBOB_BOUNCE_SERVER_MODELNAME; + dir.nr_textual_leafs = 1; + dir.textual_leafs = &leaf; + + /* manipulate the rom */ + retval = rom1394_add_unit( rom, &dir); + + /* get the computed size of the rom image */ + rom_size = rom1394_get_size(rom); + +// printf("rom1394_add_unit_directory returned %d, romsize %d:",retval,rom_size); +// for (i = 0; i < rom_size; i++) +// { +// if (i % 4 == 0) printf("\n0x%04x:", CSR_CONFIG_ROM+i*4); +// printf(" %08x", ntohl(rom[i])); +// } +// printf("\n"); +// + /* convert computed rom size from quadlets to bytes before update */ + rom_size *= sizeof(quadlet_t); + retval = raw1394_update_config_rom(handle, rom, rom_size, rom_version); +// printf("update_config_rom returned %d\n",retval); + + retval=raw1394_get_config_rom(handle, rom, 0x100, &rom_size, &rom_version); +// printf("get_config_rom returned %d, romsize %d, rom_version %d:",retval,rom_size,rom_version); +// for (i = 0; i < rom_size; i++) +// { +// if (i % 4 == 0) printf("\n0x%04x:", CSR_CONFIG_ROM+i*4); +// printf(" %08x", ntohl(rom[i])); +// } +// printf("\n"); + +// printf("You need to reload your ieee1394 modules to reset the rom.\n"); + + return 0; +} + + +// the notifier + +BounceSlaveDevice::BounceSlaveNotifier::BounceSlaveNotifier(BounceSlaveDevice *d, nodeaddr_t start) + : ARMHandler(start, BOUNCE_REGISTER_LENGTH, + RAW1394_ARM_READ | RAW1394_ARM_WRITE, // allowed operations + 0, //RAW1394_ARM_READ | RAW1394_ARM_WRITE, // operations to be notified of + 0) // operations that are replied to by us (instead of kernel) + , m_bounceslavedevice(d) +{ + +} + +BounceSlaveDevice::BounceSlaveNotifier::~BounceSlaveNotifier() +{ + +} + } // end of namespace Bounce Index: /branches/streaming-rework/libfreebob/freebob_streaming.h =================================================================== --- /branches/streaming-rework/libfreebob/freebob_streaming.h (revision 336) +++ /branches/streaming-rework/libfreebob/freebob_streaming.h (revision 424) @@ -122,4 +122,10 @@ /* verbosity */ int verbose; + + /* slave mode */ + int slave_mode; + + /* snoop mode */ + int snoop_mode; } freebob_options_t; Index: /branches/streaming-rework/support/jack/freebob_driver.c =================================================================== --- /branches/streaming-rework/support/jack/freebob_driver.c (revision 369) +++ /branches/streaming-rework/support/jack/freebob_driver.c (revision 424) @@ -642,4 +642,6 @@ driver->device_options.node_id=params->node_id; driver->device_options.port=params->port; + driver->device_options.slave_mode=params->slave_mode; + driver->device_options.snoop_mode=params->snoop_mode; if(!params->capture_ports) { @@ -1028,5 +1030,5 @@ strcpy (desc->name, "freebob"); - desc->nparams = 6; + desc->nparams = 8; params = calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); @@ -1079,4 +1081,20 @@ params[i].value.ui = 1U; strcpy (params[i].short_desc, "Provide playback ports."); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "slave"); + params[i].character = 'x'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 0U; + strcpy (params[i].short_desc, "Act as a BounceDevice slave"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "slave"); + params[i].character = 'X'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 0U; + strcpy (params[i].short_desc, "Operate in snoop mode"); strcpy (params[i].long_desc, params[i].short_desc); @@ -1115,4 +1133,6 @@ cmlparams.playback_ports=1; cmlparams.capture_ports=1; + cmlparams.slave_mode=0; + cmlparams.snoop_mode=0; for (node = params; node; node = jack_slist_next (node)) @@ -1143,4 +1163,10 @@ cmlparams.playback_ports = param->value.ui; break; + case 'x': + cmlparams.slave_mode = param->value.ui; + break; + case 'X': + cmlparams.snoop_mode = param->value.ui; + break; } } Index: /branches/streaming-rework/support/jack/freebob_driver.h =================================================================== --- /branches/streaming-rework/support/jack/freebob_driver.h (revision 247) +++ /branches/streaming-rework/support/jack/freebob_driver.h (revision 424) @@ -137,23 +137,26 @@ typedef struct _freebob_jack_settings freebob_jack_settings_t; struct _freebob_jack_settings { - int period_size_set; - jack_nframes_t period_size; - - int sample_rate_set; - int sample_rate; - - int buffer_size_set; - jack_nframes_t buffer_size; - - int port_set; - int port; - - int node_id_set; - int node_id; - - int playback_ports; - int capture_ports; - - freebob_handle_t fb_handle; + int period_size_set; + jack_nframes_t period_size; + + int sample_rate_set; + int sample_rate; + + int buffer_size_set; + jack_nframes_t buffer_size; + + int port_set; + int port; + + int node_id_set; + int node_id; + + int playback_ports; + int capture_ports; + + int slave_mode; + int snoop_mode; + + freebob_handle_t fb_handle; };