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

Revision 267, 13.9 kB (checked in by jwoithe, 16 years ago)

More Motu streaming infrastructure added.
Added more Motu device configuration details.
tests/teststreaming.c: added call to freebob_streaming_prepare() so this can
naively used to start exercising the Motu functions.

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