root/trunk/libffado/src/libieee1394/IsoHandler.cpp

Revision 870, 19.7 kB (checked in by ppalmers, 13 years ago)

try and work around buffer size issues in raw1394

Line 
1 /*
2  * Copyright (C) 2005-2008 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 2 of the License, or
12  * (at your option) version 3 of the License.
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 "config.h"
25
26 #include "IsoHandler.h"
27 #include "ieee1394service.h"
28
29 #include "libstreaming/generic/StreamProcessor.h"
30 #include "libutil/PosixThread.h"
31
32 #include <errno.h>
33 #include <netinet/in.h>
34 #include <assert.h>
35 #include <unistd.h>
36 #include <string.h>
37
38 #include <iostream>
39 using namespace std;
40 using namespace Streaming;
41
42 IMPL_DEBUG_MODULE( IsoHandler, IsoHandler, DEBUG_LEVEL_NORMAL );
43
44 /* the C callbacks */
45 enum raw1394_iso_disposition
46 IsoHandler::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     IsoHandler *xmitHandler = static_cast<IsoHandler *>(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 IsoHandler::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     IsoHandler *recvHandler = static_cast<IsoHandler *>(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 IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t)
79    : m_manager( manager )
80    , m_type ( t )
81    , m_handle( 0 )
82    , m_buf_packets( 400 )
83    , m_max_packet_size( 1024 )
84    , m_irq_interval( -1 )
85    , m_last_wakeup( -1 )
86    , m_Client( 0 )
87    , m_poll_timeout( 100 )
88    , m_realtime ( false )
89    , m_priority ( 0 )
90    , m_Thread ( NULL )
91    , m_speed( RAW1394_ISO_SPEED_400 )
92    , m_prebuffers( 0 )
93    , m_State( E_Created )
94 {
95 }
96
97 IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t,
98                        unsigned int buf_packets, unsigned int max_packet_size, int irq)
99    : m_manager( manager )
100    , m_type ( t )
101    , m_handle( 0 )
102    , m_buf_packets( buf_packets )
103    , m_max_packet_size( max_packet_size )
104    , m_irq_interval( irq )
105    , m_last_wakeup( -1 )
106    , m_Client( 0 )
107    , m_poll_timeout( 100 )
108    , m_realtime ( false )
109    , m_priority ( 0 )
110    , m_Thread ( NULL )
111    , m_speed( RAW1394_ISO_SPEED_400 )
112    , m_prebuffers( 0 )
113    , m_State( E_Created )
114 {
115 }
116
117 IsoHandler::IsoHandler(IsoHandlerManager& manager, enum EHandlerType t, unsigned int buf_packets,
118                        unsigned int max_packet_size, int irq,
119                        enum raw1394_iso_speed speed)
120    : m_manager( manager )
121    , m_type ( t )
122    , m_handle( 0 )
123    , m_buf_packets( buf_packets )
124    , m_max_packet_size( max_packet_size )
125    , m_irq_interval( irq )
126    , m_last_wakeup( -1 )
127    , m_Client( 0 )
128    , m_poll_timeout( 100 )
129    , m_realtime ( false )
130    , m_priority ( 0 )
131    , m_Thread ( NULL )
132    , m_speed( speed )
133    , m_prebuffers( 0 )
134    , m_State( E_Created )
135 {
136 }
137
138 IsoHandler::~IsoHandler() {
139     if (m_Thread) {
140         m_Thread->Stop();
141         delete m_Thread;
142     }
143 // Don't call until libraw1394's raw1394_new_handle() function has been
144 // fixed to correctly initialise the iso_packet_infos field.  Bug is
145 // confirmed present in libraw1394 1.2.1.  In any case,
146 // raw1394_destroy_handle() will do any iso system shutdown required.
147 //     raw1394_iso_shutdown(m_handle);
148     if(m_handle) {
149         if (m_State == E_Running) {
150             disable();
151         }
152         raw1394_destroy_handle(m_handle);
153     }
154 }
155
156 bool
157 IsoHandler::Init()
158 {
159     debugOutput( DEBUG_LEVEL_VERBOSE, "%p: Init thread...\n", this);
160     m_poll_fd.fd = getFileDescriptor();
161     m_poll_fd.revents = 0;
162     if (isEnabled()) {
163         m_poll_fd.events = POLLIN;
164     } else {
165         m_poll_fd.events = 0;
166     }
167     return true;
168 }
169
170 bool
171 IsoHandler::isDead()
172 {
173     if(m_last_wakeup < 0) return false; // startup artifacts
174     if(m_State != E_Running) return false; // not running can't be dead
175     int64_t now = m_manager.get1394Service().getCurrentTimeAsUsecs();
176     int64_t last_call = m_last_wakeup + ISOHANDLER_DEATH_DETECT_TIMEOUT_USECS;
177     if(now > last_call) {
178         debugOutput(DEBUG_LEVEL_VERBOSE,
179                     "(%p, %s) Handler timed out: %lld usecs since last wakeup\n",
180                     this, getTypeString(), now-m_last_wakeup);
181         return true;
182     } else {
183         return false;
184     }
185 }
186
187 bool
188 IsoHandler::waitForClient()
189 {
190     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "waiting...\n");
191     if(m_Client) {
192         bool result;
193         if (m_type == eHT_Receive) {
194             result = m_Client->waitForProducePacket();
195         } else {
196             result = m_Client->waitForConsumePacket();
197         }
198         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " returns %d\n", result);
199         return result;
200     } else {
201         debugOutputExtreme(DEBUG_LEVEL_VERBOSE, " no client\n");
202     }
203     return false;
204 }
205
206 bool
207 IsoHandler::tryWaitForClient()
208 {
209     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "waiting...\n");
210     if(m_Client) {
211         bool result;
212         if (m_type == eHT_Receive) {
213             result = m_Client->canProducePacket();
214         } else {
215             result = m_Client->canConsumePacket();
216         }
217         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " returns %d\n", result);
218         return result;
219     } else {
220         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " no client\n");
221     }
222     return false;
223 }
224
225 bool
226 IsoHandler::Execute()
227 {
228     debugOutputExtreme( DEBUG_LEVEL_VERY_VERBOSE, "%p: Execute thread...\n", this);
229
230     // bypass if not running
231     if (m_State != E_Running) {
232         debugOutput( DEBUG_LEVEL_VERBOSE, "%p: not polling since not running...\n", this);
233         usleep(m_poll_timeout * 1000);
234         debugOutput( DEBUG_LEVEL_VERBOSE, "%p: done sleeping...\n", this);
235         return true;
236     }
237
238     // wait for the availability of frames in the client
239     // (blocking for transmit handlers)
240     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Waiting for Client activity...\n", this, getTypeString());
241     if (waitForClient()) {
242 #if ISOHANDLER_USE_POLL
243         bool result = true;
244         while(result && m_Client && tryWaitForClient()) {
245             int err = poll(&m_poll_fd, 1, m_poll_timeout);
246             if (err == -1) {
247                 if (errno == EINTR) {
248                     return true;
249                 }
250                 debugFatal("%p, poll error: %s\n", this, strerror (errno));
251                 return false;
252             }
253
254             if(m_poll_fd.revents & (POLLIN)) {
255                 result=iterate();
256                 if(!result) {
257                     debugOutput( DEBUG_LEVEL_VERBOSE,
258                                 "IsoHandler (%p): Failed to iterate handler\n",
259                                 this);
260                 }
261             } else {
262                 if (m_poll_fd.revents & POLLERR) {
263                     debugWarning("error on fd for %p\n", this);
264                 }
265                 if (m_poll_fd.revents & POLLHUP) {
266                     debugWarning("hangup on fd for %p\n",this);
267                 }
268                 break;
269             }
270         }
271         return result;
272 #else
273         // iterate() is blocking if no 1394 data is available
274         // so poll'ing is not really necessary
275         bool result = true;
276         while(result && m_Client && tryWaitForClient()) {
277             result = iterate();
278 //             if (getType() == eHT_Receive) {
279 //                 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Iterate returned: %d\n",
280 //                             this, (m_type==eHT_Receive?"Receive":"Transmit"), result);
281 //             }
282         }
283         return result;
284 #endif
285     } else {
286         debugError("waitForClient() failed.\n");
287         return false;
288     }
289 }
290
291 bool
292 IsoHandler::iterate() {
293     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Iterating ISO handler...\n",
294                 this, getTypeString());
295     if(m_State == E_Running) {
296 #if ISOHANDLER_FLUSH_BEFORE_ITERATE
297         flush();
298 #endif
299         if(raw1394_loop_iterate(m_handle)) {
300             debugError( "IsoHandler (%p): Failed to iterate handler: %s\n",
301                         this, strerror(errno));
302             return false;
303         }
304         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) done interating ISO handler...\n",
305                            this, getTypeString());
306         return true;
307     } else {
308         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Not iterating a non-running handler...\n",
309                     this, getTypeString());
310         return false;
311     }
312 }
313
314 bool
315 IsoHandler::setThreadParameters(bool rt, int priority) {
316     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority);
317     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority
318     m_realtime = rt;
319     m_priority = priority;
320
321     if (m_Thread) {
322         if (m_realtime) {
323             m_Thread->AcquireRealTime(m_priority);
324         } else {
325             m_Thread->DropRealTime();
326         }
327     }
328     return true;
329 }
330
331 bool
332 IsoHandler::init()
333 {
334     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) enter...\n",this);
335     // check the state
336     if(m_State != E_Created) {
337         debugError("Incorrect state, expected E_Created, got %d\n",(int)m_State);
338         return false;
339     }
340
341     // the main handle for the ISO traffic
342     m_handle = raw1394_new_handle_on_port( m_manager.get1394Service().getPort() );
343     if ( !m_handle ) {
344         if ( !errno ) {
345             debugError("libraw1394 not compatible\n");
346         } else {
347             debugError("Could not get 1394 handle: %s\n", strerror(errno) );
348             debugError("Are ieee1394 and raw1394 drivers loaded?\n");
349         }
350         return false;
351     }
352     raw1394_set_userdata(m_handle, static_cast<void *>(this));
353
354     // bus reset handling
355     if(raw1394_busreset_notify (m_handle, RAW1394_NOTIFY_ON)) {
356         debugWarning("Could not enable busreset notification.\n");
357         debugWarning(" Error message: %s\n",strerror(errno));
358         debugWarning("Continuing without bus reset support.\n");
359     } else {
360         // apparently this cannot fail
361         raw1394_set_bus_reset_handler(m_handle, busreset_handler);
362     }
363
364 #if ISOHANDLER_PER_HANDLER_THREAD
365     // create a thread to iterate ourselves
366     debugOutput( DEBUG_LEVEL_VERBOSE, "Start thread for %p...\n", this);
367     m_Thread = new Util::PosixThread(this, m_realtime, m_priority,
368                                      PTHREAD_CANCEL_DEFERRED);
369     if(!m_Thread) {
370         debugFatal("No thread\n");
371         return false;
372     }
373     if (m_Thread->Start() != 0) {
374         debugFatal("Could not start update thread\n");
375         return false;
376     }
377 #endif
378
379     // update the internal state
380     m_State=E_Initialized;
381     return true;
382 }
383
384 bool IsoHandler::disable()
385 {
386     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p, %s) enter...\n",
387                  this, (m_type==eHT_Receive?"Receive":"Transmit"));
388
389     // check state
390     if(m_State == E_Prepared) return true;
391     if(m_State != E_Running) {
392         debugError("Incorrect state, expected E_Running, got %d\n",(int)m_State);
393         return false;
394     }
395
396     m_poll_fd.events = 0;
397
398     // this is put here to try and avoid the
399     // Runaway context problem
400     // don't know if it will help though.
401     raw1394_iso_xmit_sync(m_handle);
402     raw1394_iso_stop(m_handle);
403     m_State = E_Prepared;
404     return true;
405 }
406
407 /**
408  * Bus reset handler
409  *
410  * @return ?
411  */
412
413 int
414 IsoHandler::handleBusReset(unsigned int generation)
415 {
416     debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n");
417
418     #define CSR_CYCLE_TIME            0x200
419     #define CSR_REGISTER_BASE  0xfffff0000000ULL
420     // do a simple read on ourself in order to update the internal structures
421     // this avoids read failures after a bus reset
422     quadlet_t buf=0;
423     raw1394_read(m_handle, raw1394_get_local_id(m_handle),
424                  CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
425     return 0;
426 }
427
428 void IsoHandler::dumpInfo()
429 {
430     int channel=-1;
431     if (m_Client) channel=m_Client->getChannel();
432
433     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type................: %s\n",
434             getTypeString());
435     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel...............: %2d, %2d\n",
436             m_manager.get1394Service().getPort(), channel);
437     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Buffer, MaxPacketSize, IRQ..: %4d, %4d, %4d\n",
438             m_buf_packets, m_max_packet_size, m_irq_interval);
439     if (this->getType() == eHT_Transmit) {
440         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Speed, PreBuffers...........: %2d, %2d\n",
441                                             m_speed, m_prebuffers);
442     }
443 }
444
445 void IsoHandler::setVerboseLevel(int l)
446 {
447     setDebugLevel(l);
448     if(m_Thread) m_Thread->setVerboseLevel(l);
449 }
450
451 bool IsoHandler::registerStream(StreamProcessor *stream)
452 {
453     assert(stream);
454     debugOutput( DEBUG_LEVEL_VERBOSE, "registering stream (%p)\n", stream);
455
456     if (m_Client) {
457             debugFatal( "Generic IsoHandlers can have only one client\n");
458             return false;
459     }
460     m_Client=stream;
461     return true;
462 }
463
464 bool IsoHandler::unregisterStream(StreamProcessor *stream)
465 {
466     assert(stream);
467     debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering stream (%p)\n", stream);
468
469     if(stream != m_Client) {
470             debugFatal( "no client registered\n");
471             return false;
472     }
473     m_Client=0;
474     return true;
475 }
476
477 void IsoHandler::flush()
478 {
479     if(m_type == eHT_Receive) {
480         raw1394_iso_recv_flush(m_handle);
481     } else {
482         // do nothing
483     }
484 }
485
486 // ISO packet interface
487 enum raw1394_iso_disposition IsoHandler::putPacket(
488                     unsigned char *data, unsigned int length,
489                     unsigned char channel, unsigned char tag, unsigned char sy,
490                     unsigned int cycle, unsigned int dropped) {
491
492     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
493                        "received packet: length=%d, channel=%d, cycle=%d\n",
494                        length, channel, cycle);
495     #ifdef DEBUG
496     m_last_wakeup = m_manager.get1394Service().getCurrentTimeAsUsecs();
497     if (length > m_max_packet_size) {
498         debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
499                      this, getTypeString(), length, m_max_packet_size);
500     }
501     #endif
502     if(m_Client) {
503         return m_Client->putPacket(data, length, channel, tag, sy, cycle, dropped);
504     }
505
506     return RAW1394_ISO_OK;
507 }
508
509
510 enum raw1394_iso_disposition
511 IsoHandler::getPacket(unsigned char *data, unsigned int *length,
512                       unsigned char *tag, unsigned char *sy,
513                       int cycle, unsigned int dropped) {
514
515     debugOutputExtreme(DEBUG_LEVEL_ULTRA_VERBOSE,
516                        "sending packet: length=%d, cycle=%d\n",
517                        *length, cycle);
518     #ifdef DEBUG
519     m_last_wakeup = m_manager.get1394Service().getCurrentTimeAsUsecs();
520     #endif
521
522     if(m_Client) {
523         enum raw1394_iso_disposition retval;
524         retval = m_Client->getPacket(data, length, tag, sy, cycle, dropped, m_max_packet_size);
525         #ifdef DEBUG
526         if (*length > m_max_packet_size) {
527             debugWarning("(%p, %s) packet too large: len=%u max=%u\n",
528                          this, getTypeString(), *length, m_max_packet_size);
529         }
530         #endif
531         return retval;
532     }
533     *tag = 0;
534     *sy = 0;
535     *length = 0;
536     return RAW1394_ISO_OK;
537 }
538
539 bool IsoHandler::prepare()
540 {
541     // check the state
542     if(m_State != E_Initialized) {
543         debugError("Incorrect state, expected E_Initialized, got %d\n",(int)m_State);
544         return false;
545     }
546
547     // Don't call until libraw1394's raw1394_new_handle() function has been
548     // fixed to correctly initialise the iso_packet_infos field.  Bug is
549     // confirmed present in libraw1394 1.2.1.
550     //     raw1394_iso_shutdown(m_handle);
551     m_State = E_Prepared;
552     m_last_wakeup = -1;
553
554     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso handler (%p, client=%p)\n", this, m_Client);
555     dumpInfo();
556     if (getType() == eHT_Receive) {
557         if(m_irq_interval > 1) {
558             if(raw1394_iso_recv_init(m_handle,
559                                     iso_receive_handler,
560                                     m_buf_packets,
561                                     m_max_packet_size,
562                                     m_Client->getChannel(),
563 //                                     RAW1394_DMA_BUFFERFILL,
564                                     RAW1394_DMA_PACKET_PER_BUFFER,
565                                     m_irq_interval)) {
566                 debugFatal("Could not do receive initialisation (DMA_BUFFERFILL)!\n" );
567                 debugFatal("  %s\n",strerror(errno));
568                 return false;
569             }
570         } else {
571             if(raw1394_iso_recv_init(m_handle,
572                                     iso_receive_handler,
573                                     m_buf_packets,
574                                     m_max_packet_size,
575                                     m_Client->getChannel(),
576                                     RAW1394_DMA_PACKET_PER_BUFFER,
577                                     m_irq_interval)) {
578                 debugFatal("Could not do receive initialisation (PACKET_PER_BUFFER)!\n" );
579                 debugFatal("  %s\n",strerror(errno));
580                 return false;
581             }
582         }
583         return true;
584     } else {
585         if(raw1394_iso_xmit_init(m_handle,
586                                 iso_transmit_handler,
587                                 m_buf_packets,
588                                 m_max_packet_size,
589                                 m_Client->getChannel(),
590                                 m_speed,
591                                 m_irq_interval)) {
592             debugFatal("Could not do xmit initialisation!\n" );
593             return false;
594         }
595         return true;
596     }
597 }
598
599 bool IsoHandler::enable(int cycle)
600 {
601     debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
602     // check the state
603     if(m_State != E_Prepared) {
604         if(!prepare()) {
605             debugFatal("Could not prepare handler\n");
606             return false;
607         }
608     }
609
610     if (getType() == eHT_Receive) {
611         if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) {
612             debugFatal("Could not start receive handler (%s)\n",strerror(errno));
613             dumpInfo();
614             return false;
615         }
616     } else {
617         if(raw1394_iso_xmit_start(m_handle, cycle, m_prebuffers)) {
618             debugFatal("Could not start xmit handler (%s)\n",strerror(errno));
619             dumpInfo();
620             return false;
621         }
622     }
623
624     m_poll_fd.events = POLLIN;
625     m_State = E_Running;
626     return true;
627 }
628
629 /**
630  * @brief convert a EHandlerType to a string
631  * @param t the type
632  * @return a char * describing the state
633  */
634 const char *
635 IsoHandler::eHTToString(enum EHandlerType t) {
636     switch (t) {
637         case eHT_Receive: return "Receive";
638         case eHT_Transmit: return "Transmit";
639         default: return "error: unknown type";
640     }
641 }
Note: See TracBrowser for help on using the browser.