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

Revision 754, 15.2 kB (checked in by ppalmers, 16 years ago)

- simplify IsoHandler?
- fix some small issues

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