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

Revision 742, 25.8 kB (checked in by ppalmers, 13 years ago)

- Remove some obsolete support files and dirs

- Clean up the license statements in the source files. Everything is

GPL version 3 now.

- Add license and copyright notices to scons scripts

- Clean up some other text files

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