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

Revision 439, 24.7 kB (checked in by pieterpalmers, 16 years ago)

- some work on the AVC mixer & control stuff

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