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

Revision 560, 24.4 kB (checked in by ppalmers, 17 years ago)

- Sort the FFADODevice vector on GUID before assigning device id's

This results in the same device id for identical device setups,
independent of the way they are connected or the node numbers they
have been assigned.

- Sanitized debug message reporting a bit
- Cosmetic changes

  • 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_NORMAL );
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     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
834     setDebugLevel(l);
835 }
Note: See TracBrowser for help on using the browser.