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

Revision 1763, 24.9 kB (checked in by ppalmers, 14 years ago)

Merged revisions 1536,1541,1544-1546,1549,1554-1562,1571,1579-1581,1618,1632,1634-1635,1661,1677-1679,1703-1704,1715,1720-1723,1743-1745,1755 via svnmerge from
svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0

Also fix remaining format string warnings.

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