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

Revision 750, 16.2 kB (checked in by ppalmers, 13 years ago)

Code refactoring. Tries to simplify things and tries to put all code where it belongs.

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 "IsoHandler.h"
25 #include "ieee1394service.h"
26
27 #include "libstreaming/generic/StreamProcessor.h"
28
29 #include <errno.h>
30 #include <netinet/in.h>
31 #include <assert.h>
32 #include <unistd.h>
33 #include <string.h>
34
35 #include <iostream>
36 using namespace std;
37 using namespace Streaming;
38
39 IMPL_DEBUG_MODULE( IsoHandler, IsoHandler, DEBUG_LEVEL_NORMAL );
40
41 /* the C callbacks */
42 enum raw1394_iso_disposition
43 IsoXmitHandler::iso_transmit_handler(raw1394handle_t handle,
44         unsigned char *data, unsigned int *length,
45         unsigned char *tag, unsigned char *sy,
46         int cycle, unsigned int dropped) {
47
48     IsoXmitHandler *xmitHandler=static_cast<IsoXmitHandler *>(raw1394_get_userdata(handle));
49     assert(xmitHandler);
50
51     return xmitHandler->getPacket(data, length, tag, sy, cycle, dropped);
52 }
53
54 enum raw1394_iso_disposition
55 IsoRecvHandler::iso_receive_handler(raw1394handle_t handle, unsigned char *data,
56                         unsigned int length, unsigned char channel,
57                         unsigned char tag, unsigned char sy, unsigned int cycle,
58                         unsigned int dropped) {
59
60     IsoRecvHandler *recvHandler=static_cast<IsoRecvHandler *>(raw1394_get_userdata(handle));
61     assert(recvHandler);
62
63     return recvHandler->putPacket(data, length, channel, tag, sy, cycle, dropped);
64 }
65
66 int IsoHandler::busreset_handler(raw1394handle_t handle, unsigned int generation)
67 {
68     debugOutput( DEBUG_LEVEL_VERBOSE, "Busreset happened, generation %d...\n", generation);
69
70     IsoHandler *handler=static_cast<IsoHandler *>(raw1394_get_userdata(handle));
71     assert(handler);
72     return handler->handleBusReset(generation);
73 }
74
75
76 /* Base class implementation */
77 IsoHandler::IsoHandler(IsoHandlerManager& manager)
78    : m_manager(manager)
79    , m_handle(0)
80    , m_buf_packets(400)
81    , m_max_packet_size(1024)
82    , m_irq_interval(-1)
83    , m_packetcount(0)
84    , m_dropped(0)
85    , m_Client(0)
86    , m_State(E_Created)
87 {
88 }
89
90 IsoHandler::IsoHandler(IsoHandlerManager& manager, unsigned int buf_packets, unsigned int max_packet_size, int irq)
91    : m_manager(manager)
92    , m_handle(0)
93    , m_buf_packets(buf_packets)
94    , m_max_packet_size( max_packet_size)
95    , m_irq_interval(irq)
96    , m_packetcount(0)
97    , m_dropped(0)
98    , m_Client(0)
99    , m_State(E_Created)
100 {
101 }
102
103 IsoHandler::~IsoHandler() {
104
105 // Don't call until libraw1394's raw1394_new_handle() function has been
106 // fixed to correctly initialise the iso_packet_infos field.  Bug is
107 // confirmed present in libraw1394 1.2.1.  In any case,
108 // raw1394_destroy_handle() will do any iso system shutdown required.
109 //     raw1394_iso_shutdown(m_handle);
110     if(m_handle) {
111         if (m_State == E_Running) {
112             disable();
113         }
114         raw1394_destroy_handle(m_handle);
115     }
116 }
117
118 bool IsoHandler::iterate() {
119     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "IsoHandler (%p) iterate...\n",this);
120
121     if(m_handle) {
122         if(raw1394_loop_iterate(m_handle)) {
123             debugOutput( DEBUG_LEVEL_VERBOSE,
124                  "IsoHandler (%p): Failed to iterate handler: %s\n",
125                  this,strerror(errno));
126             return false;
127         } else {
128             return true;
129         }
130     } else {
131         return false;
132     }
133 }
134
135 bool
136 IsoHandler::init()
137 {
138     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) enter...\n",this);
139     // check the state
140     if(m_State != E_Created) {
141         debugError("Incorrect state, expected E_Created, got %d\n",(int)m_State);
142         return false;
143     }
144
145     // the main handle for the ISO traffic
146     m_handle = raw1394_new_handle_on_port( m_manager.get1394Service().getPort() );
147     if ( !m_handle ) {
148         if ( !errno ) {
149             debugError("libraw1394 not compatible\n");
150         } else {
151             debugError("Could not get 1394 handle: %s\n", strerror(errno) );
152             debugError("Are ieee1394 and raw1394 drivers loaded?\n");
153         }
154         return false;
155     }
156     raw1394_set_userdata(m_handle, static_cast<void *>(this));
157
158     // bus reset handling
159     if(raw1394_busreset_notify (m_handle, RAW1394_NOTIFY_ON)) {
160         debugWarning("Could not enable busreset notification.\n");
161         debugWarning(" Error message: %s\n",strerror(errno));
162         debugWarning("Continuing without bus reset support.\n");
163     } else {
164         // apparently this cannot fail
165         raw1394_set_bus_reset_handler(m_handle, busreset_handler);
166     }
167
168     // update the internal state
169     m_State=E_Initialized;
170     return true;
171 }
172
173 bool IsoHandler::prepare()
174 {
175     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) prepare...\n", this);
176     // check the state
177     if(m_State != E_Initialized) {
178         debugError("Incorrect state, expected E_Initialized, got %d\n",(int)m_State);
179         return false;
180     }
181     // Don't call until libraw1394's raw1394_new_handle() function has been
182     // fixed to correctly initialise the iso_packet_infos field.  Bug is
183     // confirmed present in libraw1394 1.2.1.
184 //     raw1394_iso_shutdown(m_handle);
185     m_State = E_Prepared;
186     return true;
187 }
188
189 bool IsoHandler::enable(int cycle)
190 {
191     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
192     m_State = E_Running;
193     return true;
194 }
195
196 bool IsoHandler::disable()
197 {
198     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
199
200     // check state
201     if(m_State == E_Prepared) return true;
202     if(m_State != E_Running) {
203         debugError("Incorrect state, expected E_Running, got %d\n",(int)m_State);
204         return false;
205     }
206
207     // this is put here to try and avoid the
208     // Runaway context problem
209     // don't know if it will help though.
210     raw1394_iso_xmit_sync(m_handle);
211     raw1394_iso_stop(m_handle);
212     m_State = E_Prepared;
213     return true;
214 }
215
216 /**
217  * Bus reset handler
218  *
219  * @return ?
220  */
221
222 int IsoHandler::handleBusReset(unsigned int generation) {
223     debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n");
224
225     #define CSR_CYCLE_TIME            0x200
226     #define CSR_REGISTER_BASE  0xfffff0000000ULL
227     // do a simple read on ourself in order to update the internal structures
228     // this avoids read failures after a bus reset
229     quadlet_t buf=0;
230     raw1394_read(m_handle, raw1394_get_local_id(m_handle),
231                  CSR_REGISTER_BASE | CSR_CYCLE_TIME, 4, &buf);
232     return 0;
233 }
234
235 void IsoHandler::dumpInfo()
236 {
237     int channel=-1;
238     if (m_Client) channel=m_Client->getChannel();
239
240     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type................: %s\n",
241             (this->getType()==EHT_Receive ? "Receive" : "Transmit"));
242     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel...............: %2d, %2d\n",
243             m_manager.get1394Service().getPort(), channel);
244     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Buffer, MaxPacketSize, IRQ..: %4d, %4d, %4d\n",
245             m_buf_packets, m_max_packet_size, m_irq_interval);
246     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packet count................: %10d (%5d dropped)\n",
247             this->getPacketCount(), this->getDroppedCount());
248 }
249
250 void IsoHandler::setVerboseLevel(int l)
251 {
252     setDebugLevel(l);
253 }
254
255 bool IsoHandler::registerStream(StreamProcessor *stream)
256 {
257     assert(stream);
258     debugOutput( DEBUG_LEVEL_VERBOSE, "registering stream (%p)\n", stream);
259
260     if (m_Client) {
261             debugFatal( "Generic IsoHandlers can have only one client\n");
262             return false;
263     }
264     m_Client=stream;
265     return true;
266 }
267
268 bool IsoHandler::unregisterStream(StreamProcessor *stream)
269 {
270     assert(stream);
271     debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering stream (%p)\n", stream);
272
273     if(stream != m_Client) {
274             debugFatal( "no client registered\n");
275             return false;
276     }
277     m_Client=0;
278     return true;
279 }
280
281 /* Child class implementations */
282
283 IsoRecvHandler::IsoRecvHandler(IsoHandlerManager& manager)
284                 : IsoHandler(manager)
285 {
286     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
287 }
288 IsoRecvHandler::IsoRecvHandler(IsoHandlerManager& manager, unsigned int buf_packets,
289                                unsigned int max_packet_size, int irq)
290                 : IsoHandler(manager, buf_packets,max_packet_size,irq)
291 {
292     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
293
294 }
295 IsoRecvHandler::~IsoRecvHandler()
296 {
297
298 }
299
300 void IsoRecvHandler::flush()
301 {
302     raw1394_iso_recv_flush(m_handle);
303 }
304
305 bool
306 IsoRecvHandler::init() {
307     debugOutput( DEBUG_LEVEL_VERBOSE, "init recv handler %p\n",this);
308
309     if(!(IsoHandler::init())) {
310         return false;
311     }
312     return true;
313
314 }
315
316 enum raw1394_iso_disposition IsoRecvHandler::putPacket(
317                     unsigned char *data, unsigned int length,
318                     unsigned char channel, unsigned char tag, unsigned char sy,
319                     unsigned int cycle, unsigned int dropped) {
320
321     debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
322                  "received packet: length=%d, channel=%d, cycle=%d\n",
323                  length, channel, cycle );
324     m_packetcount++;
325     m_dropped+=dropped;
326
327     if(m_Client) {
328         return m_Client->putPacket(data, length, channel, tag, sy, cycle, dropped);
329     }
330
331     return RAW1394_ISO_OK;
332 }
333
334 bool IsoRecvHandler::prepare()
335 {
336     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso receive handler (%p, client=%p)\n", this, m_Client);
337     // prepare the generic IsoHandler
338     if(!IsoHandler::prepare()) {
339         return false;
340     }
341     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso receive handler (%p)\n",this);
342     debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n", m_buf_packets);
343     debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n", m_max_packet_size);
344     debugOutput( DEBUG_LEVEL_VERBOSE, " Channel         : %d \n", m_Client->getChannel());
345     debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n", m_irq_interval);
346     debugOutput( DEBUG_LEVEL_VERBOSE, " Mode            : %s \n",
347                                (m_irq_interval > 1)?"DMA_BUFFERFILL":"PACKET_PER_BUFFER");
348
349     if(m_irq_interval > 1) {
350         if(raw1394_iso_recv_init(m_handle,
351                                 iso_receive_handler,
352                                 m_buf_packets,
353                                 m_max_packet_size,
354                                 m_Client->getChannel(),
355                                 RAW1394_DMA_BUFFERFILL,
356                                 m_irq_interval)) {
357             debugFatal("Could not do receive initialisation!\n" );
358             debugFatal("  %s\n",strerror(errno));
359
360             return false;
361         }
362     } else {
363         if(raw1394_iso_recv_init(m_handle,
364                                 iso_receive_handler,
365                                 m_buf_packets,
366                                 m_max_packet_size,
367                                 m_Client->getChannel(),
368                                 RAW1394_DMA_PACKET_PER_BUFFER,
369                                 m_irq_interval)) {
370             debugFatal("Could not do receive initialisation!\n" );
371             debugFatal("  %s\n",strerror(errno));
372
373             return false;
374         }
375     }
376     return true;
377 }
378
379 bool IsoRecvHandler::enable(int cycle)
380 {
381     debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
382     // check the state
383     if(m_State != E_Prepared) {
384         if(!prepare()) {
385             debugFatal("Could not prepare recv handler\n");
386             return false;
387         }
388     }
389     if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) {
390         debugFatal("Could not start receive handler (%s)\n",strerror(errno));
391         dumpInfo();
392         return false;
393     }
394     // start the generic IsoHandler
395     if(!IsoHandler::enable(cycle)) {
396         return false;
397     }
398     return true;
399 }
400
401 int IsoRecvHandler::handleBusReset(unsigned int generation) {
402     debugOutput( DEBUG_LEVEL_VERBOSE, "handle bus reset...\n");
403
404     //TODO: implement busreset
405
406     // pass on the busreset signal
407     if(IsoHandler::handleBusReset(generation)) {
408         return -1;
409     }
410     return 0;
411 }
412
413 /* ----------------- XMIT --------------- */
414
415 IsoXmitHandler::IsoXmitHandler(IsoHandlerManager& manager)
416                 : IsoHandler(manager), m_prebuffers(0)
417 {
418     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
419
420 }
421 IsoXmitHandler::IsoXmitHandler(IsoHandlerManager& manager, unsigned int buf_packets,
422                                unsigned int max_packet_size, int irq)
423                 : IsoHandler(manager, buf_packets, max_packet_size,irq),
424                   m_speed(RAW1394_ISO_SPEED_400), m_prebuffers(0)
425 {
426     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
427
428 }
429 IsoXmitHandler::IsoXmitHandler(IsoHandlerManager& manager, unsigned int buf_packets,
430                                unsigned int max_packet_size, int irq,
431                                enum raw1394_iso_speed speed)
432                 : IsoHandler(manager, buf_packets,max_packet_size,irq),
433                   m_speed(speed), m_prebuffers(0)
434 {
435     debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
436
437 }
438
439 IsoXmitHandler::~IsoXmitHandler()
440 {
441     // handle cleanup is done in the IsoHanlder destructor
442 }
443
444 bool
445 IsoXmitHandler::init() {
446
447     debugOutput( DEBUG_LEVEL_VERBOSE, "init xmit handler %p\n",this);
448
449     if(!(IsoHandler::init())) {
450         return false;
451     }
452
453     return true;
454 }
455
456 bool IsoXmitHandler::prepare()
457 {
458     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso transmit handler (%p, client=%p)\n", this, m_Client);
459     if(!(IsoHandler::prepare())) {
460         return false;
461     }
462
463     debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n",m_buf_packets);
464     debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n",m_max_packet_size);
465     debugOutput( DEBUG_LEVEL_VERBOSE, " Channel         : %d \n",m_Client->getChannel());
466     debugOutput( DEBUG_LEVEL_VERBOSE, " Speed           : %d \n",m_speed);
467     debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n",m_irq_interval);
468     if(raw1394_iso_xmit_init(m_handle,
469                              iso_transmit_handler,
470                              m_buf_packets,
471                              m_max_packet_size,
472                              m_Client->getChannel(),
473                              m_speed,
474                              m_irq_interval)) {
475         debugFatal("Could not do xmit initialisation!\n" );
476
477         return false;
478     }
479     return true;
480 }
481
482 bool IsoXmitHandler::enable(int cycle)
483 {
484     debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d, %d prebuffers\n",
485         cycle, m_prebuffers);
486     // check the state
487     if(m_State != E_Prepared) {
488         if(!prepare()) {
489             debugFatal("Could not prepare xmit handler\n");
490             return false;
491         }
492     }
493     if(raw1394_iso_xmit_start(m_handle, cycle, m_prebuffers)) {
494         debugFatal("Could not start xmit handler (%s)\n",strerror(errno));
495         dumpInfo();
496         return false;
497     }
498     if(!(IsoHandler::enable(cycle))) {
499         return false;
500     }
501     return true;
502 }
503
504 enum raw1394_iso_disposition IsoXmitHandler::getPacket(
505                     unsigned char *data, unsigned int *length,
506                     unsigned char *tag, unsigned char *sy,
507                     int cycle, unsigned int dropped) {
508
509     debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
510                     "sending packet: length=%d, cycle=%d\n",
511                     *length, cycle );
512     m_packetcount++;
513     m_dropped+=dropped;
514
515     if(m_Client) {
516         return m_Client->getPacket(data, length, tag, sy, cycle, dropped, m_max_packet_size);
517     }
518     return RAW1394_ISO_OK;
519 }
520
521 int IsoXmitHandler::handleBusReset(unsigned int generation) {
522     debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n");
523     //TODO: implement busreset
524     // pass on the busreset signal
525     if(IsoHandler::handleBusReset(generation)) {
526             return -1;
527     }
528     return 0;
529 }
530
531 void IsoXmitHandler::dumpInfo()
532 {
533     IsoHandler::dumpInfo();
534     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Speed, PreBuffers...........: %2d, %2d\n",
535                                           m_speed, m_prebuffers);
536 }
Note: See TracBrowser for help on using the browser.