root/branches/libffado-2.0/src/libieee1394/IsoHandlerManager.cpp

Revision 1495, 43.3 kB (checked in by ppalmers, 12 years ago)

add a minimum for the max_packetsize parameter

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 #include "config.h"
25 #include "IsoHandlerManager.h"
26 #include "ieee1394service.h"
27 #include "cycletimer.h"
28 #include "libstreaming/generic/StreamProcessor.h"
29
30 #include "libutil/Atomic.h"
31 #include "libutil/PosixThread.h"
32 #include "libutil/SystemTimeSource.h"
33 #include "libutil/Watchdog.h"
34 #include "libutil/Configuration.h"
35
36 #include <cstring>
37 #include <assert.h>
38
39 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL );
40 IMPL_DEBUG_MODULE( IsoTask, IsoTask, DEBUG_LEVEL_NORMAL );
41
42 using namespace Streaming;
43
44 // --- ISO Thread --- //
45
46 IsoTask::IsoTask(IsoHandlerManager& manager, enum IsoHandler::EHandlerType t)
47     : m_manager( manager )
48     , m_SyncIsoHandler ( NULL )
49     , m_handlerType( t )
50     , m_running( false )
51     , m_in_busreset( false )
52     , m_activity_wait_timeout_nsec (ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS * 1000LL)
53 {
54 }
55
56 IsoTask::~IsoTask()
57 {
58     sem_destroy(&m_activity_semaphore);
59 }
60
61 bool
62 IsoTask::Init()
63 {
64     request_update = 0;
65
66     int i;
67     for (i=0; i < ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT; i++) {
68         m_IsoHandler_map_shadow[i] = NULL;
69         m_poll_fds_shadow[i].events = 0;
70     }
71     m_poll_nfds_shadow = 0;
72
73     #ifdef DEBUG
74     m_last_loop_entry = 0;
75     m_successive_short_loops = 0;
76     #endif
77
78     sem_init(&m_activity_semaphore, 0, 0);
79     m_running = true;
80     return true;
81 }
82
83 bool
84 IsoTask::requestShadowMapUpdate()
85 {
86     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) enter\n", this);
87     INC_ATOMIC(&request_update);
88
89     // get the thread going again
90     signalActivity();
91
92     if (m_running) {
93         int timeout = 1000;
94         while(request_update && timeout--) {
95             Util::SystemTimeSource::SleepUsecRelative(1000);
96         }
97         if(timeout == 0) {
98             debugError("timeout waiting for shadow map update\n");
99         }
100     }
101     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) exit\n", this);
102     return true;
103 }
104
105 bool
106 IsoTask::handleBusReset()
107 {
108     bool retval = true;
109     m_in_busreset = true;
110     requestShadowMapUpdate();
111     if(request_update) {
112         debugError("shadow map update request not honored\n");
113         return false;
114     }
115
116     unsigned int i, max;
117     max = m_manager.m_IsoHandlers.size();
118     for (i = 0; i < max; i++) {
119         IsoHandler *h = m_manager.m_IsoHandlers.at(i);
120         assert(h);
121
122         // skip the handlers not intended for us
123         if(h->getType() != m_handlerType) continue;
124
125         if (!h->handleBusReset()) {
126             debugWarning("Failed to handle busreset on %p\n");
127             retval = false;
128         }
129     }
130
131     // re-enable processing
132     m_in_busreset = false;
133     requestShadowMapUpdate();
134     if(request_update) {
135         debugError("shadow map update request not honored\n");
136         return false;
137     }
138     return retval;
139 }
140
141 // updates the internal stream map
142 // note that this should be executed with the guarantee that
143 // nobody will modify the parent data structures
144 void
145 IsoTask::updateShadowMapHelper()
146 {
147     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) updating shadow vars...\n", this);
148     // we are handling a busreset
149     if(m_in_busreset) {
150         m_poll_nfds_shadow = 0;
151         return;
152     }
153     unsigned int i, cnt, max;
154     max = m_manager.m_IsoHandlers.size();
155     m_SyncIsoHandler = NULL;
156     for (i = 0, cnt = 0; i < max; i++) {
157         IsoHandler *h = m_manager.m_IsoHandlers.at(i);
158         assert(h);
159
160         // skip the handlers not intended for us
161         if(h->getType() != m_handlerType) continue;
162
163         if (h->isEnabled()) {
164             m_IsoHandler_map_shadow[cnt] = h;
165             m_poll_fds_shadow[cnt].fd = h->getFileDescriptor();
166             m_poll_fds_shadow[cnt].revents = 0;
167             m_poll_fds_shadow[cnt].events = POLLIN;
168             cnt++;
169             // FIXME: need a more generic approach here
170             if(   m_SyncIsoHandler == NULL
171                && h->getType() == IsoHandler::eHT_Transmit) {
172                 m_SyncIsoHandler = h;
173             }
174
175             debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) %s handler %p added\n",
176                                               this, h->getTypeString(), h);
177         } else {
178             debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) %s handler %p skipped (disabled)\n",
179                                               this, h->getTypeString(), h);
180         }
181         if(cnt > ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT) {
182             debugWarning("Too much ISO Handlers in thread...\n");
183             break;
184         }
185     }
186
187     // FIXME: need a more generic approach here
188     // if there are no active transmit handlers,
189     // use the first receive handler
190     if(   m_SyncIsoHandler == NULL
191        && m_poll_nfds_shadow) {
192         m_SyncIsoHandler = m_IsoHandler_map_shadow[0];
193     }
194     m_poll_nfds_shadow = cnt;
195     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) updated shadow vars...\n", this);
196 }
197
198 bool
199 IsoTask::Execute()
200 {
201     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
202                 "(%p, %s) Execute\n",
203                 this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
204     int err;
205     unsigned int i;
206     unsigned int m_poll_timeout = 10;
207
208     #ifdef DEBUG
209     uint64_t now = Util::SystemTimeSource::getCurrentTimeAsUsecs();
210     int diff = now - m_last_loop_entry;
211     if(diff < 100) {
212         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
213                            "(%p, %s) short loop detected (%d usec), cnt: %d\n",
214                            this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
215                            diff, m_successive_short_loops);
216         m_successive_short_loops++;
217         if(m_successive_short_loops > 10000) {
218             debugError("Shutting down runaway thread\n");
219             m_running = false;
220             return false;
221         }
222     } else {
223         // reset the counter
224         m_successive_short_loops = 0;
225     }
226     m_last_loop_entry = now;
227     #endif
228
229     // if some other thread requested a shadow map update, do it
230     if(request_update) {
231         updateShadowMapHelper();
232         DEC_ATOMIC(&request_update); // ack the update
233         assert(request_update >= 0);
234     }
235
236     // bypass if no handlers are registered
237     if (m_poll_nfds_shadow == 0) {
238         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
239                            "(%p, %s) bypass iterate since no handlers to poll\n",
240                            this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
241         usleep(m_poll_timeout * 1000);
242         return true;
243     }
244
245     // FIXME: what can happen is that poll() returns, but not all clients are
246     // ready. there might be some busy waiting behavior that still has to be solved.
247
248     // setup the poll here
249     // we should prevent a poll() where no events are specified, since that will only time-out
250     bool no_one_to_poll = true;
251     while(no_one_to_poll) {
252         for (i = 0; i < m_poll_nfds_shadow; i++) {
253             short events = 0;
254             IsoHandler *h = m_IsoHandler_map_shadow[i];
255             // we should only poll on a transmit handler
256             // that has a client that is ready to send
257             // something. Otherwise it will end up in
258             // busy wait looping since the packet function
259             // will defer processing (also avoids the
260             // AGAIN problem)
261             if (h->canIterateClient()) {
262                 events = POLLIN | POLLPRI;
263                 no_one_to_poll = false;
264                 // if we are going to poll() it, let's ensure
265                 // it can run until someone wants it to exit
266                 h->allowIterateLoop();
267             }
268             m_poll_fds_shadow[i].events = events;
269         }
270
271         if(no_one_to_poll) {
272             debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
273                         "(%p, %s) No one to poll, waiting for something to happen\n",
274                         this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
275             // wait for something to happen
276             switch(waitForActivity()) {
277                 case IsoTask::eAR_Error:
278                     debugError("Error while waiting for activity\n");
279                     return false;
280                 case IsoTask::eAR_Interrupted:
281                     // FIXME: what to do here?
282                     debugWarning("Interrupted while waiting for activity\n");
283                     break;
284                 case IsoTask::eAR_Timeout:
285                     // FIXME: what to do here?
286                     debugWarning("Timeout while waiting for activity\n");
287                     no_one_to_poll = false; // exit the loop to be able to detect failing handlers
288                     break;
289                 case IsoTask::eAR_Activity:
290                     // do nothing
291                     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
292                                        "(%p, %s) something happened\n",
293                                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
294                     break;
295             }
296         }
297     }
298
299     // Use a shadow map of the fd's such that we don't have to update
300     // the fd map everytime we run poll().
301     err = poll (m_poll_fds_shadow, m_poll_nfds_shadow, m_poll_timeout);
302     uint32_t ctr_at_poll_return = m_manager.get1394Service().getCycleTimer();
303
304     if (err < 0) {
305         if (errno == EINTR) {
306             debugOutput(DEBUG_LEVEL_VERBOSE, "Ignoring poll return due to signal\n");
307             return true;
308         }
309         debugFatal("poll error: %s\n", strerror (errno));
310         m_running = false;
311         return false;
312     }
313
314     // find handlers that have died
315     uint64_t ctr_at_poll_return_ticks = CYCLE_TIMER_TO_TICKS(ctr_at_poll_return);
316     bool handler_died = false;
317     for (i = 0; i < m_poll_nfds_shadow; i++) {
318         // figure out if a handler has died
319
320         // this is the time of the last packet we saw in the iterate() handler
321         uint32_t last_packet_seen = m_IsoHandler_map_shadow[i]->getLastPacketTime();
322         if (last_packet_seen == 0xFFFFFFFF) {
323             // this was not iterated yet, so can't be dead
324             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
325                         "(%p, %s) handler %d didn't see any packets yet\n",
326                         this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"), i);
327             continue;
328         }
329
330         uint64_t last_packet_seen_ticks = CYCLE_TIMER_TO_TICKS(last_packet_seen);
331         // we use a relatively large value to distinguish between "death" and xrun
332         int64_t max_diff_ticks = TICKS_PER_SECOND * 2;
333         int64_t measured_diff_ticks = diffTicks(ctr_at_poll_return_ticks, last_packet_seen_ticks);
334
335         debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
336                            "(%p, %s) check handler %d: diff = %lld, max = %lld, now: %08lX, last: %08lX\n",
337                            this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
338                            i, measured_diff_ticks, max_diff_ticks, ctr_at_poll_return, last_packet_seen);
339         if(measured_diff_ticks > max_diff_ticks) {
340             debugFatal("(%p, %s) Handler died: now: %08lX, last: %08lX, diff: %lld (max: %lld)\n",
341                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
342                        ctr_at_poll_return, last_packet_seen, measured_diff_ticks, max_diff_ticks);
343             m_IsoHandler_map_shadow[i]->notifyOfDeath();
344             handler_died = true;
345         }
346     }
347
348     if(handler_died) {
349         m_running = false;
350         return false; // one or more handlers have died
351     }
352
353     // iterate the handlers
354     for (i = 0; i < m_poll_nfds_shadow; i++) {
355         #ifdef DEBUG
356         if(m_poll_fds_shadow[i].revents) {
357             debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
358                         "(%p, %s) received events: %08X for (%d/%d, %p, %s)\n",
359                         this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
360                         m_poll_fds_shadow[i].revents,
361                         i, m_poll_nfds_shadow,
362                         m_IsoHandler_map_shadow[i],
363                         m_IsoHandler_map_shadow[i]->getTypeString());
364         }
365         #endif
366
367         // if we get here, it means two things:
368         // 1) the kernel can accept or provide packets (poll returned POLLIN)
369         // 2) the client can provide or accept packets (since we enabled polling)
370         if(m_poll_fds_shadow[i].revents & (POLLIN)) {
371             m_IsoHandler_map_shadow[i]->iterate(ctr_at_poll_return);
372         } else {
373             // there might be some error condition
374             if (m_poll_fds_shadow[i].revents & POLLERR) {
375                 debugWarning("(%p) error on fd for %d\n", this, i);
376             }
377             if (m_poll_fds_shadow[i].revents & POLLHUP) {
378                 debugWarning("(%p) hangup on fd for %d\n", this, i);
379             }
380         }
381     }
382     return true;
383 }
384
385 enum IsoTask::eActivityResult
386 IsoTask::waitForActivity()
387 {
388     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
389                        "(%p, %s) waiting for activity\n",
390                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
391     struct timespec ts;
392     int result;
393
394     if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
395         debugError("clock_gettime failed\n");
396         return eAR_Error;
397     }
398
399     ts.tv_nsec += m_activity_wait_timeout_nsec;
400     while(ts.tv_nsec >= 1000000000LL) {
401         ts.tv_sec += 1;
402         ts.tv_nsec -= 1000000000LL;
403     }
404
405     result = sem_timedwait(&m_activity_semaphore, &ts);
406
407     if(result != 0) {
408         if (errno == ETIMEDOUT) {
409             debugOutput(DEBUG_LEVEL_VERBOSE,
410                         "(%p) sem_timedwait() timed out (result=%d)\n",
411                         this, result);
412             return eAR_Timeout;
413         } else if (errno == EINTR) {
414             debugOutput(DEBUG_LEVEL_VERBOSE,
415                         "(%p) sem_timedwait() interrupted by signal (result=%d)\n",
416                         this, result);
417             return eAR_Interrupted;
418         } else if (errno == EINVAL) {
419             debugError("(%p) sem_timedwait error (result=%d errno=EINVAL)\n",
420                         this, result);
421             debugError("(%p) timeout_nsec=%lld ts.sec=%d ts.nsec=%lld\n",
422                        this, m_activity_wait_timeout_nsec, ts.tv_sec, ts.tv_nsec);
423             return eAR_Error;
424         } else {
425             debugError("(%p) sem_timedwait error (result=%d errno=%d)\n",
426                         this, result, errno);
427             debugError("(%p) timeout_nsec=%lld ts.sec=%d ts.nsec=%lld\n",
428                        this, m_activity_wait_timeout_nsec, ts.tv_sec, ts.tv_nsec);
429             return eAR_Error;
430         }
431     }
432
433     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
434                 "(%p, %s) got activity\n",
435                 this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
436     return eAR_Activity;
437 }
438
439 void
440 IsoTask::signalActivity()
441 {
442     // signal the activity cond var
443     sem_post(&m_activity_semaphore);
444     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
445                 "(%p, %s) activity\n",
446                 this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
447 }
448
449 void IsoTask::setVerboseLevel(int i) {
450     setDebugLevel(i);
451     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", i );
452 }
453
454 // -- the ISO handler manager -- //
455 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service)
456    : m_State(E_Created)
457    , m_service( service )
458    , m_realtime(false), m_priority(0)
459    , m_IsoThreadTransmit ( NULL )
460    , m_IsoTaskTransmit ( NULL )
461    , m_IsoThreadReceive ( NULL )
462    , m_IsoTaskReceive ( NULL )
463 {
464 }
465
466 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio)
467    : m_State(E_Created)
468    , m_service( service )
469    , m_realtime(run_rt), m_priority(rt_prio)
470    , m_IsoThreadTransmit ( NULL )
471    , m_IsoTaskTransmit ( NULL )
472    , m_IsoThreadReceive ( NULL )
473    , m_IsoTaskReceive ( NULL )
474 {
475 }
476
477 IsoHandlerManager::~IsoHandlerManager()
478 {
479     stopHandlers();
480     pruneHandlers();
481     if(m_IsoHandlers.size() > 0) {
482         debugError("Still some handlers in use\n");
483     }
484     if (m_IsoThreadTransmit) {
485         m_IsoThreadTransmit->Stop();
486         delete m_IsoThreadTransmit;
487     }
488     if (m_IsoThreadReceive) {
489         m_IsoThreadReceive->Stop();
490         delete m_IsoThreadReceive;
491     }
492     if (m_IsoTaskTransmit) {
493         delete m_IsoTaskTransmit;
494     }
495     if (m_IsoTaskReceive) {
496         delete m_IsoTaskReceive;
497     }
498 }
499
500 bool
501 IsoHandlerManager::handleBusReset()
502 {
503     debugOutput( DEBUG_LEVEL_NORMAL, "bus reset...\n");
504     // A few things can happen on bus reset:
505     // 1) no devices added/removed => streams are still valid, but might have to be restarted
506     // 2) a device was removed => some streams become invalid
507     // 3) a device was added => same as 1, new device is ignored
508     if (!m_IsoTaskTransmit) {
509         debugError("No xmit task\n");
510         return false;
511     }
512     if (!m_IsoTaskReceive) {
513         debugError("No receive task\n");
514         return false;
515     }
516     if (!m_IsoTaskTransmit->handleBusReset()) {
517         debugWarning("could no handle busreset on xmit\n");
518     }
519     if (!m_IsoTaskReceive->handleBusReset()) {
520         debugWarning("could no handle busreset on recv\n");
521     }
522     return true;
523 }
524
525 void
526 IsoHandlerManager::requestShadowMapUpdate()
527 {
528     if(m_IsoTaskTransmit) m_IsoTaskTransmit->requestShadowMapUpdate();
529     if(m_IsoTaskReceive) m_IsoTaskReceive->requestShadowMapUpdate();
530 }
531
532 bool
533 IsoHandlerManager::setThreadParameters(bool rt, int priority) {
534     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority);
535     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority
536     if (priority < THREAD_MIN_RTPRIO) priority = THREAD_MIN_RTPRIO; // cap the priority
537     m_realtime = rt;
538     m_priority = priority;
539
540     // grab the options from the parent
541     Util::Configuration *config = m_service.getConfiguration();
542     int ihm_iso_prio_increase = ISOHANDLERMANAGER_ISO_PRIO_INCREASE;
543     int ihm_iso_prio_increase_xmit = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT;
544     int ihm_iso_prio_increase_recv = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV;
545     if(config) {
546         config->getValueForSetting("ieee1394.isomanager.prio_increase", ihm_iso_prio_increase);
547         config->getValueForSetting("ieee1394.isomanager.prio_increase_xmit", ihm_iso_prio_increase_xmit);
548         config->getValueForSetting("ieee1394.isomanager.prio_increase_recv", ihm_iso_prio_increase_recv);
549     }
550
551     if (m_IsoThreadTransmit) {
552         if (m_realtime) {
553             m_IsoThreadTransmit->AcquireRealTime(m_priority
554                                                  + ihm_iso_prio_increase
555                                                  + ihm_iso_prio_increase_xmit);
556         } else {
557             m_IsoThreadTransmit->DropRealTime();
558         }
559     }
560     if (m_IsoThreadReceive) {
561         if (m_realtime) {
562             m_IsoThreadReceive->AcquireRealTime(m_priority
563                                                 + ihm_iso_prio_increase
564                                                 + ihm_iso_prio_increase_recv);
565         } else {
566             m_IsoThreadReceive->DropRealTime();
567         }
568     }
569
570     return true;
571 }
572
573 bool IsoHandlerManager::init()
574 {
575     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing ISO manager %p...\n", this);
576     // check state
577     if(m_State != E_Created) {
578         debugError("Manager already initialized...\n");
579         return false;
580     }
581
582     // grab the options from the parent
583     Util::Configuration *config = m_service.getConfiguration();
584     int ihm_iso_prio_increase = ISOHANDLERMANAGER_ISO_PRIO_INCREASE;
585     int ihm_iso_prio_increase_xmit = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT;
586     int ihm_iso_prio_increase_recv = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV;
587     int64_t isotask_activity_timeout_usecs = ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS;
588     if(config) {
589         config->getValueForSetting("ieee1394.isomanager.prio_increase", ihm_iso_prio_increase);
590         config->getValueForSetting("ieee1394.isomanager.prio_increase_xmit", ihm_iso_prio_increase_xmit);
591         config->getValueForSetting("ieee1394.isomanager.prio_increase_recv", ihm_iso_prio_increase_recv);
592         config->getValueForSetting("ieee1394.isomanager.isotask_activity_timeout_usecs", isotask_activity_timeout_usecs);
593     }
594
595     // create threads to iterate our ISO handlers
596     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p transmit...\n", this);
597     m_IsoTaskTransmit = new IsoTask( *this, IsoHandler::eHT_Transmit );
598     if(!m_IsoTaskTransmit) {
599         debugFatal("No task\n");
600         return false;
601     }
602     m_IsoTaskTransmit->setVerboseLevel(getDebugLevel());
603     m_IsoTaskTransmit->m_activity_wait_timeout_nsec = isotask_activity_timeout_usecs * 1000LL;
604     m_IsoThreadTransmit = new Util::PosixThread(m_IsoTaskTransmit, "ISOXMT", m_realtime,
605                                                 m_priority + ihm_iso_prio_increase
606                                                 + ihm_iso_prio_increase_xmit,
607                                                 PTHREAD_CANCEL_DEFERRED);
608
609     if(!m_IsoThreadTransmit) {
610         debugFatal("No thread\n");
611         return false;
612     }
613     m_IsoThreadTransmit->setVerboseLevel(getDebugLevel());
614
615     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p receive...\n", this);
616     m_IsoTaskReceive = new IsoTask( *this, IsoHandler::eHT_Receive );
617     if(!m_IsoTaskReceive) {
618         debugFatal("No task\n");
619         return false;
620     }
621     m_IsoTaskReceive->setVerboseLevel(getDebugLevel());
622     m_IsoThreadReceive = new Util::PosixThread(m_IsoTaskReceive, "ISORCV", m_realtime,
623                                                m_priority + ihm_iso_prio_increase
624                                                + ihm_iso_prio_increase_recv,
625                                                PTHREAD_CANCEL_DEFERRED);
626
627     if(!m_IsoThreadReceive) {
628         debugFatal("No thread\n");
629         return false;
630     }
631     m_IsoThreadReceive->setVerboseLevel(getDebugLevel());
632     // register the thread with the RT watchdog
633     Util::Watchdog *watchdog = m_service.getWatchdog();
634     if(watchdog) {
635         if(!watchdog->registerThread(m_IsoThreadTransmit)) {
636             debugWarning("could not register iso transmit thread with watchdog\n");
637         }
638         if(!watchdog->registerThread(m_IsoThreadReceive)) {
639             debugWarning("could not register iso receive thread with watchdog\n");
640         }
641     } else {
642         debugWarning("could not find valid watchdog\n");
643     }
644
645     if (m_IsoThreadTransmit->Start() != 0) {
646         debugFatal("Could not start ISO Transmit thread\n");
647         return false;
648     }
649     if (m_IsoThreadReceive->Start() != 0) {
650         debugFatal("Could not start ISO Receive thread\n");
651         return false;
652     }
653
654     m_State=E_Running;
655     return true;
656 }
657
658 bool
659 IsoHandlerManager::disable(IsoHandler *h) {
660     bool result;
661     int i=0;
662     debugOutput(DEBUG_LEVEL_VERBOSE, "Disable on IsoHandler %p\n", h);
663     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
664         it != m_IsoHandlers.end();
665         ++it )
666     {
667         if ((*it) == h) {
668             result = h->disable();
669             if(h->getType() == IsoHandler::eHT_Transmit) {
670                 result &= m_IsoTaskTransmit->requestShadowMapUpdate();
671             } else {
672                 result &= m_IsoTaskReceive->requestShadowMapUpdate();
673             }
674             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " disabled\n");
675             return result;
676         }
677         i++;
678     }
679     debugError("Handler not found\n");
680     return false;
681 }
682
683 bool
684 IsoHandlerManager::enable(IsoHandler *h) {
685     bool result;
686     int i=0;
687     debugOutput(DEBUG_LEVEL_VERBOSE, "Enable on IsoHandler %p\n", h);
688     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
689         it != m_IsoHandlers.end();
690         ++it )
691     {
692         if ((*it) == h) {
693             result = h->enable();
694             if(h->getType() == IsoHandler::eHT_Transmit) {
695                 result &= m_IsoTaskTransmit->requestShadowMapUpdate();
696             } else {
697                 result &= m_IsoTaskReceive->requestShadowMapUpdate();
698             }
699             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " enabled\n");
700             return result;
701         }
702         i++;
703     }
704     debugError("Handler not found\n");
705     return false;
706 }
707
708 void
709 IsoHandlerManager::signalActivityTransmit()
710 {
711     assert(m_IsoTaskTransmit);
712     m_IsoTaskTransmit->signalActivity();
713 }
714
715 void
716 IsoHandlerManager::signalActivityReceive()
717 {
718     assert(m_IsoTaskReceive);
719     m_IsoTaskReceive->signalActivity();
720 }
721
722 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
723 {
724     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
725     assert(handler);
726     handler->setVerboseLevel(getDebugLevel());
727     m_IsoHandlers.push_back(handler);
728     requestShadowMapUpdate();
729     return true;
730 }
731
732 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
733 {
734     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
735     assert(handler);
736
737     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
738       it != m_IsoHandlers.end();
739       ++it )
740     {
741         if ( *it == handler ) {
742             m_IsoHandlers.erase(it);
743             requestShadowMapUpdate();
744             return true;
745         }
746     }
747     debugFatal("Could not find handler (%p)\n", handler);
748     return false; //not found
749 }
750
751 /**
752  * Registers an StreamProcessor with the IsoHandlerManager.
753  *
754  * If nescessary, an IsoHandler is created to handle this stream.
755  * Once an StreamProcessor is registered to the handler, it will be included
756  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
757  *
758  * @param stream the stream to register
759  * @return true if registration succeeds
760  *
761  * \todo : currently there is a one-to-one mapping
762  *        between streams and handlers, this is not ok for
763  *        multichannel receive
764  */
765 bool IsoHandlerManager::registerStream(StreamProcessor *stream)
766 {
767     debugOutput( DEBUG_LEVEL_VERBOSE, "Registering %s stream %p\n", stream->getTypeString(), stream);
768     assert(stream);
769
770     IsoHandler* h = NULL;
771
772     // make sure the stream isn't already attached to a handler
773     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
774       it != m_IsoHandlers.end();
775       ++it )
776     {
777         if((*it)->isStreamRegistered(stream)) {
778             debugError( "stream already registered!\n");
779             return false;
780         }
781     }
782
783     // clean up all handlers that aren't used
784     pruneHandlers();
785
786     // allocate a handler for this stream
787     if (stream->getType()==StreamProcessor::ePT_Receive) {
788         // grab the options from the parent
789         Util::Configuration *config = m_service.getConfiguration();
790         int receive_mode_setting = DEFAULT_ISO_RECEIVE_MODE;
791         int bufferfill_mode_threshold = BUFFERFILL_MODE_THRESHOLD;
792         int min_interrupts_per_period = MINIMUM_INTERRUPTS_PER_PERIOD;
793         int max_nb_buffers_recv = MAX_RECV_NB_BUFFERS;
794         int min_packetsize_recv = MIN_RECV_PACKET_SIZE;
795         if(config) {
796             config->getValueForSetting("ieee1394.isomanager.iso_receive_mode", receive_mode_setting);
797             config->getValueForSetting("ieee1394.isomanager.bufferfill_mode_threshold", bufferfill_mode_threshold);
798             config->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period);
799             config->getValueForSetting("ieee1394.isomanager.max_nb_buffers_recv", max_nb_buffers_recv);
800             config->getValueForSetting("ieee1394.isomanager.min_packetsize_recv", min_packetsize_recv);
801         }
802
803         // setup the optimal parameters for the raw1394 ISO buffering
804         unsigned int packets_per_period = stream->getPacketsPerPeriod();
805         // reserve space for the 1394 header too (might not be necessary)
806         unsigned int max_packet_size = stream->getMaxPacketSize() + 8;
807         unsigned int page_size = getpagesize();
808
809         enum raw1394_iso_dma_recv_mode receive_mode;
810         switch(receive_mode_setting) {
811             case 0:
812                 if(packets_per_period < (unsigned)bufferfill_mode_threshold) {
813                     debugOutput( DEBUG_LEVEL_VERBOSE, "Using packet-per-buffer mode (auto) [%d, %d]\n",
814                                  packets_per_period, bufferfill_mode_threshold);
815                     receive_mode = RAW1394_DMA_PACKET_PER_BUFFER;
816                 } else {
817                     debugOutput( DEBUG_LEVEL_VERBOSE, "Using bufferfill mode (auto) [%d, %d]\n",
818                                  packets_per_period, bufferfill_mode_threshold);
819                     receive_mode = RAW1394_DMA_BUFFERFILL;
820                 }
821                 break;
822             case 1:
823                 debugOutput( DEBUG_LEVEL_VERBOSE, "Using packet-per-buffer mode (config)\n");
824                 receive_mode = RAW1394_DMA_PACKET_PER_BUFFER;
825                 break;
826             case 2:
827                 debugOutput( DEBUG_LEVEL_VERBOSE, "Using bufferfill mode (config)\n");
828                 receive_mode = RAW1394_DMA_BUFFERFILL;
829                 break;
830             default: debugWarning("Bogus receive mode setting in config: %d\n", receive_mode_setting);
831         }
832
833         // Ensure we don't request a packet size bigger than the
834         // kernel-enforced maximum which is currently 1 page.
835         // NOTE: PP: this is not really true AFAICT
836         if (max_packet_size > page_size) {
837             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
838             return false;
839         }
840         if (max_packet_size < (unsigned)min_packetsize_recv) {
841             debugError("min packet size (%u) < MIN_RECV_PACKET_SIZE (%u), using min value\n",
842                        max_packet_size, min_packetsize_recv);
843             max_packet_size = min_packetsize_recv;
844         }
845
846         // the interrupt/wakeup interval prediction of raw1394 is a mess...
847         int irq_interval = (packets_per_period-1) / min_interrupts_per_period;
848         if(irq_interval <= 0) irq_interval=1;
849
850         // the receive buffer size doesn't matter for the latency,
851         // it does seem to be confined to a certain region for correct
852         // operation. However it is not clear how many.
853         int buffers = max_nb_buffers_recv;
854
855         // ensure at least 2 hardware interrupts per ISO buffer wraparound
856         if(irq_interval > buffers/2) {
857             irq_interval = buffers/2;
858         }
859
860         // create the actual handler
861         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");
862         h = new IsoHandler(*this, IsoHandler::eHT_Receive,
863                            buffers, max_packet_size, irq_interval);
864
865         if(!h) {
866             debugFatal("Could not create IsoRecvHandler\n");
867             return false;
868         }
869
870         h->setReceiveMode(receive_mode);
871
872     } else if (stream->getType()==StreamProcessor::ePT_Transmit) {
873         // grab the options from the parent
874         Util::Configuration *config = m_service.getConfiguration();
875         int min_interrupts_per_period = MINIMUM_INTERRUPTS_PER_PERIOD;
876         int max_nb_buffers_xmit = MAX_XMIT_NB_BUFFERS;
877         int max_packetsize_xmit = MAX_XMIT_PACKET_SIZE;
878         int min_packetsize_xmit = MIN_XMIT_PACKET_SIZE;
879         if(config) {
880             config->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period);
881             config->getValueForSetting("ieee1394.isomanager.max_nb_buffers_xmit", max_nb_buffers_xmit);
882             config->getValueForSetting("ieee1394.isomanager.max_packetsize_xmit", max_packetsize_xmit);
883             config->getValueForSetting("ieee1394.isomanager.min_packetsize_xmit", min_packetsize_xmit);
884         }
885
886         // setup the optimal parameters for the raw1394 ISO buffering
887         // reserve space for the 1394 header too (might not be necessary)
888         unsigned int max_packet_size = stream->getMaxPacketSize() + 8;
889
890         if (max_packet_size > (unsigned)max_packetsize_xmit) {
891             debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n",
892                        max_packet_size, max_packetsize_xmit);
893             return false;
894         }
895         if (max_packet_size < (unsigned)min_packetsize_xmit) {
896             debugError("min packet size (%u) < MIN_XMIT_PACKET_SIZE (%u), using min value\n",
897                        max_packet_size, min_packetsize_xmit);
898             max_packet_size = min_packetsize_xmit;
899         }
900
901         int buffers = max_nb_buffers_xmit;
902         unsigned int packets_per_period = stream->getPacketsPerPeriod();
903
904         int irq_interval = (packets_per_period-1) / min_interrupts_per_period;
905         if(irq_interval <= 0) irq_interval=1;
906         // ensure at least 2 hardware interrupts per ISO buffer wraparound
907         if(irq_interval > buffers/2) {
908             irq_interval = buffers/2;
909         }
910
911         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");
912
913         // create the actual handler
914         h = new IsoHandler(*this, IsoHandler::eHT_Transmit,
915                            buffers, max_packet_size, irq_interval);
916
917         if(!h) {
918             debugFatal("Could not create IsoXmitHandler\n");
919             return false;
920         }
921
922     } else {
923         debugFatal("Bad stream type\n");
924         return false;
925     }
926
927     h->setVerboseLevel(getDebugLevel());
928
929     // init the handler
930     if(!h->init()) {
931         debugFatal("Could not initialize receive handler\n");
932         return false;
933     }
934
935     // register the stream with the handler
936     if(!h->registerStream(stream)) {
937         debugFatal("Could not register receive stream with handler\n");
938         return false;
939     }
940
941     // register the handler with the manager
942     if(!registerHandler(h)) {
943         debugFatal("Could not register receive handler with manager\n");
944         return false;
945     }
946     debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n", stream, h);
947
948     m_StreamProcessors.push_back(stream);
949     debugOutput( DEBUG_LEVEL_VERBOSE, " %d streams, %d handlers registered\n",
950                                       m_StreamProcessors.size(), m_IsoHandlers.size());
951     return true;
952 }
953
954 bool IsoHandlerManager::unregisterStream(StreamProcessor *stream)
955 {
956     debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering %s stream %p\n", stream->getTypeString(), stream);
957     assert(stream);
958
959     // make sure the stream isn't attached to a handler anymore
960     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
961       it != m_IsoHandlers.end();
962       ++it )
963     {
964         if((*it)->isStreamRegistered(stream)) {
965             if(!(*it)->unregisterStream(stream)) {
966                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
967                 return false;
968             }
969             debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
970         }
971     }
972
973     // clean up all handlers that aren't used
974     pruneHandlers();
975
976     // remove the stream from the registered streams list
977     for ( StreamProcessorVectorIterator it = m_StreamProcessors.begin();
978       it != m_StreamProcessors.end();
979       ++it )
980     {
981         if ( *it == stream ) {
982             m_StreamProcessors.erase(it);
983             debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
984             return true;
985         }
986     }
987     return false; //not found
988 }
989
990 /**
991  * @brief unregister a handler from the manager
992  * @note called without the lock held.
993  */
994 void IsoHandlerManager::pruneHandlers() {
995     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
996     IsoHandlerVector toUnregister;
997
998     // find all handlers that are not in use
999     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1000           it != m_IsoHandlers.end();
1001           ++it )
1002     {
1003         if(!((*it)->inUse())) {
1004             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
1005             toUnregister.push_back(*it);
1006         }
1007     }
1008     // delete them
1009     for ( IsoHandlerVectorIterator it = toUnregister.begin();
1010           it != toUnregister.end();
1011           ++it )
1012     {
1013         unregisterHandler(*it);
1014
1015         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
1016
1017         // Now the handler's been unregistered it won't be reused
1018         // again.  Therefore it really needs to be formally deleted
1019         // to free up the raw1394 handle.  Otherwise things fall
1020         // apart after several xrun recoveries as the system runs
1021         // out of resources to support all the disused but still
1022         // allocated raw1394 handles.  At least this is the current
1023         // theory as to why we end up with "memory allocation"
1024         // failures after several Xrun recoveries.
1025         delete *it;
1026     }
1027 }
1028
1029 bool
1030 IsoHandlerManager::stopHandlerForStream(Streaming::StreamProcessor *stream) {
1031     // check state
1032     if(m_State != E_Running) {
1033         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1034         return false;
1035     }
1036     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1037       it != m_IsoHandlers.end();
1038       ++it )
1039     {
1040         if((*it)->isStreamRegistered(stream)) {
1041             debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler %p for stream %p\n", *it, stream);
1042             if(!(*it)->disable()) {
1043                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not disable handler (%p)\n",*it);
1044                 return false;
1045             }
1046             bool result;
1047             if((*it)->getType() == IsoHandler::eHT_Transmit) {
1048                 result = m_IsoTaskTransmit->requestShadowMapUpdate();
1049             } else {
1050                 result = m_IsoTaskReceive->requestShadowMapUpdate();
1051             }
1052             if(!result) {
1053                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
1054                 return false;
1055             }
1056             return true;
1057         }
1058     }
1059     debugError("Stream %p has no attached handler\n", stream);
1060     return false;
1061 }
1062
1063 int
1064 IsoHandlerManager::getPacketLatencyForStream(Streaming::StreamProcessor *stream) {
1065     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1066       it != m_IsoHandlers.end();
1067       ++it )
1068     {
1069         if((*it)->isStreamRegistered(stream)) {
1070             return (*it)->getIrqInterval();
1071         }
1072     }
1073     debugError("Stream %p has no attached handler\n", stream);
1074     return 0;
1075 }
1076
1077 void
1078 IsoHandlerManager::flushHandlerForStream(Streaming::StreamProcessor *stream) {
1079     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1080       it != m_IsoHandlers.end();
1081       ++it )
1082     {
1083         if((*it)->isStreamRegistered(stream)) {
1084             (*it)->flush();
1085         }
1086     }
1087     debugError("Stream %p has no attached handler\n", stream);
1088     return;
1089 }
1090
1091 IsoHandler *
1092 IsoHandlerManager::getHandlerForStream(Streaming::StreamProcessor *stream) {
1093     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1094       it != m_IsoHandlers.end();
1095       ++it )
1096     {
1097         if((*it)->isStreamRegistered(stream)) {
1098             return (*it);
1099         }
1100     }
1101     debugError("Stream %p has no attached handler\n", stream);
1102     return NULL;
1103 }
1104
1105 bool
1106 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream) {
1107     return startHandlerForStream(stream, -1);
1108 }
1109
1110 bool
1111 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream, int cycle) {
1112     // check state
1113     if(m_State != E_Running) {
1114         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1115         return false;
1116     }
1117     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1118       it != m_IsoHandlers.end();
1119       ++it )
1120     {
1121         if((*it)->isStreamRegistered(stream)) {
1122             debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler %p for stream %p\n", *it, stream);
1123             if(!(*it)->enable(cycle)) {
1124                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not enable handler (%p)\n",*it);
1125                 return false;
1126             }
1127             bool result;
1128             if((*it)->getType() == IsoHandler::eHT_Transmit) {
1129                 result = m_IsoTaskTransmit->requestShadowMapUpdate();
1130             } else {
1131                 result = m_IsoTaskReceive->requestShadowMapUpdate();
1132             }
1133             if(!result) {
1134                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
1135                 return false;
1136             }
1137             return true;
1138         }
1139     }
1140     debugError("Stream %p has no attached handler\n", stream);
1141     return false;
1142 }
1143
1144 bool IsoHandlerManager::stopHandlers() {
1145     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
1146
1147     // check state
1148     if(m_State != E_Running) {
1149         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1150         return false;
1151     }
1152
1153     bool retval=true;
1154
1155     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1156         it != m_IsoHandlers.end();
1157         ++it )
1158     {
1159         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handler (%p)\n",*it);
1160         if(!(*it)->disable()){
1161             debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it);
1162             retval=false;
1163         }
1164         bool result;
1165         if((*it)->getType() == IsoHandler::eHT_Transmit) {
1166             result = m_IsoTaskTransmit->requestShadowMapUpdate();
1167         } else {
1168             result = m_IsoTaskReceive->requestShadowMapUpdate();
1169         }
1170         if(!result) {
1171             debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
1172             return false;
1173         }
1174     }
1175
1176     if (retval) {
1177         m_State=E_Prepared;
1178     } else {
1179         m_State=E_Error;
1180     }
1181     return retval;
1182 }
1183
1184 bool IsoHandlerManager::reset() {
1185     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
1186     // check state
1187     if(m_State == E_Error) {
1188         debugFatal("Resetting from error condition not yet supported...\n");
1189         return false;
1190     }
1191     // if not in an error condition, reset means stop the handlers
1192     return stopHandlers();
1193 }
1194
1195 void IsoHandlerManager::setVerboseLevel(int i) {
1196     setDebugLevel(i);
1197     // propagate the debug level
1198     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1199           it != m_IsoHandlers.end();
1200           ++it )
1201     {
1202         (*it)->setVerboseLevel(i);
1203     }
1204     if(m_IsoThreadTransmit) m_IsoThreadTransmit->setVerboseLevel(i);
1205     if(m_IsoTaskTransmit)   m_IsoTaskTransmit->setVerboseLevel(i);
1206     if(m_IsoThreadReceive)  m_IsoThreadReceive->setVerboseLevel(i);
1207     if(m_IsoTaskReceive)    m_IsoTaskReceive->setVerboseLevel(i);
1208     setDebugLevel(i);
1209     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", i );
1210 }
1211
1212 void IsoHandlerManager::dumpInfo() {
1213     #ifdef DEBUG
1214     unsigned int i=0;
1215     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
1216     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
1217
1218     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1219           it != m_IsoHandlers.end();
1220           ++it )
1221     {
1222         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
1223         (*it)->dumpInfo();
1224     }
1225     #endif
1226 }
1227
1228 const char *
1229 IsoHandlerManager::eHSToString(enum eHandlerStates s) {
1230     switch (s) {
1231         default: return "Invalid";
1232         case E_Created: return "Created";
1233         case E_Prepared: return "Prepared";
1234         case E_Running: return "Running";
1235         case E_Error: return "Error";
1236     }
1237 }
Note: See TracBrowser for help on using the browser.