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

Revision 341, 15.7 kB (checked in by pieterpalmers, 17 years ago)

- changed bebob avdevice to use debugmodule instead of printf/cout
- fixed some minor merge side-effects
- implement a RT safe mechanism to obtain the cycle counter.

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 #include <unistd.h>
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     // update the cycle counter value for initial value
130     updateCycleCounter();
131
132         return true;
133 }
134
135 bool IsoHandler::stop()
136 {
137         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
138         raw1394_iso_stop(m_handle);
139         return true;
140 }
141
142 /**
143  * Returns the current value of the cycle counter
144  *
145  * @return the current value of the cycle counter
146  */
147 #define CSR_CYCLE_TIME            0x200
148 #define CSR_REGISTER_BASE  0xfffff0000000ULL
149
150 #define CYCLE_COUNTER_GET_SECS(x)   (((x & 0xFE000000) >> 25))
151 #define CYCLE_COUNTER_GET_CYCLES(x) (((x & 0x01FFF000) >> 12))
152 #define CYCLE_COUNTER_GET_TICKS(x)  (((x & 0x00000FFF)))
153 #define CYCLE_COUNTER_TO_TICKS(x) ((CYCLE_COUNTER_GET_SECS(x)   * 24576000) +\
154                                    (CYCLE_COUNTER_GET_CYCLES(x) *     3072) +\
155                                    (CYCLE_COUNTER_GET_TICKS(x)            ))
156
157 unsigned int IsoHandler::getCycleCounter() {
158      return m_cyclecounter;
159 }
160
161 void IsoHandler::updateCycleCounter() {
162     quadlet_t buf=0;
163    
164     // normally we should be able to use the same handle
165     // because it is not iterated on by any other stuff
166     // but I'm not sure
167     raw1394_read(m_handle_util, raw1394_get_local_id(m_handle_util),
168         CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
169    
170     m_cyclecounter= ntohl(buf) & 0xFFFFFFFF;
171    
172 //     debugOutput(DEBUG_LEVEL_VERBOSE,"Updating timestamp: %08X (%2u sec + %2u cycles + %04u ticks)\n",
173 //           m_cyclecounter,
174 //           CYCLE_COUNTER_GET_SECS(m_cyclecounter),
175 //           CYCLE_COUNTER_GET_CYCLES(m_cyclecounter),
176 //           CYCLE_COUNTER_GET_TICKS(m_cyclecounter)
177 //           );   
178    
179    
180     usleep(100);
181 }
182
183 void IsoHandler::dumpInfo()
184 {
185
186         int channel=-1;
187         if (m_Client) channel=m_Client->getChannel();
188
189         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type    : %s\n",
190              (this->getType()==EHT_Receive ? "Receive" : "Transmit"));
191         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel  : %d, %d\n",
192              m_port, channel);
193         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packet count   : %d (%d dropped)\n\n",
194              this->getPacketCount(), this->getDroppedCount());
195
196 };
197
198 void IsoHandler::setVerboseLevel(int l)
199 {
200         setDebugLevel(l);
201 }
202
203 bool IsoHandler::registerStream(IsoStream *stream)
204 {
205         assert(stream);
206         debugOutput( DEBUG_LEVEL_VERBOSE, "registering stream (%p)\n", stream);
207
208         if (m_Client) {
209                 debugFatal( "Generic IsoHandlers can have only one client\n"); 
210                 return false;
211         }
212
213         m_Client=stream;
214
215         m_Client->setHandler(this);
216
217         return true;
218
219 }
220
221 bool IsoHandler::unregisterStream(IsoStream *stream)
222 {
223         assert(stream);
224         debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering stream (%p)\n", stream);
225
226         if(stream != m_Client) {
227                 debugFatal( "no client registered\n"); 
228                 return false;
229         }
230
231         m_Client->clearHandler();
232        
233         m_Client=0;
234         return true;
235
236 }
237
238 /* Child class implementations */
239
240 IsoRecvHandler::IsoRecvHandler(int port)
241                 : IsoHandler(port)
242 {
243         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
244 }
245 IsoRecvHandler::IsoRecvHandler(int port, unsigned int buf_packets,
246                                unsigned int max_packet_size, int irq)
247                 : IsoHandler(port, buf_packets,max_packet_size,irq)
248 {
249         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
250
251 }
252 IsoRecvHandler::~IsoRecvHandler()
253 {
254 // Don't call until libraw1394's raw1394_new_handle() function has been
255 // fixed to correctly initialise the iso_packet_infos field.  Bug is
256 // confirmed present in libraw1394 1.2.1.  In any case,
257 // raw1394_destroy_handle() will do any iso system shutdown required.
258 //      raw1394_iso_shutdown(m_handle);
259         raw1394_destroy_handle(m_handle);
260         m_handle = NULL;
261 }
262
263 bool
264 IsoRecvHandler::init() {
265         debugOutput( DEBUG_LEVEL_VERBOSE, "init recv handler %p\n",this);
266
267         if(!(IsoHandler::init())) {
268                 return false;
269         }
270         return true;
271
272 }
273
274 enum raw1394_iso_disposition IsoRecvHandler::putPacket(unsigned char *data, unsigned int length,
275                               unsigned char channel, unsigned char tag, unsigned char sy,
276                                   unsigned int cycle, unsigned int dropped) {
277
278         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
279                      "received packet: length=%d, channel=%d, cycle=%d\n",
280                      length, channel, cycle );
281         m_packetcount++;
282         m_dropped+=dropped;
283
284         if(m_Client) {
285                 return m_Client->putPacket(data, length, channel, tag, sy, cycle, dropped);
286         }
287        
288         return RAW1394_ISO_OK;
289 }
290
291 bool IsoRecvHandler::prepare()
292 {
293 // Don't call until libraw1394's raw1394_new_handle() function has been
294 // fixed to correctly initialise the iso_packet_infos field.  Bug is
295 // confirmed present in libraw1394 1.2.1.
296 //      raw1394_iso_shutdown(m_handle);
297        
298         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso receive handler (%p)\n",this);
299         debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n",m_buf_packets);
300         debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n",m_max_packet_size);
301         debugOutput( DEBUG_LEVEL_VERBOSE, " Channel         : %d \n",m_Client->getChannel());
302         debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n",m_irq_interval);
303
304         if(raw1394_iso_recv_init(m_handle,   iso_receive_handler,
305                                          m_buf_packets,
306                                          m_max_packet_size,
307                                              m_Client->getChannel(),
308                                              RAW1394_DMA_BUFFERFILL,
309                                          m_irq_interval)) {
310                 debugFatal("Could not do receive initialisation!\n" );
311                 debugFatal("  %s\n",strerror(errno));
312
313                 return false;
314         }
315         return true;
316 }
317
318 bool IsoRecvHandler::start(int cycle)
319 {
320         debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
321        
322         if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) {
323                 debugFatal("Could not start receive handler (%s)\n",strerror(errno));
324                 return false;
325         }
326         return true;
327 }
328
329 int IsoRecvHandler::handleBusReset(unsigned int generation) {
330         debugOutput( DEBUG_LEVEL_VERBOSE, "handle bus reset...\n");
331         //TODO: implement busreset
332         return 0;
333 }
334
335 /* ----------------- XMIT --------------- */
336
337 IsoXmitHandler::IsoXmitHandler(int port)
338                 : IsoHandler(port), m_prebuffers(0)
339 {
340         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
341
342 }
343 IsoXmitHandler::IsoXmitHandler(int port, unsigned int buf_packets,
344                                unsigned int max_packet_size, int irq)
345                 : IsoHandler(port, buf_packets, max_packet_size,irq),
346                   m_speed(RAW1394_ISO_SPEED_400), m_prebuffers(0)
347 {
348         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
349
350 }
351 IsoXmitHandler::IsoXmitHandler(int port, unsigned int buf_packets,
352                                unsigned int max_packet_size, int irq,
353                                enum raw1394_iso_speed speed)
354                 : IsoHandler(port, buf_packets,max_packet_size,irq),
355                   m_speed(speed), m_prebuffers(0)
356 {
357         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
358
359 }
360
361 IsoXmitHandler::~IsoXmitHandler()
362 {
363 // Don't call until libraw1394's raw1394_new_handle() function has been
364 // fixed to correctly initialise the iso_packet_infos field.  Bug is
365 // confirmed present in libraw1394 1.2.1.  In any case,
366 // raw1394_destroy_handle() will do any iso system shutdown required.
367 //      raw1394_iso_shutdown(m_handle);
368         raw1394_destroy_handle(m_handle);
369         m_handle = NULL;
370 }
371
372 bool
373 IsoXmitHandler::init() {
374
375         debugOutput( DEBUG_LEVEL_VERBOSE, "init xmit handler %p\n",this);
376
377         if(!(IsoHandler::init())) {
378                 return false;
379         }
380
381         return true;
382
383 }
384
385 enum raw1394_iso_disposition IsoXmitHandler::getPacket(unsigned char *data, unsigned int *length,
386                               unsigned char *tag, unsigned char *sy,
387                               int cycle, unsigned int dropped) {
388
389         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
390                      "sending packet: length=%d, cycle=%d\n",
391                      *length, cycle );
392         m_packetcount++;
393         m_dropped+=dropped;
394
395         if(m_Client) {
396         return m_Client->getPacket(data, length, tag, sy, cycle, dropped, m_max_packet_size);
397         }
398        
399         return RAW1394_ISO_OK;
400 }
401
402 bool IsoXmitHandler::prepare()
403 {
404         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso transmit handler (%p, client=%p)\n",this,m_Client);
405        
406 //      raw1394_iso_shutdown(m_handle);
407         debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n",m_buf_packets);
408         debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n",m_max_packet_size);
409         debugOutput( DEBUG_LEVEL_VERBOSE, " Channel         : %d \n",m_Client->getChannel());
410         debugOutput( DEBUG_LEVEL_VERBOSE, " Speed           : %d \n",m_speed);
411         debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n",m_irq_interval);
412
413         if(raw1394_iso_xmit_init(m_handle,
414                              iso_transmit_handler,
415                              m_buf_packets,
416                              m_max_packet_size,
417                                  m_Client->getChannel(),
418                                  m_speed,
419                              m_irq_interval)) {
420                 debugFatal("Could not do xmit initialisation!\n" );
421
422                 return false;
423         }
424
425         return true;
426 }
427
428 bool IsoXmitHandler::start(int cycle)
429 {
430         debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
431         if(raw1394_iso_xmit_start(m_handle, cycle, m_prebuffers)) {
432                 debugFatal("Could not start xmit handler (%s)\n",strerror(errno));
433                 return false;
434         }
435         return true;
436 }
437
438 int IsoXmitHandler::handleBusReset(unsigned int generation) {
439         debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n");
440         //TODO: implement busreset
441         return 0;
442 }
443
444 }
445
446 /* multichannel receive  */
447 #if 0
448 IsoRecvHandler::IsoRecvHandler(int port)
449                 : IsoHandler(port)
450 {
451         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
452 }
453 IsoRecvHandler::IsoRecvHandler(int port, unsigned int buf_packets,
454                                unsigned int max_packet_size, int irq)
455                 : IsoHandler(port, buf_packets,max_packet_size,irq)
456 {
457         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
458
459 }
460 IsoRecvHandler::~IsoRecvHandler()
461 {
462 // Don't call until libraw1394's raw1394_new_handle() function has been
463 // fixed to correctly initialise the iso_packet_infos field.  Bug is
464 // confirmed present in libraw1394 1.2.1.  In any case,
465 // raw1394_destroy_handle() (in the base class destructor) will do any iso
466 // system shutdown required.
467         raw1394_iso_shutdown(m_handle);
468
469 }
470
471 bool
472 IsoRecvHandler::initialize() {
473         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
474
475         IsoHandler *base=static_cast<IsoHandler *>(this);
476
477         if(!(base->initialize())) {
478                 return false;
479         }
480
481         raw1394_set_userdata(m_handle, static_cast<void *>(this));
482
483         if(raw1394_iso_multichannel_recv_init(m_handle,
484                                          iso_receive_handler,
485                                          m_buf_packets,
486                                          m_max_packet_size,
487                                          m_irq_interval)) {
488                 debugFatal("Could not do multichannel receive initialisation!\n" );
489
490                 return false;
491         }
492
493         return true;
494
495 }
496
497 enum raw1394_iso_disposition IsoRecvHandler::putPacket(unsigned char *data, unsigned int length,
498                               unsigned char channel, unsigned char tag, unsigned char sy,
499                                   unsigned int cycle, unsigned int dropped) {
500
501         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
502                      "received packet: length=%d, channel=%d, cycle=%d\n",
503                      length, channel, cycle );
504        
505         return RAW1394_ISO_OK;
506 }
507
508 // an recv handler can have multiple destination IsoStreams
509 // NOTE: this implementation even allows for already registered
510 // streams to be registered again.
511 int IsoRecvHandler::registerStream(IsoRecvStream *stream)
512 {
513         assert(stream);
514         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
515
516         m_Clients.push_back(stream);
517
518         listen(stream->getChannel());
519         return 0;
520
521 }
522
523 int IsoRecvHandler::unregisterStream(IsoRecvStream *stream)
524 {
525         assert(stream);
526         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
527
528     for ( IsoRecvStreamVectorIterator it = m_Clients.begin();
529           it != m_Clients.end();
530           ++it )
531     {
532         IsoRecvStream* s = *it;
533         if ( s == stream ) {
534                         unListen(s->getChannel());
535             m_Clients.erase(it);
536                         return 0;
537         }
538     }
539
540         return -1; //not found
541
542 }
543
544 void IsoRecvHandler::listen(int channel) {
545         int retval;
546         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
547
548         retval=raw1394_iso_recv_listen_channel(m_handle, channel);
549
550 }
551
552 void IsoRecvHandler::unListen(int channel) {
553         int retval;
554         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
555
556         retval=raw1394_iso_recv_unlisten_channel(m_handle, channel);
557
558 }
559
560 int IsoRecvHandler::start(int cycle)
561 {
562         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
563         return raw1394_iso_recv_start(m_handle, cycle, -1, 0);
564 }
565 #endif
Note: See TracBrowser for help on using the browser.