root/trunk/freebob/src/ieee1394service.cpp

Revision 42, 14.0 kB (checked in by wagi, 19 years ago)

Register/unregister AvDevice? in AvDevicePool? when detected/disappeared.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* ieee1394service.cpp
2  * Copyright (C) 2004 by Daniel Wagner
3  *
4  * This file is part of FreeBob.
5  *
6  * FreeBob is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * FreeBob is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with FreeBob; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20
21 #include <errno.h>
22 #include <libavc1394/avc1394.h>
23 #include <libavc1394/avc1394_vcr.h>
24 #include <libiec61883/iec61883.h>
25
26 #include "ieee1394service.h"
27 #include "threads.h"
28 #include "debugmodule.h"
29 #include "avdevicepool.h"
30
31 #include "avdevice.h"
32 #include "avdescriptor.h"
33 #include "avmusicidentifierdescriptor.h"
34 #include "avmusicstatusdescriptor.h"
35 #include "avinfoblock.h"
36 #include "avgeneralmusicstatusinfoblock.h"
37 #include "avnameinfoblock.h"
38 #include "avaudioinfoblock.h"
39 #include "avmidiinfoblock.h"
40 #include "avaudiosyncinfoblock.h"
41 #include "avsourcepluginfoblock.h"
42 #include "avoutputplugstatusinfoblock.h"
43
44 Ieee1394Service* Ieee1394Service::m_pInstance = 0;
45
46 Ieee1394Service::Ieee1394Service()
47     : m_iPort( 0 )
48     , m_bInitialised( false )
49     , m_bRHThreadRunning( false )
50     , m_iGenerationCount( 0 )
51 {
52     pthread_mutex_init( &m_mutex, NULL );
53 }
54
55 Ieee1394Service::~Ieee1394Service()
56 {
57     stopRHThread();
58
59     if ( m_rhHandle ) {
60         raw1394_destroy_handle( m_rhHandle );
61         m_rhHandle = 0;
62     }
63
64     if ( m_handle ) {
65         raw1394_destroy_handle( m_handle );
66         m_handle = 0;
67     }
68
69     m_pInstance = 0;
70 }
71
72 FBReturnCodes
73 Ieee1394Service::initialize()
74 {
75     if ( !m_bInitialised ) {
76         m_rhHandle = raw1394_new_handle();
77         m_handle = raw1394_new_handle();
78         if ( !m_rhHandle || !m_handle ) {
79             if ( !errno ) {
80                 fprintf( stderr,  "libraw1394 not compatible.\n" );
81             } else {
82                 perror ("Could not get 1394 handle");
83                 fprintf (stderr, "Is ieee1394 and raw1394 driver loaded?\n");
84             }
85             return eFBRC_Creating1394HandleFailed;
86         }
87
88         // Store this instance in the user data pointer, in order
89         // to be able to retrieve the instance in the pure C bus reset
90         // call back function.
91         raw1394_set_userdata( m_rhHandle,  this );
92
93         if ( raw1394_set_port( m_rhHandle,  m_iPort ) < 0 ) {
94             perror( "Could not set port" );
95             return eFBRC_Setting1394PortFailed;
96         }
97
98         if ( raw1394_set_port( m_handle,  m_iPort ) < 0 ) {
99             perror( "Could not set port" );
100             return eFBRC_Setting1394PortFailed;
101         }
102
103         raw1394_set_bus_reset_handler( m_rhHandle,  this->resetHandler );
104
105         startRHThread();
106
107         m_bInitialised = true;
108
109         asyncCall( this, &Ieee1394Service::discoveryDevices,
110                    m_iGenerationCount);
111     }
112     return eFBRC_Success;
113 }
114
115 void
116 Ieee1394Service::shutdown()
117 {
118     delete this;
119 }
120
121 Ieee1394Service*
122 Ieee1394Service::instance()
123 {
124     if ( !m_pInstance ) {
125         m_pInstance = new Ieee1394Service;
126     }
127     return m_pInstance;
128 }
129
130 FBReturnCodes
131 Ieee1394Service::discoveryDevices( unsigned int iGeneration )
132 {
133     //scan bus
134     int iNodeCount = raw1394_get_nodecount( m_handle );
135     for ( int iNodeId = 0; iNodeId < iNodeCount; ++iNodeId ) {
136         rom1394_directory romDir;
137         rom1394_get_directory( m_handle, iNodeId, &romDir );
138         printRomDirectory( iNodeId, &romDir );
139
140         switch (rom1394_get_node_type( &romDir )) {
141         case ROM1394_NODE_TYPE_UNKNOWN:
142             debugPrint (DEBUG_LEVEL_INFO,
143                         "Node %d has node type UNKNOWN\n", iNodeId);
144             break;
145         case ROM1394_NODE_TYPE_DC:
146             debugPrint (DEBUG_LEVEL_INFO,
147                         "Node %d has node type DC\n", iNodeId);
148             break;
149         case ROM1394_NODE_TYPE_AVC:
150             debugPrint (DEBUG_LEVEL_INFO,
151                         "Node %d has node type AVC\n", iNodeId);
152             printAvcUnitInfo( iNodeId );
153
154             if ( avc1394_check_subunit_type( m_handle, iNodeId,
155                                              AVC1394_SUBUNIT_TYPE_AUDIO ) ) {
156
157                 octlet_t oGuid = rom1394_get_guid( m_handle, iNodeId );
158                 AvDevice* pAvDevice
159                     = AvDevicePool::instance()->getAvDevice( oGuid );
160                 if ( !pAvDevice ) {
161                     pAvDevice = new AvDevice( oGuid );
162                 }
163                 pAvDevice->setNodeId( iNodeId );
164                 pAvDevice->setPort( m_iPort );
165
166                 if ( !pAvDevice->isInitialised() ) {
167                     FBReturnCodes eStatus = pAvDevice->initialize();
168                     if ( eStatus != eFBRC_Success ) {
169                         debugError( "AvDevice with GUID 0x%08x%08x could "
170                                     "not be initialized\n",
171                                     (quadlet_t) (oGuid>>32),
172                                     (quadlet_t) (oGuid & 0xffffffff) );
173
174                         delete pAvDevice;
175                         return eStatus;
176                     }
177                 }
178
179                 // XXX Pieter's test code.
180                 avDeviceTests( oGuid, m_iPort, iNodeId );
181             }
182             break;
183         case ROM1394_NODE_TYPE_SBP2:
184             debugPrint( DEBUG_LEVEL_INFO,
185                         "Node %d has node type SBP2\n", iNodeId);
186             break;
187         case ROM1394_NODE_TYPE_CPU:
188             debugPrint( DEBUG_LEVEL_INFO,
189                         "Node %d has node type CPU\n", iNodeId);
190             break;
191         default:
192             debugPrint( DEBUG_LEVEL_INFO,
193                         "No matching node type found for node %d\n", iNodeId);
194         }
195     }
196
197     AvDevicePool::instance()->removeObsoleteDevices( iGeneration );
198     return eFBRC_Success;
199 }
200
201
202 void
203 Ieee1394Service::avDeviceTests(octlet_t oGuid, int iPort, int iNodeId)
204 {
205     // PP: just a static try, don't want to mess with the device manager yet...
206     // Remark: the AvDevice and AvDescriptor aren't debugged thouroughly yet!
207     //         the following code is the only debug I had time for... to be continued! (later this week)
208                 debugPrint (DEBUG_LEVEL_INFO, "  Trying to create an AvDevice...\n");
209
210                 AvDevice *test=new AvDevice(oGuid);
211                 test->setNodeId( iNodeId );
212                 test->setPort( iPort );
213                 debugPrint (DEBUG_LEVEL_INFO, "   Created...\n");
214                 test->initialize();
215                 if (test->isInitialised()) {
216                         unsigned char fmt;
217                         quadlet_t fdf;
218                         test->getInputPlugSignalFormat(0,&fmt,&fdf);
219                         debugPrint (DEBUG_LEVEL_INFO, "   fmt=%02X fdf=%08X\n",fmt,fdf);
220                         test->getInputPlugSignalFormat(1,&fmt,&fdf);
221                         debugPrint (DEBUG_LEVEL_INFO, "   fmt=%02X fdf=%08X\n",fmt,fdf);
222                         test->getOutputPlugSignalFormat(0,&fmt,&fdf);
223                         debugPrint (DEBUG_LEVEL_INFO, "   fmt=%02X fdf=%08X\n",fmt,fdf);
224                         test->getOutputPlugSignalFormat(1,&fmt,&fdf);
225                         debugPrint (DEBUG_LEVEL_INFO, "   fmt=%02X fdf=%08X\n",fmt,fdf);
226                         test->printConnections();
227                 }
228
229                 debugPrint (DEBUG_LEVEL_INFO, "   Deleting AvDevice...\n");
230                 delete test;
231 }
232
233
234 void
235 Ieee1394Service::printAvcUnitInfo( int iNodeId )
236 {
237     printf( "AVC: video monitor?......%s\n",
238             avc1394_check_subunit_type( m_handle, iNodeId,
239                                         AVC1394_SUBUNIT_TYPE_VIDEO_MONITOR ) ?
240             "yes":"no" );
241     printf( "AVC: audio?..............%s\n",
242             avc1394_check_subunit_type( m_handle, iNodeId,
243                                         AVC1394_SUBUNIT_TYPE_AUDIO ) ?
244             "yes":"no" );
245     printf( "AVC; printer?............%s\n",
246             avc1394_check_subunit_type( m_handle, iNodeId,
247                                         AVC1394_SUBUNIT_TYPE_PRINTER ) ?
248             "yes":"no" );
249     printf( "AVC: disk recorder?......%s\n",
250             avc1394_check_subunit_type( m_handle, iNodeId,
251                                         AVC1394_SUBUNIT_TYPE_DISC_RECORDER ) ?
252             "yes":"no" );
253     printf( "AVC: video recorder?.....%s\n",
254             avc1394_check_subunit_type( m_handle, iNodeId,
255                                         AVC1394_SUBUNIT_TYPE_TAPE_RECORDER ) ?
256             "yes":"no" );
257     printf( "AVC: vcr?................%s\n",
258             avc1394_check_subunit_type( m_handle, iNodeId,
259                                         AVC1394_SUBUNIT_TYPE_VCR ) ?
260             "yes":"no" );
261     printf( "AVC: tuner?..............%s\n",
262             avc1394_check_subunit_type( m_handle, iNodeId,
263                                         AVC1394_SUBUNIT_TYPE_TUNER ) ?
264             "yes":"no" );
265     printf( "AVC: CA?.................%s\n",
266             avc1394_check_subunit_type( m_handle, iNodeId,
267                                         AVC1394_SUBUNIT_TYPE_CA ) ?
268             "yes":"no" );
269     printf( "AVC: video camera?.......%s\n",
270             avc1394_check_subunit_type( m_handle, iNodeId,
271                                         AVC1394_SUBUNIT_TYPE_VIDEO_CAMERA ) ?
272             "yes":"no" );
273     printf( "AVC: panel?..............%s\n",
274             avc1394_check_subunit_type(m_handle, iNodeId,
275                                         AVC1394_SUBUNIT_TYPE_PANEL ) ?
276             "yes":"no" );
277     printf( "AVC: camera storage?.....%s\n",
278             avc1394_check_subunit_type( m_handle, iNodeId,
279                                         AVC1394_SUBUNIT_TYPE_CAMERA_STORAGE ) ?
280             "yes":"no" );
281     printf( "AVC: bulletin board?.....%s\n",
282             avc1394_check_subunit_type( m_handle, iNodeId,
283                                         AVC1394_SUBUNIT_TYPE_BULLETIN_BOARD ) ?
284             "yes":"no" );
285     printf( "AVC: vendor specific?....%s\n",
286             avc1394_check_subunit_type( m_handle, iNodeId,
287                                         AVC1394_SUBUNIT_TYPE_VENDOR_UNIQUE ) ?
288             "yes":"no" );
289     printf( "AVC: extended?...........%s\n",
290             avc1394_check_subunit_type( m_handle, iNodeId,
291                                         AVC1394_SUBUNIT_TYPE_EXTENDED ) ?
292             "yes":"no" );
293     printf( "AVC: unit?...............%s\n",
294             avc1394_check_subunit_type( m_handle, iNodeId,
295                                         AVC1394_SUBUNIT_TYPE_UNIT ) ?
296             "yes":"no" );
297     printf( "AVC: music?..............%s\n",
298             avc1394_check_subunit_type( m_handle, iNodeId,
299                                         AVC1394_SUBUNIT_TYPE_MUSIC ) ?
300             "yes":"no" );
301 }
302
303 void
304 Ieee1394Service::printRomDirectory( int iNodeId,  rom1394_directory* pRomDir )
305 {
306     int iBusInfoBlockLength
307         = rom1394_get_bus_info_block_length( m_handle,  iNodeId );
308     int iBusId = rom1394_get_bus_id( m_handle,  iNodeId );
309     octlet_t oGuid = rom1394_get_guid( m_handle, iNodeId );
310     rom1394_bus_options busOptions;
311     rom1394_get_bus_options( m_handle, iNodeId, &busOptions );
312
313     printf( "\nNode %d: \n", iNodeId );
314     printf( "-------------------------------------------------\n" );
315     printf( "bus info block length = %d\n", iBusInfoBlockLength);
316     printf( "bus id = 0x%08x\n", iBusId );
317     printf( "bus options:\n" );
318     printf( "    isochronous resource manager capable: %d\n", busOptions.irmc );
319     printf ("    cycle master capable                : %d\n", busOptions.cmc );
320     printf ("    isochronous capable                 : %d\n", busOptions.isc );
321     printf ("    bus manager capable                 : %d\n", busOptions.bmc );
322     printf ("    cycle master clock accuracy         : %d ppm\n", busOptions.cyc_clk_acc );
323     printf( "    maximum asynchronous record size    : %d bytes\n", busOptions.max_rec );
324     printf("GUID: 0x%08x%08x\n", (quadlet_t) (oGuid>>32),
325            (quadlet_t) (oGuid & 0xffffffff) );
326     printf( "directory:\n");
327     printf( "    node capabilities    : 0x%08x\n", pRomDir->node_capabilities );
328     printf( "    vendor id            : 0x%08x\n", pRomDir->vendor_id );
329     printf( "    unit spec id         : 0x%08x\n", pRomDir->unit_spec_id );
330     printf( "    unit software version: 0x%08x\n", pRomDir->unit_sw_version );
331     printf( "    model id             : 0x%08x\n", pRomDir->model_id );
332     printf( "    textual leaves       : %s\n",     pRomDir->label );
333 }
334
335 int
336 Ieee1394Service::resetHandler( raw1394handle_t handle,
337                                unsigned int iGeneration )
338 {
339     debugPrint( DEBUG_LEVEL_INFO,
340                 "Bus reset has occurred (generation = %d).\n", iGeneration );
341     raw1394_update_generation (handle, iGeneration);
342     Ieee1394Service* pInstance
343         = (Ieee1394Service*) raw1394_get_userdata (handle);
344     pInstance->setGenerationCount( iGeneration );
345
346     // dw: let's rescan the bus.  this might not the correct order
347     // of commands.
348     asyncCall( pInstance, &Ieee1394Service::discoveryDevices, iGeneration );
349     return 0;
350 }
351
352 bool
353 Ieee1394Service::startRHThread()
354 {
355     if ( m_bRHThreadRunning ) {
356         return true;
357     }
358     debugPrint( DEBUG_LEVEL_INFO,
359                 "Starting bus reset handler thread.\n" );
360     pthread_mutex_lock( &m_mutex );
361     pthread_create( &m_thread, NULL, rHThread, this );
362     pthread_mutex_unlock( &m_mutex );
363     m_bRHThreadRunning = true;
364     return true;
365 }
366
367 void
368 Ieee1394Service::stopRHThread()
369 {
370     if ( m_bRHThreadRunning ) {
371         debugPrint( DEBUG_LEVEL_INFO,
372                     "Stopping bus reset handler thread.\n" );
373         pthread_mutex_lock (&m_mutex);
374         pthread_cancel (m_thread);
375         pthread_join (m_thread, NULL);
376         pthread_mutex_unlock (&m_mutex);
377     }
378     m_bRHThreadRunning = false;
379 }
380
381 void*
382 Ieee1394Service::rHThread( void* arg )
383 {
384     Ieee1394Service* pIeee1394Service = (Ieee1394Service*) arg;
385
386     while (true) {
387         raw1394_loop_iterate (pIeee1394Service->m_rhHandle);
388         pthread_testcancel ();
389     }
390
391     return NULL;
392 }
393
394 void
395 Ieee1394Service::setGenerationCount( unsigned int iGeneration )
396 {
397     m_iGenerationCount = iGeneration;
398 }
399
400 unsigned int
401 Ieee1394Service::getGenerationCount()
402 {
403     return m_iGenerationCount;
404 }
Note: See TracBrowser for help on using the browser.