root/trunk/libffado/src/libstreaming/util/IsoHandler.cpp

Revision 748, 19.5 kB (checked in by ppalmers, 15 years ago)

try to reorganize things such that less information is duplicated

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "IsoHandler.h"
25 #include "../generic/StreamProcessor.h"
26
27 #include "libutil/TimeSource.h"
28 #include "libutil/SystemTimeSource.h"
29
30 #include <errno.h>
31 #include <netinet/in.h>
32 #include <assert.h>
33 #include <unistd.h>
34 #include <string.h>
35
36 #include <iostream>
37 using namespace std;
38
39 namespace Streaming
40 {
41
42 IMPL_DEBUG_MODULE( IsoHandler, IsoHandler, DEBUG_LEVEL_NORMAL );
43
44 /* the C callbacks */
45 enum raw1394_iso_disposition
46 IsoXmitHandler::iso_transmit_handler(raw1394handle_t handle,
47         unsigned char *data, unsigned int *length,
48         unsigned char *tag, unsigned char *sy,
49         int cycle, unsigned int dropped) {
50
51     IsoXmitHandler *xmitHandler=static_cast<IsoXmitHandler *>(raw1394_get_userdata(handle));
52     assert(xmitHandler);
53
54     return xmitHandler->getPacket(data, length, tag, sy, cycle, dropped);
55 }
56
57 enum raw1394_iso_disposition
58 IsoRecvHandler::iso_receive_handler(raw1394handle_t handle, unsigned char *data,
59                         unsigned int length, unsigned char channel,
60                         unsigned char tag, unsigned char sy, unsigned int cycle,
61                         unsigned int dropped) {
62
63     IsoRecvHandler *recvHandler=static_cast<IsoRecvHandler *>(raw1394_get_userdata(handle));
64     assert(recvHandler);
65
66     return recvHandler->putPacket(data, length, channel, tag, sy, cycle, dropped);
67 }
68
69 int IsoHandler::busreset_handler(raw1394handle_t handle, unsigned int generation)
70 {
71     debugOutput( DEBUG_LEVEL_VERBOSE, "Busreset happened, generation %d...\n", generation);
72
73     IsoHandler *handler=static_cast<IsoHandler *>(raw1394_get_userdata(handle));
74     assert(handler);
75     return handler->handleBusReset(generation);
76 }
77
78
79 /* Base class implementation */
80 IsoHandler::IsoHandler(int port)
81    :  m_handle(0), m_handle_util(0), m_port(port),
82    m_buf_packets(400), m_max_packet_size(1024), m_irq_interval(-1),
83    m_packetcount(0), m_dropped(0), m_Client(0),
84    m_State(E_Created)
85 {
86 }
87
88 IsoHandler::IsoHandler(int port, unsigned int buf_packets, unsigned int max_packet_size, int irq)
89    : m_handle(0), m_port(port),
90    m_buf_packets(buf_packets), m_max_packet_size( max_packet_size),
91    m_irq_interval(irq),
92    m_packetcount(0), m_dropped(0), m_Client(0),
93    m_State(E_Created)
94 {
95 }
96
97 IsoHandler::~IsoHandler() {
98
99 // Don't call until libraw1394's raw1394_new_handle() function has been
100 // fixed to correctly initialise the iso_packet_infos field.  Bug is
101 // confirmed present in libraw1394 1.2.1.  In any case,
102 // raw1394_destroy_handle() will do any iso system shutdown required.
103 //     raw1394_iso_shutdown(m_handle);
104
105     if(m_handle) {
106         if (m_State == E_Running) {
107             stop();
108         }
109
110         raw1394_destroy_handle(m_handle);
111     }
112
113     if(m_handle_util) raw1394_destroy_handle(m_handle_util);
114
115 }
116
117 bool IsoHandler::iterate() {
118     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "IsoHandler (%p) iterate...\n",this);
119
120     if(m_handle) {
121         if(raw1394_loop_iterate(m_handle)) {
122             debugOutput( DEBUG_LEVEL_VERBOSE,
123                  "IsoHandler (%p): Failed to iterate handler: %s\n",
124                  this,strerror(errno));
125             return false;
126         } else {
127             return true;
128         }
129     } else {
130         return false;
131     }
132 }
133
134 bool
135 IsoHandler::init()
136 {
137     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) enter...\n",this);
138
139     // check the state
140     if(m_State != E_Created) {
141         debugError("Incorrect state, expected E_Created, got %d\n",(int)m_State);
142         return false;
143     }
144
145     // the main handle for the ISO traffic
146     m_handle = raw1394_new_handle_on_port( m_port );
147     if ( !m_handle ) {
148         if ( !errno ) {
149             debugError("libraw1394 not compatible\n");
150         } else {
151             debugError("Could not get 1394 handle: %s\n", strerror(errno) );
152             debugError("Are ieee1394 and raw1394 drivers loaded?\n");
153         }
154         return false;
155     }
156     raw1394_set_userdata(m_handle, static_cast<void *>(this));
157
158     // a second handle for utility stuff
159     m_handle_util = raw1394_new_handle_on_port( m_port );
160     if ( !m_handle_util ) {
161         if ( !errno ) {
162             debugError("libraw1394 not compatible\n");
163         } else {
164             debugError("Could not get 1394 handle: %s\n", strerror(errno) );
165             debugError("Are ieee1394 and raw1394 drivers loaded?\n");
166         }
167
168         raw1394_destroy_handle(m_handle);
169         return false;
170     }
171     raw1394_set_userdata(m_handle_util, static_cast<void *>(this));
172
173     // bus reset handling
174     if(raw1394_busreset_notify (m_handle, RAW1394_NOTIFY_ON)) {
175         debugWarning("Could not enable busreset notification.\n");
176         debugWarning(" Error message: %s\n",strerror(errno));
177         debugWarning("Continuing without bus reset support.\n");
178     } else {
179         // apparently this cannot fail
180         raw1394_set_bus_reset_handler(m_handle, busreset_handler);
181     }
182
183     // test the cycle timer read function
184     int err;
185     uint32_t cycle_timer;
186     uint64_t local_time;
187     err=raw1394_read_cycle_timer(m_handle_util, &cycle_timer, &local_time);
188     if(err) {
189         debugError("raw1394_read_cycle_timer failed.\n");
190         debugError(" Error: %s\n", strerror(err));
191         debugError(" Your system doesn't seem to support the raw1394_read_cycle_timer call\n");
192         return false;
193     }
194
195     // update the internal state
196     m_State=E_Initialized;
197
198     return true;
199 }
200
201 bool IsoHandler::prepare()
202 {
203     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) enter...\n",this);
204
205     // check the state
206     if(m_State != E_Initialized) {
207         debugError("Incorrect state, expected E_Initialized, got %d\n",(int)m_State);
208         return false;
209     }
210
211     // Don't call until libraw1394's raw1394_new_handle() function has been
212     // fixed to correctly initialise the iso_packet_infos field.  Bug is
213     // confirmed present in libraw1394 1.2.1.
214
215 //     raw1394_iso_shutdown(m_handle);
216
217     m_State = E_Prepared;
218
219     return true;
220 }
221
222 bool IsoHandler::start(int cycle)
223 {
224     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
225
226     // check the state
227     if(m_State != E_Prepared) {
228         debugError("Incorrect state, expected E_Prepared, got %d\n",(int)m_State);
229         return false;
230     }
231
232     m_State=E_Running;
233
234     return true;
235 }
236
237 bool IsoHandler::stop()
238 {
239     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
240
241     // check state
242     if(m_State != E_Running) {
243         debugError("Incorrect state, expected E_Running, got %d\n",(int)m_State);
244         return false;
245     }
246
247     // this is put here to try and avoid the
248     // Runaway context problem
249     // don't know if it will help though.
250     raw1394_iso_xmit_sync(m_handle);
251
252     raw1394_iso_stop(m_handle);
253
254     m_State=E_Prepared;
255
256     return true;
257 }
258
259 /**
260  * Bus reset handler
261  *
262  * @return ?
263  */
264
265 int IsoHandler::handleBusReset(unsigned int generation) {
266     debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n");
267
268     #define CSR_CYCLE_TIME            0x200
269     #define CSR_REGISTER_BASE  0xfffff0000000ULL
270     // do a simple read on ourself in order to update the internal structures
271     // this avoids read failures after a bus reset
272     quadlet_t buf=0;
273     raw1394_read(m_handle, raw1394_get_local_id(m_handle),
274                  CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
275     return 0;
276 }
277
278 void IsoHandler::dumpInfo()
279 {
280     int channel=-1;
281     if (m_Client) channel=m_Client->getChannel();
282
283     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type    : %s\n",
284             (this->getType()==EHT_Receive ? "Receive" : "Transmit"));
285     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel   : %2d, %2d\n",
286             m_port, channel);
287     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packet count    : %10d (%5d dropped)\n",
288             this->getPacketCount(), this->getDroppedCount());
289 }
290
291 void IsoHandler::setVerboseLevel(int l)
292 {
293     setDebugLevel(l);
294 }
295
296 bool IsoHandler::registerStream(StreamProcessor *stream)
297 {
298     assert(stream);
299     debugOutput( DEBUG_LEVEL_VERBOSE, "registering stream (%p)\n", stream);
300
301     if (m_Client) {
302             debugFatal( "Generic IsoHandlers can have only one client\n");
303             return false;
304     }
305     m_Client=stream;
306     m_Client->setHandler(this);
307     return true;
308 }
309
310 bool IsoHandler::unregisterStream(StreamProcessor *stream)
311 {
312     assert(stream);
313     debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering stream (%p)\n", stream);
314
315     if(stream != m_Client) {
316             debugFatal( "no client registered\n");
317             return false;
318     }
319
320     m_Client->clearHandler();
321
322     m_Client=0;
323     return true;
324
325 }
326
327 /* Child class implementations */
328
329 IsoRecvHandler::IsoRecvHandler(int port)
330                 : IsoHandler(port)
331 {
332     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
333 }
334 IsoRecvHandler::IsoRecvHandler(int port, unsigned int buf_packets,
335                                unsigned int max_packet_size, int irq)
336                 : IsoHandler(port, buf_packets,max_packet_size,irq)
337 {
338     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
339
340 }
341 IsoRecvHandler::~IsoRecvHandler()
342 {
343
344 }
345
346 bool
347 IsoRecvHandler::init() {
348     debugOutput( DEBUG_LEVEL_VERBOSE, "init recv handler %p\n",this);
349
350     if(!(IsoHandler::init())) {
351         return false;
352     }
353     return true;
354
355 }
356
357 enum raw1394_iso_disposition IsoRecvHandler::putPacket(
358                     unsigned char *data, unsigned int length,
359                     unsigned char channel, unsigned char tag, unsigned char sy,
360                     unsigned int cycle, unsigned int dropped) {
361
362     debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
363                  "received packet: length=%d, channel=%d, cycle=%d\n",
364                  length, channel, cycle );
365     m_packetcount++;
366     m_dropped+=dropped;
367
368     if(m_Client) {
369         return m_Client->putPacket(data, length, channel, tag, sy, cycle, dropped);
370     }
371
372     return RAW1394_ISO_OK;
373 }
374
375 bool IsoRecvHandler::prepare()
376 {
377
378     // prepare the generic IsoHandler
379     if(!IsoHandler::prepare()) {
380         return false;
381     }
382
383     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso receive handler (%p)\n",this);
384     debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n", m_buf_packets);
385     debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n", m_max_packet_size);
386     debugOutput( DEBUG_LEVEL_VERBOSE, " Channel         : %d \n", m_Client->getChannel());
387     debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n", m_irq_interval);
388     debugOutput( DEBUG_LEVEL_VERBOSE, " Mode            : %s \n",
389                                (m_irq_interval > 1)?"DMA_BUFFERFILL":"PACKET_PER_BUFFER");
390
391     if(m_irq_interval > 1) {
392         if(raw1394_iso_recv_init(m_handle,
393                                 iso_receive_handler,
394                                 m_buf_packets,
395                                 m_max_packet_size,
396                                 m_Client->getChannel(),
397                                 RAW1394_DMA_BUFFERFILL,
398                                 m_irq_interval)) {
399             debugFatal("Could not do receive initialisation!\n" );
400             debugFatal("  %s\n",strerror(errno));
401
402             return false;
403         }
404     } else {
405         if(raw1394_iso_recv_init(m_handle,
406                                 iso_receive_handler,
407                                 m_buf_packets,
408                                 m_max_packet_size,
409                                 m_Client->getChannel(),
410                                 RAW1394_DMA_PACKET_PER_BUFFER,
411                                 m_irq_interval)) {
412             debugFatal("Could not do receive initialisation!\n" );
413             debugFatal("  %s\n",strerror(errno));
414
415             return false;
416         }
417     }
418     return true;
419 }
420
421 bool IsoRecvHandler::start(int cycle)
422 {
423     debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
424
425     // start the generic IsoHandler
426     if(!IsoHandler::start(cycle)) {
427         return false;
428     }
429
430     if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) {
431         debugFatal("Could not start receive handler (%s)\n",strerror(errno));
432         return false;
433     }
434     return true;
435 }
436
437 int IsoRecvHandler::handleBusReset(unsigned int generation) {
438     debugOutput( DEBUG_LEVEL_VERBOSE, "handle bus reset...\n");
439
440     //TODO: implement busreset
441
442     // pass on the busreset signal
443     if(IsoHandler::handleBusReset(generation)) {
444         return -1;
445     }
446     return 0;
447 }
448
449 /* ----------------- XMIT --------------- */
450
451 IsoXmitHandler::IsoXmitHandler(int port)
452                 : IsoHandler(port), m_prebuffers(0)
453 {
454     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
455
456 }
457 IsoXmitHandler::IsoXmitHandler(int port, unsigned int buf_packets,
458                                unsigned int max_packet_size, int irq)
459                 : IsoHandler(port, buf_packets, max_packet_size,irq),
460                   m_speed(RAW1394_ISO_SPEED_400), m_prebuffers(0)
461 {
462     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
463
464 }
465 IsoXmitHandler::IsoXmitHandler(int port, unsigned int buf_packets,
466                                unsigned int max_packet_size, int irq,
467                                enum raw1394_iso_speed speed)
468                 : IsoHandler(port, buf_packets,max_packet_size,irq),
469                   m_speed(speed), m_prebuffers(0)
470 {
471     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
472
473 }
474
475 IsoXmitHandler::~IsoXmitHandler()
476 {
477     // handle cleanup is done in the IsoHanlder destructor
478 }
479
480 bool
481 IsoXmitHandler::init() {
482
483     debugOutput( DEBUG_LEVEL_VERBOSE, "init xmit handler %p\n",this);
484
485     if(!(IsoHandler::init())) {
486         return false;
487     }
488
489     return true;
490 }
491
492 bool IsoXmitHandler::prepare()
493 {
494     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso transmit handler (%p, client=%p)\n",this,m_Client);
495
496     if(!(IsoHandler::prepare())) {
497         return false;
498     }
499
500     debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n",m_buf_packets);
501     debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n",m_max_packet_size);
502     debugOutput( DEBUG_LEVEL_VERBOSE, " Channel         : %d \n",m_Client->getChannel());
503     debugOutput( DEBUG_LEVEL_VERBOSE, " Speed           : %d \n",m_speed);
504     debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n",m_irq_interval);
505
506     if(raw1394_iso_xmit_init(m_handle,
507                              iso_transmit_handler,
508                              m_buf_packets,
509                              m_max_packet_size,
510                              m_Client->getChannel(),
511                              m_speed,
512                              m_irq_interval)) {
513         debugFatal("Could not do xmit initialisation!\n" );
514
515         return false;
516     }
517
518     return true;
519 }
520
521 bool IsoXmitHandler::start(int cycle)
522 {
523     debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d, %d prebuffers\n",
524         cycle, m_prebuffers);
525
526     if(!(IsoHandler::start(cycle))) {
527         return false;
528     }
529
530     if(raw1394_iso_xmit_start(m_handle, cycle, m_prebuffers)) {
531         debugFatal("Could not start xmit handler (%s)\n",strerror(errno));
532         return false;
533     }
534     return true;
535 }
536
537 enum raw1394_iso_disposition IsoXmitHandler::getPacket(
538                     unsigned char *data, unsigned int *length,
539                     unsigned char *tag, unsigned char *sy,
540                     int cycle, unsigned int dropped) {
541
542     debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
543                     "sending packet: length=%d, cycle=%d\n",
544                     *length, cycle );
545     m_packetcount++;
546     m_dropped+=dropped;
547
548     if(m_Client) {
549         return m_Client->getPacket(data, length, tag, sy, cycle, dropped, m_max_packet_size);
550     }
551
552     return RAW1394_ISO_OK;
553 }
554
555 int IsoXmitHandler::handleBusReset(unsigned int generation) {
556     debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n");
557     //TODO: implement busreset
558
559     // pass on the busreset signal
560     if(IsoHandler::handleBusReset(generation)) {
561             return -1;
562     }
563
564     return 0;
565 }
566
567 }
568
569 /* multichannel receive  */
570 #if 0
571 IsoRecvHandler::IsoRecvHandler(int port)
572         : IsoHandler(port)
573 {
574     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
575 }
576 IsoRecvHandler::IsoRecvHandler(int port, unsigned int buf_packets,
577                                unsigned int max_packet_size, int irq)
578         : IsoHandler(port, buf_packets,max_packet_size,irq)
579 {
580     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
581
582 }
583 IsoRecvHandler::~IsoRecvHandler()
584 {
585 // Don't call until libraw1394's raw1394_new_handle() function has been
586 // fixed to correctly initialise the iso_packet_infos field.  Bug is
587 // confirmed present in libraw1394 1.2.1.  In any case,
588 // raw1394_destroy_handle() (in the base class destructor) will do any iso
589 // system shutdown required.
590     raw1394_iso_shutdown(m_handle);
591
592 }
593
594 bool
595 IsoRecvHandler::initialize() {
596     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
597
598     IsoHandler *base=static_cast<IsoHandler *>(this);
599
600     if(!(base->initialize())) {
601         return false;
602     }
603
604     raw1394_set_userdata(m_handle, static_cast<void *>(this));
605
606     if(raw1394_iso_multichannel_recv_init(m_handle,
607                                          iso_receive_handler,
608                                          m_buf_packets,
609                                          m_max_packet_size,
610                                          m_irq_interval)) {
611         debugFatal("Could not do multichannel receive initialisation!\n" );
612
613         return false;
614     }
615
616     return true;
617
618 }
619
620 enum raw1394_iso_disposition IsoRecvHandler::putPacket(unsigned char *data, unsigned int length,
621                       unsigned char channel, unsigned char tag, unsigned char sy,
622                       unsigned int cycle, unsigned int dropped) {
623
624     debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
625                  "received packet: length=%d, channel=%d, cycle=%d\n",
626                  length, channel, cycle );
627
628     return RAW1394_ISO_OK;
629 }
630
631 // an recv handler can have multiple destination StreamProcessors
632 // NOTE: this implementation even allows for already registered
633 // streams to be registered again.
634 int IsoRecvHandler::registerStream(IsoRecvStream *stream)
635 {
636     assert(stream);
637     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
638
639     m_Clients.push_back(stream);
640
641     listen(stream->getChannel());
642     return 0;
643
644 }
645
646 int IsoRecvHandler::unregisterStream(IsoRecvStream *stream)
647 {
648     assert(stream);
649     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
650
651     for ( IsoRecvStreamVectorIterator it = m_Clients.begin();
652           it != m_Clients.end();
653           ++it )
654     {
655         IsoRecvStream* s = *it;
656         if ( s == stream ) {
657             unListen(s->getChannel());
658             m_Clients.erase(it);
659             return 0;
660         }
661     }
662
663     return -1; //not found
664
665 }
666
667 void IsoRecvHandler::listen(int channel) {
668     int retval;
669     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
670
671     retval=raw1394_iso_recv_listen_channel(m_handle, channel);
672
673 }
674
675 void IsoRecvHandler::unListen(int channel) {
676     int retval;
677     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
678
679     retval=raw1394_iso_recv_unlisten_channel(m_handle, channel);
680
681 }
682
683 int IsoRecvHandler::start(int cycle)
684 {
685     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
686     return raw1394_iso_recv_start(m_handle, cycle, -1, 0);
687 }
688 #endif
Note: See TracBrowser for help on using the browser.