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

Revision 864, 18.7 kB (checked in by ppalmers, 15 years ago)

update license to GPLv2 or GPLv3 instead of GPLv2 or any later version. Update copyrights to reflect the new year

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_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.