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

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

Merge all changes from 2.0 branch into trunk (since r1361). This _should_ contain all forward merges done in the mean time. At this moment in time both branches should be in sync.

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