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

Revision 1246, 24.8 kB (checked in by ppalmers, 13 years ago)

add dead handler detection

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 "IsoHandler.h"
27 #include "ieee1394service.h"
28 #include "IsoHandlerManager.h"
29
30 #include "cycletimer.h"
31
32 #include "libstreaming/generic/StreamProcessor.h"
33 #include "libutil/PosixThread.h"
34
35 #include <errno.h>
36 #include "libutil/ByteSwap.h"
37 #include <assert.h>
38 #include <unistd.h>
39 #include <string.h>
40
41 #include <iostream>
42 using namespace std;
43 using namespace Streaming;
44
45 IMPL_DEBUG_MODULE( IsoHandler, IsoHandler, DEBUG_LEVEL_NORMAL );
46
47 /* the C callbacks */
48 enum raw1394_iso_disposition
49 IsoHandler::iso_transmit_handler(raw1394handle_t handle,
50         unsigned char *data, unsigned int *length,
51         unsigned char *tag, unsigned char *sy,
52         int cycle, unsigned int dropped1) {
53
54     IsoHandler *xmitHandler = static_cast<IsoHandler *>(raw1394_get_userdata(handle));
55     assert(xmitHandler);
56     unsigned int skipped = (dropped1 & 0xFFFF0000) >> 16;
57     unsigned int dropped = dropped1 & 0xFFFF;
58     return xmitHandler->getPacket(data, length, tag, sy, cycle, dropped, skipped);
59 }
60
61 enum raw1394_iso_disposition
62 IsoHandler::iso_receive_handler(raw1394handle_t handle, unsigned char *data,
63                         unsigned int length, unsigned char channel,
64                         unsigned char tag, unsigned char sy, unsigned int cycle,
65                         unsigned int dropped1) {
66
67     IsoHandler *recvHandler = static_cast<IsoHandler *>(raw1394_get_userdata(handle));
68     assert(recvHandler);
69
70     unsigned int skipped = (dropped1 & 0xFFFF0000) >> 16;
71     unsigned int dropped = dropped1 & 0xFFFF;
72
73     return recvHandler->putPacket(data, length, channel, tag, sy, cycle, dropped, skipped);
74 }
75
76 int IsoHandler::busreset_handler(raw1394handle_t handle, unsigned int generation)
77 {
78     debugOutput( DEBUG_LEVEL_VERBOSE, "Busreset happened, generation %d...\n", generation);
79
80     IsoHandler *handler = static_cast<IsoHandler *>(raw1394_get_userdata(handle));
81     assert(handler);
82     return handler->handleBusReset(generation);
83 }
84
85 IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t)
86    : m_manager( manager )
87    , m_type ( t )
88    , m_handle( 0 )
89    , m_buf_packets( 400 )
90    , m_max_packet_size( 1024 )
91    , m_irq_interval( -1 )
92    , m_last_cycle( -1 )
93    , m_last_now( 0xFFFFFFFF )
94    , m_Client( 0 )
95    , m_speed( RAW1394_ISO_SPEED_400 )
96    , m_prebuffers( 0 )
97    , m_dont_exit_iterate_loop( true )
98    , m_State( E_Created )
99 #ifdef DEBUG
100    , m_packets ( 0 )
101    , m_dropped( 0 )
102    , m_min_ahead( 7999 )
103 #endif
104 {
105 }
106
107 IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t,
108                        unsigned int buf_packets, unsigned int max_packet_size, int irq)
109    : m_manager( manager )
110    , m_type ( t )
111    , m_handle( 0 )
112    , m_buf_packets( buf_packets )
113    , m_max_packet_size( max_packet_size )
114    , m_irq_interval( irq )
115    , m_last_cycle( -1 )
116    , m_last_now( 0xFFFFFFFF )
117    , m_Client( 0 )
118    , m_speed( RAW1394_ISO_SPEED_400 )
119    , m_prebuffers( 0 )
120    , m_State( E_Created )
121 #ifdef DEBUG
122    , m_packets ( 0 )
123    , m_dropped( 0 )
124    , m_min_ahead( 7999 )
125 #endif
126 {
127 }
128
129 IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t, unsigned int buf_packets,
130                        unsigned int max_packet_size, int irq,
131                        enum raw1394_iso_speed speed)
132    : m_manager( manager )
133    , m_type ( t )
134    , m_handle( 0 )
135    , m_buf_packets( buf_packets )
136    , m_max_packet_size( max_packet_size )
137    , m_irq_interval( irq )
138    , m_last_cycle( -1 )
139    , m_last_now( 0xFFFFFFFF )
140    , m_Client( 0 )
141    , m_speed( speed )
142    , m_prebuffers( 0 )
143    , m_State( E_Created )
144 #ifdef DEBUG
145    , m_packets( 0 )
146    , m_dropped( 0 )
147 #endif
148 {
149 }
150
151 IsoHandler::~IsoHandler() {
152 // Don't call until libraw1394's raw1394_new_handle() function has been
153 // fixed to correctly initialise the iso_packet_infos field.  Bug is
154 // confirmed present in libraw1394 1.2.1.  In any case,
155 // raw1394_destroy_handle() will do any iso system shutdown required.
156 //     raw1394_iso_shutdown(m_handle);
157     if(m_handle) {
158         if (m_State == E_Running) {
159             disable();
160         }
161         raw1394_destroy_handle(m_handle);
162     }
163 }
164
165 bool
166 IsoHandler::canIterateClient()
167 {
168     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "checking...\n");
169     if(m_Client) {
170         bool result;
171         if (m_type == eHT_Receive) {
172             result = m_Client->canProducePacket();
173         } else {
174             result = m_Client->canConsumePacket();
175         }
176         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " returns %d\n", result);
177         return result;
178     } else {
179         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " no client\n");
180     }
181     return false;
182 }
183
184 bool
185 IsoHandler::iterate() {
186     return iterate(m_manager.get1394Service().getCycleTimer());
187 }
188
189 bool
190 IsoHandler::iterate(uint32_t cycle_timer_now) {
191     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Iterating ISO handler at %08X...\n",
192                        this, getTypeString(), cycle_timer_now);
193     m_last_now = cycle_timer_now;
194     if(m_State == E_Running) {
195 #if ISOHANDLER_FLUSH_BEFORE_ITERATE
196         flush();
197 #endif
198         if(raw1394_loop_iterate(m_handle)) {
199             debugError( "IsoHandler (%p): Failed to iterate handler: %s\n",
200                         this, strerror(errno));
201             return false;
202         }
203         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) done interating ISO handler...\n",
204                            this, getTypeString());
205         return true;
206     } else {
207         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Not iterating a non-running handler...\n",
208                     this, getTypeString());
209         return false;
210     }
211 }
212
213 bool
214 IsoHandler::init()
215 {
216     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) enter...\n",this);
217     // check the state
218     if(m_State != E_Created) {
219         debugError("Incorrect state, expected E_Created, got %d\n",(int)m_State);
220         return false;
221     }
222
223     // the main handle for the ISO traffic
224     m_handle = raw1394_new_handle_on_port( m_manager.get1394Service().getPort() );
225     if ( !m_handle ) {
226         if ( !errno ) {
227             debugError("libraw1394 not compatible\n");
228         } else {
229             debugError("Could not get 1394 handle: %s\n", strerror(errno) );
230             debugError("Are ieee1394 and raw1394 drivers loaded?\n");
231         }
232         return false;
233     }
234     raw1394_set_userdata(m_handle, static_cast<void *>(this));
235
236     // bus reset handling
237     if(raw1394_busreset_notify (m_handle, RAW1394_NOTIFY_ON)) {
238         debugWarning("Could not enable busreset notification.\n");
239         debugWarning(" Error message: %s\n",strerror(errno));
240         debugWarning("Continuing without bus reset support.\n");
241     } else {
242         // apparently this cannot fail
243         raw1394_set_bus_reset_handler(m_handle, busreset_handler);
244     }
245
246     // update the internal state
247     m_State=E_Initialized;
248     return true;
249 }
250
251 bool IsoHandler::disable()
252 {
253     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) enter...\n",
254                  this, (m_type==eHT_Receive?"Receive":"Transmit"));
255
256     // check state
257     if(m_State == E_Prepared) return true;
258     if(m_State != E_Running) {
259         debugError("Incorrect state, expected E_Running, got %d\n",(int)m_State);
260         return false;
261     }
262
263     // this is put here to try and avoid the
264     // Runaway context problem
265     // don't know if it will help though.
266     raw1394_iso_xmit_sync(m_handle);
267     raw1394_iso_stop(m_handle);
268     m_State = E_Prepared;
269     return true;
270 }
271
272 /**
273  * Bus reset handler
274  *
275  * @return ?
276  */
277
278 int
279 IsoHandler::handleBusReset(unsigned int generation)
280 {
281     debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n");
282
283     #define CSR_CYCLE_TIME            0x200
284     #define CSR_REGISTER_BASE  0xfffff0000000ULL
285     // do a simple read on ourself in order to update the internal structures
286     // this avoids read failures after a bus reset
287     quadlet_t buf=0;
288     raw1394_read(m_handle, raw1394_get_local_id(m_handle),
289                  CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
290
291     // notify the client of the fact that we have died
292     m_Client->handlerDied();
293
294     if(!disable()) {
295         debugError("(%p) Could not disable IsoHandler\n", this);
296     }
297
298     // request the manager to update it's shadow map
299     m_manager.requestShadowMapUpdate();
300     return 0;
301 }
302
303 /**
304  * Call this if you find out that this handler has died for some
305  * external reason.
306  */
307 void
308 IsoHandler::notifyOfDeath()
309 {
310     // notify the client of the fact that we have died
311     m_Client->handlerDied();
312 }
313
314 void IsoHandler::dumpInfo()
315 {
316     int channel=-1;
317     if (m_Client) channel=m_Client->getChannel();
318
319     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type................: %s\n",
320             getTypeString());
321     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel...............: %2d, %2d\n",
322             m_manager.get1394Service().getPort(), channel);
323     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Buffer, MaxPacketSize, IRQ..: %4d, %4d, %4d\n",
324             m_buf_packets, m_max_packet_size, m_irq_interval);
325     if (this->getType() == eHT_Transmit) {
326         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Speed, PreBuffers...........: %2d, %2d\n",
327                                             m_speed, m_prebuffers);
328         #ifdef DEBUG
329         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Min ISOXMT bufferfill : %04d\n", m_min_ahead);
330         #endif
331     }
332     #ifdef DEBUG
333     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Last cycle, dropped.........: %4d, %4u\n",
334             m_last_cycle, m_dropped);
335     #endif
336
337 }
338
339 void IsoHandler::setVerboseLevel(int l)
340 {
341     setDebugLevel(l);
342 }
343
344 bool IsoHandler::registerStream(StreamProcessor *stream)
345 {
346     assert(stream);
347     debugOutput( DEBUG_LEVEL_VERBOSE, "registering stream (%p)\n", stream);
348
349     if (m_Client) {
350             debugFatal( "Generic IsoHandlers can have only one client\n");
351             return false;
352     }
353     m_Client=stream;
354     return true;
355 }
356
357 bool IsoHandler::unregisterStream(StreamProcessor *stream)
358 {
359     assert(stream);
360     debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering stream (%p)\n", stream);
361
362     if(stream != m_Client) {
363             debugFatal( "no client registered\n");
364             return false;
365     }
366     m_Client=0;
367     return true;
368 }
369
370 void IsoHandler::flush()
371 {
372     if(m_type == eHT_Receive) {
373         raw1394_iso_recv_flush(m_handle);
374     } else {
375         // do nothing
376     }
377 }
378
379 // ISO packet interface
380 enum raw1394_iso_disposition IsoHandler::putPacket(
381                     unsigned char *data, unsigned int length,
382                     unsigned char channel, unsigned char tag, unsigned char sy,
383                     unsigned int cycle, unsigned int dropped, unsigned int skipped) {
384
385     // keep track of dropped cycles
386     int dropped_cycles = 0;
387     if (m_last_cycle != (int)cycle && m_last_cycle != -1) {
388         dropped_cycles = diffCycles(cycle, m_last_cycle) - 1;
389         #ifdef DEBUG
390         if (dropped_cycles < 0) {
391             debugWarning("(%p) dropped < 1 (%d), cycle: %d, last_cycle: %d, dropped: %d, 'skipped'=%u\n",
392                          this, dropped_cycles, cycle, m_last_cycle, dropped, skipped);
393         }
394         if (dropped_cycles > 0) {
395             debugOutput(DEBUG_LEVEL_NORMAL,
396                         "(%p) dropped %d packets on cycle %u, 'dropped'=%u, 'skipped'=%u, cycle=%d, m_last_cycle=%d\n",
397                         this, dropped_cycles, cycle, dropped, skipped, cycle, m_last_cycle);
398             m_dropped += dropped_cycles;
399         }
400         #endif
401     }
402     m_last_cycle = cycle;
403
404     uint32_t pkt_ctr = cycle << 12;
405
406     // if we assume that one iterate() loop doesn't take longer than 0.5 seconds,
407     // the seconds field won't change while the iterate loop runs
408     // this means that we can preset 'now' before running iterate()
409     uint32_t now_secs = CYCLE_TIMER_GET_SECS(m_last_now);
410     // causality results in the fact that 'now' is always after 'cycle'
411     // except if additional packets are received between setting the
412     // m_last_now and the starting the iterate() loop.
413     // this causes the m_last_now to be set at a time before the last packet
414     // in this loop is received. however, it's not going to be >4000 cycles.
415     // hence:
416     // - if the m_last_now > cycle, there is no need to unwrap
417     //   both values are within the same second
418     // - if m_last_now < cycle it can mean two things:
419     //    * m_last_now has wrapped, but is still later than cycle
420     //      hence diffCycles(m_last_now, cycle) > 0. We should unwrap
421     //    * m_last_now has not wrapped, and cycle is ahead of m_last_now
422     //      this means that the cycle is more recent than the saved
423     //      m_last_now value
424     // . Hence if we calculate
425     // the unwrapped difference, and it's larger than 0, this means
426     // that m_last_now is after the current cycle. .
427     // it m_last_now is before the current cycle, we should not unwrap
428     // NOTE: another option is to reread the m_last_now
429     if( (CYCLE_TIMER_GET_CYCLES(m_last_now) < cycle)
430         && diffCycles(CYCLE_TIMER_GET_CYCLES(m_last_now), cycle) >= 0) {
431         debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
432                            "unwrapping %d => %d, %d\n",
433                            CYCLE_TIMER_GET_CYCLES(m_last_now),
434                            cycle);
435         // the cycle field has wrapped, substract one second
436         if(now_secs == 0) {
437             now_secs = 127;
438         } else  {
439             now_secs -= 1;
440         }
441     }
442
443     #ifdef DEBUG
444     if( (CYCLE_TIMER_GET_CYCLES(m_last_now) < cycle)
445         && diffCycles(CYCLE_TIMER_GET_CYCLES(m_last_now), cycle) < 0
446         // ignore this on dropped cycles, since it's normal
447         // that now is ahead on the received packets (as we miss packets)
448         && dropped_cycles == 0)
449     {
450         debugOutput(DEBUG_LEVEL_VERBOSE, "Special non-unwrapping happened\n");
451     }
452     #endif
453     pkt_ctr |= (now_secs & 0x7F) << 25;
454
455     #if ISOHANDLER_CHECK_CTR_RECONSTRUCTION
456     // add a seconds field
457     uint32_t now = m_manager.get1394Service().getCycleTimer();
458     uint32_t now_secs_ref = CYCLE_TIMER_GET_SECS(now);
459     // causality results in the fact that 'now' is always after 'cycle'
460     // or at best, equal (if this handler was called within 125us after
461     // the packet was on the wire).
462     if(CYCLE_TIMER_GET_CYCLES(now) < cycle) {
463         // the cycle field has wrapped, substract one second
464         if(now_secs_ref == 0) {
465             now_secs_ref = 127;
466         } else  {
467             now_secs_ref -= 1;
468         }
469     }
470     uint32_t pkt_ctr_ref = cycle << 12;
471     pkt_ctr_ref |= (now_secs_ref & 0x7F) << 25;
472
473     if(pkt_ctr != pkt_ctr_ref) {
474         debugWarning("reconstructed CTR counter discrepancy\n");
475         debugWarning(" ingredients: %X, %lX, %lX, %lX, %lX, %ld, %ld\n",
476                        cycle, pkt_ctr_ref, pkt_ctr, now, m_last_now, now_secs_ref, now_secs);
477     }
478     #endif
479
480     // leave the offset field (for now?)
481
482     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
483                        "received packet: length=%d, channel=%d, cycle=%d\n",
484                        length, channel, cycle);
485     #ifdef DEBUG
486     m_packets++;
487     if (length > m_max_packet_size) {
488         debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
489                      this, getTypeString(), length, m_max_packet_size);
490     }
491     if(m_last_cycle == -1) {
492         debugOutput(DEBUG_LEVEL_VERBOSE, "Handler for %s SP %p is alive (cycle = %u)\n", getTypeString(), this, cycle);
493     }
494     #endif
495
496     // iterate the client if required
497     if(m_Client) {
498         enum raw1394_iso_disposition retval = m_Client->putPacket(data, length, channel, tag, sy, pkt_ctr, dropped_cycles, skipped);
499         if (retval == RAW1394_ISO_OK) {
500             if (m_dont_exit_iterate_loop) {
501                 return RAW1394_ISO_OK;
502             } else {
503                 m_dont_exit_iterate_loop = true;
504                 debugOutput(DEBUG_LEVEL_VERBOSE,
505                                 "(%p) loop exit requested\n",
506                                 this);
507                 return RAW1394_ISO_DEFER;
508             }
509         } else {
510             return retval;
511         }
512     }
513
514     return RAW1394_ISO_OK;
515 }
516
517 enum raw1394_iso_disposition
518 IsoHandler::getPacket(unsigned char *data, unsigned int *length,
519                       unsigned char *tag, unsigned char *sy,
520                       int cycle, unsigned int dropped, unsigned int skipped) {
521
522     uint32_t pkt_ctr;
523     if (cycle < 0) {
524         // mark invalid
525         pkt_ctr = 0xFFFFFFFF;
526     } else {
527         pkt_ctr = cycle << 12;
528
529 #if 0 // we don't need this for xmit
530         // if we assume that one iterate() loop doesn't take longer than 0.5 seconds,
531         // the seconds field won't change while the iterate loop runs
532         // this means that we can preset 'now' before running iterate()
533         uint32_t now_secs = CYCLE_TIMER_GET_SECS(m_last_now);
534         // causality results in the fact that 'now' is always after 'cycle'
535         if(CYCLE_TIMER_GET_CYCLES(m_last_now) > (unsigned int)cycle) {
536             // the cycle field has wrapped, add one second
537             now_secs += 1;
538             // no need for this:
539             //if(now_secs == 128) {
540             //    now_secs = 0;
541             //}
542             // since we mask later on
543         }
544         pkt_ctr |= (now_secs & 0x7F) << 25;
545
546         #if ISOHANDLER_CHECK_CTR_RECONSTRUCTION
547         // add a seconds field
548         uint32_t now = m_manager.get1394Service().getCycleTimer();
549         uint32_t now_secs_ref = CYCLE_TIMER_GET_SECS(now);
550         // causality results in the fact that 'now' is always after 'cycle'
551         if(CYCLE_TIMER_GET_CYCLES(now) > (unsigned int)cycle) {
552             // the cycle field has wrapped, add one second
553             now_secs_ref += 1;
554             // no need for this:
555             //if(now_secs == 128) {
556             //    now_secs = 0;
557             //}
558             // since we mask later on
559         }
560         uint32_t pkt_ctr_ref = cycle << 12;
561         pkt_ctr_ref |= (now_secs_ref & 0x7F) << 25;
562    
563         if(pkt_ctr != pkt_ctr_ref) {
564             debugWarning("reconstructed CTR counter discrepancy\n");
565             pkt_ctr=pkt_ctr_ref;
566         }
567         #endif
568 #endif
569     }
570
571     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
572                        "sending packet: length=%d, cycle=%d\n",
573                        *length, cycle);
574
575     #ifdef DEBUG
576     m_packets++;
577     if(m_last_cycle == -1) {
578         debugOutput(DEBUG_LEVEL_VERBOSE, "Handler for %s SP %p is alive (cycle = %d)\n", getTypeString(), this, cycle);
579     }
580     #endif
581
582     // keep track of dropped cycles
583     int dropped_cycles = 0;
584     if (m_last_cycle != cycle && m_last_cycle != -1) {
585         dropped_cycles = diffCycles(cycle, m_last_cycle) - 1;
586         // correct for skipped packets
587         // since those are not dropped, but only delayed
588         dropped_cycles -= skipped;
589
590         #ifdef DEBUG
591         if(skipped) {
592             debugOutput(DEBUG_LEVEL_NORMAL,
593                         "(%p) skipped %d cycles, cycle: %d, last_cycle: %d, dropped: %d\n",
594                         this, skipped, cycle, m_last_cycle, dropped);
595         }
596         if (dropped_cycles < 0) {
597             debugWarning("(%p) dropped < 1 (%d), cycle: %d, last_cycle: %d, dropped: %d, skipped: %d\n",
598                          this, dropped_cycles, cycle, m_last_cycle, dropped, skipped);
599         }
600         if (dropped_cycles > 0) {
601             debugOutput(DEBUG_LEVEL_NORMAL,
602                         "(%p) dropped %d packets on cycle %u (last_cycle=%u, dropped=%d, skipped: %d)\n",
603                         this, dropped_cycles, cycle, m_last_cycle, dropped, skipped);
604             m_dropped += dropped_cycles - skipped;
605         }
606         #endif
607     }
608     if (cycle >= 0) {
609         m_last_cycle = cycle;
610        
611         #ifdef DEBUG
612 /*        int ahead = diffCycles(cycle, now_cycles);
613         if (ahead < m_min_ahead) m_min_ahead = ahead;
614 */
615         #endif
616     }
617
618     if(m_Client) {
619         enum raw1394_iso_disposition retval;
620         retval = m_Client->getPacket(data, length, tag, sy, pkt_ctr, dropped, skipped, m_max_packet_size);
621         #ifdef DEBUG
622         if (*length > m_max_packet_size) {
623             debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
624                          this, getTypeString(), *length, m_max_packet_size);
625         }
626         #endif
627         if (retval == RAW1394_ISO_OK) {
628             if (m_dont_exit_iterate_loop) {
629                 return RAW1394_ISO_OK;
630             } else {
631                 m_dont_exit_iterate_loop = true;
632                 debugOutput(DEBUG_LEVEL_VERBOSE,
633                                 "(%p) loop exit requested\n",
634                                 this);
635                 return RAW1394_ISO_DEFER;
636             }
637         } else {
638             return retval;
639         }
640     }
641
642     *tag = 0;
643     *sy = 0;
644     *length = 0;
645     return RAW1394_ISO_OK;
646 }
647
648 bool IsoHandler::prepare()
649 {
650     // check the state
651     if(m_State != E_Initialized) {
652         debugError("Incorrect state, expected E_Initialized, got %d\n",(int)m_State);
653         return false;
654     }
655
656     // Don't call until libraw1394's raw1394_new_handle() function has been
657     // fixed to correctly initialise the iso_packet_infos field.  Bug is
658     // confirmed present in libraw1394 1.2.1.
659     //     raw1394_iso_shutdown(m_handle);
660     m_State = E_Prepared;
661
662     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso handler (%p, client=%p)\n", this, m_Client);
663     dumpInfo();
664     if (getType() == eHT_Receive) {
665         if(m_irq_interval > 1) {
666             if(raw1394_iso_recv_init(m_handle,
667                                     iso_receive_handler,
668                                     m_buf_packets,
669                                     m_max_packet_size,
670                                     m_Client->getChannel(),
671                                     RAW1394_DMA_BUFFERFILL,
672 //                                     RAW1394_DMA_PACKET_PER_BUFFER,
673                                     m_irq_interval)) {
674                 debugFatal("Could not do receive initialisation (DMA_BUFFERFILL)!\n" );
675                 debugFatal("  %s\n",strerror(errno));
676                 return false;
677             }
678         } else {
679             if(raw1394_iso_recv_init(m_handle,
680                                     iso_receive_handler,
681                                     m_buf_packets,
682                                     m_max_packet_size,
683                                     m_Client->getChannel(),
684                                     RAW1394_DMA_PACKET_PER_BUFFER,
685                                     m_irq_interval)) {
686                 debugFatal("Could not do receive initialisation (PACKET_PER_BUFFER)!\n" );
687                 debugFatal("  %s\n",strerror(errno));
688                 return false;
689             }
690         }
691         return true;
692     } else {
693         if(raw1394_iso_xmit_init(m_handle,
694                                 iso_transmit_handler,
695                                 m_buf_packets,
696                                 m_max_packet_size,
697                                 m_Client->getChannel(),
698                                 m_speed,
699                                 m_irq_interval)) {
700             debugFatal("Could not do xmit initialisation!\n" );
701             return false;
702         }
703         return true;
704     }
705 }
706
707 bool IsoHandler::enable(int cycle)
708 {
709     debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
710     // check the state
711     if(m_State != E_Prepared) {
712         if(!prepare()) {
713             debugFatal("Could not prepare handler\n");
714             return false;
715         }
716     }
717
718     if (getType() == eHT_Receive) {
719         if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) {
720             debugFatal("Could not start receive handler (%s)\n",strerror(errno));
721             dumpInfo();
722             return false;
723         }
724     } else {
725         if(raw1394_iso_xmit_start(m_handle, cycle, m_prebuffers)) {
726             debugFatal("Could not start xmit handler (%s)\n",strerror(errno));
727             dumpInfo();
728             return false;
729         }
730     }
731
732 #ifdef DEBUG
733     m_min_ahead = 7999;
734 #endif
735
736     // indicate that the first iterate() still has to occur.
737     m_last_now = 0xFFFFFFFF;
738
739     m_State = E_Running;
740     return true;
741 }
742
743 /**
744  * @brief convert a EHandlerType to a string
745  * @param t the type
746  * @return a char * describing the state
747  */
748 const char *
749 IsoHandler::eHTToString(enum EHandlerType t) {
750     switch (t) {
751         case eHT_Receive: return "Receive";
752         case eHT_Transmit: return "Transmit";
753         default: return "error: unknown type";
754     }
755 }
Note: See TracBrowser for help on using the browser.