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

Revision 750, 29.1 kB (checked in by ppalmers, 16 years ago)

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

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2007 by Daniel Wagner
3  * Copyright (C) 2005-2007 by Pieter Palmers
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "ieee1394service.h"
26 #include "ARMHandler.h"
27 #include "cycletimer.h"
28 #include "IsoHandlerManager.h"
29
30 #include <libavc1394/avc1394.h>
31 #include <libraw1394/csr.h>
32 #include <libiec61883/iec61883.h>
33
34 #include <errno.h>
35 #include <netinet/in.h>
36
37 #include <string.h>
38
39 #include <iostream>
40 #include <iomanip>
41
42 #define FFADO_MAX_FIREWIRE_PORTS 16
43
44 IMPL_DEBUG_MODULE( Ieee1394Service, Ieee1394Service, DEBUG_LEVEL_NORMAL );
45
46 Ieee1394Service::Ieee1394Service()
47     : m_handle( 0 ), m_resetHandle( 0 ), m_rtHandle( 0 )
48     , m_port( -1 )
49     , m_threadRunning( false )
50     , m_isoManager( new IsoHandlerManager( *this ) )
51 {
52     pthread_mutex_init( &m_mutex, 0 );
53
54     for (unsigned int i=0; i<64; i++) {
55         m_channels[i].channel=-1;
56         m_channels[i].bandwidth=-1;
57         m_channels[i].alloctype=AllocFree;
58         m_channels[i].xmit_node=0xFFFF;
59         m_channels[i].xmit_plug=-1;
60         m_channels[i].recv_node=0xFFFF;
61         m_channels[i].recv_plug=-1;
62     }
63 }
64
65 Ieee1394Service::~Ieee1394Service()
66 {
67     delete m_isoManager;
68     stopRHThread();
69     for ( arm_handler_vec_t::iterator it = m_armHandlers.begin();
70           it != m_armHandlers.end();
71           ++it )
72     {
73         debugOutput(DEBUG_LEVEL_VERBOSE, "Unregistering ARM handler for 0x%016llX\n", (*it)->getStart());
74         int err=raw1394_arm_unregister(m_resetHandle, (*it)->getStart());
75         if (err) {
76             debugError(" Failed to unregister ARM handler for 0x%016llX\n", (*it)->getStart());
77             debugError(" Error: %s\n", strerror(errno));
78         }
79     }
80
81     if ( m_handle ) {
82         raw1394_destroy_handle( m_handle );
83     }
84     if ( m_resetHandle ) {
85         raw1394_destroy_handle( m_resetHandle );
86     }
87     if ( m_rtHandle ) {
88         raw1394_destroy_handle( m_rtHandle );
89     }
90 }
91
92 unsigned int
93 Ieee1394Service::detectNbPorts( )
94 {
95     raw1394handle_t tmp_handle = raw1394_new_handle();
96     if ( tmp_handle == NULL ) {
97         debugError("Could not get libraw1394 handle.\n");
98         return 0;
99     }
100     struct raw1394_portinfo pinf[FFADO_MAX_FIREWIRE_PORTS];
101     int nb_detected_ports = raw1394_get_port_info(tmp_handle, pinf, FFADO_MAX_FIREWIRE_PORTS);
102     raw1394_destroy_handle(tmp_handle);
103
104     if (nb_detected_ports < 0) {
105         debugError("Failed to detect number of ports\n");
106         return 0;
107     }
108     return nb_detected_ports;
109 }
110
111 bool
112 Ieee1394Service::initialize( int port )
113 {
114     using namespace std;
115
116     m_handle = raw1394_new_handle_on_port( port );
117     if ( !m_handle ) {
118         if ( !errno ) {
119             debugFatal("libraw1394 not compatible\n");
120         } else {
121             debugFatal("Ieee1394Service::initialize: Could not get 1394 handle: %s\n",
122                 strerror(errno) );
123             debugFatal("Is ieee1394 and raw1394 driver loaded?\n");
124         }
125         return false;
126     }
127
128     m_resetHandle = raw1394_new_handle_on_port( port );
129     if ( !m_resetHandle ) {
130         if ( !errno ) {
131             debugFatal("libraw1394 not compatible\n");
132         } else {
133             debugFatal("Ieee1394Service::initialize: Could not get 1394 handle: %s",
134                 strerror(errno) );
135             debugFatal("Is ieee1394 and raw1394 driver loaded?\n");
136         }
137         return false;
138     }
139    
140     m_rtHandle = raw1394_new_handle_on_port( port );
141     if ( !m_rtHandle ) {
142         if ( !errno ) {
143             debugFatal("libraw1394 not compatible\n");
144         } else {
145             debugFatal("Ieee1394Service::initialize: Could not get 1394 handle: %s",
146                 strerror(errno) );
147             debugFatal("Is ieee1394 and raw1394 driver loaded?\n");
148         }
149         return false;
150     }
151
152     // test the cycle timer read function
153     int err;
154     uint32_t cycle_timer;
155     uint64_t local_time;
156     err=raw1394_read_cycle_timer(m_handle, &cycle_timer, &local_time);
157     if(err) {
158         debugError("raw1394_read_cycle_timer failed.\n");
159         debugError(" Error: %s\n", strerror(err));
160         debugError(" Your system doesn't seem to support the raw1394_read_cycle_timer call\n");
161         return false;
162     }
163
164     m_port = port;
165
166     // obtain port name
167     raw1394handle_t tmp_handle = raw1394_new_handle();
168     if ( tmp_handle == NULL ) {
169         debugError("Could not get temporaty libraw1394 handle.\n");
170         return false;
171     }
172     struct raw1394_portinfo pinf[FFADO_MAX_FIREWIRE_PORTS];
173     int nb_detected_ports = raw1394_get_port_info(tmp_handle, pinf, FFADO_MAX_FIREWIRE_PORTS);
174     raw1394_destroy_handle(tmp_handle);
175
176     if (nb_detected_ports < 0) {
177         debugError("Failed to detect number of ports\n");
178         return false;
179     }
180
181     if(nb_detected_ports && port < FFADO_MAX_FIREWIRE_PORTS) {
182         m_portName = pinf[port].name;
183     } else {
184         m_portName = "Unknown";
185     }
186     if (m_portName == "") {
187         m_portName = "Unknown";
188     }
189
190     raw1394_set_userdata( m_handle, this );
191     raw1394_set_userdata( m_resetHandle, this );
192     raw1394_set_userdata( m_rtHandle, this );
193     raw1394_set_bus_reset_handler( m_resetHandle,
194                                    this->resetHandlerLowLevel );
195
196     m_default_arm_handler = raw1394_set_arm_tag_handler( m_resetHandle,
197                                    this->armHandlerLowLevel );
198
199     if(!m_isoManager) {
200         debugFatal("No IsoHandlerManager available, bad!\n");
201         return false;
202     }
203     m_isoManager->setVerboseLevel(getDebugLevel());
204     if(!m_isoManager->init()) {
205         debugFatal("Could not initialize IsoHandlerManager\n");
206         return false;
207     }
208
209     startRHThread();
210     return true;
211 }
212
213 bool
214 Ieee1394Service::setThreadParameters(bool rt, int priority) {
215     if (m_isoManager) {
216         return m_isoManager->setThreadParameters(rt, priority);
217     } else {
218         return true;
219     }
220 }
221
222 int
223 Ieee1394Service::getNodeCount()
224 {
225     return raw1394_get_nodecount( m_handle );
226 }
227
228 nodeid_t Ieee1394Service::getLocalNodeId() {
229     return raw1394_get_local_id(m_handle) & 0x3F;
230 }
231
232 /**
233  * Returns the current value of the cycle timer (in ticks)
234  *
235  * @return the current value of the cycle timer (in ticks)
236  */
237
238 unsigned int
239 Ieee1394Service::getCycleTimerTicks() {
240     // the new api should be realtime safe.
241     // it might cause a reschedule when turning preemption,
242     // back on but that won't hurt us if we have sufficient
243     // priority
244     int err;
245     uint32_t cycle_timer;
246     uint64_t local_time;
247     err=raw1394_read_cycle_timer(m_rtHandle, &cycle_timer, &local_time);
248     if(err) {
249         debugWarning("raw1394_read_cycle_timer: %s\n", strerror(err));
250     }
251     return CYCLE_TIMER_TO_TICKS(cycle_timer);
252 }
253
254 /**
255  * Returns the current value of the cycle timer (as is)
256  *
257  * @return the current value of the cycle timer (as is)
258  */
259
260 unsigned int
261 Ieee1394Service::getCycleTimer() {
262     // the new api should be realtime safe.
263     // it might cause a reschedule when turning preemption,
264     // back on but that won't hurt us if we have sufficient
265     // priority
266     int err;
267     uint32_t cycle_timer;
268     uint64_t local_time;
269     err=raw1394_read_cycle_timer(m_rtHandle, &cycle_timer, &local_time);
270     if(err) {
271         debugWarning("raw1394_read_cycle_timer: %s\n", strerror(err));
272     }
273     return cycle_timer;
274 }
275
276 bool
277 Ieee1394Service::read( fb_nodeid_t nodeId,
278                        fb_nodeaddr_t addr,
279                        size_t length,
280                        fb_quadlet_t* buffer )
281 {
282     using namespace std;
283     if ( raw1394_read( m_handle, nodeId, addr, length*4, buffer ) == 0 ) {
284
285         #ifdef DEBUG
286         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
287             "read: node 0x%X, addr = 0x%016llX, length = %u\n",
288             nodeId, addr, length);
289         printBuffer( DEBUG_LEVEL_VERY_VERBOSE, length, buffer );
290         #endif
291
292         return true;
293     } else {
294         #ifdef DEBUG
295         debugError("raw1394_read failed: node 0x%X, addr = 0x%016llX, length = %u\n",
296               nodeId, addr, length);
297         #endif
298
299         return false;
300     }
301 }
302
303
304 bool
305 Ieee1394Service::read_quadlet( fb_nodeid_t nodeId,
306                                fb_nodeaddr_t addr,
307                                fb_quadlet_t* buffer )
308 {
309     return read( nodeId,  addr, sizeof( *buffer )/4, buffer );
310 }
311
312 bool
313 Ieee1394Service::read_octlet( fb_nodeid_t nodeId,
314                               fb_nodeaddr_t addr,
315                               fb_octlet_t* buffer )
316 {
317     return read( nodeId, addr, sizeof( *buffer )/4,
318                  reinterpret_cast<fb_quadlet_t*>( buffer ) );
319 }
320
321
322 bool
323 Ieee1394Service::write( fb_nodeid_t nodeId,
324                         fb_nodeaddr_t addr,
325                         size_t length,
326                         fb_quadlet_t* data )
327 {
328     using namespace std;
329
330     #ifdef DEBUG
331     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"write: node 0x%X, addr = 0x%016X, length = %d\n",
332                 nodeId, addr, length);
333     printBuffer( DEBUG_LEVEL_VERY_VERBOSE, length, data );
334     #endif
335
336     return raw1394_write( m_handle, nodeId, addr, length*4, data ) == 0;
337 }
338
339
340 bool
341 Ieee1394Service::write_quadlet( fb_nodeid_t nodeId,
342                                 fb_nodeaddr_t addr,
343                                 fb_quadlet_t data )
344 {
345     return write( nodeId, addr, sizeof( data )/4, &data );
346 }
347
348 bool
349 Ieee1394Service::write_octlet( fb_nodeid_t nodeId,
350                                fb_nodeaddr_t addr,
351                                fb_octlet_t data )
352 {
353     return write( nodeId, addr, sizeof( data )/4,
354                   reinterpret_cast<fb_quadlet_t*>( &data ) );
355 }
356
357 fb_octlet_t
358 Ieee1394Service::byteSwap_octlet(fb_octlet_t value) {
359     #if __BYTE_ORDER == __BIG_ENDIAN
360         return value;
361     #elif __BYTE_ORDER == __LITTLE_ENDIAN
362         fb_octlet_t value_new;
363         fb_quadlet_t *in_ptr=reinterpret_cast<fb_quadlet_t *>(&value);
364         fb_quadlet_t *out_ptr=reinterpret_cast<fb_quadlet_t *>(&value_new);
365         *(out_ptr+1)=htonl(*(in_ptr));
366         *(out_ptr)=htonl(*(in_ptr+1));
367         return value_new;
368     #else
369         #error Unknown endiannes
370     #endif
371 }
372
373 bool
374 Ieee1394Service::lockCompareSwap64(  fb_nodeid_t nodeId,
375                         fb_nodeaddr_t addr,
376                         fb_octlet_t  compare_value,
377                         fb_octlet_t  swap_value,
378                         fb_octlet_t* result )
379 {
380     #ifdef DEBUG
381     debugOutput(DEBUG_LEVEL_VERBOSE,"lockCompareSwap64: node 0x%X, addr = 0x%016llX\n",
382                 nodeId, addr);
383     debugOutput(DEBUG_LEVEL_VERBOSE,"  if (*(addr)==0x%016llX) *(addr)=0x%016llX\n",
384                 compare_value, swap_value);
385     fb_octlet_t buffer;
386     if(!read_octlet( nodeId, addr,&buffer )) {
387         debugWarning("Could not read register\n");
388     } else {
389         debugOutput(DEBUG_LEVEL_VERBOSE,"before = 0x%016llX\n", buffer);
390     }
391
392     #endif
393
394     // do endiannes swapping
395     compare_value=byteSwap_octlet(compare_value);
396     swap_value=byteSwap_octlet(swap_value);
397
398     int retval=raw1394_lock64(m_handle, nodeId, addr, RAW1394_EXTCODE_COMPARE_SWAP,
399                           swap_value, compare_value, result);
400
401     #ifdef DEBUG
402     if(!read_octlet( nodeId, addr,&buffer )) {
403         debugWarning("Could not read register\n");
404     } else {
405         debugOutput(DEBUG_LEVEL_VERBOSE,"after = 0x%016llX\n", buffer);
406     }
407     #endif
408
409     *result=byteSwap_octlet(*result);
410
411     return (retval == 0);
412 }
413
414 fb_quadlet_t*
415 Ieee1394Service::transactionBlock( fb_nodeid_t nodeId,
416                                    fb_quadlet_t* buf,
417                                    int len,
418                                    unsigned int* resp_len )
419 {
420     for (int i = 0; i < len; ++i) {
421         buf[i] = ntohl( buf[i] );
422     }
423
424     fb_quadlet_t* result =
425         avc1394_transaction_block2( m_handle,
426                                     nodeId,
427                                     buf,
428                                     len,
429                                     resp_len,
430                                     10 );
431
432     for ( unsigned int i = 0; i < *resp_len; ++i ) {
433         result[i] = htonl( result[i] );
434     }
435
436     return result;
437 }
438
439
440 bool
441 Ieee1394Service::transactionBlockClose()
442 {
443     avc1394_transaction_block_close( m_handle );
444     return true;
445 }
446
447 int
448 Ieee1394Service::getVerboseLevel()
449 {
450     return getDebugLevel();
451 }
452
453 void
454 Ieee1394Service::printBuffer( unsigned int level, size_t length, fb_quadlet_t* buffer ) const
455 {
456
457     for ( unsigned int i=0; i < length; ++i ) {
458         if ( ( i % 4 ) == 0 ) {
459             if ( i > 0 ) {
460                 debugOutputShort(level,"\n");
461             }
462             debugOutputShort(level," %4d: ",i*4);
463         }
464         debugOutputShort(level,"%08X ",buffer[i]);
465     }
466     debugOutputShort(level,"\n");
467 }
468 void
469 Ieee1394Service::printBufferBytes( unsigned int level, size_t length, byte_t* buffer ) const
470 {
471
472     for ( unsigned int i=0; i < length; ++i ) {
473         if ( ( i % 16 ) == 0 ) {
474             if ( i > 0 ) {
475                 debugOutputShort(level,"\n");
476             }
477             debugOutputShort(level," %4d: ",i*16);
478         }
479         debugOutputShort(level,"%02X ",buffer[i]);
480     }
481     debugOutputShort(level,"\n");
482 }
483
484 int
485 Ieee1394Service::resetHandlerLowLevel( raw1394handle_t handle,
486                                        unsigned int generation )
487 {
488     raw1394_update_generation ( handle, generation );
489     Ieee1394Service* instance
490         = (Ieee1394Service*) raw1394_get_userdata( handle );
491     instance->resetHandler( generation );
492
493     return 0;
494 }
495
496 bool
497 Ieee1394Service::resetHandler( unsigned int generation )
498 {
499     quadlet_t buf=0;
500
501     // do a simple read on ourself in order to update the internal structures
502     // this avoids failures after a bus reset
503     read_quadlet( getLocalNodeId() & 0xFFC0,
504                   CSR_REGISTER_BASE | CSR_CYCLE_TIME,
505                   &buf );
506
507     for ( reset_handler_vec_t::iterator it = m_busResetHandlers.begin();
508           it != m_busResetHandlers.end();
509           ++it )
510     {
511         Functor* func = *it;
512         ( *func )();
513     }
514
515     return true;
516 }
517
518 bool Ieee1394Service::registerARMHandler(ARMHandler *h) {
519     debugOutput(DEBUG_LEVEL_VERBOSE, "Registering ARM handler (%p) for 0x%016llX, length %u\n",
520         h, h->getStart(), h->getLength());
521
522     int err=raw1394_arm_register(m_resetHandle, h->getStart(),
523                          h->getLength(), h->getBuffer(), (octlet_t)h,
524                          h->getAccessRights(),
525                          h->getNotificationOptions(),
526                          h->getClientTransactions());
527     if (err) {
528         debugError("Failed to register ARM handler for 0x%016llX\n", h->getStart());
529         debugError(" Error: %s\n", strerror(errno));
530         return false;
531     }
532
533     m_armHandlers.push_back( h );
534
535     return true;
536 }
537
538 bool Ieee1394Service::unregisterARMHandler( ARMHandler *h ) {
539     debugOutput(DEBUG_LEVEL_VERBOSE, "Unregistering ARM handler (%p) for 0x%016llX\n",
540         h, h->getStart());
541
542     for ( arm_handler_vec_t::iterator it = m_armHandlers.begin();
543           it != m_armHandlers.end();
544           ++it )
545     {
546         if((*it) == h) {
547             int err=raw1394_arm_unregister(m_resetHandle, h->getStart());
548             if (err) {
549                 debugError("Failed to unregister ARM handler (%p)\n", h);
550                 debugError(" Error: %s\n", strerror(errno));
551             } else {
552                 m_armHandlers.erase(it);
553                 return true;
554             }
555         }
556     }
557     debugOutput(DEBUG_LEVEL_VERBOSE, " handler not found!\n");
558
559     return false;
560 }
561 /**
562  * @brief Tries to find a free ARM address range
563  *
564  * @param start  address to start with
565  * @param length length of the block needed (bytes)
566  * @param step   step to use when searching (bytes)
567  * @return The base address that is free, and 0xFFFFFFFFFFFFFFFF when failed
568  */
569 nodeaddr_t Ieee1394Service::findFreeARMBlock( nodeaddr_t start, size_t length, size_t step ) {
570     debugOutput(DEBUG_LEVEL_VERBOSE, "Finding free ARM block of %d bytes, from 0x%016llX in steps of %d bytes\n",
571         length, start, step);
572
573     int cnt=0;
574     const int maxcnt=10;
575     int err=1;
576     while(err && cnt++ < maxcnt) {
577         // try to register
578         err=raw1394_arm_register(m_resetHandle, start, length, 0, 0, 0, 0, 0);
579
580         if (err) {
581             debugOutput(DEBUG_LEVEL_VERBOSE, " -> cannot use 0x%016llX\n", start);
582             debugError("    Error: %s\n", strerror(errno));
583             start += step;
584         } else {
585             debugOutput(DEBUG_LEVEL_VERBOSE, " -> use 0x%016llX\n", start);
586             err=raw1394_arm_unregister(m_resetHandle, start);
587             if (err) {
588                 debugOutput(DEBUG_LEVEL_VERBOSE, " error unregistering test handler\n");
589                 debugError("    Error: %s\n", strerror(errno));
590                 return 0xFFFFFFFFFFFFFFFFLLU;
591             }
592             return start;
593         }
594     }
595     debugOutput(DEBUG_LEVEL_VERBOSE, " Could not find free block in %d tries\n",cnt);
596     return 0xFFFFFFFFFFFFFFFFLLU;
597 }
598
599 int
600 Ieee1394Service::armHandlerLowLevel(raw1394handle_t handle,
601                      unsigned long arm_tag,
602                      byte_t request_type, unsigned int requested_length,
603                      void *data)
604 {
605     Ieee1394Service* instance
606         = (Ieee1394Service*) raw1394_get_userdata( handle );
607     instance->armHandler( arm_tag, request_type, requested_length, data );
608
609     return 0;
610 }
611
612 bool
613 Ieee1394Service::armHandler(  unsigned long arm_tag,
614                      byte_t request_type, unsigned int requested_length,
615                      void *data)
616 {
617     for ( arm_handler_vec_t::iterator it = m_armHandlers.begin();
618           it != m_armHandlers.end();
619           ++it )
620     {
621         if((*it) == (ARMHandler *)arm_tag) {
622             struct raw1394_arm_request_response *arm_req_resp;
623             arm_req_resp  = (struct raw1394_arm_request_response *) data;
624             raw1394_arm_request_t arm_req=arm_req_resp->request;
625             raw1394_arm_response_t arm_resp=arm_req_resp->response;
626
627             debugOutput(DEBUG_LEVEL_VERBOSE,"ARM handler for address 0x%016llX called\n",
628                 (*it)->getStart());
629             debugOutput(DEBUG_LEVEL_VERBOSE," request type   : 0x%02X\n",request_type);
630             debugOutput(DEBUG_LEVEL_VERBOSE," request length : %04d\n",requested_length);
631
632             switch(request_type) {
633                 case RAW1394_ARM_READ:
634                     (*it)->handleRead(arm_req);
635                     *arm_resp=*((*it)->getResponse());
636                     break;
637                 case RAW1394_ARM_WRITE:
638                     (*it)->handleWrite(arm_req);
639                     *arm_resp=*((*it)->getResponse());
640                     break;
641                 case RAW1394_ARM_LOCK:
642                     (*it)->handleLock(arm_req);
643                     *arm_resp=*((*it)->getResponse());
644                     break;
645                 default:
646                     debugWarning("Unknown request type received, ignoring...\n");
647             }
648
649             return true;
650         }
651     }
652
653     debugOutput(DEBUG_LEVEL_VERBOSE,"default ARM handler called\n");
654
655     m_default_arm_handler(m_resetHandle, arm_tag, request_type, requested_length, data );
656     return true;
657 }
658
659 bool
660 Ieee1394Service::startRHThread()
661 {
662     int i;
663
664     if ( m_threadRunning ) {
665         return true;
666     }
667     pthread_mutex_lock( &m_mutex );
668     i = pthread_create( &m_thread, 0, rHThread, this );
669     pthread_mutex_unlock( &m_mutex );
670     if (i) {
671         debugFatal("Could not start ieee1394 service thread\n");
672         return false;
673     }
674     m_threadRunning = true;
675
676     return true;
677 }
678
679 void
680 Ieee1394Service::stopRHThread()
681 {
682     if ( m_threadRunning ) {
683         pthread_mutex_lock (&m_mutex);
684         pthread_cancel (m_thread);
685         pthread_join (m_thread, 0);
686         pthread_mutex_unlock (&m_mutex);
687         m_threadRunning = false;
688     }
689 }
690
691 void*
692 Ieee1394Service::rHThread( void* arg )
693 {
694     Ieee1394Service* pIeee1394Service = (Ieee1394Service*) arg;
695
696     while (true) {
697         raw1394_loop_iterate (pIeee1394Service->m_resetHandle);
698         pthread_testcancel ();
699     }
700
701     return 0;
702 }
703
704 bool
705 Ieee1394Service::addBusResetHandler( Functor* functor )
706 {
707     debugOutput(DEBUG_LEVEL_VERBOSE, "Adding busreset handler (%p)\n", functor);
708     m_busResetHandlers.push_back( functor );
709     return true;
710 }
711
712 bool
713 Ieee1394Service::remBusResetHandler( Functor* functor )
714 {
715     debugOutput(DEBUG_LEVEL_VERBOSE, "Removing busreset handler (%p)\n", functor);
716
717     for ( reset_handler_vec_t::iterator it = m_busResetHandlers.begin();
718           it != m_busResetHandlers.end();
719           ++it )
720     {
721         if ( *it == functor ) {
722             debugOutput(DEBUG_LEVEL_VERBOSE, " found\n");
723             m_busResetHandlers.erase( it );
724             return true;
725         }
726     }
727     debugOutput(DEBUG_LEVEL_VERBOSE, " not found\n");
728     return false;
729 }
730
731 /**
732  * Allocates an iso channel for use by the interface in a similar way to
733  * libiec61883.  Returns -1 on error (due to there being no free channels)
734  * or an allocated channel number.
735  *
736  * Does not perform anything other than registering the channel and the
737  * bandwidth at the IRM
738  *
739  * Also allocates the necessary bandwidth (in ISO allocation units).
740  *
741  * FIXME: As in libiec61883, channel 63 is not requested; this is either a
742  * bug or it's omitted since that's the channel preferred by video devices.
743  *
744  * @param bandwidth the bandwidth to allocate for this channel
745  * @return the channel number
746  */
747 signed int Ieee1394Service::allocateIsoChannelGeneric(unsigned int bandwidth) {
748     debugOutput(DEBUG_LEVEL_VERBOSE, "Allocating ISO channel using generic method...\n" );
749
750     struct ChannelInfo cinfo;
751
752     int c = -1;
753     for (c = 0; c < 63; c++) {
754         if (raw1394_channel_modify (m_handle, c, RAW1394_MODIFY_ALLOC) == 0)
755             break;
756     }
757     if (c < 63) {
758         if (raw1394_bandwidth_modify(m_handle, bandwidth, RAW1394_MODIFY_ALLOC) < 0) {
759             debugFatal("Could not allocate bandwidth of %d\n", bandwidth);
760
761             raw1394_channel_modify (m_handle, c, RAW1394_MODIFY_FREE);
762             return -1;
763         } else {
764             cinfo.channel=c;
765             cinfo.bandwidth=bandwidth;
766             cinfo.alloctype=AllocGeneric;
767
768             cinfo.xmit_node=-1;
769             cinfo.xmit_plug=-1;
770             cinfo.recv_node=-1;
771             cinfo.recv_plug=-1;
772
773             if (registerIsoChannel(c, cinfo)) {
774                 return c;
775             } else {
776                 raw1394_bandwidth_modify(m_handle, bandwidth, RAW1394_MODIFY_FREE);
777                 raw1394_channel_modify (m_handle, c, RAW1394_MODIFY_FREE);
778                 return -1;
779             }
780         }
781     }
782     return -1;
783 }
784
785 /**
786  * Allocates an iso channel for use by the interface in a similar way to
787  * libiec61883.  Returns -1 on error (due to there being no free channels)
788  * or an allocated channel number.
789  *
790  * Uses IEC61883 Connection Management Procedure to establish the connection.
791  *
792  * Also allocates the necessary bandwidth (in ISO allocation units).
793  *
794  * @param xmit_node  node id of the transmitter
795  * @param xmit_plug  the output plug to use. If -1, find the first online plug, and
796  * upon return, contains the plug number used.
797  * @param recv_node  node id of the receiver
798  * @param recv_plug the input plug to use. If -1, find the first online plug, and
799  * upon return, contains the plug number used.
800  *
801  * @return the channel number
802  */
803
804 signed int Ieee1394Service::allocateIsoChannelCMP(
805     nodeid_t xmit_node, int xmit_plug,
806     nodeid_t recv_node, int recv_plug
807     ) {
808
809     debugOutput(DEBUG_LEVEL_VERBOSE, "Allocating ISO channel using IEC61883 CMP...\n" );
810
811     struct ChannelInfo cinfo;
812
813     int c = -1;
814     int bandwidth=1;
815
816     // do connection management: make connection
817     c = iec61883_cmp_connect(
818         m_handle,
819         xmit_node | 0xffc0,
820         &xmit_plug,
821         recv_node | 0xffc0,
822         &recv_plug,
823         &bandwidth);
824
825     if((c<0) || (c>63)) {
826         debugError("Could not do CMP from %04X:%02d to %04X:%02d\n",
827             xmit_node, xmit_plug, recv_node, recv_plug
828             );
829         return -1;
830     }
831
832     cinfo.channel=c;
833     cinfo.bandwidth=bandwidth;
834     cinfo.alloctype=AllocCMP;
835
836     cinfo.xmit_node=xmit_node;
837     cinfo.xmit_plug=xmit_plug;
838     cinfo.recv_node=recv_node;
839     cinfo.recv_plug=recv_plug;
840
841     if (registerIsoChannel(c, cinfo)) {
842         return c;
843     }
844
845     return -1;
846 }
847
848 /**
849  * Deallocates an iso channel.  Silently ignores a request to deallocate
850  * a negative channel number.
851  *
852  * Figures out the method that was used to allocate the channel (generic, cmp, ...)
853  * and uses the appropriate method to deallocate. Also frees the bandwidth
854  * that was reserved along with this channel.
855  *
856  * @param c channel number
857  * @return true if successful
858  */
859 bool Ieee1394Service::freeIsoChannel(signed int c) {
860     debugOutput(DEBUG_LEVEL_VERBOSE, "Freeing ISO channel %d...\n", c );
861
862     if (c < 0 || c > 63) {
863         debugWarning("Invalid channel number: %d\n", c);
864         return false;
865     }
866
867     switch (m_channels[c].alloctype) {
868         default:
869             debugError(" BUG: invalid allocation type!\n");
870             return false;
871
872         case AllocFree:
873             debugWarning(" Channel %d not registered\n", c);
874             return false;
875
876         case AllocGeneric:
877             debugOutput(DEBUG_LEVEL_VERBOSE, " allocated using generic routine...\n" );
878             debugOutput(DEBUG_LEVEL_VERBOSE, " freeing %d bandwidth units...\n", m_channels[c].bandwidth );
879             if (raw1394_bandwidth_modify(m_handle, m_channels[c].bandwidth, RAW1394_MODIFY_FREE) !=0) {
880                 debugWarning("Failed to deallocate bandwidth\n");
881             }
882             debugOutput(DEBUG_LEVEL_VERBOSE, " freeing channel %d...\n", m_channels[c].channel );
883             if (raw1394_channel_modify (m_handle, m_channels[c].channel, RAW1394_MODIFY_FREE) != 0) {
884                 debugWarning("Failed to free channel\n");
885             }
886             if (!unregisterIsoChannel(c))
887                 return false;
888             return true;
889
890         case AllocCMP:
891             debugOutput(DEBUG_LEVEL_VERBOSE, " allocated using IEC61883 CMP...\n" );
892             debugOutput(DEBUG_LEVEL_VERBOSE, " performing IEC61883 CMP disconnect...\n" );
893             if(iec61883_cmp_disconnect(
894                     m_handle,
895                     m_channels[c].xmit_node | 0xffc0,
896                     m_channels[c].xmit_plug,
897                     m_channels[c].recv_node | 0xffc0,
898                     m_channels[c].recv_plug,
899                     m_channels[c].channel,
900                     m_channels[c].bandwidth) != 0) {
901                 debugWarning("Could not do CMP disconnect for channel %d!\n",c);
902             }
903             if (!unregisterIsoChannel(c))
904                 return false;
905             return true;
906     }
907
908     // unreachable
909     debugError("BUG: unreachable code reached!\n");
910
911     return false;
912 }
913
914 /**
915  * Registers a channel as managed by this ieee1394service
916  * @param c channel number
917  * @param cinfo channel info struct
918  * @return true if successful
919  */
920 bool Ieee1394Service::registerIsoChannel(unsigned int c, struct ChannelInfo cinfo) {
921     if (c < 63) {
922         if (m_channels[c].alloctype != AllocFree) {
923             debugWarning("Channel %d already registered with bandwidth %d\n",
924                 m_channels[c].channel, m_channels[c].bandwidth);
925         }
926
927         memcpy(&m_channels[c], &cinfo, sizeof(struct ChannelInfo));
928
929     } else return false;
930     return true;
931 }
932
933 /**
934  * unegisters a channel from this ieee1394service
935  * @param c channel number
936  * @return true if successful
937  */
938 bool Ieee1394Service::unregisterIsoChannel(unsigned int c) {
939     if (c < 63) {
940         if (m_channels[c].alloctype == AllocFree) {
941             debugWarning("Channel %d not registered\n", c);
942             return false;
943         }
944
945         m_channels[c].channel=-1;
946         m_channels[c].bandwidth=-1;
947         m_channels[c].alloctype=AllocFree;
948         m_channels[c].xmit_node=0xFFFF;
949         m_channels[c].xmit_plug=-1;
950         m_channels[c].recv_node=0xFFFF;
951         m_channels[c].recv_plug=-1;
952
953     } else return false;
954     return true;
955 }
956
957 /**
958  * Returns the current value of the `bandwidth available' register on
959  * the IRM, or -1 on error.
960  * @return
961  */
962 signed int Ieee1394Service::getAvailableBandwidth() {
963     quadlet_t buffer;
964     signed int result = raw1394_read (m_handle, raw1394_get_irm_id (m_handle),
965         CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
966         sizeof (quadlet_t), &buffer);
967
968     if (result < 0)
969         return -1;
970     return ntohl(buffer);
971 }
972
973 void
974 Ieee1394Service::setVerboseLevel(int l)
975 {
976     if (m_isoManager) m_isoManager->setVerboseLevel(l);
977     setDebugLevel(l);
978     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
979 }
980
981 void
982 Ieee1394Service::show()
983 {
984     debugOutput( DEBUG_LEVEL_VERBOSE, "Port:  %d\n", getPort() );
985     debugOutput( DEBUG_LEVEL_VERBOSE, " Name: %s\n", getPortName().c_str() );
986     debugOutputShort( DEBUG_LEVEL_NORMAL, "Iso handler info:\n");
987     if (m_isoManager) m_isoManager->dumpInfo();
988 }
Note: See TracBrowser for help on using the browser.