root/branches/streaming-rework/src/libstreaming/IsoHandler.cpp

Revision 383, 28.3 kB (checked in by pieterpalmers, 16 years ago)

mostly whitespace fixes

Line 
1 /* $Id$ */
2
3 /*
4  *   FreeBob Streaming API
5  *   FreeBob = Firewire (pro-)audio for linux
6  *
7  *   http://freebob.sf.net
8  *
9  *   Copyright (C) 2006 Pieter Palmers <pieterpalmers@users.sourceforge.net>
10  *
11  *   This program is free software {} you can redistribute it and/or modify
12  *   it under the terms of the GNU General Public License as published by
13  *   the Free Software Foundation {} either version 2 of the License, or
14  *   (at your option) any later version.
15  *
16  *   This program is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY {} without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with this program {} if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  *
26  *
27  */
28
29 #include "IsoHandler.h"
30 #include "IsoStream.h"
31 #include "cyclecounter.h"
32
33 #include "libutil/Time.h"
34 #include "libutil/TimeSource.h"
35 #include "libutil/SystemTimeSource.h"
36
37 #include <errno.h>
38 #include <netinet/in.h>
39 #include <assert.h>
40 #include <unistd.h>
41
42 #include <iostream>
43 using namespace std;
44
45
46 #define CC_SLEEP_TIME_AFTER_UPDATE     100
47 #define CC_SLEEP_TIME_AFTER_FAILURE     10
48 #define CC_DLL_COEFF     ((0.01)*((float)(CC_SLEEP_TIME_AFTER_UPDATE/1000.0)))
49
50 #define CC_MAX_RATE_ERROR           (2/100.0)
51 #define CC_INIT_MAX_TRIES 10
52
53
54 namespace FreebobStreaming
55 {
56
57 IMPL_DEBUG_MODULE( IsoHandler, IsoHandler, DEBUG_LEVEL_NORMAL );
58
59 /* the C callbacks */
60 enum raw1394_iso_disposition
61 IsoXmitHandler::iso_transmit_handler(raw1394handle_t handle,
62                 unsigned char *data, unsigned int *length,
63                 unsigned char *tag, unsigned char *sy,
64                 int cycle, unsigned int dropped) {
65
66         IsoXmitHandler *xmitHandler=static_cast<IsoXmitHandler *>(raw1394_get_userdata(handle));
67         assert(xmitHandler);
68
69         return xmitHandler->getPacket(data, length, tag, sy, cycle, dropped);
70 }
71
72 enum raw1394_iso_disposition
73 IsoRecvHandler::iso_receive_handler(raw1394handle_t handle, unsigned char *data,
74                                                 unsigned int length, unsigned char channel,
75                                                 unsigned char tag, unsigned char sy, unsigned int cycle,
76                                                 unsigned int dropped) {
77
78         IsoRecvHandler *recvHandler=static_cast<IsoRecvHandler *>(raw1394_get_userdata(handle));
79         assert(recvHandler);
80
81         return recvHandler->putPacket(data, length, channel, tag, sy, cycle, dropped);
82 }
83
84 int IsoHandler::busreset_handler(raw1394handle_t handle, unsigned int generation)
85 {       
86         debugOutput( DEBUG_LEVEL_VERBOSE, "Busreset happened, generation %d...\n", generation);
87
88         IsoHandler *handler=static_cast<IsoHandler *>(raw1394_get_userdata(handle));
89         assert(handler);
90         return handler->handleBusReset(generation);
91 }
92
93
94 /* Base class implementation */
95 IsoHandler::IsoHandler(int port)
96    : TimeSource(), m_handle(0), m_handle_util(0), m_port(port),
97    m_buf_packets(400), m_max_packet_size(1024), m_irq_interval(-1),
98    m_cyclecounter_ticks(0), m_lastmeas_usecs(0), m_ticks_per_usec(24.576),
99    m_ticks_per_usec_dll_err2(0),
100    m_packetcount(0), m_dropped(0), m_Client(0)
101 {
102     InitTime();
103     m_TimeSource=new FreebobUtil::SystemTimeSource();
104 }
105
106 IsoHandler::IsoHandler(int port, unsigned int buf_packets, unsigned int max_packet_size, int irq)
107    : TimeSource(), m_handle(0), m_port(port),
108    m_buf_packets(buf_packets), m_max_packet_size( max_packet_size),
109    m_irq_interval(irq),
110    m_cyclecounter_ticks(0), m_lastmeas_usecs(0), m_ticks_per_usec(24.576),
111    m_ticks_per_usec_dll_err2(0),
112    m_packetcount(0), m_dropped(0), m_Client(0)
113 {
114     InitTime();
115     m_TimeSource=new FreebobUtil::SystemTimeSource();
116 }
117
118 IsoHandler::~IsoHandler() {
119     if(m_handle) {
120             stop();
121         raw1394_destroy_handle(m_handle);
122     }
123     if(m_handle_util) raw1394_destroy_handle(m_handle_util);
124    
125     delete m_TimeSource;
126 }
127
128 bool
129 IsoHandler::init()
130 {
131     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) enter...\n",this);
132
133     m_handle = raw1394_new_handle_on_port( m_port );
134     if ( !m_handle ) {
135         if ( !errno ) {
136                         cerr << "libraw1394 not compatible" << endl;
137         } else {
138                         perror( "IsoHandler::Initialize: Could not get 1394 handle" );
139                         cerr << "Is ieee1394 and raw1394 driver loaded?" << endl;
140         }
141         return false;
142     }
143     raw1394_set_userdata(m_handle, static_cast<void *>(this));
144    
145     // a second handle for utility stuff
146     m_handle_util = raw1394_new_handle_on_port( m_port );
147     if ( !m_handle_util ) {
148         if ( !errno ) {
149                         cerr << "libraw1394 not compatible" << endl;
150         } else {
151                         perror( "IsoHandler::Initialize: Could not get 1394 handle" );
152                         cerr << "Is ieee1394 and raw1394 driver loaded?" << endl;
153         }
154         return false;
155     }
156        
157     raw1394_set_userdata(m_handle_util, static_cast<void *>(this));
158        
159     if(raw1394_busreset_notify (m_handle, RAW1394_NOTIFY_ON)) {
160         debugWarning("Could not enable busreset notification.\n");
161         debugWarning(" Error message: %s\n",strerror(errno));
162         }
163        
164         raw1394_set_bus_reset_handler(m_handle, busreset_handler);
165
166     // initialize the local timesource
167     m_TimeSource_NbCycleWraps=0;
168     quadlet_t buf=0;
169     unsigned int new_counter;
170    
171     raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),
172         CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
173
174     new_counter= ntohl(buf) & 0xFFFFFFFF;
175     m_TimeSource_LastSecs=CYCLE_COUNTER_GET_SECS(new_counter);
176
177     // update the cycle counter value for initial value
178     initCycleCounter();
179    
180     return true;
181 }
182
183 bool
184 IsoHandler::setSyncMaster(FreebobUtil::TimeSource *t)
185 {
186     m_TimeSource=t;
187
188     // update the cycle counter value for initial value
189     initCycleCounter();
190
191     return true;
192 }
193
194 bool IsoHandler::stop()
195 {
196     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
197     raw1394_iso_stop(m_handle);
198     return true;
199 }
200
201 /**
202  * Bus reset handler
203  *
204  * @return ?
205  */
206  
207 int IsoHandler::handleBusReset(unsigned int generation) {
208     debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n");
209    
210     // as busreset can elect a new cycle master,
211     // we need to re-initialize our timing code
212     initCycleCounter();
213    
214     return 0;
215 }
216
217 /**
218  * Returns the current value of the cycle counter (in ticks)
219  *
220  * @return the current value of the cycle counter (in ticks)
221  */
222
223 unsigned int IsoHandler::getCycleCounter() {
224     // calculate the cycle counter based upon the current time
225     // and the estimated tick rate
226     freebob_microsecs_t now=m_TimeSource->getCurrentTimeAsUsecs();
227
228     // linear interpolation
229     int delta_usecs=now-m_lastmeas_usecs;
230
231     float offset=m_ticks_per_usec * ((float)delta_usecs);
232
233     unsigned int pred_ticks=m_cyclecounter_ticks+(unsigned int)offset;
234
235     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Get CC: d_usecs=%d, offset=%f, cc_ticks=%lu, pred_ticks=%lu\n",
236       delta_usecs, offset, m_cyclecounter_ticks,pred_ticks
237       );
238
239     // if we need to wrap, do it
240     if (pred_ticks > TICKS_PER_SECOND * 128) {
241         pred_ticks -= TICKS_PER_SECOND * 128;
242     }
243    
244     return pred_ticks;
245 }
246
247 bool IsoHandler::updateCycleCounter() {
248     quadlet_t buf=0;
249
250     freebob_microsecs_t prev_usecs=m_lastmeas_usecs;
251     unsigned int prev_ticks=m_cyclecounter_ticks;
252    
253     freebob_microsecs_t new_usecs;
254     unsigned int new_ticks;
255     unsigned int new_counter;
256    
257     /* To estimate the cycle counter, we implement a
258        DLL based routine, that maps the cycle counter
259        on the system clock.
260        
261        For more info, refer to:
262         "Using a DLL to filter time"
263         Fons Adriaensen
264        
265         Can be found at:
266         http://users.skynet.be/solaris/linuxaudio/downloads/usingdll.pdf
267         or maybe at:
268         http://www.kokkinizita.net/linuxaudio
269    
270         Basically what we do is estimate the next point (T1,CC1_est)
271         based upon the previous point (T0, CC0) and the estimated rate (R).
272         Then we compare our estimation with the measured cycle counter
273         at T1 (=CC1_meas). We then calculate the estimation error on R:
274         err=(CC1_meas-CC0)/(T1-T2) - (CC1_est-CC0)/(T1-T2)
275         and try to minimize this on average (DLL)
276        
277         Note that in order to have a contignous mapping, we should
278         update CC0<=CC1_est instead of CC0<=CC1_meas. The measurement
279         serves only to correct the error 'on average'.
280        
281         In the code, the following variable names are used:
282         T0=prev_usecs
283         T1=next_usecs
284        
285         CC0=prev_ticks
286         CC1_est=est_ticks
287         CC1_meas=meas_ticks
288        
289      */
290    
291     // normally we should be able to use the same handle
292     // because it is not iterated on by any other stuff
293     // but I'm not sure
294     raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),
295         CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
296     new_usecs=m_TimeSource->getCurrentTimeAsUsecs();
297
298     new_counter= ntohl(buf) & 0xFFFFFFFF;
299     new_ticks=CYCLE_COUNTER_TO_TICKS(new_counter);
300
301     // the difference in system time
302     int delta_usecs=new_usecs-prev_usecs;
303     // this cannot be 0, because m_TimeSource->getCurrentTimeAsUsecs should
304     // never return the same value (maybe in future terrahz processors?)
305     assert(delta_usecs);
306    
307     // the measured cycle counter difference
308     unsigned int delta_ticks_meas;
309     if (new_ticks > prev_ticks) {
310         delta_ticks_meas=new_ticks - prev_ticks;
311     } else { // wraparound
312         delta_ticks_meas=CYCLE_COUNTER_UNWRAP_TICKS(new_ticks) - prev_ticks;
313     }
314    
315     // the estimated cycle counter difference
316     unsigned int delta_ticks_est=(unsigned int)(m_ticks_per_usec * ((float)delta_usecs));
317    
318     // the measured & estimated rate
319     float rate_meas=((float)delta_ticks_meas/(float)delta_usecs);
320     float rate_est=((float)m_ticks_per_usec);
321    
322     // these make sure we don't update when the measurement is
323     // bad. We know the nominal rate, and it can't be that far
324     // off. The thing is that there is a problem in measuring
325     // both usecs and ticks at the same time (no provision in
326     // the kernel.
327     // We know that there are some tolerances on both
328     // the system clock and the firewire clock such that the
329     // actual difference is rather small. So we discard values
330     // that are too far from the nominal rate.
331     // Otherwise the DLL has to have a very low bandwidth, in
332     // order not to be desturbed too much by these bad measurements
333     // resulting in very slow locking.
334    
335     if (   (rate_meas < 24.576*(1.0+CC_MAX_RATE_ERROR))
336         && (rate_meas > 24.576*(1.0-CC_MAX_RATE_ERROR))) {
337
338 #ifdef DEBUG
339
340         int diff=(int)delta_ticks_est;
341        
342         // calculate the difference in predicted ticks and
343         // measured ticks
344         diff -= delta_ticks_meas;
345        
346        
347         if (diff > 24000 || diff < -24000) { // approx +/-1 msec error
348             debugOutput(DEBUG_LEVEL_VERBOSE,"Bad pred (%p): diff=%d, dt_est=%u, dt_meas=%u, d=%dus, err=%fus\n", this,
349                 diff, delta_ticks_est, delta_ticks_meas, delta_usecs, (((float)diff)/24.576)
350                 );
351         } else {
352             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Good pred: diff=%d, dt_est=%u, dt_meas=%u, d=%dus, err=%fus\n",
353                 diff, delta_ticks_est, delta_ticks_meas, delta_usecs, (((float)diff)/24.576)
354                 );
355         }
356 #endif
357         // DLL the error to obtain the rate.
358         // (note: the DLL makes the error=0)
359         // only update the DLL if the rate is within 10% of the expected
360         // rate
361         float err=rate_meas-rate_est;
362        
363         // 2nd order DLL update
364 //         const float w=6.28*0.0001;
365 //         const float b=w*1.45;
366 //         const float c=w*w;
367 //         
368 //         m_ticks_per_usec += b*err + m_ticks_per_usec_dll_err2;
369 //         m_ticks_per_usec_dll_err2 += c * err;
370
371         // first order DLL update
372          m_ticks_per_usec += CC_DLL_COEFF*err;
373    
374         if (   (m_ticks_per_usec > 24.576*(1.0+CC_MAX_RATE_ERROR))
375             || (m_ticks_per_usec < 24.576*(1.0-CC_MAX_RATE_ERROR))) {
376             debugOutput(DEBUG_LEVEL_VERBOSE, "Warning: DLL ticks/usec near clipping (%8.4f)\n",
377                         m_ticks_per_usec);
378         }
379        
380         // update the internal values
381         // note: the next cyclecounter point is
382         //       the estimated one, not the measured one!
383         m_cyclecounter_ticks += delta_ticks_est;
384         // if we need to wrap, do it
385         if (m_cyclecounter_ticks > TICKS_PER_SECOND * 128) {
386             m_cyclecounter_ticks -= TICKS_PER_SECOND * 128;
387         }
388
389         m_lastmeas_usecs = new_usecs;
390
391         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"U TS: %10u -> %10u, d=%7uus, dt_est=%7u,  dt_meas=%7u, erate=%6.4f, mrate=%6f\n",
392               prev_ticks, m_cyclecounter_ticks, delta_usecs,
393               delta_ticks_est, delta_ticks_meas, m_ticks_per_usec, rate_meas
394               );
395
396         // the estimate is good
397         return true;
398     } else {
399         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"U TS: Not updating, rate out of range (%6.4f)\n",
400               rate_meas
401               );
402         return false;
403
404     }
405 }
406
407 void IsoHandler::initCycleCounter() {
408     quadlet_t buf=0;
409
410     freebob_microsecs_t prev_usecs;
411     unsigned int prev_ticks;
412     unsigned int prev_counter;
413    
414     freebob_microsecs_t new_usecs;
415     unsigned int new_ticks;
416     unsigned int new_counter;
417    
418     float rate=0.0;
419    
420     unsigned int try_cnt=0;
421    
422     // make sure that we start with a decent rate,
423     // meaning that we want two successive (usecs,ticks)
424     // points that make sense.
425    
426     while ( (try_cnt++ < CC_INIT_MAX_TRIES) &&
427            (   (rate > 24.576*(1.0+CC_MAX_RATE_ERROR))
428            || (rate < 24.576*(1.0-CC_MAX_RATE_ERROR)))) {
429            
430         // normally we should be able to use the same handle
431         // because it is not iterated on by any other stuff
432         // but I'm not sure
433         raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),
434             CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
435         prev_usecs=m_TimeSource->getCurrentTimeAsUsecs();
436        
437         prev_counter= ntohl(buf) & 0xFFFFFFFF;
438         prev_ticks=CYCLE_COUNTER_TO_TICKS(prev_counter);
439        
440         usleep(CC_SLEEP_TIME_AFTER_UPDATE);
441        
442         // normally we should be able to use the same handle
443         // because it is not iterated on by any other stuff
444         // but I'm not sure
445         raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),
446             CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
447         new_usecs=m_TimeSource->getCurrentTimeAsUsecs();
448
449         new_counter= ntohl(buf) & 0xFFFFFFFF;
450         new_ticks=CYCLE_COUNTER_TO_TICKS(new_counter);
451        
452         unsigned int delta_ticks;
453        
454         if (new_ticks > prev_ticks) {
455             delta_ticks=new_ticks - prev_ticks;
456         } else { // wraparound
457             delta_ticks=CYCLE_COUNTER_UNWRAP_TICKS(new_ticks) - prev_ticks;
458         }
459        
460         int delta_usecs=new_usecs-prev_usecs;
461        
462         // this cannot be 0, because m_TimeSource->getCurrentTimeAsUsecs should
463         // never return the same value (maybe in future terrahz processors?)
464         assert(delta_usecs);
465        
466         rate=((float)delta_ticks/(float)delta_usecs);
467        
468         // update the internal values
469         m_cyclecounter_ticks=new_ticks;
470         m_lastmeas_usecs=new_usecs;
471        
472         debugOutput(DEBUG_LEVEL_VERBOSE,"Try %d: rate=%6.4f\n",
473             try_cnt,rate
474             );
475
476     }
477    
478     // this is not fatal, the DLL will eventually correct this
479     if(try_cnt == CC_INIT_MAX_TRIES) {
480         debugWarning("Failed to properly initialize cycle counter...\n");
481     }
482    
483     // initialize this to the nominal value
484     m_ticks_per_usec = 24.576;
485     m_ticks_per_usec_dll_err2 = 0;
486    
487 }
488
489 void IsoHandler::dumpInfo()
490 {
491
492     int channel=-1;
493     if (m_Client) channel=m_Client->getChannel();
494
495     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type    : %s\n",
496             (this->getType()==EHT_Receive ? "Receive" : "Transmit"));
497     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel  : %2d, %2d\n",
498             m_port, channel);
499     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packet count   : %10d (%5d dropped)\n",
500             this->getPacketCount(), this->getDroppedCount());
501     #ifdef DEBUG
502     unsigned int cc=this->getCycleCounter();
503         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Cycle counter  : %10lu (%03us, %04ucycles, %04uticks)\n",
504             cc,TICKS_TO_SECS(cc),TICKS_TO_CYCLES(cc),TICKS_TO_OFFSET(cc));
505     #endif
506     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Ticks/usec     : %8.6f (dll2: %8.6e)\n\n",
507             this->getTicksPerUsec(), m_ticks_per_usec_dll_err2);
508
509 };
510
511 void IsoHandler::setVerboseLevel(int l)
512 {
513     setDebugLevel(l);
514 }
515
516 bool IsoHandler::registerStream(IsoStream *stream)
517 {
518     assert(stream);
519     debugOutput( DEBUG_LEVEL_VERBOSE, "registering stream (%p)\n", stream);
520
521     if (m_Client) {
522             debugFatal( "Generic IsoHandlers can have only one client\n");     
523             return false;
524     }
525
526     m_Client=stream;
527
528     m_Client->setHandler(this);
529
530     return true;
531
532 }
533
534 bool IsoHandler::unregisterStream(IsoStream *stream)
535 {
536     assert(stream);
537     debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering stream (%p)\n", stream);
538
539     if(stream != m_Client) {
540             debugFatal( "no client registered\n");     
541             return false;
542     }
543
544     m_Client->clearHandler();
545    
546     m_Client=0;
547     return true;
548
549 }
550
551 /* The timesource interface */
552 freebob_microsecs_t IsoHandler::getCurrentTime() {
553     quadlet_t buf=0;
554     unsigned int new_counter;
555    
556     raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),
557         CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
558    
559     new_counter= ntohl(buf) & 0xFFFFFFFF;
560        
561     // this assumes that it never happens that there are more than 2
562     // minutes between calls
563     if (CYCLE_COUNTER_GET_SECS(new_counter) < m_TimeSource_LastSecs) {
564         m_TimeSource_NbCycleWraps++;
565     }
566    
567     freebob_microsecs_t ticks=m_TimeSource_NbCycleWraps * 128 * TICKS_PER_SECOND
568             + CYCLE_COUNTER_TO_TICKS(new_counter);
569    
570     m_TimeSource_LastSecs=CYCLE_COUNTER_GET_SECS(new_counter);
571    
572     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Wraps=%4u, LastSecs=%3u, nowSecs=%3u, ticks=%10u\n",
573               m_TimeSource_NbCycleWraps, m_TimeSource_LastSecs,
574               CYCLE_COUNTER_GET_SECS(new_counter), ticks
575               );
576              
577     return  ticks;
578 }
579
580 freebob_microsecs_t IsoHandler::getCurrentTimeAsUsecs() {
581     float tmp=getCurrentTime();
582     float tmp2 = tmp * USECS_PER_TICK;
583     freebob_microsecs_t retval=(freebob_microsecs_t)tmp2;
584    
585     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"tmp=%f, tmp2=%f, retval=%u\n",
586               tmp, tmp2,retval
587               );
588    
589     return retval;
590 }
591
592
593
594 /* Child class implementations */
595
596 IsoRecvHandler::IsoRecvHandler(int port)
597                 : IsoHandler(port)
598 {
599     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
600 }
601 IsoRecvHandler::IsoRecvHandler(int port, unsigned int buf_packets,
602                                unsigned int max_packet_size, int irq)
603                 : IsoHandler(port, buf_packets,max_packet_size,irq)
604 {
605     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
606
607 }
608 IsoRecvHandler::~IsoRecvHandler()
609 {
610 // Don't call until libraw1394's raw1394_new_handle() function has been
611 // fixed to correctly initialise the iso_packet_infos field.  Bug is
612 // confirmed present in libraw1394 1.2.1.  In any case,
613 // raw1394_destroy_handle() will do any iso system shutdown required.
614 //      raw1394_iso_shutdown(m_handle);
615         raw1394_destroy_handle(m_handle);
616         m_handle = NULL;
617 }
618
619 bool
620 IsoRecvHandler::init() {
621     debugOutput( DEBUG_LEVEL_VERBOSE, "init recv handler %p\n",this);
622
623     if(!(IsoHandler::init())) {
624         return false;
625     }
626     return true;
627
628 }
629
630 enum raw1394_iso_disposition IsoRecvHandler::putPacket(unsigned char *data, unsigned int length,
631                     unsigned char channel, unsigned char tag, unsigned char sy,
632                     unsigned int cycle, unsigned int dropped) {
633
634     debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
635                  "received packet: length=%d, channel=%d, cycle=%d\n",
636                  length, channel, cycle );
637     m_packetcount++;
638     m_dropped+=dropped;
639
640     if(m_Client) {
641         return m_Client->putPacket(data, length, channel, tag, sy, cycle, dropped);
642     }
643    
644     return RAW1394_ISO_OK;
645 }
646
647 bool IsoRecvHandler::prepare()
648 {
649 // Don't call until libraw1394's raw1394_new_handle() function has been
650 // fixed to correctly initialise the iso_packet_infos field.  Bug is
651 // confirmed present in libraw1394 1.2.1.
652 //      raw1394_iso_shutdown(m_handle);
653
654     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso receive handler (%p)\n",this);
655     debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n",m_buf_packets);
656     debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n",m_max_packet_size);
657     debugOutput( DEBUG_LEVEL_VERBOSE, " Channel         : %d \n",m_Client->getChannel());
658     debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n",m_irq_interval);
659
660         if(raw1394_iso_recv_init(m_handle,   iso_receive_handler,
661                              m_buf_packets,
662                              m_max_packet_size,
663                              m_Client->getChannel(),
664                              RAW1394_DMA_BUFFERFILL,
665                              m_irq_interval)) {
666         debugFatal("Could not do receive initialisation!\n" );
667         debugFatal("  %s\n",strerror(errno));
668
669         return false;
670     }
671     return true;
672 }
673
674 bool IsoRecvHandler::start(int cycle)
675 {
676     debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
677    
678     if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) {
679         debugFatal("Could not start receive handler (%s)\n",strerror(errno));
680         return false;
681     }
682     return true;
683 }
684
685 int IsoRecvHandler::handleBusReset(unsigned int generation) {
686     debugOutput( DEBUG_LEVEL_VERBOSE, "handle bus reset...\n");
687    
688     //TODO: implement busreset
689    
690     // pass on the busreset signal
691     if(IsoHandler::handleBusReset(generation)) {
692         return -1;
693     }
694     return 0;
695 }
696
697 /* ----------------- XMIT --------------- */
698
699 IsoXmitHandler::IsoXmitHandler(int port)
700                 : IsoHandler(port), m_prebuffers(0)
701 {
702     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
703
704 }
705 IsoXmitHandler::IsoXmitHandler(int port, unsigned int buf_packets,
706                                unsigned int max_packet_size, int irq)
707                 : IsoHandler(port, buf_packets, max_packet_size,irq),
708                   m_speed(RAW1394_ISO_SPEED_400), m_prebuffers(0)
709 {
710     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
711
712 }
713 IsoXmitHandler::IsoXmitHandler(int port, unsigned int buf_packets,
714                                unsigned int max_packet_size, int irq,
715                                enum raw1394_iso_speed speed)
716                 : IsoHandler(port, buf_packets,max_packet_size,irq),
717                   m_speed(speed), m_prebuffers(0)
718 {
719     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
720
721 }
722
723 IsoXmitHandler::~IsoXmitHandler()
724 {
725 // Don't call until libraw1394's raw1394_new_handle() function has been
726 // fixed to correctly initialise the iso_packet_infos field.  Bug is
727 // confirmed present in libraw1394 1.2.1.  In any case,
728 // raw1394_destroy_handle() will do any iso system shutdown required.
729 //      raw1394_iso_shutdown(m_handle);
730         raw1394_destroy_handle(m_handle);
731         m_handle = NULL;
732 }
733
734 bool
735 IsoXmitHandler::init() {
736
737     debugOutput( DEBUG_LEVEL_VERBOSE, "init xmit handler %p\n",this);
738
739     if(!(IsoHandler::init())) {
740         return false;
741     }
742
743     return true;
744
745 }
746
747 enum raw1394_iso_disposition IsoXmitHandler::getPacket(unsigned char *data, unsigned int *length,
748                               unsigned char *tag, unsigned char *sy,
749                               int cycle, unsigned int dropped) {
750
751         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
752                      "sending packet: length=%d, cycle=%d\n",
753                      *length, cycle );
754         m_packetcount++;
755         m_dropped+=dropped;
756
757         if(m_Client) {
758         return m_Client->getPacket(data, length, tag, sy, cycle, dropped, m_max_packet_size);
759         }
760        
761         return RAW1394_ISO_OK;
762 }
763
764 bool IsoXmitHandler::prepare()
765 {
766     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso transmit handler (%p, client=%p)\n",this,m_Client);
767
768 //      raw1394_iso_shutdown(m_handle);
769     debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n",m_buf_packets);
770     debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n",m_max_packet_size);
771     debugOutput( DEBUG_LEVEL_VERBOSE, " Channel         : %d \n",m_Client->getChannel());
772     debugOutput( DEBUG_LEVEL_VERBOSE, " Speed           : %d \n",m_speed);
773     debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n",m_irq_interval);
774
775     if(raw1394_iso_xmit_init(m_handle,
776                              iso_transmit_handler,
777                              m_buf_packets,
778                              m_max_packet_size,
779                              m_Client->getChannel(),
780                              m_speed,
781                              m_irq_interval)) {
782         debugFatal("Could not do xmit initialisation!\n" );
783
784         return false;
785     }
786
787     return true;
788 }
789
790 bool IsoXmitHandler::start(int cycle)
791 {
792     debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
793     if(raw1394_iso_xmit_start(m_handle, cycle, m_prebuffers)) {
794         debugFatal("Could not start xmit handler (%s)\n",strerror(errno));
795         return false;
796     }
797     return true;
798 }
799
800 int IsoXmitHandler::handleBusReset(unsigned int generation) {
801     debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n");
802     //TODO: implement busreset
803    
804     // pass on the busreset signal
805     if(IsoHandler::handleBusReset(generation)) {
806             return -1;
807     }
808    
809     return 0;
810 }
811
812 }
813
814 /* multichannel receive  */
815 #if 0
816 IsoRecvHandler::IsoRecvHandler(int port)
817                 : IsoHandler(port)
818 {
819         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
820 }
821 IsoRecvHandler::IsoRecvHandler(int port, unsigned int buf_packets,
822                                unsigned int max_packet_size, int irq)
823                 : IsoHandler(port, buf_packets,max_packet_size,irq)
824 {
825         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
826
827 }
828 IsoRecvHandler::~IsoRecvHandler()
829 {
830 // Don't call until libraw1394's raw1394_new_handle() function has been
831 // fixed to correctly initialise the iso_packet_infos field.  Bug is
832 // confirmed present in libraw1394 1.2.1.  In any case,
833 // raw1394_destroy_handle() (in the base class destructor) will do any iso
834 // system shutdown required.
835         raw1394_iso_shutdown(m_handle);
836
837 }
838
839 bool
840 IsoRecvHandler::initialize() {
841         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
842
843         IsoHandler *base=static_cast<IsoHandler *>(this);
844
845         if(!(base->initialize())) {
846                 return false;
847         }
848
849         raw1394_set_userdata(m_handle, static_cast<void *>(this));
850
851         if(raw1394_iso_multichannel_recv_init(m_handle,
852                                          iso_receive_handler,
853                                          m_buf_packets,
854                                          m_max_packet_size,
855                                          m_irq_interval)) {
856                 debugFatal("Could not do multichannel receive initialisation!\n" );
857
858                 return false;
859         }
860
861         return true;
862
863 }
864
865 enum raw1394_iso_disposition IsoRecvHandler::putPacket(unsigned char *data, unsigned int length,
866                               unsigned char channel, unsigned char tag, unsigned char sy,
867                                   unsigned int cycle, unsigned int dropped) {
868
869         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
870                      "received packet: length=%d, channel=%d, cycle=%d\n",
871                      length, channel, cycle );
872        
873         return RAW1394_ISO_OK;
874 }
875
876 // an recv handler can have multiple destination IsoStreams
877 // NOTE: this implementation even allows for already registered
878 // streams to be registered again.
879 int IsoRecvHandler::registerStream(IsoRecvStream *stream)
880 {
881         assert(stream);
882         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
883
884         m_Clients.push_back(stream);
885
886         listen(stream->getChannel());
887         return 0;
888
889 }
890
891 int IsoRecvHandler::unregisterStream(IsoRecvStream *stream)
892 {
893         assert(stream);
894         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
895
896     for ( IsoRecvStreamVectorIterator it = m_Clients.begin();
897           it != m_Clients.end();
898           ++it )
899     {
900         IsoRecvStream* s = *it;
901         if ( s == stream ) {
902                         unListen(s->getChannel());
903             m_Clients.erase(it);
904                         return 0;
905         }
906     }
907
908         return -1; //not found
909
910 }
911
912 void IsoRecvHandler::listen(int channel) {
913         int retval;
914         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
915
916         retval=raw1394_iso_recv_listen_channel(m_handle, channel);
917
918 }
919
920 void IsoRecvHandler::unListen(int channel) {
921         int retval;
922         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
923
924         retval=raw1394_iso_recv_unlisten_channel(m_handle, channel);
925
926 }
927
928 int IsoRecvHandler::start(int cycle)
929 {
930         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
931         return raw1394_iso_recv_start(m_handle, cycle, -1, 0);
932 }
933 #endif
Note: See TracBrowser for help on using the browser.