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

Revision 445, 24.4 kB (checked in by pieterpalmers, 16 years ago)

* name change from FreeBoB to FFADO
* replaced tabs by 4 spaces
* got rid of end-of-line spaces
* made all license and copyrights conform

library becomes LGPL, apps become GPL
explicitly state LGPL v2.1 and GPL v2 (don't like v3 draft)

copyrights are 2005-2007 Daniel & Pieter
except for the MotU stuff (C) Jonathan, Pieter

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