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

Revision 739, 25.8 kB (checked in by ppalmers, 16 years ago)

- Adapt the ffado external API (upgrade to v3)

NEEDS NEW JACK BACKEND

- simplify FFADODevice constructor even more
- implement first framework support for supporting multiple adapters.

currently all firewire adapters are scanned for supported devices unless specified otherwise
however attaching devices to separate adapters is not supported. using multiple adapters at
that are connected together might work.

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