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

Revision 866, 18.4 kB (checked in by ppalmers, 15 years ago)

- weed out some unused functions
- introduce 'debugOutputExtreme' allowing to disable debug statements in the speed-sensitive sections. This should reduce the cpu load on a 'normal' debug build significantly.

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