root/branches/streaming-rework/src/libieee1394/ieee1394service.cpp

Revision 429, 23.7 kB (checked in by jwoithe, 15 years ago)

Fix Ieee1394Service::freeIsoChannel() so it actually deallocates a channel
and its bandwidth. In short, unregisterIsoChannel() returns false on error
and (most importantly) one can't call unregisterIsoChannel() before
raw1394_bandwidth_modify() and raw1394_channel_modify() because it wipes the
very information one needs for these calls to succeed.

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