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

Revision 415, 23.8 kB (checked in by pieterpalmers, 15 years ago)

ieee1394service:
- implemented 64bit compare-swap-lock operation (needed for DICE)
- small name change of (un)registerARMhandler to (un)registerARMHandler

iavdevice.h:
- made the stream start/stop functions return bool instead of int
- updated function documentation for consistency and to reflect changes

BeBoB avdevice:
- replaced the 2 fixed streamprocessor pointers with a 2 vectors of streamprocessors
- implemented the 'snoop mode' (cannot be activated yet)

libstreaming:
- removed unused 'type' attribute from AmdtpPortInfo? & children

mh_avdevice, motu_avdevice, rme_avdevice:
- replaced m_1394service with m_p1394service for consistence

maudio_avdevice.cpp:
- removed unused code

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