root/branches/libfreebob-2.0/src/libstreaming/IsoHandler.cpp

Revision 309, 14.9 kB (checked in by jwoithe, 18 years ago)

MOTU: Fixed false "missed rx cycle" report following xrun recovery.
Ensure iso rx/tx contexts are deallocated during shutdown/xrun recovery by explicitly deleting IsoHandlers? in IsoHandlerManager::pruneHandlers(). If they aren't deleted here they never get deleted because the reference is lost.
IsoHandler? destructor should only call stop() if the handle is valid.
IsoXmitHandler?'s destructor sets the handle NULL to prevent double-free by the inherited IsoHandler? destructor.
Don't call raw1394_iso_shutdown() from our code. libraw1394 1.2.1 has a bug whereby raw1394_new_handle() fails to initialise the iso_packet_infos field. The bug hits us particularly in IsoRecvHandler::prepare(). It's also not really necessary to call raw1394_iso_shutdown() since raw1394_destroy_handle() will do any cleanups we happen to need.
MOTU: the receive stream no longer falsely complains of buffer problems during device shutdown.
MOTU: fixed a false "missed cycle" detection immediately after the stream was enabled.

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 <errno.h>
32 #include <netinet/in.h>
33 #include <assert.h>
34
35
36 #include <iostream>
37 using namespace std;
38
39
40 namespace FreebobStreaming
41 {
42
43 IMPL_DEBUG_MODULE( IsoHandler, IsoHandler, DEBUG_LEVEL_NORMAL );
44
45 /* the C callbacks */
46 enum raw1394_iso_disposition
47 IsoXmitHandler::iso_transmit_handler(raw1394handle_t handle,
48                 unsigned char *data, unsigned int *length,
49                 unsigned char *tag, unsigned char *sy,
50                 int cycle, unsigned int dropped) {
51
52         IsoXmitHandler *xmitHandler=static_cast<IsoXmitHandler *>(raw1394_get_userdata(handle));
53         assert(xmitHandler);
54
55         return xmitHandler->getPacket(data, length, tag, sy, cycle, dropped);
56 }
57
58 enum raw1394_iso_disposition
59 IsoRecvHandler::iso_receive_handler(raw1394handle_t handle, unsigned char *data,
60                                                 unsigned int length, unsigned char channel,
61                                                 unsigned char tag, unsigned char sy, unsigned int cycle,
62                                                 unsigned int dropped) {
63
64         IsoRecvHandler *recvHandler=static_cast<IsoRecvHandler *>(raw1394_get_userdata(handle));
65         assert(recvHandler);
66
67         return recvHandler->putPacket(data, length, channel, tag, sy, cycle, dropped);
68 }
69
70 int IsoHandler::busreset_handler(raw1394handle_t handle, unsigned int generation)
71 {       
72         debugOutput( DEBUG_LEVEL_VERBOSE, "Busreset happened, generation %d...\n", generation);
73
74         IsoHandler *handler=static_cast<IsoHandler *>(raw1394_get_userdata(handle));
75         assert(handler);
76         return handler->handleBusReset(generation);
77 }
78
79
80 /* Base class implementation */
81
82 IsoHandler::~IsoHandler() {
83     if(m_handle) {
84         stop();
85         raw1394_destroy_handle(m_handle);
86     }
87     if(m_handle_util) raw1394_destroy_handle(m_handle_util);
88    
89 }
90
91 bool
92 IsoHandler::init()
93 {
94         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) enter...\n",this);
95
96         m_handle = raw1394_new_handle_on_port( m_port );
97         if ( !m_handle ) {
98                 if ( !errno ) {
99                         cerr << "libraw1394 not compatible" << endl;
100                 } else {
101                         perror( "IsoHandler::Initialize: Could not get 1394 handle" );
102                         cerr << "Is ieee1394 and raw1394 driver loaded?" << endl;
103                 }
104                 return false;
105         }
106         raw1394_set_userdata(m_handle, static_cast<void *>(this));
107        
108         // a second handle for utility stuff
109         m_handle_util = raw1394_new_handle_on_port( m_port );
110         if ( !m_handle_util ) {
111                 if ( !errno ) {
112                         cerr << "libraw1394 not compatible" << endl;
113                 } else {
114                         perror( "IsoHandler::Initialize: Could not get 1394 handle" );
115                         cerr << "Is ieee1394 and raw1394 driver loaded?" << endl;
116                 }
117                 return false;
118         }
119        
120         raw1394_set_userdata(m_handle_util, static_cast<void *>(this));
121        
122         if(raw1394_busreset_notify (m_handle, RAW1394_NOTIFY_ON)) {
123                 debugWarning("Could not enable busreset notification.\n");
124                 debugWarning(" Error message: %s\n",strerror(errno));
125         }
126        
127         raw1394_set_bus_reset_handler(m_handle, busreset_handler);
128
129         return true;
130 }
131
132 bool IsoHandler::stop()
133 {
134         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
135         raw1394_iso_stop(m_handle);
136         return true;
137 }
138
139 /**
140  * Returns the current value of the cycle counter
141  *
142  * @return the current value of the cycle counter
143  */
144 #define CSR_CYCLE_TIME            0x200
145 #define CSR_REGISTER_BASE  0xfffff0000000ULL
146
147 unsigned int IsoHandler::getCycleCounter() {
148     quadlet_t buf=0;
149    
150     // normally we should be able to use the same handle
151     // because it is not iterated on by any other stuff
152     // but I'm not sure
153     raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),
154         CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
155        
156     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Current timestamp: %08X = %u\n",buf, ntohl(buf));
157    
158     return ntohl(buf) & 0xFFFFFFFF;
159 }
160
161 void IsoHandler::dumpInfo()
162 {
163
164         int channel=-1;
165         if (m_Client) channel=m_Client->getChannel();
166
167         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type    : %s\n",
168              (this->getType()==EHT_Receive ? "Receive" : "Transmit"));
169         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel  : %d, %d\n",
170              m_port, channel);
171         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packet count   : %d (%d dropped)\n\n",
172              this->getPacketCount(), this->getDroppedCount());
173
174 };
175
176 void IsoHandler::setVerboseLevel(int l)
177 {
178         setDebugLevel(l);
179 }
180
181 bool IsoHandler::registerStream(IsoStream *stream)
182 {
183         assert(stream);
184         debugOutput( DEBUG_LEVEL_VERBOSE, "registering stream (%p)\n", stream);
185
186         if (m_Client) {
187                 debugFatal( "Generic IsoHandlers can have only one client\n"); 
188                 return false;
189         }
190
191         m_Client=stream;
192
193         m_Client->setHandler(this);
194
195         return true;
196
197 }
198
199 bool IsoHandler::unregisterStream(IsoStream *stream)
200 {
201         assert(stream);
202         debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering stream (%p)\n", stream);
203
204         if(stream != m_Client) {
205                 debugFatal( "no client registered\n"); 
206                 return false;
207         }
208
209         m_Client->clearHandler();
210        
211         m_Client=0;
212         return true;
213
214 }
215
216 /* Child class implementations */
217
218 IsoRecvHandler::IsoRecvHandler(int port)
219                 : IsoHandler(port)
220 {
221         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
222 }
223 IsoRecvHandler::IsoRecvHandler(int port, unsigned int buf_packets,
224                                unsigned int max_packet_size, int irq)
225                 : IsoHandler(port, buf_packets,max_packet_size,irq)
226 {
227         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
228
229 }
230 IsoRecvHandler::~IsoRecvHandler()
231 {
232 // Don't call until libraw1394's raw1394_new_handle() function has been
233 // fixed to correctly initialise the iso_packet_infos field.  Bug is
234 // confirmed present in libraw1394 1.2.1.  In any case,
235 // raw1394_destroy_handle() will do any iso system shutdown required.
236 //      raw1394_iso_shutdown(m_handle);
237         raw1394_destroy_handle(m_handle);
238         m_handle = NULL;
239 }
240
241 bool
242 IsoRecvHandler::init() {
243         debugOutput( DEBUG_LEVEL_VERBOSE, "init recv handler %p\n",this);
244
245         if(!(IsoHandler::init())) {
246                 return false;
247         }
248         return true;
249
250 }
251
252 enum raw1394_iso_disposition IsoRecvHandler::putPacket(unsigned char *data, unsigned int length,
253                               unsigned char channel, unsigned char tag, unsigned char sy,
254                                   unsigned int cycle, unsigned int dropped) {
255
256         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
257                      "received packet: length=%d, channel=%d, cycle=%d\n",
258                      length, channel, cycle );
259         m_packetcount++;
260         m_dropped+=dropped;
261
262         if(m_Client) {
263                 return m_Client->putPacket(data, length, channel, tag, sy, cycle, dropped);
264         }
265        
266         return RAW1394_ISO_OK;
267 }
268
269 bool IsoRecvHandler::prepare()
270 {
271 // Don't call until libraw1394's raw1394_new_handle() function has been
272 // fixed to correctly initialise the iso_packet_infos field.  Bug is
273 // confirmed present in libraw1394 1.2.1.
274 //      raw1394_iso_shutdown(m_handle);
275        
276         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso receive handler (%p)\n",this);
277         debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n",m_buf_packets);
278         debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n",m_max_packet_size);
279         debugOutput( DEBUG_LEVEL_VERBOSE, " Channel         : %d \n",m_Client->getChannel());
280         debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n",m_irq_interval);
281
282         if(raw1394_iso_recv_init(m_handle,   iso_receive_handler,
283                                          m_buf_packets,
284                                          m_max_packet_size,
285                                              m_Client->getChannel(),
286                                              RAW1394_DMA_BUFFERFILL,
287                                          m_irq_interval)) {
288                 debugFatal("Could not do receive initialisation!\n" );
289                 debugFatal("  %s\n",strerror(errno));
290
291                 return false;
292         }
293         return true;
294 }
295
296 bool IsoRecvHandler::start(int cycle)
297 {
298         debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
299        
300         if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) {
301                 debugFatal("Could not start receive handler (%s)\n",strerror(errno));
302                 return false;
303         }
304         return true;
305 }
306
307 int IsoRecvHandler::handleBusReset(unsigned int generation) {
308         debugOutput( DEBUG_LEVEL_VERBOSE, "handle bus reset...\n");
309         //TODO: implement busreset
310         return 0;
311 }
312
313 /* ----------------- XMIT --------------- */
314
315 IsoXmitHandler::IsoXmitHandler(int port)
316                 : IsoHandler(port), m_prebuffers(0)
317 {
318         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
319
320 }
321 IsoXmitHandler::IsoXmitHandler(int port, unsigned int buf_packets,
322                                unsigned int max_packet_size, int irq)
323                 : IsoHandler(port, buf_packets, max_packet_size,irq),
324                   m_speed(RAW1394_ISO_SPEED_400), m_prebuffers(0)
325 {
326         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
327
328 }
329 IsoXmitHandler::IsoXmitHandler(int port, unsigned int buf_packets,
330                                unsigned int max_packet_size, int irq,
331                                enum raw1394_iso_speed speed)
332                 : IsoHandler(port, buf_packets,max_packet_size,irq),
333                   m_speed(speed), m_prebuffers(0)
334 {
335         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
336
337 }
338
339 IsoXmitHandler::~IsoXmitHandler()
340 {
341 // Don't call until libraw1394's raw1394_new_handle() function has been
342 // fixed to correctly initialise the iso_packet_infos field.  Bug is
343 // confirmed present in libraw1394 1.2.1.  In any case,
344 // raw1394_destroy_handle() will do any iso system shutdown required.
345 //      raw1394_iso_shutdown(m_handle);
346         raw1394_destroy_handle(m_handle);
347         m_handle = NULL;
348 }
349
350 bool
351 IsoXmitHandler::init() {
352
353         debugOutput( DEBUG_LEVEL_VERBOSE, "init xmit handler %p\n",this);
354
355         if(!(IsoHandler::init())) {
356                 return false;
357         }
358
359         return true;
360
361 }
362
363 enum raw1394_iso_disposition IsoXmitHandler::getPacket(unsigned char *data, unsigned int *length,
364                               unsigned char *tag, unsigned char *sy,
365                               int cycle, unsigned int dropped) {
366
367         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
368                      "sending packet: length=%d, cycle=%d\n",
369                      *length, cycle );
370         m_packetcount++;
371         m_dropped+=dropped;
372
373         if(m_Client) {
374         return m_Client->getPacket(data, length, tag, sy, cycle, dropped, m_max_packet_size);
375         }
376        
377         return RAW1394_ISO_OK;
378 }
379
380 bool IsoXmitHandler::prepare()
381 {
382         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso transmit handler (%p, client=%p)\n",this,m_Client);
383        
384 //      raw1394_iso_shutdown(m_handle);
385         debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n",m_buf_packets);
386         debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n",m_max_packet_size);
387         debugOutput( DEBUG_LEVEL_VERBOSE, " Channel         : %d \n",m_Client->getChannel());
388         debugOutput( DEBUG_LEVEL_VERBOSE, " Speed           : %d \n",m_speed);
389         debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n",m_irq_interval);
390
391         if(raw1394_iso_xmit_init(m_handle,
392                              iso_transmit_handler,
393                              m_buf_packets,
394                              m_max_packet_size,
395                                  m_Client->getChannel(),
396                                  m_speed,
397                              m_irq_interval)) {
398                 debugFatal("Could not do xmit initialisation!\n" );
399
400                 return false;
401         }
402
403         return true;
404 }
405
406 bool IsoXmitHandler::start(int cycle)
407 {
408         debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
409         if(raw1394_iso_xmit_start(m_handle, cycle, m_prebuffers)) {
410                 debugFatal("Could not start xmit handler (%s)\n",strerror(errno));
411                 return false;
412         }
413         return true;
414 }
415
416 int IsoXmitHandler::handleBusReset(unsigned int generation) {
417         debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n");
418         //TODO: implement busreset
419         return 0;
420 }
421
422 }
423
424 /* multichannel receive  */
425 #if 0
426 IsoRecvHandler::IsoRecvHandler(int port)
427                 : IsoHandler(port)
428 {
429         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
430 }
431 IsoRecvHandler::IsoRecvHandler(int port, unsigned int buf_packets,
432                                unsigned int max_packet_size, int irq)
433                 : IsoHandler(port, buf_packets,max_packet_size,irq)
434 {
435         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
436
437 }
438 IsoRecvHandler::~IsoRecvHandler()
439 {
440 // Don't call until libraw1394's raw1394_new_handle() function has been
441 // fixed to correctly initialise the iso_packet_infos field.  Bug is
442 // confirmed present in libraw1394 1.2.1.  In any case,
443 // raw1394_destroy_handle() (in the base class destructor) will do any iso
444 // system shutdown required.
445         raw1394_iso_shutdown(m_handle);
446
447 }
448
449 bool
450 IsoRecvHandler::initialize() {
451         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
452
453         IsoHandler *base=static_cast<IsoHandler *>(this);
454
455         if(!(base->initialize())) {
456                 return false;
457         }
458
459         raw1394_set_userdata(m_handle, static_cast<void *>(this));
460
461         if(raw1394_iso_multichannel_recv_init(m_handle,
462                                          iso_receive_handler,
463                                          m_buf_packets,
464                                          m_max_packet_size,
465                                          m_irq_interval)) {
466                 debugFatal("Could not do multichannel receive initialisation!\n" );
467
468                 return false;
469         }
470
471         return true;
472
473 }
474
475 enum raw1394_iso_disposition IsoRecvHandler::putPacket(unsigned char *data, unsigned int length,
476                               unsigned char channel, unsigned char tag, unsigned char sy,
477                                   unsigned int cycle, unsigned int dropped) {
478
479         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
480                      "received packet: length=%d, channel=%d, cycle=%d\n",
481                      length, channel, cycle );
482        
483         return RAW1394_ISO_OK;
484 }
485
486 // an recv handler can have multiple destination IsoStreams
487 // NOTE: this implementation even allows for already registered
488 // streams to be registered again.
489 int IsoRecvHandler::registerStream(IsoRecvStream *stream)
490 {
491         assert(stream);
492         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
493
494         m_Clients.push_back(stream);
495
496         listen(stream->getChannel());
497         return 0;
498
499 }
500
501 int IsoRecvHandler::unregisterStream(IsoRecvStream *stream)
502 {
503         assert(stream);
504         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
505
506     for ( IsoRecvStreamVectorIterator it = m_Clients.begin();
507           it != m_Clients.end();
508           ++it )
509     {
510         IsoRecvStream* s = *it;
511         if ( s == stream ) {
512                         unListen(s->getChannel());
513             m_Clients.erase(it);
514                         return 0;
515         }
516     }
517
518         return -1; //not found
519
520 }
521
522 void IsoRecvHandler::listen(int channel) {
523         int retval;
524         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
525
526         retval=raw1394_iso_recv_listen_channel(m_handle, channel);
527
528 }
529
530 void IsoRecvHandler::unListen(int channel) {
531         int retval;
532         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
533
534         retval=raw1394_iso_recv_unlisten_channel(m_handle, channel);
535
536 }
537
538 int IsoRecvHandler::start(int cycle)
539 {
540         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
541         return raw1394_iso_recv_start(m_handle, cycle, -1, 0);
542 }
543 #endif
Note: See TracBrowser for help on using the browser.