2 * Copyright (C) 2005-2008 by Pieter Palmers
4 * This file is part of FFADO
5 * FFADO = Free Firewire (pro-)audio drivers for linux
7 * FFADO is based upon FreeBoB.
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) version 3 of the License.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #ifndef __FFADO_ISOHANDLERMANAGER__
25 #define __FFADO_ISOHANDLERMANAGER__
29 #include "debugmodule/debugmodule.h"
31 #include "libutil/Thread.h"
36 #include <semaphore.h>
38 class Ieee1394Service
;
40 //enum IsoHandler::EHandlerType;
43 class StreamProcessor
;
44 typedef std::vector
<StreamProcessor
*> StreamProcessorVector
;
45 typedef std::vector
<StreamProcessor
*>::iterator StreamProcessorVectorIterator
;
49 \brief The ISO Handler management class
51 This class manages the use of ISO handlers by ISO streams.
52 You can register an Streaming::StreamProcessor with an IsoHandlerManager. This
53 manager will assign an IsoHandler to the stream. If nescessary
54 the manager allocates a new handler. If there is already a handler
55 that can handle the Streaming::StreamProcessor (e.g. in case of multichannel receive),
60 class IsoHandlerManager
66 \brief The Base Class for ISO Handlers
68 These classes perform the actual ISO communication through libraw1394.
69 They are different from Streaming::StreamProcessors because one handler can provide multiple
70 streams with packets in case of ISO multichannel receive.
81 IsoHandler(IsoHandlerManager
& manager
, enum EHandlerType t
);
82 IsoHandler(IsoHandlerManager
& manager
, enum EHandlerType t
,
83 unsigned int buf_packets
, unsigned int max_packet_size
, int irq
);
84 IsoHandler(IsoHandlerManager
& manager
, enum EHandlerType t
,
85 unsigned int buf_packets
, unsigned int max_packet_size
, int irq
, enum raw1394_iso_speed speed
);
88 private: // the ISO callback interface
89 static enum raw1394_iso_disposition
90 iso_receive_handler(raw1394handle_t handle
, unsigned char *data
,
91 unsigned int length
, unsigned char channel
,
92 unsigned char tag
, unsigned char sy
, unsigned int cycle
,
93 unsigned int dropped
);
95 enum raw1394_iso_disposition
96 putPacket(unsigned char *data
, unsigned int length
,
97 unsigned char channel
, unsigned char tag
, unsigned char sy
,
98 unsigned int cycle
, unsigned int dropped
);
100 static enum raw1394_iso_disposition
iso_transmit_handler(raw1394handle_t handle
,
101 unsigned char *data
, unsigned int *length
,
102 unsigned char *tag
, unsigned char *sy
,
103 int cycle
, unsigned int dropped
);
104 enum raw1394_iso_disposition
105 getPacket(unsigned char *data
, unsigned int *length
,
106 unsigned char *tag
, unsigned char *sy
,
107 int cycle
, unsigned int dropped
, unsigned int skipped
);
112 * Iterate the handler, transporting ISO packets to the client(s)
113 * @return true if success
118 * Iterate the handler, transporting ISO packets to the client(s)
119 * @param ctr_now the CTR time at which the iterate call is done.
120 * @return true if success
122 bool iterate(uint32_t ctr_now
);
124 int getFileDescriptor() { return raw1394_get_fd(m_handle
);};
127 void setVerboseLevel(int l
);
129 // the enable/disable functions should only be used from within the loop that iterates()
130 // but not from within the iterate callback. use the requestEnable / requestDisable functions
132 bool enable() {return enable(-1);};
133 bool enable(int cycle
);
136 // functions to request enable or disable at the next opportunity
137 bool requestEnable(int cycle
= -1);
138 bool requestDisable();
140 // Manually set the start cycle for the iso handler
141 void setIsoStartCycle(signed int cycle
= -1);
144 * updates the internal state if required
148 enum EHandlerType
getType() {return m_type
;};
149 const char *getTypeString() {return eHTToString(m_type
); };
152 const char *eHTToString(enum EHandlerType
);
155 {return m_State
== eHS_Running
;};
157 // no setter functions, because those would require a re-init
158 unsigned int getMaxPacketSize() { return m_max_packet_size
;};
159 unsigned int getNbBuffers() { return m_buf_packets
;};
160 int getIrqInterval() { return m_irq_interval
;};
164 bool inUse() {return (m_Client
!= 0) ;};
165 bool isStreamRegistered(Streaming::StreamProcessor
*s
) {return (m_Client
== s
);};
167 bool registerStream(Streaming::StreamProcessor
*);
168 bool unregisterStream(Streaming::StreamProcessor
*);
170 bool canIterateClient(); // FIXME: implement with functor
174 * @brief get last cycle number seen by handler
175 * @return cycle number
177 int getLastCycle() {return m_last_cycle
;};
180 * @brief returns the CTR value saved at the last iterate() call
181 * @return CTR value saved at last iterate() call
183 uint32_t getLastIterateTime() {return m_last_now
;};
186 * @brief returns the CTR value saved at the last iterate handler call
187 * @return CTR value saved at last iterate handler call
189 uint32_t getLastPacketTime() {return m_last_packet_handled_at
;};
192 * @brief set iso receive mode. doesn't have any effect if the stream is running
193 * @param m receive mode
195 void setReceiveMode(enum raw1394_iso_dma_recv_mode m
)
196 {m_receive_mode
= m
;}
198 void notifyOfDeath();
199 bool handleBusReset();
202 IsoHandlerManager
& m_manager
;
203 enum EHandlerType m_type
;
204 raw1394handle_t m_handle
;
205 unsigned int m_buf_packets
;
206 unsigned int m_max_packet_size
;
210 uint32_t m_last_packet_handled_at
;
211 enum raw1394_iso_dma_recv_mode m_receive_mode
;
213 Streaming::StreamProcessor
*m_Client
; // FIXME: implement with functors
215 enum raw1394_iso_speed m_speed
;
218 enum EHandlerStates
{
223 enum EHandlerStates m_State
;
224 enum EHandlerStates m_NextState
;
225 int m_switch_on_cycle
;
227 pthread_mutex_t m_disable_lock
;
230 unsigned int m_packets
;
232 unsigned int m_dropped
;
233 unsigned int m_skipped
;
236 unsigned int m_deferred_cycles
;
239 DECLARE_DEBUG_MODULE
;
242 typedef std::vector
<IsoHandler
*> IsoHandlerVector
;
243 typedef std::vector
<IsoHandler
*>::iterator IsoHandlerVectorIterator
;
247 // threads that will handle the packet framing
248 // one thread per direction, as a compromise for one per
249 // channel and one for all
250 class IsoTask
: public Util::RunnableInterface
252 friend class IsoHandlerManager
;
254 IsoTask(IsoHandlerManager
& manager
, enum IsoHandler::EHandlerType
);
262 * @brief requests the thread to sync it's stream map with the manager
264 void requestShadowMapUpdate();
265 enum eActivityResult
{
273 * @brief signals that something happened in one of the clients of this task
275 void signalActivity();
277 * @brief wait until something happened in one of the clients of this task
279 enum eActivityResult
waitForActivity();
282 * @brief This should be called when a busreset has happened.
284 bool handleBusReset();
286 void setVerboseLevel(int i
);
289 IsoHandlerManager
& m_manager
;
291 // the event request structure
292 int32_t request_update
;
294 // static allocation due to RT constraints
295 // this is the map used by the actual thread
296 // it is a shadow of the m_StreamProcessors vector
297 struct pollfd m_poll_fds_shadow
[ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT
];
298 IsoHandler
* m_IsoHandler_map_shadow
[ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT
];
299 unsigned int m_poll_nfds_shadow
;
300 IsoHandler
* m_SyncIsoHandler
;
302 // updates the streams map
303 void updateShadowMapHelper();
306 uint64_t m_last_loop_entry
;
307 int m_successive_short_loops
;
310 enum IsoHandler::EHandlerType m_handlerType
;
314 // activity signaling
315 sem_t m_activity_semaphore
;
316 long long int m_activity_wait_timeout_nsec
;
319 DECLARE_DEBUG_MODULE
;
322 //// the IsoHandlerManager itself
325 IsoHandlerManager(Ieee1394Service
& service
);
326 IsoHandlerManager(Ieee1394Service
& service
, bool run_rt
, int rt_prio
);
327 virtual ~IsoHandlerManager();
329 bool setThreadParameters(bool rt
, int priority
);
331 void setVerboseLevel(int l
); ///< set the verbose level
333 void dumpInfo(); ///< print some information about the manager to stdout/stderr
334 void dumpInfoForStream(Streaming::StreamProcessor
*); ///< print some info about the stream's handler
336 bool registerStream(Streaming::StreamProcessor
*); ///< register an iso stream with the manager
337 bool unregisterStream(Streaming::StreamProcessor
*); ///< unregister an iso stream from the manager
339 bool startHandlers(); ///< start the managed ISO handlers
340 bool startHandlers(int cycle
); ///< start the managed ISO handlers
341 bool stopHandlers(); ///< stop the managed ISO handlers
343 bool reset(); ///< reset the ISO manager and all streams
347 * @brief signals that something happened in one of the clients
349 void signalActivityTransmit();
350 void signalActivityReceive();
352 ///> disables the handler attached to the stream
353 bool stopHandlerForStream(Streaming::StreamProcessor
*);
354 ///> starts the handler attached to the specific stream
355 bool startHandlerForStream(Streaming::StreamProcessor
*);
356 ///> starts the handler attached to the specific stream on a specific cycle
357 bool startHandlerForStream(Streaming::StreamProcessor
*, int cycle
);
359 ///> Directly tells the handler attached to the stream to start on
360 ///> the given cycle regardless of what is passed to
361 ///> startHandlerForStream().
362 void setIsoStartCycleForStream(Streaming::StreamProcessor
*stream
, signed int cycle
);
365 * returns the latency of a wake-up for this stream.
366 * The latency is the time it takes for a packet is delivered to the
367 * stream after it has been received (was on the wire).
368 * expressed in cycles
370 int getPacketLatencyForStream(Streaming::StreamProcessor
*);
373 * Enables the isohandler manager to ignore missed packets. This
374 * behaviour is needed by some interfaces which don't send empty
375 * placeholder packets when no data needs to be sent.
377 void setMissedCyclesOK(bool ok
) { m_MissedCyclesOK
= ok
; };
380 IsoHandler
* getHandlerForStream(Streaming::StreamProcessor
*stream
);
381 void requestShadowMapUpdate();
383 Ieee1394Service
& get1394Service() {return m_service
;};
386 * This should be called when a busreset has happened.
388 bool handleBusReset();
392 enum eHandlerStates
{
399 enum eHandlerStates m_State
;
400 const char *eHSToString(enum eHandlerStates
);
403 Ieee1394Service
& m_service
;
404 // note: there is a disctinction between streams and handlers
405 // because one handler can serve multiple streams (in case of
406 // multichannel receive)
408 // only streams are allowed to be registered externally.
409 // we allocate a handler if we need one, otherwise the stream
410 // is assigned to another handler
412 // the collection of handlers
413 IsoHandlerVector m_IsoHandlers
;
415 bool registerHandler(IsoHandler
*);
416 bool unregisterHandler(IsoHandler
*);
417 void pruneHandlers();
419 // the collection of streams
420 Streaming::StreamProcessorVector m_StreamProcessors
;
422 // handler thread/task
425 Util::Thread
* m_IsoThreadTransmit
;
426 IsoTask
* m_IsoTaskTransmit
;
427 Util::Thread
* m_IsoThreadReceive
;
428 IsoTask
* m_IsoTaskReceive
;
430 bool m_MissedCyclesOK
;
433 DECLARE_DEBUG_MODULE
;
437 #endif /* __FFADO_ISOHANDLERMANAGER__ */