root/trunk/libffado/src/libieee1394/IsoHandlerManager.h

Revision 1849, 14.3 kB (checked in by jwoithe, 11 years ago)

IsoHandlerManager?: some interfaces (eg: RME) do not send placeholder iso packets when there is no data to send. For such interfaces IsoHandler? wrongly interprets this as a dropped packet. Therefore provide a mechanism to disable the dropped packet check. The default state is unchanged from the original code: a missing packet is regarded as a dropped packet.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
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.
13  *
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.
18  *
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/>.
21  *
22  */
23
24 #ifndef __FFADO_ISOHANDLERMANAGER__
25 #define __FFADO_ISOHANDLERMANAGER__
26
27 #include "config.h"
28
29 #include "debugmodule/debugmodule.h"
30
31 #include "libutil/Thread.h"
32
33 #include <sys/poll.h>
34 #include <errno.h>
35 #include <vector>
36 #include <semaphore.h>
37
38 class Ieee1394Service;
39 //class IsoHandler;
40 //enum IsoHandler::EHandlerType;
41
42 namespace Streaming {
43     class StreamProcessor;
44     typedef std::vector<StreamProcessor *> StreamProcessorVector;
45     typedef std::vector<StreamProcessor *>::iterator StreamProcessorVectorIterator;
46 }
47
48 /*!
49 \brief The ISO Handler management class
50
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),
56  it can be assigned.
57
58 */
59
60 class IsoHandlerManager
61 {
62     friend class IsoTask;
63
64 ////
65 /*!
66     \brief The Base Class for ISO Handlers
67
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.
71
72  */
73
74     class IsoHandler
75     {
76         public:
77             enum EHandlerType {
78                 eHT_Receive,
79                 eHT_Transmit
80             };
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);
86             ~IsoHandler();
87
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);
94
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);
99
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);
108
109         public:
110
111     /**
112          * Iterate the handler, transporting ISO packets to the client(s)
113          * @return true if success
114      */
115             bool iterate();
116
117     /**
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
121      */
122             bool iterate(uint32_t ctr_now);
123
124             int getFileDescriptor() { return raw1394_get_fd(m_handle);};
125
126             bool init();
127             void setVerboseLevel(int l);
128
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
131     // for that
132             bool enable() {return enable(-1);};
133             bool enable(int cycle);
134             bool disable();
135
136     // functions to request enable or disable at the next opportunity
137             bool requestEnable(int cycle = -1);
138             bool requestDisable();
139
140     /**
141              * updates the internal state if required
142      */
143             void updateState();
144
145             enum EHandlerType getType() {return m_type;};
146             const char *getTypeString() {return eHTToString(m_type); };
147
148     // pretty printing
149             const char *eHTToString(enum EHandlerType);
150
151             bool isEnabled()
152             {return m_State == eHS_Running;};
153
154     // no setter functions, because those would require a re-init
155             unsigned int getMaxPacketSize() { return m_max_packet_size;};
156             unsigned int getNbBuffers() { return m_buf_packets;};
157             int getIrqInterval() { return m_irq_interval;};
158
159             void dumpInfo();
160
161             bool inUse() {return (m_Client != 0) ;};
162             bool isStreamRegistered(Streaming::StreamProcessor *s) {return (m_Client == s);};
163
164             bool registerStream(Streaming::StreamProcessor *);
165             bool unregisterStream(Streaming::StreamProcessor *);
166
167             bool canIterateClient(); // FIXME: implement with functor
168
169
170     /**
171              * @brief get last cycle number seen by handler
172              * @return cycle number
173      */
174             int getLastCycle() {return m_last_cycle;};
175
176     /**
177              * @brief returns the CTR value saved at the last iterate() call
178              * @return CTR value saved at last iterate() call
179      */
180             uint32_t getLastIterateTime() {return m_last_now;};
181
182     /**
183              * @brief returns the CTR value saved at the last iterate handler call
184              * @return CTR value saved at last iterate handler call
185      */
186             uint32_t getLastPacketTime() {return m_last_packet_handled_at;};
187
188     /**
189              * @brief set iso receive mode. doesn't have any effect if the stream is running
190              * @param m receive mode
191      */
192             void setReceiveMode(enum raw1394_iso_dma_recv_mode m)
193             {m_receive_mode = m;}
194
195             void notifyOfDeath();
196             bool handleBusReset();
197
198         private:
199             IsoHandlerManager& m_manager;
200             enum EHandlerType m_type;
201             raw1394handle_t m_handle;
202             unsigned int    m_buf_packets;
203             unsigned int    m_max_packet_size;
204             int             m_irq_interval;
205             int             m_last_cycle;
206             uint32_t        m_last_now;
207             uint32_t        m_last_packet_handled_at;
208             enum raw1394_iso_dma_recv_mode m_receive_mode;
209
210             Streaming::StreamProcessor *m_Client; // FIXME: implement with functors
211
212             enum raw1394_iso_speed m_speed;
213
214     // the state machine
215             enum EHandlerStates {
216                 eHS_Stopped,
217                 eHS_Running,
218                 eHS_Error,
219             };
220             enum EHandlerStates m_State;
221             enum EHandlerStates m_NextState;
222             int m_switch_on_cycle;
223
224         public:
225             unsigned int    m_packets;
226 #ifdef DEBUG
227             unsigned int    m_dropped;
228             unsigned int    m_skipped;
229             int             m_min_ahead;
230 #endif
231
232         protected:
233             DECLARE_DEBUG_MODULE;
234     };
235
236     typedef std::vector<IsoHandler *> IsoHandlerVector;
237     typedef std::vector<IsoHandler *>::iterator IsoHandlerVectorIterator;
238
239 ////
240    
241 // threads that will handle the packet framing
242 // one thread per direction, as a compromise for one per
243 // channel and one for all
244     class IsoTask : public Util::RunnableInterface
245     {
246         friend class IsoHandlerManager;
247         public:
248             IsoTask(IsoHandlerManager& manager, enum IsoHandler::EHandlerType);
249             virtual ~IsoTask();
250
251         private:
252             bool Init();
253             bool Execute();
254
255         /**
256              * @brief requests the thread to sync it's stream map with the manager
257          */
258             void requestShadowMapUpdate();
259             enum eActivityResult {
260                 eAR_Activity,
261                 eAR_Timeout,
262                 eAR_Interrupted,
263                 eAR_Error
264             };
265
266         /**
267              * @brief signals that something happened in one of the clients of this task
268          */
269             void signalActivity();
270         /**
271              * @brief wait until something happened in one of the clients of this task
272          */
273             enum eActivityResult waitForActivity();
274
275         /**
276              * @brief This should be called when a busreset has happened.
277          */
278             bool handleBusReset();
279
280             void setVerboseLevel(int i);
281
282         protected:
283             IsoHandlerManager& m_manager;
284
285         // the event request structure
286             int32_t request_update;
287
288         // static allocation due to RT constraints
289         // this is the map used by the actual thread
290         // it is a shadow of the m_StreamProcessors vector
291             struct pollfd   m_poll_fds_shadow[ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT];
292             IsoHandler *    m_IsoHandler_map_shadow[ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT];
293             unsigned int    m_poll_nfds_shadow;
294             IsoHandler *    m_SyncIsoHandler;
295
296         // updates the streams map
297             void updateShadowMapHelper();
298
299 #ifdef DEBUG
300             uint64_t m_last_loop_entry;
301             int m_successive_short_loops;
302 #endif
303
304             enum IsoHandler::EHandlerType m_handlerType;
305             bool m_running;
306             bool m_in_busreset;
307
308         // activity signaling
309             sem_t m_activity_semaphore;
310             long long int m_activity_wait_timeout_nsec;
311
312         // debug stuff
313             DECLARE_DEBUG_MODULE;
314     };
315    
316 //// the IsoHandlerManager itself
317     public:
318
319         IsoHandlerManager(Ieee1394Service& service);
320         IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio);
321         virtual ~IsoHandlerManager();
322
323         bool setThreadParameters(bool rt, int priority);
324
325         void setVerboseLevel(int l); ///< set the verbose level
326
327         void dumpInfo(); ///< print some information about the manager to stdout/stderr
328         void dumpInfoForStream(Streaming::StreamProcessor *); ///< print some info about the stream's handler
329
330         bool registerStream(Streaming::StreamProcessor *); ///< register an iso stream with the manager
331         bool unregisterStream(Streaming::StreamProcessor *); ///< unregister an iso stream from the manager
332
333         bool startHandlers(); ///< start the managed ISO handlers
334         bool startHandlers(int cycle); ///< start the managed ISO handlers
335         bool stopHandlers(); ///< stop the managed ISO handlers
336
337         bool reset(); ///< reset the ISO manager and all streams
338         bool init();
339
340         /**
341          * @brief signals that something happened in one of the clients
342          */
343         void signalActivityTransmit();
344         void signalActivityReceive();
345
346         ///> disables the handler attached to the stream
347         bool stopHandlerForStream(Streaming::StreamProcessor *);
348         ///> starts the handler attached to the specific stream
349         bool startHandlerForStream(Streaming::StreamProcessor *);
350         ///> starts the handler attached to the specific stream on a specific cycle
351         bool startHandlerForStream(Streaming::StreamProcessor *, int cycle);
352
353         /**
354          * returns the latency of a wake-up for this stream.
355          * The latency is the time it takes for a packet is delivered to the
356          * stream after it has been received (was on the wire).
357          * expressed in cycles
358          */
359         int getPacketLatencyForStream(Streaming::StreamProcessor *);
360
361         /**
362          * Enables the isohandler manager to ignore missed packets.  This
363          * behaviour is needed by some interfaces which don't send empty
364          * placeholder packets when no data needs to be sent.
365          */
366         void setMissedCyclesOK(bool ok) { m_MissedCyclesOK = ok; };
367
368     private:
369         IsoHandler * getHandlerForStream(Streaming::StreamProcessor *stream);
370         void requestShadowMapUpdate();
371     public:
372         Ieee1394Service& get1394Service() {return m_service;};
373
374         /**
375          * This should be called when a busreset has happened.
376          */
377         bool handleBusReset();
378
379     // the state machine
380     private:
381         enum eHandlerStates {
382             E_Created,
383             E_Prepared,
384             E_Running,
385             E_Error
386         };
387
388         enum eHandlerStates m_State;
389         const char *eHSToString(enum eHandlerStates);
390
391     private:
392         Ieee1394Service&  m_service;
393         // note: there is a disctinction between streams and handlers
394         // because one handler can serve multiple streams (in case of
395         // multichannel receive)
396
397         // only streams are allowed to be registered externally.
398         // we allocate a handler if we need one, otherwise the stream
399         // is assigned to another handler
400
401         // the collection of handlers
402         IsoHandlerVector m_IsoHandlers;
403
404         bool registerHandler(IsoHandler *);
405         bool unregisterHandler(IsoHandler *);
406         void pruneHandlers();
407
408         // the collection of streams
409         Streaming::StreamProcessorVector m_StreamProcessors;
410
411         // handler thread/task
412         bool            m_realtime;
413         int             m_priority;
414         Util::Thread *  m_IsoThreadTransmit;
415         IsoTask *       m_IsoTaskTransmit;
416         Util::Thread *  m_IsoThreadReceive;
417         IsoTask *       m_IsoTaskReceive;
418
419         bool            m_MissedCyclesOK;
420
421         // debug stuff
422         DECLARE_DEBUG_MODULE;
423
424 };
425
426 #endif /* __FFADO_ISOHANDLERMANAGER__  */
427
428
429
Note: See TracBrowser for help on using the browser.