root/trunk/freebob/src/ieee1394service.cpp

Revision 21, 15.1 kB (checked in by pieterpalmers, 19 years ago)

- Fixed some bugs in AvDescriptor? and AvDevice?
- Added more tests of the new classes to ieee1394service
- Modified the debuglevel to hide low level AVC transactions by AvDevice?
- Added AvMusicIdentifierDescriptor? and AvMusicStatusDescriptor? as a first

attempt at parsing device info.

- Added AvInfoBlock? to handle infoblocks (still very embryonal)

  • 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 "ieee1394service.h"
25 #include "debugmodule.h"
26
27 #include "avdevice.h"
28 #include "avdescriptor.h"
29 #include "avmusicidentifierdescriptor.h"
30 #include "avmusicstatusdescriptor.h"
31 #include "avinfoblock.h"
32
33 Ieee1394Service* Ieee1394Service::m_pInstance = 0;
34
35 Ieee1394Service::Ieee1394Service()
36     : m_iPort( 0 )
37     , m_bInitialised( false )
38     , m_bRHThreadRunning( false )
39     , m_iGenerationCount( 0 )
40 {
41     pthread_mutex_init( &m_mutex, NULL );
42 }
43
44 Ieee1394Service::~Ieee1394Service()
45 {
46     stopRHThread();
47
48     if ( m_rhHandle ) {
49         raw1394_destroy_handle( m_rhHandle );
50         m_rhHandle = 0;
51     }
52
53     if ( m_handle ) {
54         raw1394_destroy_handle( m_handle );
55         m_handle = 0;
56     }
57
58     m_pInstance = 0;
59 }
60
61 FBReturnCodes
62 Ieee1394Service::initialize()
63 {
64     if ( !m_bInitialised ) {
65         m_rhHandle = raw1394_new_handle();
66         m_handle = raw1394_new_handle();
67         if ( !m_rhHandle || !m_handle ) {
68             if ( !errno ) {
69                 fprintf( stderr,  "libraw1394 not compatible.\n" );
70             } else {
71                 perror ("Could not get 1394 handle");
72                 fprintf (stderr, "Is ieee1394 and raw1394 driver loaded?\n");
73             }
74             return eFBRC_Creating1394HandleFailed;
75         }
76
77         // Store this instance in the user data pointer, in order
78         // to be able to retrieve the instance in the pure C bus reset
79         // call back function.
80         raw1394_set_userdata( m_rhHandle,  this );
81
82         if ( raw1394_set_port( m_rhHandle,  m_iPort ) < 0 ) {
83             perror( "Could not set port" );
84             return eFBRC_Setting1394PortFailed;
85         }
86
87         if ( raw1394_set_port( m_handle,  m_iPort ) < 0 ) {
88             perror( "Could not set port" );
89             return eFBRC_Setting1394PortFailed;
90         }
91
92         raw1394_set_bus_reset_handler( m_rhHandle,  this->resetHandler );
93
94         startRHThread();
95
96         discoveryDevices();
97         m_bInitialised = true;
98     }
99     return eFBRC_Success;
100 }
101
102 void
103 Ieee1394Service::shutdown()
104 {
105     delete this;
106 }
107
108 Ieee1394Service*
109 Ieee1394Service::instance()
110 {
111     if ( !m_pInstance ) {
112         m_pInstance = new Ieee1394Service;
113     }
114     return m_pInstance;
115 }
116
117 FBReturnCodes
118 Ieee1394Service::discoveryDevices()
119 {
120     //scan bus
121     int iNodeCount = raw1394_get_nodecount( m_handle );
122     for ( int iNodeId = 0; iNodeId < iNodeCount; ++iNodeId ) {
123         rom1394_directory romDir;
124         rom1394_get_directory( m_handle, iNodeId, &romDir );
125         printRomDirectory( iNodeId, &romDir );
126
127         switch (rom1394_get_node_type( &romDir )) {
128         case ROM1394_NODE_TYPE_UNKNOWN:
129             debugPrint (DEBUG_LEVEL_INFO,
130                         "Node %d has node type UNKNOWN\n", iNodeId);
131             break;
132         case ROM1394_NODE_TYPE_DC:
133             debugPrint (DEBUG_LEVEL_INFO,
134                         "Node %d has node type DC\n", iNodeId);
135             break;
136         case ROM1394_NODE_TYPE_AVC:
137             debugPrint (DEBUG_LEVEL_INFO,
138                         "Node %d has node type AVC\n", iNodeId);
139             printAvcUnitInfo( iNodeId );
140
141             if ( avc1394_check_subunit_type( m_handle, iNodeId,
142                                              AVC1394_SUBUNIT_TYPE_AUDIO ) ) {
143
144                 // XXX
145                 // create avcDevice which discovers itself :)
146
147                 // PP: just a static try, don't want to mess with the device manager yet...
148                 // Remark: the AvDevice and AvDescriptor aren't debugged thouroughly yet!
149                 //         the following code is the only debug I had time for... to be continued! (later this week)
150                 debugPrint (DEBUG_LEVEL_INFO, "  Trying to create an AvDevice...\n");
151
152                 AvDevice *test=new AvDevice(m_iPort, iNodeId);
153                 debugPrint (DEBUG_LEVEL_INFO, "   Created...\n");
154                 test->Initialize();
155                 if (test->isInitialised()) {
156                         debugPrint (DEBUG_LEVEL_INFO, "   Init successfull...\n");
157                         debugPrint (DEBUG_LEVEL_INFO, "   Trying to create an AvDescriptor...\n");
158                         AvDescriptor *testdesc=new AvDescriptor(test,AVC1394_SUBUNIT_TYPE_MUSIC | AVC1394_SUBUNIT_ID_0,0x00);
159                         debugPrint (DEBUG_LEVEL_INFO, "    Created...\n");
160                         debugPrint (DEBUG_LEVEL_INFO, "    Opening...\n");
161                         testdesc->OpenReadOnly();
162                        
163                         debugPrint (DEBUG_LEVEL_INFO, "    Loading...\n");
164
165                         testdesc->Load();
166                                                
167                         debugPrint (DEBUG_LEVEL_INFO, "   Trying to create another AvDescriptor...\n");
168                         AvDescriptor *testdesc2=new AvDescriptor(test,AVC1394_SUBUNIT_TYPE_MUSIC | AVC1394_SUBUNIT_ID_0,0x80);
169                         debugPrint (DEBUG_LEVEL_INFO, "    Created...\n");
170                         debugPrint (DEBUG_LEVEL_INFO, "    Opening...\n");
171                         testdesc2->OpenReadOnly();
172                        
173                         debugPrint (DEBUG_LEVEL_INFO, "    Loading...\n");
174
175                         testdesc2->Load();
176                        
177                         unsigned char *buff=new unsigned char[testdesc->getLength()];
178                        
179                         testdesc->readBuffer(0,testdesc->getLength(),buff);
180                         debugPrint (DEBUG_LEVEL_INFO, "    AvDescriptor 1 Contents:\n");
181                        
182                         hexDump(buff,testdesc->getLength());
183                        
184                         delete buff;
185                        
186                         buff=new unsigned char[testdesc2->getLength()];
187                        
188                         testdesc2->readBuffer(0,testdesc2->getLength(),buff);
189                        
190                         debugPrint (DEBUG_LEVEL_INFO, "    AvDescriptor 2 Contents:\n");
191                         hexDump(buff,testdesc2->getLength());
192                         delete buff;
193                        
194                        
195                         debugPrint (DEBUG_LEVEL_INFO, "    Closing AvDescriptors...\n");
196
197                         testdesc->Close();
198                         testdesc2->Close();
199                        
200                         debugPrint (DEBUG_LEVEL_INFO, "    Deleting AvDescriptors...\n");
201
202                         delete testdesc;
203                         delete testdesc2;
204                        
205                         // test the AvMusicIdentifierDescriptor
206                         debugPrint (DEBUG_LEVEL_INFO, "   Trying to create an AvMusicIdentifierDescriptor...\n");
207                         AvMusicIdentifierDescriptor *testdesc_mid=new AvMusicIdentifierDescriptor(test);
208                         debugPrint (DEBUG_LEVEL_INFO, "    Created...\n");
209                         testdesc_mid->printCapabilities();
210                         debugPrint (DEBUG_LEVEL_INFO, "    Deleting AvMusicIdentifierDescriptor...\n");
211                         delete testdesc_mid;
212                        
213                         // test the AvMusicStatusDescriptor
214                         debugPrint (DEBUG_LEVEL_INFO, "   Trying to create an AvMusicStatusDescriptor...\n");
215                         AvMusicStatusDescriptor *testdesc_mid2=new AvMusicStatusDescriptor(test);
216                         debugPrint (DEBUG_LEVEL_INFO, "    Created...\n");
217                         testdesc_mid2->printCapabilities();
218                        
219                         // test the AvInfoBlock
220                         debugPrint (DEBUG_LEVEL_INFO, "    Trying to create an AvInfoBlock...\n");
221                        
222                         AvInfoBlock *testblock1=new AvInfoBlock(testdesc_mid2,0);
223                         debugPrint (DEBUG_LEVEL_INFO, "      Length: 0x%04X (%d)  Type: 0x%04X\n",testblock1->getLength(),testblock1->getLength(),testblock1->getType());
224                        
225                         debugPrint (DEBUG_LEVEL_INFO, "    Trying to fetch next block...\n");
226                         // PP: might be better to have something like AvInfoBlock::moveToNextBlock();
227                         AvInfoBlock *testblock2=new AvInfoBlock(testdesc_mid2,2+testblock1->getLength());
228                        
229                         debugPrint (DEBUG_LEVEL_INFO, "      Length: 0x%04X (%d)  Type: 0x%04X\n",testblock2->getLength(),testblock2->getLength(),testblock2->getType());
230                        
231                         debugPrint (DEBUG_LEVEL_INFO, "    Deleting AvInfoBlocks...\n");
232                         delete testblock1;
233                         delete testblock2;
234                        
235                         debugPrint (DEBUG_LEVEL_INFO, "    Deleting AvMusicStatusDescriptor...\n");
236                         delete testdesc_mid2;                   
237                 }
238                 debugPrint (DEBUG_LEVEL_INFO, "   Deleting AvDevice...\n");
239                 delete test;
240
241             }
242             break;
243         case ROM1394_NODE_TYPE_SBP2:
244             debugPrint( DEBUG_LEVEL_INFO,
245                         "Node %d has node type SBP2\n", iNodeId);
246             break;
247         case ROM1394_NODE_TYPE_CPU:
248             debugPrint( DEBUG_LEVEL_INFO,
249                         "Node %d has node type CPU\n", iNodeId);
250             break;
251         default:
252             debugPrint( DEBUG_LEVEL_INFO,
253                         "No matching node type found for node %d\n", iNodeId);
254         }
255     }
256     return eFBRC_Success;
257 }
258
259 void
260 Ieee1394Service::printAvcUnitInfo( int iNodeId )
261 {
262     printf( "AVC: video monitor?......%s\n",
263             avc1394_check_subunit_type( m_handle, iNodeId,
264                                         AVC1394_SUBUNIT_TYPE_VIDEO_MONITOR ) ?
265             "yes":"no" );
266     printf( "AVC: audio?..............%s\n",
267             avc1394_check_subunit_type( m_handle, iNodeId,
268                                         AVC1394_SUBUNIT_TYPE_AUDIO ) ?
269             "yes":"no" );
270     printf( "AVC; printer?............%s\n",
271             avc1394_check_subunit_type( m_handle, iNodeId,
272                                         AVC1394_SUBUNIT_TYPE_PRINTER ) ?
273             "yes":"no" );
274     printf( "AVC: disk recorder?......%s\n",
275             avc1394_check_subunit_type( m_handle, iNodeId,
276                                         AVC1394_SUBUNIT_TYPE_DISC_RECORDER ) ?
277             "yes":"no" );
278     printf( "AVC: video recorder?.....%s\n",
279             avc1394_check_subunit_type( m_handle, iNodeId,
280                                         AVC1394_SUBUNIT_TYPE_TAPE_RECORDER ) ?
281             "yes":"no" );
282     printf( "AVC: vcr?................%s\n",
283             avc1394_check_subunit_type( m_handle, iNodeId,
284                                         AVC1394_SUBUNIT_TYPE_VCR ) ?
285             "yes":"no" );
286     printf( "AVC: tuner?..............%s\n",
287             avc1394_check_subunit_type( m_handle, iNodeId,
288                                         AVC1394_SUBUNIT_TYPE_TUNER ) ?
289             "yes":"no" );
290     printf( "AVC: CA?.................%s\n",
291             avc1394_check_subunit_type( m_handle, iNodeId,
292                                         AVC1394_SUBUNIT_TYPE_CA ) ?
293             "yes":"no" );
294     printf( "AVC: video camera?.......%s\n",
295             avc1394_check_subunit_type( m_handle, iNodeId,
296                                         AVC1394_SUBUNIT_TYPE_VIDEO_CAMERA ) ?
297             "yes":"no" );
298     printf( "AVC: panel?..............%s\n",
299             avc1394_check_subunit_type(m_handle, iNodeId,
300                                         AVC1394_SUBUNIT_TYPE_PANEL ) ?
301             "yes":"no" );
302     printf( "AVC: camera storage?.....%s\n",
303             avc1394_check_subunit_type( m_handle, iNodeId,
304                                         AVC1394_SUBUNIT_TYPE_CAMERA_STORAGE ) ?
305             "yes":"no" );
306     printf( "AVC: bulletin board?.....%s\n",
307             avc1394_check_subunit_type( m_handle, iNodeId,
308                                         AVC1394_SUBUNIT_TYPE_BULLETIN_BOARD ) ?
309             "yes":"no" );
310     printf( "AVC: vendor specific?....%s\n",
311             avc1394_check_subunit_type( m_handle, iNodeId,
312                                         AVC1394_SUBUNIT_TYPE_VENDOR_UNIQUE ) ?
313             "yes":"no" );
314     printf( "AVC: extended?...........%s\n",
315             avc1394_check_subunit_type( m_handle, iNodeId,
316                                         AVC1394_SUBUNIT_TYPE_EXTENDED ) ?
317             "yes":"no" );
318     printf( "AVC: unit?...............%s\n",
319             avc1394_check_subunit_type( m_handle, iNodeId,
320                                         AVC1394_SUBUNIT_TYPE_UNIT ) ?
321             "yes":"no" );
322     printf( "AVC: music?..............%s\n",
323             avc1394_check_subunit_type( m_handle, iNodeId,
324                                         AVC1394_SUBUNIT_TYPE_MUSIC ) ?
325             "yes":"no" );
326 }
327
328 void
329 Ieee1394Service::printRomDirectory( int iNodeId,  rom1394_directory* pRomDir )
330 {
331     int iBusInfoBlockLength
332         = rom1394_get_bus_info_block_length( m_handle,  iNodeId );
333     int iBusId = rom1394_get_bus_id( m_handle,  iNodeId );
334     octlet_t oGuid = rom1394_get_guid( m_handle, iNodeId );
335     rom1394_bus_options busOptions;
336     rom1394_get_bus_options( m_handle, iNodeId, &busOptions );
337
338     printf( "\nNode %d: \n", iNodeId );
339     printf( "-------------------------------------------------\n" );
340     printf( "bus info block length = %d\n", iBusInfoBlockLength);
341     printf( "bus id = 0x%08x\n", iBusId );
342     printf( "bus options:\n" );
343     printf( "    isochronous resource manager capable: %d\n", busOptions.irmc );
344     printf ("    cycle master capable                : %d\n", busOptions.cmc );
345     printf ("    isochronous capable                 : %d\n", busOptions.isc );
346     printf ("    bus manager capable                 : %d\n", busOptions.bmc );
347     printf ("    cycle master clock accuracy         : %d ppm\n", busOptions.cyc_clk_acc );
348     printf( "    maximum asynchronous record size    : %d bytes\n", busOptions.max_rec );
349     printf("GUID: 0x%08x%08x\n", (quadlet_t) (oGuid>>32),
350            (quadlet_t) (oGuid & 0xffffffff) );
351     printf( "directory:\n");
352     printf( "    node capabilities    : 0x%08x\n", pRomDir->node_capabilities );
353     printf( "    vendor id            : 0x%08x\n", pRomDir->vendor_id );
354     printf( "    unit spec id         : 0x%08x\n", pRomDir->unit_spec_id );
355     printf( "    unit software version: 0x%08x\n", pRomDir->unit_sw_version );
356     printf( "    model id             : 0x%08x\n", pRomDir->model_id );
357     printf( "    textual leaves       : %s\n",     pRomDir->label );
358 }
359
360 int
361 Ieee1394Service::resetHandler( raw1394handle_t handle,
362                                unsigned int iGeneration )
363 {
364     debugPrint( DEBUG_LEVEL_INFO,
365                 "Bus reset has occurred (generation = %d).\n", iGeneration );
366     raw1394_update_generation (handle, iGeneration);
367     Ieee1394Service* pInstance
368         = (Ieee1394Service*) raw1394_get_userdata (handle);
369     pInstance->setGenerationCount( iGeneration );
370     return 0;
371 }
372
373 bool
374 Ieee1394Service::startRHThread()
375 {
376     if ( m_bRHThreadRunning ) {
377         return true;
378     }
379     debugPrint( DEBUG_LEVEL_INFO,
380                 "Starting bus reset handler thread.\n" );
381     pthread_mutex_lock( &m_mutex );
382     pthread_create( &m_thread, NULL, rHThread, this );
383     pthread_mutex_unlock( &m_mutex );
384     m_bRHThreadRunning = true;
385     return true;
386 }
387
388 void
389 Ieee1394Service::stopRHThread()
390 {
391     if ( m_bRHThreadRunning ) {
392         debugPrint( DEBUG_LEVEL_INFO,
393                     "Stopping bus reset handler thread.\n" );
394         pthread_mutex_lock (&m_mutex);
395         pthread_cancel (m_thread);
396         pthread_join (m_thread, NULL);
397         pthread_mutex_unlock (&m_mutex);
398     }
399     m_bRHThreadRunning = false;
400 }
401
402 void*
403 Ieee1394Service::rHThread( void* arg )
404 {
405     Ieee1394Service* pIeee1394Service = (Ieee1394Service*) arg;
406
407     while (true) {
408         raw1394_loop_iterate (pIeee1394Service->m_rhHandle);
409         pthread_testcancel ();
410     }
411
412     return NULL;
413 }
414
415 void
416 Ieee1394Service::setGenerationCount( unsigned int iGeneration )
417 {
418     m_iGenerationCount = iGeneration;
419 }
420
421 unsigned int
422 Ieee1394Service::getGenerationCount()
423 {
424     return m_iGenerationCount;
425 }
Note: See TracBrowser for help on using the browser.