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
;
238 DECLARE_DEBUG_MODULE
;
241 typedef std::vector
<IsoHandler
*> IsoHandlerVector
;
242 typedef std::vector
<IsoHandler
*>::iterator IsoHandlerVectorIterator
;
246 // threads that will handle the packet framing
247 // one thread per direction, as a compromise for one per
248 // channel and one for all
249 class IsoTask
: public Util::RunnableInterface
251 friend class IsoHandlerManager
;
253 IsoTask(IsoHandlerManager
& manager
, enum IsoHandler::EHandlerType
);
261 * @brief requests the thread to sync it's stream map with the manager
263 void requestShadowMapUpdate();
264 enum eActivityResult
{
272 * @brief signals that something happened in one of the clients of this task
274 void signalActivity();
276 * @brief wait until something happened in one of the clients of this task
278 enum eActivityResult
waitForActivity();
281 * @brief This should be called when a busreset has happened.
283 bool handleBusReset();
285 void setVerboseLevel(int i
);
288 IsoHandlerManager
& m_manager
;
290 // the event request structure
291 int32_t request_update
;
293 // static allocation due to RT constraints
294 // this is the map used by the actual thread
295 // it is a shadow of the m_StreamProcessors vector
296 struct pollfd m_poll_fds_shadow
[ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT
];
297 IsoHandler
* m_IsoHandler_map_shadow
[ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT
];
298 unsigned int m_poll_nfds_shadow
;
299 IsoHandler
* m_SyncIsoHandler
;
301 // updates the streams map
302 void updateShadowMapHelper();
305 uint64_t m_last_loop_entry
;
306 int m_successive_short_loops
;
309 enum IsoHandler::EHandlerType m_handlerType
;
313 // activity signaling
314 sem_t m_activity_semaphore
;
315 long long int m_activity_wait_timeout_nsec
;
318 DECLARE_DEBUG_MODULE
;
321 //// the IsoHandlerManager itself
324 IsoHandlerManager(Ieee1394Service
& service
);
325 IsoHandlerManager(Ieee1394Service
& service
, bool run_rt
, int rt_prio
);
326 virtual ~IsoHandlerManager();
328 bool setThreadParameters(bool rt
, int priority
);
330 void setVerboseLevel(int l
); ///< set the verbose level
332 void dumpInfo(); ///< print some information about the manager to stdout/stderr
333 void dumpInfoForStream(Streaming::StreamProcessor
*); ///< print some info about the stream's handler
335 bool registerStream(Streaming::StreamProcessor
*); ///< register an iso stream with the manager
336 bool unregisterStream(Streaming::StreamProcessor
*); ///< unregister an iso stream from the manager
338 bool startHandlers(); ///< start the managed ISO handlers
339 bool startHandlers(int cycle
); ///< start the managed ISO handlers
340 bool stopHandlers(); ///< stop the managed ISO handlers
342 bool reset(); ///< reset the ISO manager and all streams
346 * @brief signals that something happened in one of the clients
348 void signalActivityTransmit();
349 void signalActivityReceive();
351 ///> disables the handler attached to the stream
352 bool stopHandlerForStream(Streaming::StreamProcessor
*);
353 ///> starts the handler attached to the specific stream
354 bool startHandlerForStream(Streaming::StreamProcessor
*);
355 ///> starts the handler attached to the specific stream on a specific cycle
356 bool startHandlerForStream(Streaming::StreamProcessor
*, int cycle
);
358 ///> Directly tells the handler attached to the stream to start on
359 ///> the given cycle regardless of what is passed to
360 ///> startHandlerForStream().
361 void setIsoStartCycleForStream(Streaming::StreamProcessor
*stream
, signed int cycle
);
364 * returns the latency of a wake-up for this stream.
365 * The latency is the time it takes for a packet is delivered to the
366 * stream after it has been received (was on the wire).
367 * expressed in cycles
369 int getPacketLatencyForStream(Streaming::StreamProcessor
*);
372 * Enables the isohandler manager to ignore missed packets. This
373 * behaviour is needed by some interfaces which don't send empty
374 * placeholder packets when no data needs to be sent.
376 void setMissedCyclesOK(bool ok
) { m_MissedCyclesOK
= ok
; };
379 IsoHandler
* getHandlerForStream(Streaming::StreamProcessor
*stream
);
380 void requestShadowMapUpdate();
382 Ieee1394Service
& get1394Service() {return m_service
;};
385 * This should be called when a busreset has happened.
387 bool handleBusReset();
391 enum eHandlerStates
{
398 enum eHandlerStates m_State
;
399 const char *eHSToString(enum eHandlerStates
);
402 Ieee1394Service
& m_service
;
403 // note: there is a disctinction between streams and handlers
404 // because one handler can serve multiple streams (in case of
405 // multichannel receive)
407 // only streams are allowed to be registered externally.
408 // we allocate a handler if we need one, otherwise the stream
409 // is assigned to another handler
411 // the collection of handlers
412 IsoHandlerVector m_IsoHandlers
;
414 bool registerHandler(IsoHandler
*);
415 bool unregisterHandler(IsoHandler
*);
416 void pruneHandlers();
418 // the collection of streams
419 Streaming::StreamProcessorVector m_StreamProcessors
;
421 // handler thread/task
424 Util::Thread
* m_IsoThreadTransmit
;
425 IsoTask
* m_IsoTaskTransmit
;
426 Util::Thread
* m_IsoThreadReceive
;
427 IsoTask
* m_IsoTaskReceive
;
429 bool m_MissedCyclesOK
;
432 DECLARE_DEBUG_MODULE
;
436 #endif /* __FFADO_ISOHANDLERMANAGER__ */