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

Revision 860, 18.7 kB (checked in by ppalmers, 16 years ago)

clean up synchronization in streamprocessor

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