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

Revision 906, 17.5 kB (checked in by ppalmers, 16 years ago)

implement support for kernel space skipped cycles notification (non-public experimental code)

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