2 * Copyright (C) 2005-2008 by Pieter Palmers
4 * This file is part of FFADO
5 * FFADO = Free Firewire (pro-)audio drivers for linux
7 * FFADO is based upon FreeBoB.
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) version 3 of the License.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "IsoHandlerManager.h"
27 #include "ieee1394service.h"
28 #include "cycletimer.h"
29 #include "libstreaming/generic/StreamProcessor.h"
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"
41 IMPL_DEBUG_MODULE( IsoHandlerManager
, IsoHandlerManager
, DEBUG_LEVEL_NORMAL
);
42 IMPL_DEBUG_MODULE( IsoHandlerManager::IsoTask
, IsoTask
, DEBUG_LEVEL_NORMAL
);
43 IMPL_DEBUG_MODULE( IsoHandlerManager::IsoHandler
, IsoHandler
, DEBUG_LEVEL_NORMAL
);
45 using namespace Streaming
;
47 // --- ISO Thread --- //
49 IsoHandlerManager::IsoTask::IsoTask(IsoHandlerManager
& manager
, enum IsoHandler::EHandlerType t
)
50 : m_manager( manager
)
51 , m_SyncIsoHandler ( NULL
)
54 , m_in_busreset( false )
55 , m_activity_wait_timeout_nsec (ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS
* 1000LL)
59 IsoHandlerManager::IsoTask::~IsoTask()
61 sem_destroy(&m_activity_semaphore
);
65 IsoHandlerManager::IsoTask::Init()
70 for (i
=0; i
< ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT
; i
++) {
71 m_IsoHandler_map_shadow
[i
] = NULL
;
72 m_poll_fds_shadow
[i
].events
= 0;
74 m_poll_nfds_shadow
= 0;
77 m_last_loop_entry
= 0;
78 m_successive_short_loops
= 0;
81 sem_init(&m_activity_semaphore
, 0, 0);
87 IsoHandlerManager::IsoTask::requestShadowMapUpdate()
89 debugOutput(DEBUG_LEVEL_VERBOSE
, "(%p) enter\n", this);
90 INC_ATOMIC(&request_update
);
92 // get the thread going again
94 debugOutput(DEBUG_LEVEL_VERBOSE
, "(%p) exit\n", this);
98 IsoHandlerManager::IsoTask::handleBusReset()
102 // nothing to do here
105 m_in_busreset
= true;
106 requestShadowMapUpdate();
109 max
= m_manager
.m_IsoHandlers
.size();
110 for (i
= 0; i
< max
; i
++) {
111 IsoHandler
*h
= m_manager
.m_IsoHandlers
.at(i
);
114 // skip the handlers not intended for us
115 if(h
->getType() != m_handlerType
) continue;
117 if (!h
->handleBusReset()) {
118 debugWarning("Failed to handle busreset on %p\n", h
);
123 // re-enable processing
124 m_in_busreset
= false;
125 requestShadowMapUpdate();
129 // updates the internal stream map
130 // note that this should be executed with the guarantee that
131 // nobody will modify the parent data structures
133 IsoHandlerManager::IsoTask::updateShadowMapHelper()
135 debugOutput( DEBUG_LEVEL_VERBOSE
, "(%p) updating shadow vars...\n", this);
136 // we are handling a busreset
138 m_poll_nfds_shadow
= 0;
141 unsigned int i
, cnt
, max
;
142 max
= m_manager
.m_IsoHandlers
.size();
143 m_SyncIsoHandler
= NULL
;
144 for (i
= 0, cnt
= 0; i
< max
; i
++) {
146 // FIXME: This is a very crude guard against some other thread
147 // deleting handlers while this function is running. While this
148 // didn't tend to happen with the old kernel firewire stack, delays
149 // in shutdown experienced in the new stack mean it can happen that
150 // a handler disappears during the running of this function. This
151 // test should prevent "out of range" exceptions in most cases.
152 // However, it is racy: if the deletion happens between this
153 // conditional and the following at() call, an out of range
154 // condition can still happen.
155 if (i
>=m_manager
.m_IsoHandlers
.size())
158 IsoHandler
*h
= m_manager
.m_IsoHandlers
.at(i
);
161 // skip the handlers not intended for us
162 if(h
->getType() != m_handlerType
) continue;
164 // update the state of the handler
165 // FIXME: maybe this is not the best place to do this
166 // it might be better to eliminate the 'requestShadowMapUpdate'
167 // entirely and replace it with a mechanism that implements all
168 // actions on the m_manager.m_IsoHandlers in the loop
172 if (h
->isEnabled()) {
173 m_IsoHandler_map_shadow
[cnt
] = h
;
174 m_poll_fds_shadow
[cnt
].fd
= h
->getFileDescriptor();
175 m_poll_fds_shadow
[cnt
].revents
= 0;
176 m_poll_fds_shadow
[cnt
].events
= POLLIN
;
178 // FIXME: need a more generic approach here
179 if( m_SyncIsoHandler
== NULL
180 && h
->getType() == IsoHandler::eHT_Transmit
) {
181 m_SyncIsoHandler
= h
;
184 debugOutput( DEBUG_LEVEL_VERBOSE
, "(%p) %s handler %p added\n",
185 this, h
->getTypeString(), h
);
187 debugOutput( DEBUG_LEVEL_VERBOSE
, "(%p) %s handler %p skipped (disabled)\n",
188 this, h
->getTypeString(), h
);
190 if(cnt
> ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT
) {
191 debugWarning("Too much ISO Handlers in thread...\n");
196 // FIXME: need a more generic approach here
197 // if there are no active transmit handlers,
198 // use the first receive handler
199 if( m_SyncIsoHandler
== NULL
200 && m_poll_nfds_shadow
) {
201 m_SyncIsoHandler
= m_IsoHandler_map_shadow
[0];
203 m_poll_nfds_shadow
= cnt
;
204 debugOutput( DEBUG_LEVEL_VERBOSE
, "(%p) updated shadow vars...\n", this);
208 IsoHandlerManager::IsoTask::Execute()
210 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE
,
211 "(%p, %s) Execute\n",
212 this, (m_handlerType
== IsoHandler::eHT_Transmit
? "Transmit": "Receive"));
215 unsigned int m_poll_timeout
= 10;
218 uint64_t now
= Util::SystemTimeSource::getCurrentTimeAsUsecs();
219 int diff
= now
- m_last_loop_entry
;
221 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE
,
222 "(%p, %s) short loop detected (%d usec), cnt: %d\n",
223 this, (m_handlerType
== IsoHandler::eHT_Transmit
? "Transmit": "Receive"),
224 diff
, m_successive_short_loops
);
225 m_successive_short_loops
++;
226 if(m_successive_short_loops
> 10000) {
227 debugError("Shutting down runaway thread\n");
233 m_successive_short_loops
= 0;
235 m_last_loop_entry
= now
;
238 // if some other thread requested a shadow map update, do it
240 updateShadowMapHelper();
241 DEC_ATOMIC(&request_update
); // ack the update
242 assert(request_update
>= 0);
245 // bypass if no handlers are registered
246 if (m_poll_nfds_shadow
== 0) {
247 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE
,
248 "(%p, %s) bypass iterate since no handlers to poll\n",
249 this, (m_handlerType
== IsoHandler::eHT_Transmit
? "Transmit": "Receive"));
250 usleep(m_poll_timeout
* 1000);
254 // FIXME: what can happen is that poll() returns, but not all clients are
255 // ready. there might be some busy waiting behavior that still has to be solved.
257 // setup the poll here
258 // we should prevent a poll() where no events are specified, since that will only time-out
259 bool no_one_to_poll
= true;
260 while(no_one_to_poll
) {
261 for (i
= 0; i
< m_poll_nfds_shadow
; i
++) {
263 IsoHandler
*h
= m_IsoHandler_map_shadow
[i
];
264 // we should only poll on a transmit handler
265 // that has a client that is ready to send
266 // something. Otherwise it will end up in
267 // busy wait looping since the packet function
268 // will defer processing (also avoids the
270 if (h
->canIterateClient()) {
271 events
= POLLIN
| POLLPRI
;
272 no_one_to_poll
= false;
274 m_poll_fds_shadow
[i
].events
= events
;
278 debugOutputExtreme(DEBUG_LEVEL_VERBOSE
,
279 "(%p, %s) No one to poll, waiting for something to happen\n",
280 this, (m_handlerType
== IsoHandler::eHT_Transmit
? "Transmit": "Receive"));
281 // wait for something to happen
282 switch(waitForActivity()) {
283 case IsoHandlerManager::IsoTask::eAR_Error
:
284 debugError("Error while waiting for activity\n");
286 case IsoHandlerManager::IsoTask::eAR_Interrupted
:
287 // FIXME: what to do here?
288 debugWarning("Interrupted while waiting for activity\n");
290 case IsoHandlerManager::IsoTask::eAR_Timeout
:
291 // FIXME: what to do here?
292 debugWarning("Timeout while waiting for activity\n");
293 no_one_to_poll
= false; // exit the loop to be able to detect failing handlers
295 case IsoHandlerManager::IsoTask::eAR_Activity
:
297 debugOutputExtreme(DEBUG_LEVEL_VERBOSE
,
298 "(%p, %s) something happened\n",
299 this, (m_handlerType
== IsoHandler::eHT_Transmit
? "Transmit": "Receive"));
305 // Use a shadow map of the fd's such that we don't have to update
306 // the fd map everytime we run poll().
307 err
= poll (m_poll_fds_shadow
, m_poll_nfds_shadow
, m_poll_timeout
);
308 uint32_t ctr_at_poll_return
= m_manager
.get1394Service().getCycleTimer();
311 if (errno
== EINTR
) {
312 debugOutput(DEBUG_LEVEL_VERBOSE
, "Ignoring poll return due to signal\n");
315 debugFatal("poll error: %s\n", strerror (errno
));
320 // find handlers that have died
321 uint64_t ctr_at_poll_return_ticks
= CYCLE_TIMER_TO_TICKS(ctr_at_poll_return
);
322 bool handler_died
= false;
323 for (i
= 0; i
< m_poll_nfds_shadow
; i
++) {
324 // figure out if a handler has died
326 // this is the time of the last packet we saw in the iterate() handler
327 uint32_t last_packet_seen
= m_IsoHandler_map_shadow
[i
]->getLastPacketTime();
328 if (last_packet_seen
== 0xFFFFFFFF) {
329 // this was not iterated yet, so can't be dead
330 debugOutput(DEBUG_LEVEL_VERY_VERBOSE
,
331 "(%p, %s) handler %d didn't see any packets yet\n",
332 this, (m_handlerType
== IsoHandler::eHT_Transmit
? "Transmit": "Receive"), i
);
336 uint64_t last_packet_seen_ticks
= CYCLE_TIMER_TO_TICKS(last_packet_seen
);
337 // we use a relatively large value to distinguish between "death" and xrun
338 int64_t max_diff_ticks
= TICKS_PER_SECOND
* 2;
339 int64_t measured_diff_ticks
= diffTicks(ctr_at_poll_return_ticks
, last_packet_seen_ticks
);
341 debugOutputExtreme(DEBUG_LEVEL_VERBOSE
,
342 "(%p, %s) check handler %d: diff = %"PRId64
", max = %"PRId64
", now: %08X, last: %08X\n",
343 this, (m_handlerType
== IsoHandler::eHT_Transmit
? "Transmit": "Receive"),
344 i
, measured_diff_ticks
, max_diff_ticks
, ctr_at_poll_return
, last_packet_seen
);
345 if(measured_diff_ticks
> max_diff_ticks
) {
346 debugFatal("(%p, %s) Handler died: now: %08X, last: %08X, diff: %"PRId64
" (max: %"PRId64
")\n",
347 this, (m_handlerType
== IsoHandler::eHT_Transmit
? "Transmit": "Receive"),
348 ctr_at_poll_return
, last_packet_seen
, measured_diff_ticks
, max_diff_ticks
);
349 m_IsoHandler_map_shadow
[i
]->notifyOfDeath();
356 return false; // one or more handlers have died
359 // iterate the handlers
360 for (i
= 0; i
< m_poll_nfds_shadow
; i
++) {
362 if(m_poll_fds_shadow
[i
].revents
) {
363 debugOutputExtreme(DEBUG_LEVEL_VERBOSE
,
364 "(%p, %s) received events: %08X for (%d/%d, %p, %s)\n",
365 this, (m_handlerType
== IsoHandler::eHT_Transmit
? "Transmit": "Receive"),
366 m_poll_fds_shadow
[i
].revents
,
367 i
, m_poll_nfds_shadow
,
368 m_IsoHandler_map_shadow
[i
],
369 m_IsoHandler_map_shadow
[i
]->getTypeString());
373 // if we get here, it means two things:
374 // 1) the kernel can accept or provide packets (poll returned POLLIN)
375 // 2) the client can provide or accept packets (since we enabled polling)
376 if(m_poll_fds_shadow
[i
].revents
& (POLLIN
)) {
377 m_IsoHandler_map_shadow
[i
]->iterate(ctr_at_poll_return
);
379 // there might be some error condition
380 if (m_poll_fds_shadow
[i
].revents
& POLLERR
) {
381 debugWarning("(%p) error on fd for %d\n", this, i
);
383 if (m_poll_fds_shadow
[i
].revents
& POLLHUP
) {
384 debugWarning("(%p) hangup on fd for %d\n", this, i
);
391 enum IsoHandlerManager::IsoTask::eActivityResult
392 IsoHandlerManager::IsoTask::waitForActivity()
394 debugOutputExtreme(DEBUG_LEVEL_VERBOSE
,
395 "(%p, %s) waiting for activity\n",
396 this, (m_handlerType
== IsoHandler::eHT_Transmit
? "Transmit": "Receive"));
400 // sem_timedwait() cannot be set up to use any clock rather than
401 // CLOCK_REALTIME. Therefore we get the time from CLOCK_REALTIME here.
402 // Doing this rather than Util::SystemTimeSource::clockGettime() doesn't
403 // pose a problem here because the resulting time is only used with
404 // sem_timedwait() to implement timeout functionality.
405 if (clock_gettime(CLOCK_REALTIME
, &ts
) == -1) {
406 debugError("clock_gettime failed\n");
410 ts
.tv_nsec
+= m_activity_wait_timeout_nsec
;
411 while(ts
.tv_nsec
>= 1000000000LL) {
413 ts
.tv_nsec
-= 1000000000LL;
416 result
= sem_timedwait(&m_activity_semaphore
, &ts
);
419 if (errno
== ETIMEDOUT
) {
420 debugOutput(DEBUG_LEVEL_VERBOSE
,
421 "(%p) sem_timedwait() timed out (result=%d)\n",
424 } else if (errno
== EINTR
) {
425 debugOutput(DEBUG_LEVEL_VERBOSE
,
426 "(%p) sem_timedwait() interrupted by signal (result=%d)\n",
428 return eAR_Interrupted
;
429 } else if (errno
== EINVAL
) {
430 debugError("(%p) sem_timedwait error (result=%d errno=EINVAL)\n",
432 debugError("(%p) timeout_nsec=%lld ts.sec=%"PRId64
" ts.nsec=%"PRId64
"\n",
433 this, m_activity_wait_timeout_nsec
,
434 (int64_t)ts
.tv_sec
, (int64_t)ts
.tv_nsec
);
437 debugError("(%p) sem_timedwait error (result=%d errno=%d)\n",
438 this, result
, errno
);
439 debugError("(%p) timeout_nsec=%lld ts.sec=%"PRId64
" ts.nsec=%"PRId64
"\n",
440 this, m_activity_wait_timeout_nsec
,
441 (int64_t)ts
.tv_sec
, (int64_t)ts
.tv_nsec
);
446 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE
,
447 "(%p, %s) got activity\n",
448 this, (m_handlerType
== IsoHandler::eHT_Transmit
? "Transmit": "Receive"));
453 IsoHandlerManager::IsoTask::signalActivity()
455 // signal the activity cond var
456 sem_post(&m_activity_semaphore
);
457 debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE
,
458 "(%p, %s) activity\n",
459 this, (m_handlerType
== IsoHandler::eHT_Transmit
? "Transmit": "Receive"));
462 void IsoHandlerManager::IsoTask::setVerboseLevel(int i
) {
464 debugOutput( DEBUG_LEVEL_VERBOSE
, "Setting verbose level to %d...\n", i
);
467 // -- the ISO handler manager -- //
468 IsoHandlerManager::IsoHandlerManager(Ieee1394Service
& service
)
470 , m_service( service
)
471 , m_realtime(false), m_priority(0)
472 , m_IsoThreadTransmit ( NULL
)
473 , m_IsoTaskTransmit ( NULL
)
474 , m_IsoThreadReceive ( NULL
)
475 , m_IsoTaskReceive ( NULL
)
479 IsoHandlerManager::IsoHandlerManager(Ieee1394Service
& service
, bool run_rt
, int rt_prio
)
481 , m_service( service
)
482 , m_realtime(run_rt
), m_priority(rt_prio
)
483 , m_IsoThreadTransmit ( NULL
)
484 , m_IsoTaskTransmit ( NULL
)
485 , m_IsoThreadReceive ( NULL
)
486 , m_IsoTaskReceive ( NULL
)
487 , m_MissedCyclesOK ( false )
491 IsoHandlerManager::~IsoHandlerManager()
495 if(m_IsoHandlers
.size() > 0) {
496 debugError("Still some handlers in use\n");
498 if (m_IsoThreadTransmit
) {
499 m_IsoThreadTransmit
->Stop();
500 delete m_IsoThreadTransmit
;
502 if (m_IsoThreadReceive
) {
503 m_IsoThreadReceive
->Stop();
504 delete m_IsoThreadReceive
;
506 if (m_IsoTaskTransmit
) {
507 delete m_IsoTaskTransmit
;
509 if (m_IsoTaskReceive
) {
510 delete m_IsoTaskReceive
;
515 IsoHandlerManager::handleBusReset()
517 debugOutput( DEBUG_LEVEL_NORMAL
, "bus reset...\n");
518 // A few things can happen on bus reset:
519 // 1) no devices added/removed => streams are still valid, but might have to be restarted
520 // 2) a device was removed => some streams become invalid
521 // 3) a device was added => same as 1, new device is ignored
522 if (!m_IsoTaskTransmit
) {
523 debugError("No xmit task\n");
526 if (!m_IsoTaskReceive
) {
527 debugError("No receive task\n");
530 if (!m_IsoTaskTransmit
->handleBusReset()) {
531 debugWarning("could no handle busreset on xmit\n");
533 if (!m_IsoTaskReceive
->handleBusReset()) {
534 debugWarning("could no handle busreset on recv\n");
540 IsoHandlerManager::requestShadowMapUpdate()
542 if(m_IsoTaskTransmit
) m_IsoTaskTransmit
->requestShadowMapUpdate();
543 if(m_IsoTaskReceive
) m_IsoTaskReceive
->requestShadowMapUpdate();
547 IsoHandlerManager::setThreadParameters(bool rt
, int priority
) {
548 debugOutput( DEBUG_LEVEL_VERBOSE
, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt
, priority
);
549 if (priority
> THREAD_MAX_RTPRIO
) priority
= THREAD_MAX_RTPRIO
; // cap the priority
550 if (priority
< THREAD_MIN_RTPRIO
) priority
= THREAD_MIN_RTPRIO
; // cap the priority
552 m_priority
= priority
;
554 // grab the options from the parent
555 Util::Configuration
*config
= m_service
.getConfiguration();
556 int ihm_iso_prio_increase
= ISOHANDLERMANAGER_ISO_PRIO_INCREASE
;
557 int ihm_iso_prio_increase_xmit
= ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT
;
558 int ihm_iso_prio_increase_recv
= ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV
;
560 config
->getValueForSetting("ieee1394.isomanager.prio_increase", ihm_iso_prio_increase
);
561 config
->getValueForSetting("ieee1394.isomanager.prio_increase_xmit", ihm_iso_prio_increase_xmit
);
562 config
->getValueForSetting("ieee1394.isomanager.prio_increase_recv", ihm_iso_prio_increase_recv
);
565 if (m_IsoThreadTransmit
) {
567 m_IsoThreadTransmit
->AcquireRealTime(m_priority
568 + ihm_iso_prio_increase
569 + ihm_iso_prio_increase_xmit
);
571 m_IsoThreadTransmit
->DropRealTime();
574 if (m_IsoThreadReceive
) {
576 m_IsoThreadReceive
->AcquireRealTime(m_priority
577 + ihm_iso_prio_increase
578 + ihm_iso_prio_increase_recv
);
580 m_IsoThreadReceive
->DropRealTime();
587 bool IsoHandlerManager::init()
589 debugOutput( DEBUG_LEVEL_VERBOSE
, "Initializing ISO manager %p...\n", this);
591 if(m_State
!= E_Created
) {
592 debugError("Manager already initialized...\n");
596 // grab the options from the parent
597 Util::Configuration
*config
= m_service
.getConfiguration();
598 int ihm_iso_prio_increase
= ISOHANDLERMANAGER_ISO_PRIO_INCREASE
;
599 int ihm_iso_prio_increase_xmit
= ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT
;
600 int ihm_iso_prio_increase_recv
= ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV
;
601 int64_t isotask_activity_timeout_usecs
= ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS
;
603 config
->getValueForSetting("ieee1394.isomanager.prio_increase", ihm_iso_prio_increase
);
604 config
->getValueForSetting("ieee1394.isomanager.prio_increase_xmit", ihm_iso_prio_increase_xmit
);
605 config
->getValueForSetting("ieee1394.isomanager.prio_increase_recv", ihm_iso_prio_increase_recv
);
606 config
->getValueForSetting("ieee1394.isomanager.isotask_activity_timeout_usecs", isotask_activity_timeout_usecs
);
609 // create threads to iterate our ISO handlers
610 debugOutput( DEBUG_LEVEL_VERBOSE
, "Create iso thread for %p transmit...\n", this);
611 m_IsoTaskTransmit
= new IsoTask( *this, IsoHandler::eHT_Transmit
);
612 if(!m_IsoTaskTransmit
) {
613 debugFatal("No task\n");
616 m_IsoTaskTransmit
->setVerboseLevel(getDebugLevel());
617 m_IsoTaskTransmit
->m_activity_wait_timeout_nsec
= isotask_activity_timeout_usecs
* 1000LL;
618 m_IsoThreadTransmit
= new Util::PosixThread(m_IsoTaskTransmit
, "ISOXMT", m_realtime
,
619 m_priority
+ ihm_iso_prio_increase
620 + ihm_iso_prio_increase_xmit
,
621 PTHREAD_CANCEL_DEFERRED
);
623 if(!m_IsoThreadTransmit
) {
624 debugFatal("No thread\n");
627 m_IsoThreadTransmit
->setVerboseLevel(getDebugLevel());
629 debugOutput( DEBUG_LEVEL_VERBOSE
, "Create iso thread for %p receive...\n", this);
630 m_IsoTaskReceive
= new IsoTask( *this, IsoHandler::eHT_Receive
);
631 if(!m_IsoTaskReceive
) {
632 debugFatal("No task\n");
635 m_IsoTaskReceive
->setVerboseLevel(getDebugLevel());
636 m_IsoThreadReceive
= new Util::PosixThread(m_IsoTaskReceive
, "ISORCV", m_realtime
,
637 m_priority
+ ihm_iso_prio_increase
638 + ihm_iso_prio_increase_recv
,
639 PTHREAD_CANCEL_DEFERRED
);
641 if(!m_IsoThreadReceive
) {
642 debugFatal("No thread\n");
645 m_IsoThreadReceive
->setVerboseLevel(getDebugLevel());
646 // register the thread with the RT watchdog
647 Util::Watchdog
*watchdog
= m_service
.getWatchdog();
649 if(!watchdog
->registerThread(m_IsoThreadTransmit
)) {
650 debugWarning("could not register iso transmit thread with watchdog\n");
652 if(!watchdog
->registerThread(m_IsoThreadReceive
)) {
653 debugWarning("could not register iso receive thread with watchdog\n");
656 debugWarning("could not find valid watchdog\n");
659 if (m_IsoThreadTransmit
->Start() != 0) {
660 debugFatal("Could not start ISO Transmit thread\n");
663 if (m_IsoThreadReceive
->Start() != 0) {
664 debugFatal("Could not start ISO Receive thread\n");
673 IsoHandlerManager::signalActivityTransmit()
675 assert(m_IsoTaskTransmit
);
676 m_IsoTaskTransmit
->signalActivity();
680 IsoHandlerManager::signalActivityReceive()
682 assert(m_IsoTaskReceive
);
683 m_IsoTaskReceive
->signalActivity();
686 bool IsoHandlerManager::registerHandler(IsoHandler
*handler
)
688 debugOutput( DEBUG_LEVEL_VERBOSE
, "enter...\n");
690 handler
->setVerboseLevel(getDebugLevel());
691 m_IsoHandlers
.push_back(handler
);
692 requestShadowMapUpdate();
696 bool IsoHandlerManager::unregisterHandler(IsoHandler
*handler
)
698 debugOutput( DEBUG_LEVEL_VERBOSE
, "enter...\n");
701 for ( IsoHandlerVectorIterator it
= m_IsoHandlers
.begin();
702 it
!= m_IsoHandlers
.end();
705 if ( *it
== handler
) {
706 m_IsoHandlers
.erase(it
);
707 requestShadowMapUpdate();
711 debugFatal("Could not find handler (%p)\n", handler
);
712 return false; //not found
716 * Registers an StreamProcessor with the IsoHandlerManager.
718 * If nescessary, an IsoHandler is created to handle this stream.
719 * Once an StreamProcessor is registered to the handler, it will be included
720 * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
722 * @param stream the stream to register
723 * @return true if registration succeeds
725 * \todo : currently there is a one-to-one mapping
726 * between streams and handlers, this is not ok for
727 * multichannel receive
729 bool IsoHandlerManager::registerStream(StreamProcessor
*stream
)
731 debugOutput( DEBUG_LEVEL_VERBOSE
, "Registering %s stream %p\n", stream
->getTypeString(), stream
);
734 IsoHandler
* h
= NULL
;
736 // make sure the stream isn't already attached to a handler
737 for ( IsoHandlerVectorIterator it
= m_IsoHandlers
.begin();
738 it
!= m_IsoHandlers
.end();
741 if((*it
)->isStreamRegistered(stream
)) {
742 debugError( "stream already registered!\n");
747 // clean up all handlers that aren't used
750 // allocate a handler for this stream
751 if (stream
->getType()==StreamProcessor::ePT_Receive
) {
752 // grab the options from the parent
753 Util::Configuration
*config
= m_service
.getConfiguration();
754 int receive_mode_setting
= DEFAULT_ISO_RECEIVE_MODE
;
755 int bufferfill_mode_threshold
= BUFFERFILL_MODE_THRESHOLD
;
756 int min_interrupts_per_period
= MINIMUM_INTERRUPTS_PER_PERIOD
;
757 int max_nb_buffers_recv
= MAX_RECV_NB_BUFFERS
;
758 int min_packetsize_recv
= MIN_RECV_PACKET_SIZE
;
760 config
->getValueForSetting("ieee1394.isomanager.iso_receive_mode", receive_mode_setting
);
761 config
->getValueForSetting("ieee1394.isomanager.bufferfill_mode_threshold", bufferfill_mode_threshold
);
762 config
->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period
);
763 config
->getValueForSetting("ieee1394.isomanager.max_nb_buffers_recv", max_nb_buffers_recv
);
764 config
->getValueForSetting("ieee1394.isomanager.min_packetsize_recv", min_packetsize_recv
);
767 // setup the optimal parameters for the raw1394 ISO buffering
768 unsigned int packets_per_period
= stream
->getPacketsPerPeriod();
769 // reserve space for the 1394 header too (might not be necessary)
770 unsigned int max_packet_size
= stream
->getMaxPacketSize() + 8;
771 unsigned int page_size
= getpagesize();
773 enum raw1394_iso_dma_recv_mode receive_mode
=
774 RAW1394_DMA_PACKET_PER_BUFFER
;
775 switch(receive_mode_setting
) {
777 if(packets_per_period
< (unsigned)bufferfill_mode_threshold
) {
778 debugOutput( DEBUG_LEVEL_VERBOSE
, "Using packet-per-buffer mode (auto) [%d, %d]\n",
779 packets_per_period
, bufferfill_mode_threshold
);
780 receive_mode
= RAW1394_DMA_PACKET_PER_BUFFER
;
782 debugOutput( DEBUG_LEVEL_VERBOSE
, "Using bufferfill mode (auto) [%d, %d]\n",
783 packets_per_period
, bufferfill_mode_threshold
);
784 receive_mode
= RAW1394_DMA_BUFFERFILL
;
788 debugOutput( DEBUG_LEVEL_VERBOSE
, "Using packet-per-buffer mode (config)\n");
789 receive_mode
= RAW1394_DMA_PACKET_PER_BUFFER
;
792 debugOutput( DEBUG_LEVEL_VERBOSE
, "Using bufferfill mode (config)\n");
793 receive_mode
= RAW1394_DMA_BUFFERFILL
;
795 default: debugWarning("Bogus receive mode setting in config: %d\n", receive_mode_setting
);
798 // Ensure we don't request a packet size bigger than the
799 // kernel-enforced maximum which is currently 1 page.
800 // NOTE: PP: this is not really true AFAICT
801 if (max_packet_size
> page_size
) {
802 debugError("max packet size (%u) > page size (%u)\n", max_packet_size
, page_size
);
805 if (max_packet_size
< (unsigned)min_packetsize_recv
) {
806 debugError("min packet size (%u) < MIN_RECV_PACKET_SIZE (%u), using min value\n",
807 max_packet_size
, min_packetsize_recv
);
808 max_packet_size
= min_packetsize_recv
;
811 // apparently a too small value causes issues too
812 if(max_packet_size
< 200) max_packet_size
= 200;
814 // the interrupt/wakeup interval prediction of raw1394 is a mess...
815 int irq_interval
= (packets_per_period
-1) / min_interrupts_per_period
;
816 if(irq_interval
<= 0) irq_interval
=1;
818 // the receive buffer size doesn't matter for the latency,
819 // it does seem to be confined to a certain region for correct
820 // operation. However it is not clear how many.
821 int buffers
= max_nb_buffers_recv
;
823 // ensure at least 2 hardware interrupts per ISO buffer wraparound
824 if(irq_interval
> buffers
/2) {
825 irq_interval
= buffers
/2;
828 // create the actual handler
829 debugOutput( DEBUG_LEVEL_VERBOSE
, " creating IsoRecvHandler\n");
830 h
= new IsoHandler(*this, IsoHandler::eHT_Receive
,
831 buffers
, max_packet_size
, irq_interval
);
834 debugFatal("Could not create IsoRecvHandler\n");
838 h
->setReceiveMode(receive_mode
);
840 } else if (stream
->getType()==StreamProcessor::ePT_Transmit
) {
841 // grab the options from the parent
842 Util::Configuration
*config
= m_service
.getConfiguration();
843 int min_interrupts_per_period
= MINIMUM_INTERRUPTS_PER_PERIOD
;
844 int max_nb_buffers_xmit
= MAX_XMIT_NB_BUFFERS
;
845 int max_packetsize_xmit
= MAX_XMIT_PACKET_SIZE
;
846 int min_packetsize_xmit
= MIN_XMIT_PACKET_SIZE
;
848 config
->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period
);
849 config
->getValueForSetting("ieee1394.isomanager.max_nb_buffers_xmit", max_nb_buffers_xmit
);
850 config
->getValueForSetting("ieee1394.isomanager.max_packetsize_xmit", max_packetsize_xmit
);
851 config
->getValueForSetting("ieee1394.isomanager.min_packetsize_xmit", min_packetsize_xmit
);
854 // setup the optimal parameters for the raw1394 ISO buffering
855 // reserve space for the 1394 header too (might not be necessary)
856 unsigned int max_packet_size
= stream
->getMaxPacketSize() + 8;
858 if (max_packet_size
> (unsigned)max_packetsize_xmit
) {
859 debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n",
860 max_packet_size
, max_packetsize_xmit
);
863 if (max_packet_size
< (unsigned)min_packetsize_xmit
) {
864 debugError("min packet size (%u) < MIN_XMIT_PACKET_SIZE (%u), using min value\n",
865 max_packet_size
, min_packetsize_xmit
);
866 max_packet_size
= min_packetsize_xmit
;
869 int buffers
= max_nb_buffers_xmit
;
870 unsigned int packets_per_period
= stream
->getPacketsPerPeriod();
872 int irq_interval
= (packets_per_period
-1) / min_interrupts_per_period
;
873 if(irq_interval
<= 0) irq_interval
=1;
874 // ensure at least 2 hardware interrupts per ISO buffer wraparound
875 if(irq_interval
> buffers
/2) {
876 irq_interval
= buffers
/2;
879 debugOutput( DEBUG_LEVEL_VERBOSE
, " creating IsoXmitHandler\n");
881 // create the actual handler
882 h
= new IsoHandler(*this, IsoHandler::eHT_Transmit
,
883 buffers
, max_packet_size
, irq_interval
);
886 debugFatal("Could not create IsoXmitHandler\n");
891 debugFatal("Bad stream type\n");
895 h
->setVerboseLevel(getDebugLevel());
897 // register the stream with the handler
898 if(!h
->registerStream(stream
)) {
899 debugFatal("Could not register receive stream with handler\n");
903 // register the handler with the manager
904 if(!registerHandler(h
)) {
905 debugFatal("Could not register receive handler with manager\n");
908 debugOutput( DEBUG_LEVEL_VERBOSE
, " registered stream (%p) with handler (%p)\n", stream
, h
);
910 m_StreamProcessors
.push_back(stream
);
911 debugOutput( DEBUG_LEVEL_VERBOSE
, " %zd streams, %zd handlers registered\n",
912 m_StreamProcessors
.size(), m_IsoHandlers
.size());
916 bool IsoHandlerManager::unregisterStream(StreamProcessor
*stream
)
918 debugOutput( DEBUG_LEVEL_VERBOSE
, "Unregistering %s stream %p\n", stream
->getTypeString(), stream
);
921 // make sure the stream isn't attached to a handler anymore
922 for ( IsoHandlerVectorIterator it
= m_IsoHandlers
.begin();
923 it
!= m_IsoHandlers
.end();
926 if((*it
)->isStreamRegistered(stream
)) {
927 if(!(*it
)->unregisterStream(stream
)) {
928 debugOutput( DEBUG_LEVEL_VERBOSE
, " could not unregister stream (%p) from handler (%p)...\n",stream
,*it
);
931 debugOutput( DEBUG_LEVEL_VERBOSE
, " unregistered stream (%p) from handler (%p)...\n",stream
,*it
);
935 // clean up all handlers that aren't used
938 // remove the stream from the registered streams list
939 for ( StreamProcessorVectorIterator it
= m_StreamProcessors
.begin();
940 it
!= m_StreamProcessors
.end();
943 if ( *it
== stream
) {
944 m_StreamProcessors
.erase(it
);
945 debugOutput( DEBUG_LEVEL_VERBOSE
, " deleted stream (%p) from list...\n", *it
);
949 return false; //not found
953 * @brief unregister a handler from the manager
954 * @note called without the lock held.
956 void IsoHandlerManager::pruneHandlers() {
957 debugOutput( DEBUG_LEVEL_VERBOSE
, "enter...\n");
958 IsoHandlerVector toUnregister
;
960 // find all handlers that are not in use
961 for ( IsoHandlerVectorIterator it
= m_IsoHandlers
.begin();
962 it
!= m_IsoHandlers
.end();
965 if(!((*it
)->inUse())) {
966 debugOutput( DEBUG_LEVEL_VERBOSE
, " handler (%p) not in use\n",*it
);
967 toUnregister
.push_back(*it
);
971 for ( IsoHandlerVectorIterator it
= toUnregister
.begin();
972 it
!= toUnregister
.end();
975 unregisterHandler(*it
);
977 debugOutput( DEBUG_LEVEL_VERBOSE
, " deleting handler (%p)\n",*it
);
979 // Now the handler's been unregistered it won't be reused
980 // again. Therefore it really needs to be formally deleted
981 // to free up the raw1394 handle. Otherwise things fall
982 // apart after several xrun recoveries as the system runs
983 // out of resources to support all the disused but still
984 // allocated raw1394 handles. At least this is the current
985 // theory as to why we end up with "memory allocation"
986 // failures after several Xrun recoveries.
992 IsoHandlerManager::getPacketLatencyForStream(Streaming::StreamProcessor
*stream
) {
993 for ( IsoHandlerVectorIterator it
= m_IsoHandlers
.begin();
994 it
!= m_IsoHandlers
.end();
997 if((*it
)->isStreamRegistered(stream
)) {
998 return (*it
)->getIrqInterval();
1001 debugError("Stream %p has no attached handler\n", stream
);
1005 IsoHandlerManager::IsoHandler
*
1006 IsoHandlerManager::getHandlerForStream(Streaming::StreamProcessor
*stream
) {
1007 for ( IsoHandlerVectorIterator it
= m_IsoHandlers
.begin();
1008 it
!= m_IsoHandlers
.end();
1011 if((*it
)->isStreamRegistered(stream
)) {
1015 debugError("Stream %p has no attached handler\n", stream
);
1020 IsoHandlerManager::dumpInfoForStream(Streaming::StreamProcessor
*stream
)
1022 IsoHandler
*h
= getHandlerForStream(stream
);
1025 debugOutputShort( DEBUG_LEVEL_NORMAL
, " Packets, Dropped, Skipped : %d, %d, %d\n",
1026 h
->m_packets
, h
->m_dropped
, h
->m_skipped
);
1028 debugOutputShort( DEBUG_LEVEL_NORMAL
, " Packets : %d\n", h
->m_packets
);
1031 debugError("No handler for stream %p??\n", stream
);
1035 void IsoHandlerManager::setIsoStartCycleForStream(Streaming::StreamProcessor
*stream
, signed int cycle
) {
1036 // Permit the direct manipulation of the m_switch_on_cycle field from
1037 // the stream's handler. This is usually used to set it to -1 so the
1038 // kernel (at least with the ieee1394 stack) starts the streaming as
1039 // soon as possible, something that is required for some interfaces (eg:
1040 // RME). Note that as of 20 Dec 2010 it seems that ordinarily
1041 // m_switch_on_cycle remains fixed at 0 (its initialised value) because
1042 // requestEnable() doesn't set it. This allows the override configured
1043 // by this function to take effect.
1044 IsoHandler
*h
= getHandlerForStream(stream
);
1045 h
->setIsoStartCycle(cycle
);
1049 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor
*stream
) {
1050 return startHandlerForStream(stream
, -1);
1054 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor
*stream
, int cycle
) {
1056 if(m_State
!= E_Running
) {
1057 debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State
));
1060 for ( IsoHandlerVectorIterator it
= m_IsoHandlers
.begin();
1061 it
!= m_IsoHandlers
.end();
1064 if((*it
)->isStreamRegistered(stream
)) {
1065 debugOutput( DEBUG_LEVEL_VERBOSE
, " starting handler %p for stream %p\n", *it
, stream
);
1066 if(!(*it
)->requestEnable(cycle
)) {
1067 debugOutput( DEBUG_LEVEL_VERBOSE
, " could not request enable for handler %p)\n",*it
);
1071 if((*it
)->getType() == IsoHandler::eHT_Transmit
) {
1072 m_IsoTaskTransmit
->requestShadowMapUpdate();
1074 m_IsoTaskReceive
->requestShadowMapUpdate();
1077 debugOutput(DEBUG_LEVEL_VERY_VERBOSE
, " requested enable for handler %p\n", *it
);
1081 debugError("Stream %p has no attached handler\n", stream
);
1086 IsoHandlerManager::stopHandlerForStream(Streaming::StreamProcessor
*stream
) {
1088 if(m_State
!= E_Running
) {
1089 debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State
));
1092 for ( IsoHandlerVectorIterator it
= m_IsoHandlers
.begin();
1093 it
!= m_IsoHandlers
.end();
1096 if((*it
)->isStreamRegistered(stream
)) {
1097 debugOutput( DEBUG_LEVEL_VERBOSE
, " stopping handler %p for stream %p\n", *it
, stream
);
1098 if(!(*it
)->requestDisable()) {
1099 debugOutput( DEBUG_LEVEL_VERBOSE
, " could not request disable for handler %p\n",*it
);
1103 if((*it
)->getType() == IsoHandler::eHT_Transmit
) {
1104 m_IsoTaskTransmit
->requestShadowMapUpdate();
1106 m_IsoTaskReceive
->requestShadowMapUpdate();
1109 debugOutput(DEBUG_LEVEL_VERBOSE
, " requested disable for handler %p\n", *it
);
1113 debugError("Stream %p has no attached handler\n", stream
);
1117 bool IsoHandlerManager::stopHandlers() {
1118 debugOutput( DEBUG_LEVEL_VERBOSE
, "enter...\n");
1121 if(m_State
!= E_Running
) {
1122 debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State
));
1128 for ( IsoHandlerVectorIterator it
= m_IsoHandlers
.begin();
1129 it
!= m_IsoHandlers
.end();
1132 debugOutput( DEBUG_LEVEL_VERBOSE
, "Stopping handler (%p)\n",*it
);
1134 if(!(*it
)->requestDisable()) {
1135 debugOutput( DEBUG_LEVEL_VERBOSE
, " could not request disable for handler %p\n",*it
);
1139 if((*it
)->getType() == IsoHandler::eHT_Transmit
) {
1140 m_IsoTaskTransmit
->requestShadowMapUpdate();
1142 m_IsoTaskReceive
->requestShadowMapUpdate();
1145 debugOutput(DEBUG_LEVEL_VERBOSE
, " requested disable for handler %p\n", *it
);
1156 bool IsoHandlerManager::reset() {
1157 debugOutput( DEBUG_LEVEL_VERBOSE
, "enter...\n");
1159 if(m_State
== E_Error
) {
1160 debugFatal("Resetting from error condition not yet supported...\n");
1163 // if not in an error condition, reset means stop the handlers
1164 return stopHandlers();
1167 void IsoHandlerManager::setVerboseLevel(int i
) {
1169 // propagate the debug level
1170 for ( IsoHandlerVectorIterator it
= m_IsoHandlers
.begin();
1171 it
!= m_IsoHandlers
.end();
1174 (*it
)->setVerboseLevel(i
);
1176 if(m_IsoThreadTransmit
) m_IsoThreadTransmit
->setVerboseLevel(i
);
1177 if(m_IsoTaskTransmit
) m_IsoTaskTransmit
->setVerboseLevel(i
);
1178 if(m_IsoThreadReceive
) m_IsoThreadReceive
->setVerboseLevel(i
);
1179 if(m_IsoTaskReceive
) m_IsoTaskReceive
->setVerboseLevel(i
);
1181 debugOutput( DEBUG_LEVEL_VERBOSE
, "Setting verbose level to %d...\n", i
);
1184 void IsoHandlerManager::dumpInfo() {
1187 debugOutputShort( DEBUG_LEVEL_NORMAL
, "Dumping IsoHandlerManager Stream handler information...\n");
1188 debugOutputShort( DEBUG_LEVEL_NORMAL
, " State: %d\n",(int)m_State
);
1190 for ( IsoHandlerVectorIterator it
= m_IsoHandlers
.begin();
1191 it
!= m_IsoHandlers
.end();
1194 debugOutputShort( DEBUG_LEVEL_NORMAL
, " IsoHandler %d (%p)\n",i
++,*it
);
1201 IsoHandlerManager::eHSToString(enum eHandlerStates s
) {
1203 default: return "Invalid";
1204 case E_Created
: return "Created";
1205 case E_Prepared
: return "Prepared";
1206 case E_Running
: return "Running";
1207 case E_Error
: return "Error";
1214 /* the C callbacks */
1215 enum raw1394_iso_disposition
1216 IsoHandlerManager::IsoHandler::iso_transmit_handler(raw1394handle_t handle
,
1217 unsigned char *data
, unsigned int *length
,
1218 unsigned char *tag
, unsigned char *sy
,
1219 int cycle
, unsigned int dropped1
) {
1221 IsoHandler
*xmitHandler
= static_cast<IsoHandler
*>(raw1394_get_userdata(handle
));
1222 assert(xmitHandler
);
1223 unsigned int skipped
= (dropped1
& 0xFFFF0000) >> 16;
1224 unsigned int dropped
= dropped1
& 0xFFFF;
1225 return xmitHandler
->getPacket(data
, length
, tag
, sy
, cycle
, dropped
, skipped
);
1228 enum raw1394_iso_disposition
1229 IsoHandlerManager::IsoHandler::iso_receive_handler(raw1394handle_t handle
, unsigned char *data
,
1230 unsigned int length
, unsigned char channel
,
1231 unsigned char tag
, unsigned char sy
, unsigned int cycle
,
1232 unsigned int dropped
) {
1234 IsoHandler
*recvHandler
= static_cast<IsoHandler
*>(raw1394_get_userdata(handle
));
1235 assert(recvHandler
);
1237 return recvHandler
->putPacket(data
, length
, channel
, tag
, sy
, cycle
, dropped
);
1240 IsoHandlerManager::IsoHandler::IsoHandler(IsoHandlerManager
& manager
, enum EHandlerType t
)
1241 : m_manager( manager
)
1244 , m_buf_packets( 400 )
1245 , m_max_packet_size( 1024 )
1246 , m_irq_interval( -1 )
1247 , m_last_cycle( -1 )
1248 , m_last_now( 0xFFFFFFFF )
1249 , m_last_packet_handled_at( 0xFFFFFFFF )
1250 , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER
)
1252 , m_speed( RAW1394_ISO_SPEED_400
)
1253 , m_State( eHS_Stopped
)
1254 , m_NextState( eHS_Stopped
)
1255 , m_switch_on_cycle(0)
1260 , m_min_ahead( 7999 )
1263 pthread_mutex_init(&m_disable_lock
, NULL
);
1266 IsoHandlerManager::IsoHandler::IsoHandler(IsoHandlerManager
& manager
, enum EHandlerType t
,
1267 unsigned int buf_packets
, unsigned int max_packet_size
, int irq
)
1268 : m_manager( manager
)
1271 , m_buf_packets( buf_packets
)
1272 , m_max_packet_size( max_packet_size
)
1273 , m_irq_interval( irq
)
1274 , m_last_cycle( -1 )
1275 , m_last_now( 0xFFFFFFFF )
1276 , m_last_packet_handled_at( 0xFFFFFFFF )
1277 , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER
)
1279 , m_speed( RAW1394_ISO_SPEED_400
)
1280 , m_State( eHS_Stopped
)
1281 , m_NextState( eHS_Stopped
)
1282 , m_switch_on_cycle(0)
1287 , m_min_ahead( 7999 )
1290 pthread_mutex_init(&m_disable_lock
, NULL
);
1293 IsoHandlerManager::IsoHandler::IsoHandler(IsoHandlerManager
& manager
, enum EHandlerType t
, unsigned int buf_packets
,
1294 unsigned int max_packet_size
, int irq
,
1295 enum raw1394_iso_speed speed
)
1296 : m_manager( manager
)
1299 , m_buf_packets( buf_packets
)
1300 , m_max_packet_size( max_packet_size
)
1301 , m_irq_interval( irq
)
1302 , m_last_cycle( -1 )
1303 , m_last_now( 0xFFFFFFFF )
1304 , m_last_packet_handled_at( 0xFFFFFFFF )
1305 , m_receive_mode ( RAW1394_DMA_PACKET_PER_BUFFER
)
1308 , m_State( eHS_Stopped
)
1309 , m_NextState( eHS_Stopped
)
1310 , m_switch_on_cycle(0)
1315 , m_min_ahead( 7999 )
1317 , m_deferred_cycles( 0 )
1319 pthread_mutex_init(&m_disable_lock
, NULL
);
1322 IsoHandlerManager::IsoHandler::~IsoHandler() {
1323 // Don't call until libraw1394's raw1394_new_handle() function has been
1324 // fixed to correctly initialise the iso_packet_infos field. Bug is
1325 // confirmed present in libraw1394 1.2.1. In any case,
1326 // raw1394_destroy_handle() will do any iso system shutdown required.
1327 // raw1394_iso_shutdown(m_handle);
1329 // Typically, by the time this function is called the IsoTask thread would
1330 // have called disable() on the handler (in the FW_ISORCV/FW_ISOXMT
1331 // threads). However, the raw1394_destroy_handle() call therein takes
1332 // upwards of 20 milliseconds to complete under the new kernel firewire
1333 // stack, and may not have completed by the time ~IsoHandler() is called by
1334 // the "jackd" thread. Thus, wait for the lock before testing the state
1335 // of the handle so any in-progress disable() is complete.
1336 if (pthread_mutex_trylock(&m_disable_lock
) == EBUSY
) {
1337 debugOutput(DEBUG_LEVEL_VERBOSE
, "waiting for disable lock\n");
1338 pthread_mutex_lock(&m_disable_lock
);
1340 pthread_mutex_unlock(&m_disable_lock
);
1342 if (m_State
== eHS_Running
) {
1343 debugError("BUG: Handler still running!\n");
1347 pthread_mutex_destroy(&m_disable_lock
);
1351 IsoHandlerManager::IsoHandler::canIterateClient()
1353 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE
, "checking...\n");
1357 if (m_type
== eHT_Receive
) {
1358 result
= m_Client
->canProducePacket();
1360 result
= m_Client
->canConsumePacket();
1362 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE
, " returns %d\n", result
);
1363 return result
&& (m_State
!= eHS_Error
);
1365 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE
, " no client\n");
1371 IsoHandlerManager::IsoHandler::iterate() {
1372 return iterate(m_manager
.get1394Service().getCycleTimer());
1376 IsoHandlerManager::IsoHandler::iterate(uint32_t cycle_timer_now
) {
1377 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE
, "(%p, %s) Iterating ISO handler at %08X...\n",
1378 this, getTypeString(), cycle_timer_now
);
1379 m_last_now
= cycle_timer_now
;
1380 if(m_State
== eHS_Running
) {
1383 #if ISOHANDLER_FLUSH_BEFORE_ITERATE
1384 // this flushes all packets received since the poll() returned
1385 // from kernel to userspace such that they are processed by this
1386 // iterate. Doing so might result in lower latency capability
1387 // and/or better reliability
1388 if(m_type
== eHT_Receive
) {
1389 raw1394_iso_recv_flush(m_handle
);
1393 if(raw1394_loop_iterate(m_handle
)) {
1394 debugError( "IsoHandler (%p): Failed to iterate handler: %s\n",
1395 this, strerror(errno
));
1398 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE
, "(%p, %s) done interating ISO handler...\n",
1399 this, getTypeString());
1402 debugOutput(DEBUG_LEVEL_VERBOSE
, "(%p, %s) Not iterating a non-running handler...\n",
1403 this, getTypeString());
1415 IsoHandlerManager::IsoHandler::handleBusReset()
1417 debugOutput( DEBUG_LEVEL_NORMAL
, "bus reset...\n");
1418 m_last_packet_handled_at
= 0xFFFFFFFF;
1420 #define CSR_CYCLE_TIME 0x200
1421 #define CSR_REGISTER_BASE 0xfffff0000000ULL
1422 // do a simple read on ourself in order to update the internal structures
1423 // this avoids read failures after a bus reset
1425 raw1394_read(m_handle
, raw1394_get_local_id(m_handle
),
1426 CSR_REGISTER_BASE
| CSR_CYCLE_TIME
, 4, &buf
);
1428 return m_Client
->handleBusReset();
1432 * Call this if you find out that this handler has died for some
1436 IsoHandlerManager::IsoHandler::notifyOfDeath()
1438 m_State
= eHS_Error
;
1439 m_NextState
= eHS_Error
;
1441 // notify the client of the fact that we have died
1442 m_Client
->handlerDied();
1444 // wake ourselves up
1445 if(m_handle
) raw1394_wake_up(m_handle
);
1448 void IsoHandlerManager::IsoHandler::dumpInfo()
1451 if (m_Client
) channel
=m_Client
->getChannel();
1453 debugOutputShort( DEBUG_LEVEL_NORMAL
, " Handler type................: %s\n",
1455 debugOutputShort( DEBUG_LEVEL_NORMAL
, " Port, Channel...............: %2d, %2d\n",
1456 m_manager
.get1394Service().getPort(), channel
);
1457 debugOutputShort( DEBUG_LEVEL_NORMAL
, " Buffer, MaxPacketSize, IRQ..: %4d, %4d, %4d\n",
1458 m_buf_packets
, m_max_packet_size
, m_irq_interval
);
1459 if (this->getType() == eHT_Transmit
) {
1460 debugOutputShort( DEBUG_LEVEL_NORMAL
, " Speed ..................: %2d\n",
1463 debugOutputShort( DEBUG_LEVEL_NORMAL
, " Min ISOXMT bufferfill : %04d\n", m_min_ahead
);
1467 debugOutputShort( DEBUG_LEVEL_NORMAL
, " Last cycle, dropped.........: %4d, %4u, %4u\n",
1468 m_last_cycle
, m_dropped
, m_skipped
);
1473 void IsoHandlerManager::IsoHandler::setVerboseLevel(int l
)
1476 debugOutput( DEBUG_LEVEL_VERBOSE
, "Setting verbose level to %d...\n", l
);
1479 bool IsoHandlerManager::IsoHandler::registerStream(StreamProcessor
*stream
)
1482 debugOutput( DEBUG_LEVEL_VERBOSE
, "registering stream (%p)\n", stream
);
1485 debugFatal( "Generic IsoHandlers can have only one client\n");
1492 bool IsoHandlerManager::IsoHandler::unregisterStream(StreamProcessor
*stream
)
1495 debugOutput( DEBUG_LEVEL_VERBOSE
, "unregistering stream (%p)\n", stream
);
1497 if(stream
!= m_Client
) {
1498 debugFatal( "no client registered\n");
1505 // ISO packet interface
1506 enum raw1394_iso_disposition
IsoHandlerManager::IsoHandler::putPacket(
1507 unsigned char *data
, unsigned int length
,
1508 unsigned char channel
, unsigned char tag
, unsigned char sy
,
1509 unsigned int cycle
, unsigned int dropped
) {
1510 // keep track of dropped cycles
1511 int dropped_cycles
= 0;
1512 if (m_last_cycle
!= (int)cycle
&& m_last_cycle
!= -1 && m_manager
.m_MissedCyclesOK
== false) {
1513 dropped_cycles
= diffCycles(cycle
, m_last_cycle
) - 1;
1515 if (dropped_cycles
< 0) {
1516 debugWarning("(%p) dropped < 1 (%d), cycle: %d, last_cycle: %d, dropped: %d\n",
1517 this, dropped_cycles
, cycle
, m_last_cycle
, dropped
);
1519 if (dropped_cycles
> 0) {
1520 debugOutput(DEBUG_LEVEL_VERBOSE
,
1521 "(%p) dropped %d packets on cycle %u, 'dropped'=%u, cycle=%d, m_last_cycle=%d\n",
1522 this, dropped_cycles
, cycle
, dropped
, cycle
, m_last_cycle
);
1523 m_dropped
+= dropped_cycles
;
1527 m_last_cycle
= cycle
;
1529 // the m_last_now value is set when the iterate() function is called.
1530 uint32_t now_cycles
= CYCLE_TIMER_GET_CYCLES(m_last_now
);
1532 // two cases can occur:
1533 // (1) this packet has been received before iterate() was called (normal case).
1534 // (2) this packet has been received after iterate() was called.
1535 // happens when the kernel flushes more packets while we are already processing.
1537 // In case (1) now_cycles is a small number of cycles larger than cycle. In
1538 // case (2) now_cycles is a small number of cycles smaller than cycle.
1539 // hence abs(diffCycles(now_cycles, cycles)) has to be 'small'
1541 // we can calculate the time of arrival for this packet as
1542 // 'now' + diffCycles(cycles, now_cycles) * TICKS_PER_CYCLE
1543 // in its properly wrapped version
1544 int64_t diff_cycles
= diffCycles(cycle
, now_cycles
);
1545 int64_t tmp
= CYCLE_TIMER_TO_TICKS(m_last_now
);
1546 tmp
+= diff_cycles
* (int64_t)TICKS_PER_CYCLE
;
1547 uint64_t pkt_ctr_ticks
= wrapAtMinMaxTicks(tmp
);
1548 uint32_t pkt_ctr
= TICKS_TO_CYCLE_TIMER(pkt_ctr_ticks
);
1550 if( (now_cycles
< cycle
)
1551 && diffCycles(now_cycles
, cycle
) < 0
1552 // ignore this on dropped cycles, since it's normal
1553 // that now is ahead on the received packets (as we miss packets)
1554 && dropped_cycles
== 0)
1556 debugOutput(DEBUG_LEVEL_VERY_VERBOSE
, "Special non-unwrapping happened\n");
1560 #if ISOHANDLER_CHECK_CTR_RECONSTRUCTION
1561 // add a seconds field
1562 uint32_t now
= m_manager
.get1394Service().getCycleTimer();
1563 uint32_t now_secs_ref
= CYCLE_TIMER_GET_SECS(now
);
1564 // causality results in the fact that 'now' is always after 'cycle'
1565 // or at best, equal (if this handler was called within 125us after
1566 // the packet was on the wire).
1567 if(CYCLE_TIMER_GET_CYCLES(now
) < cycle
) {
1568 // the cycle field has wrapped, substract one second
1569 if(now_secs_ref
== 0) {
1575 uint32_t pkt_ctr_ref
= cycle
<< 12;
1576 pkt_ctr_ref
|= (now_secs_ref
& 0x7F) << 25;
1578 if((pkt_ctr
& ~0x0FFFL
) != pkt_ctr_ref
) {
1579 debugWarning("reconstructed CTR counter discrepancy\n");
1580 debugWarning(" ingredients: %X, %X, %X, %X, %X, %d, %ld, %ld, %"PRId64
"\n",
1581 cycle
, pkt_ctr_ref
, pkt_ctr
,
1582 now
, m_last_now
, now_secs_ref
,
1583 (long int)CYCLE_TIMER_GET_SECS(now
),
1584 (long int)CYCLE_TIMER_GET_SECS(m_last_now
),
1586 debugWarning(" diffcy = %"PRId64
" \n", diff_cycles
);
1589 m_last_packet_handled_at
= pkt_ctr
;
1591 // leave the offset field (for now?)
1593 debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE
,
1594 "received packet: length=%d, channel=%d, cycle=%d, at %08X\n",
1595 length
, channel
, cycle
, pkt_ctr
);
1598 if (length
> m_max_packet_size
) {
1599 debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
1600 this, getTypeString(), length
, m_max_packet_size
);
1602 if(m_last_cycle
== -1) {
1603 debugOutput(DEBUG_LEVEL_VERBOSE
, "Handler for %s SP %p is alive (cycle = %u)\n", getTypeString(), this, cycle
);
1607 // iterate the client if required
1609 return m_Client
->putPacket(data
, length
, channel
, tag
, sy
, pkt_ctr
, dropped_cycles
);
1611 return RAW1394_ISO_OK
;
1614 enum raw1394_iso_disposition
1615 IsoHandlerManager::IsoHandler::getPacket(unsigned char *data
, unsigned int *length
,
1616 unsigned char *tag
, unsigned char *sy
,
1617 int cycle
, unsigned int dropped
, unsigned int skipped
) {
1622 pkt_ctr
= 0xFFFFFFFF;
1624 // the m_last_now value is set when the iterate() function is called.
1625 uint32_t now_cycles
= CYCLE_TIMER_GET_CYCLES(m_last_now
);
1627 // two cases can occur:
1628 // (1) this packet has been received before iterate() was called (normal case).
1629 // (2) this packet has been received after iterate() was called.
1630 // happens when the kernel flushes more packets while we are already processing.
1632 // In case (1) now_cycles is a small number of cycles larger than cycle. In
1633 // case (2) now_cycles is a small number of cycles smaller than cycle.
1634 // hence abs(diffCycles(now_cycles, cycles)) has to be 'small'
1636 // we can calculate the time of arrival for this packet as
1637 // 'now' + diffCycles(cycles, now_cycles) * TICKS_PER_CYCLE
1638 // in its properly wrapped version
1639 int64_t diff_cycles
= diffCycles(cycle
, now_cycles
);
1640 int64_t tmp
= CYCLE_TIMER_TO_TICKS(m_last_now
);
1641 tmp
+= diff_cycles
* (int64_t)TICKS_PER_CYCLE
;
1642 uint64_t pkt_ctr_ticks
= wrapAtMinMaxTicks(tmp
);
1643 pkt_ctr
= TICKS_TO_CYCLE_TIMER(pkt_ctr_ticks
);
1645 //debugOutput(DEBUG_LEVEL_VERBOSE, "cy=%d, now_cy=%d, diff_cy=%lld, tmp=%lld, pkt_ctr_ticks=%lld, pkt_ctr=%d\n",
1646 // cycle, now_cycles, diff_cycles, tmp, pkt_ctr_ticks, pkt_ctr);
1647 #if ISOHANDLER_CHECK_CTR_RECONSTRUCTION
1648 // add a seconds field
1649 uint32_t now
= m_manager
.get1394Service().getCycleTimer();
1650 uint32_t now_secs_ref
= CYCLE_TIMER_GET_SECS(now
);
1651 // causality results in the fact that 'now' is always after 'cycle'
1652 if(CYCLE_TIMER_GET_CYCLES(now
) > (unsigned int)cycle
) {
1653 // the cycle field has wrapped, add one second
1655 // no need for this:
1656 if(now_secs_ref
== 128) {
1660 uint32_t pkt_ctr_ref
= cycle
<< 12;
1661 pkt_ctr_ref
|= (now_secs_ref
& 0x7F) << 25;
1663 if(((pkt_ctr
& ~0x0FFFL
) != pkt_ctr_ref
) && (m_packets
> m_buf_packets
)) {
1664 debugWarning("reconstructed CTR counter discrepancy\n");
1665 debugWarning(" ingredients: %X, %X, %X, %X, %X, %d, %ld, %ld, %"PRId64
"\n",
1666 cycle
, pkt_ctr_ref
, pkt_ctr
,
1667 now
, m_last_now
, now_secs_ref
,
1668 (long int)CYCLE_TIMER_GET_SECS(now
),
1669 (long int)CYCLE_TIMER_GET_SECS(m_last_now
),
1671 debugWarning(" diffcy = %"PRId64
" \n", diff_cycles
);
1675 if (m_packets
< m_buf_packets
) { // these are still prebuffer packets
1676 m_last_packet_handled_at
= 0xFFFFFFFF;
1678 m_last_packet_handled_at
= pkt_ctr
;
1680 debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE
,
1681 "sending packet: length=%d, cycle=%d, at %08X\n",
1682 *length
, cycle
, pkt_ctr
);
1687 if(m_last_cycle
== -1) {
1688 debugOutput(DEBUG_LEVEL_VERBOSE
, "Handler for %s SP %p is alive. cycle=%d state=%i\n", getTypeString(), this, cycle
, m_State
);
1692 if (m_last_cycle
== -1)
1693 m_deferred_cycles
= 0;
1695 // keep track of dropped cycles
1696 int dropped_cycles
= 0;
1697 if (m_last_cycle
!= cycle
&& m_last_cycle
!= -1) {
1698 dropped_cycles
= diffCycles(cycle
, m_last_cycle
) - 1;
1699 // correct for skipped packets
1700 // since those are not dropped, but only delayed
1701 dropped_cycles
-= skipped
;
1703 // Correct for cycles previously seen but deferred
1704 if (dropped_cycles
== 0)
1705 m_deferred_cycles
= 0;
1707 dropped_cycles
-= m_deferred_cycles
;
1711 debugOutput(DEBUG_LEVEL_VERY_VERBOSE
,
1712 "(%p) skipped %d cycles, cycle: %d, last_cycle: %d, dropped: %d\n",
1713 this, skipped
, cycle
, m_last_cycle
, dropped
);
1714 m_skipped
+= skipped
;
1716 if (dropped_cycles
< 0) {
1717 debugWarning("(%p) dropped < 1 (%d), cycle: %d, last_cycle: %d, dropped: %d, skipped: %d\n",
1718 this, dropped_cycles
, cycle
, m_last_cycle
, dropped
, skipped
);
1720 if (dropped_cycles
> 0) {
1721 debugOutput(DEBUG_LEVEL_VERBOSE
,
1722 "(%p) dropped %d packets on cycle %u (last_cycle=%u, dropped=%d, skipped: %d)\n",
1723 this, dropped_cycles
, cycle
, m_last_cycle
, dropped
, skipped
);
1724 m_dropped
+= dropped_cycles
- skipped
;
1730 // if (cycle >= 0) {
1731 // int ahead = diffCycles(cycle, now_cycles);
1732 // if (ahead < m_min_ahead) m_min_ahead = ahead;
1736 debugOutput(DEBUG_LEVEL_VERBOSE
,
1737 "(%p) OHCI issue on cycle %u (dropped_cycles=%d, last_cycle=%u, dropped=%d, skipped: %d)\n",
1738 this, cycle
, dropped_cycles
, m_last_cycle
, dropped
, skipped
);
1743 enum raw1394_iso_disposition retval
;
1744 retval
= m_Client
->getPacket(data
, length
, tag
, sy
, pkt_ctr
, dropped_cycles
, skipped
, m_max_packet_size
);
1746 if (*length
> m_max_packet_size
) {
1747 debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
1748 this, getTypeString(), *length
, m_max_packet_size
);
1752 if (retval
!=RAW1394_ISO_DEFER
&& retval
!=RAW1394_ISO_AGAIN
) {
1753 m_last_cycle
= cycle
;
1755 m_deferred_cycles
++;
1761 m_last_cycle
= cycle
;
1766 return RAW1394_ISO_OK
;
1770 IsoHandlerManager::IsoHandler::enable(int cycle
)
1772 debugOutput( DEBUG_LEVEL_VERBOSE
, "start on cycle %d\n", cycle
);
1775 if(m_State
!= eHS_Stopped
) {
1776 debugError("Incorrect state, expected eHS_Stopped, got %d\n",(int)m_State
);
1780 assert(m_handle
== NULL
);
1782 // create a handle for the ISO traffic
1783 m_handle
= raw1394_new_handle_on_port( m_manager
.get1394Service().getPort() );
1786 debugError("libraw1394 not compatible\n");
1788 debugError("Could not get 1394 handle: %s\n", strerror(errno
) );
1789 debugError("Are ieee1394 and raw1394 drivers loaded?\n");
1793 raw1394_set_userdata(m_handle
, static_cast<void *>(this));
1795 // Reset housekeeping data before preparing and starting the handler.
1796 // If only done afterwards, the transmit handler could be called before
1797 // these have been reset, leading to problems in getPacket().
1804 // indicate that the first iterate() still has to occur.
1805 m_last_now
= 0xFFFFFFFF;
1806 m_last_packet_handled_at
= 0xFFFFFFFF;
1808 // prepare the handler, allocate the resources
1809 debugOutput( DEBUG_LEVEL_VERBOSE
, "Preparing iso handler (%p, client=%p)\n", this, m_Client
);
1811 if (getType() == eHT_Receive
) {
1812 if(raw1394_iso_recv_init(m_handle
,
1813 iso_receive_handler
,
1816 m_Client
->getChannel(),
1819 debugFatal("Could not do receive initialization (PACKET_PER_BUFFER)!\n" );
1820 debugFatal(" %s\n",strerror(errno
));
1824 if(raw1394_iso_recv_start(m_handle
, cycle
, -1, 0)) {
1825 debugFatal("Could not start receive handler (%s)\n",strerror(errno
));
1830 if(raw1394_iso_xmit_init(m_handle
,
1831 iso_transmit_handler
,
1834 m_Client
->getChannel(),
1837 debugFatal("Could not do xmit initialisation!\n" );
1841 if(raw1394_iso_xmit_start(m_handle
, cycle
, 0)) {
1842 debugFatal("Could not start xmit handler (%s)\n", strerror(errno
));
1848 m_State
= eHS_Running
;
1849 m_NextState
= eHS_Running
;
1854 IsoHandlerManager::IsoHandler::disable()
1856 signed int i
, have_lock
= 0;
1858 debugOutput( DEBUG_LEVEL_VERBOSE
, "(%p, %s) enter...\n",
1859 this, (m_type
==eHT_Receive
?"Receive":"Transmit"));
1861 i
= pthread_mutex_trylock(&m_disable_lock
);
1866 // Some other thread is disabling this handler, a process which can
1867 // take considerable time when using the new kernel firewire stack.
1868 // Wait until it is finished before returning so the present caller
1869 // can act knowing that the disable has occurred and is complete
1870 // (which is what normally would be expected).
1871 debugOutput( DEBUG_LEVEL_VERBOSE
, "waiting for disable lock\n");
1872 pthread_mutex_lock(&m_disable_lock
);
1873 debugOutput( DEBUG_LEVEL_VERBOSE
, "now have disable lock\n");
1874 if (m_State
== eHS_Stopped
) {
1875 debugOutput( DEBUG_LEVEL_VERBOSE
, "another disable() has completed\n");
1876 pthread_mutex_unlock(&m_disable_lock
);
1883 if(m_State
!= eHS_Running
) {
1884 debugError("Incorrect state, expected eHS_Running, got %d\n",(int)m_State
);
1886 pthread_mutex_unlock(&m_disable_lock
);
1890 assert(m_handle
!= NULL
);
1892 debugOutput( DEBUG_LEVEL_VERBOSE
, "(%p, %s) wake up handle...\n",
1893 this, (m_type
==eHT_Receive
?"Receive":"Transmit"));
1895 // wake up any waiting reads/polls
1896 raw1394_wake_up(m_handle
);
1898 // this is put here to try and avoid the
1899 // Runaway context problem
1900 // don't know if it will help though.
1901 /* if(m_State != eHS_Error) { // if the handler is dead, this might block forever
1902 raw1394_iso_xmit_sync(m_handle);
1904 debugOutput( DEBUG_LEVEL_VERBOSE
, "(%p, %s) stop...\n",
1905 this, (m_type
==eHT_Receive
?"Receive":"Transmit"));
1908 raw1394_iso_stop(m_handle
);
1909 // deallocate resources
1911 // Don't call until libraw1394's raw1394_new_handle() function has been
1912 // fixed to correctly initialise the iso_packet_infos field. Bug is
1913 // confirmed present in libraw1394 1.2.1.
1914 raw1394_iso_shutdown(m_handle
);
1916 // When running on the new kernel firewire stack, this call can take of
1917 // the order of 20 milliseconds to return, in which time other threads
1918 // may wish to test the state of the handler and call this function
1919 // themselves. The m_disable_lock mutex is used to work around this.
1920 raw1394_destroy_handle(m_handle
);
1923 m_State
= eHS_Stopped
;
1924 m_NextState
= eHS_Stopped
;
1927 pthread_mutex_unlock(&m_disable_lock
);
1931 // functions to request enable or disable at the next opportunity
1933 IsoHandlerManager::IsoHandler::requestEnable(int cycle
)
1935 if (m_State
== eHS_Running
) {
1936 debugError("Enable requested on enabled stream '%s'\n", getTypeString());
1939 if (m_State
!= eHS_Stopped
) {
1940 debugError("Enable requested on stream '%s' with state: %d\n", getTypeString(), m_State
);
1943 m_NextState
= eHS_Running
;
1948 IsoHandlerManager::IsoHandler::requestDisable()
1950 if (m_State
== eHS_Stopped
) {
1951 // Don't treat this as an error condition because during a user
1952 // shutdown the stream would have been disabled by
1953 // stopHandlerForStream(). Therefore when requestDisable() is
1954 // subnsequently called by IsoHandlerManager::stopHandlers() in the
1955 // IsoHandlerManager destructor with the stream disabled the
1956 // condition is not an error.
1958 // For now print a warning, but this might be removed in future if
1959 // the above framework remains in place.
1960 debugWarning("Disable requested on disabled stream\n");
1963 if (m_State
!= eHS_Running
) {
1964 debugError("Disable requested on stream with state=%d\n", m_State
);
1967 m_NextState
= eHS_Stopped
;
1971 // Explicitly preset m_switch_on_cycle since requestEnable doesn't do this
1972 // and thus all enables requested via that route always occur on cycle 0.
1974 IsoHandlerManager::IsoHandler::setIsoStartCycle(signed int cycle
)
1976 m_switch_on_cycle
= cycle
;
1980 IsoHandlerManager::IsoHandler::updateState()
1982 // execute state changes requested
1983 if(m_State
!= m_NextState
) {
1984 debugOutput(DEBUG_LEVEL_VERBOSE
, "(%p) handler needs state update from %d => %d\n", this, m_State
, m_NextState
);
1985 if(m_State
== eHS_Stopped
&& m_NextState
== eHS_Running
) {
1986 debugOutput(DEBUG_LEVEL_VERBOSE
, "handler has to be enabled\n");
1987 enable(m_switch_on_cycle
);
1988 } else if(m_State
== eHS_Running
&& m_NextState
== eHS_Stopped
) {
1989 debugOutput(DEBUG_LEVEL_VERBOSE
, "handler has to be disabled\n");
1992 debugError("Unknown state transition\n");
1998 * @brief convert a EHandlerType to a string
2000 * @return a char * describing the state
2003 IsoHandlerManager::IsoHandler::eHTToString(enum EHandlerType t
) {
2005 case eHT_Receive
: return "Receive";
2006 case eHT_Transmit
: return "Transmit";
2007 default: return "error: unknown type";