root/trunk/freebob/src/avdevice.cpp

Revision 58, 16.2 kB (checked in by wagi, 18 years ago)

Remove unused raw1394 handle code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* avdevice.cpp
2  * Copyright (C) 2004 by Daniel Wagner, Pieter Palmers
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 #include <errno.h>
21 #include <libavc1394/avc1394.h>
22 #include <libavc1394/avc1394_vcr.h>
23 #include "threads.h"
24 #include "avdevice.h"
25 #include "avdevicepool.h"
26 #include "avdevicesubunit.h"
27 #include "avdeviceaudiosubunit.h"
28 #include "avdevicemusicsubunit.h"
29
30 #undef AVC1394_GET_RESPONSE_OPERAN
31 #define AVC1394_GET_RESPONSE_OPERAND(x, n) (((x) & (0xFF000000 >> (((n)%4)*8))) >> (((3-(n))%4)*8))
32
33 AvDevice::AvDevice(octlet_t oGuid)
34     : m_iNodeId( -1 )
35     , m_iPort( -1 )
36     , m_bInitialised( false )
37     , m_oGuid( oGuid )
38     , m_iGeneration( 0 )
39     , cSubUnits( 0 )
40     , m_iNbAsyncDestinationPlugs( 0 )
41     , m_iNbAsyncSourcePlugs( 0 )
42     , m_iNbIsoDestinationPlugs( 0 )
43     , m_iNbIsoSourcePlugs( 0 )
44     , m_iNbExtDestinationPlugs( 0 )
45     , m_iNbExtSourcePlugs( 0 )
46 {
47     setDebugLevel( DEBUG_LEVEL_MODERATE );
48     AvDevicePool::instance()->registerAvDevice( this );
49 }
50
51
52 AvDevice::~AvDevice()
53 {
54     vector<AvDeviceSubunit *>::iterator it;
55     for( it = cSubUnits.begin(); it != cSubUnits.end(); it++ ) {
56         delete *it;
57     }
58     AvDevicePool::instance()->unregisterAvDevice( this );
59 }
60
61 void
62 AvDevice::execute( EStates state )
63 {
64     switch ( state ) {
65     case eScanAndCreate:
66         if ( initialize() == eFBRC_Success ) {
67             // Put ourself to sleep until a something happends
68             sleepCall( this, &AvDevice::execute, eCheckState );
69         } else {
70             asyncCall( this, &AvDevice::execute, eDestroy );
71         }
72         break;
73     case eCheckState:
74         {
75             if ( m_iGeneration
76                  != Ieee1394Service::instance()->getGenerationCount() ) {
77                 asyncCall( this, &AvDevice::execute, eDestroy );
78             }
79         }
80         break;
81     case eDestroy:
82         destroyCall( this );
83         break;
84     default:
85         debugError( "Invalid state: %d\n", state );
86     }
87 }
88
89 FBReturnCodes
90 AvDevice::initialize()
91 {
92     if ( !m_bInitialised ) {
93         FBReturnCodes eStatus = enumerateSubUnits();
94         if ( eStatus != eFBRC_Success ) {
95             debugError( "Could not enumrate SubUnits\n" );
96             return eStatus;
97         }
98
99         m_bInitialised = true;
100     }
101     return eFBRC_Success;
102 }
103
104 bool AvDevice::isInitialised()
105 {
106     return m_bInitialised;
107 }
108
109 FBReturnCodes
110 AvDevice::enumerateSubUnits()
111 {
112     // enumerate the subunits present in this device, create an
113     // AvDeviceSubunit for them, and add this object to the cSubUnits
114     // vector
115     unsigned char table_entry;
116     unsigned char subunit_maxid;
117     unsigned char subunit_type;
118     // buffer these table entries, because the memory content pointed
119     // to by the response pointer can change due to other libraw
120     // operations on this handle
121     quadlet_t table_entries;
122     quadlet_t request[6];
123     quadlet_t *response;
124     AvDeviceSubunit *tmpAvDeviceSubunit=NULL;
125
126     Ieee1394Service* p1394Service = Ieee1394Service::instance();
127
128     // check the number of I/O plugs
129     request[0] = AVC1394_CTYPE_STATUS
130                  | AVC1394_SUBUNIT_TYPE_UNIT
131                  | AVC1394_SUBUNIT_ID_IGNORE
132                  | AVC1394_COMMAND_PLUG_INFO
133                  | 0x0000;
134     request[1] = 0xFFFFFFFF;
135     response = p1394Service->avcExecuteTransaction( m_iNodeId, request, 2, 2 );
136     request[1] = 0x02020606;
137     response = request;
138     if ( response ) {
139         m_iNbIsoDestinationPlugs
140             = AVC1394_GET_RESPONSE_OPERAND( response[1], 0 );
141         m_iNbIsoSourcePlugs
142             = AVC1394_GET_RESPONSE_OPERAND( response[1], 1 );
143         m_iNbExtDestinationPlugs
144             = AVC1394_GET_RESPONSE_OPERAND( response[1], 2 );
145         m_iNbExtSourcePlugs
146             = AVC1394_GET_RESPONSE_OPERAND( response[1], 3 );
147     }
148
149     request[0] = AVC1394_CTYPE_STATUS
150                  | AVC1394_SUBUNIT_TYPE_UNIT
151                  | AVC1394_SUBUNIT_ID_IGNORE
152                  | AVC1394_COMMAND_PLUG_INFO
153                  | 0x01;
154     request[1] = 0xFFFFFFFF;
155     response = p1394Service->avcExecuteTransaction( m_iNodeId, request, 2, 2 );
156     if ( response != NULL ) {
157         m_iNbAsyncDestinationPlugs
158             = AVC1394_GET_RESPONSE_OPERAND( response[1], 0 );
159         m_iNbAsyncSourcePlugs
160             = AVC1394_GET_RESPONSE_OPERAND( response[1], 1 );
161     }
162
163     debugPrint( DEBUG_LEVEL_DEVICE,
164                 "AvDevice: %d Isochronous source plugs, "
165                 "%d Isochronous destination plugs\n",
166                 m_iNbIsoSourcePlugs, m_iNbIsoDestinationPlugs);
167     debugPrint( DEBUG_LEVEL_DEVICE,
168                 "AvDevice: %d External source plugs, "
169                 "%d External destination plugs\n",
170                 m_iNbExtSourcePlugs, m_iNbExtDestinationPlugs);
171     debugPrint( DEBUG_LEVEL_DEVICE,
172                 "AvDevice: %d Asynchronous source plugs, "
173                 "%d Asynchronous destination plugs\n",
174                 m_iNbAsyncSourcePlugs, m_iNbAsyncDestinationPlugs);
175
176
177     // create the subunits
178     for (unsigned int i = 0; i < 8; i++ ) {
179         // cycle through the 8 pages (max 32 subunits; 4
180         // subunits/page)
181
182
183         request[0] = AVC1394_CTYPE_STATUS
184                      | AVC1394_SUBUNIT_TYPE_UNIT
185                      | AVC1394_SUBUNIT_ID_IGNORE
186                      | AVC1394_COMMAND_SUBUNIT_INFO
187                      | ((i<<4) & 0xF0) | 0x07;
188         request[1] = 0xFFFFFFFF;
189         response = p1394Service->avcExecuteTransaction( m_iNodeId, request, 6, 2 );
190
191         table_entries=response[1]; /// XXX buggy code! response could be 0!
192
193         if ( response != NULL ) {
194             // this way of processing the table entries assumes that
195             // the subunit type is not "extended"
196
197             // stop processing when a "not implemented" is received
198             // (according to spec)
199             if ( (response[0]&0xFF000000) == AVC1394_RESPONSE_NOT_IMPLEMENTED) {
200                 break;
201             }
202
203             // warning: don't do unsigned int j!
204             // comparison >= 0 is always true for uint
205             for ( int j = 3; j >= 0; j-- ) {
206                 // cycle through the 8 pages (max 32
207                 // subunits; 4 subunits/page)
208                 table_entry   = (table_entries >> (j*8)) & 0xFF;
209                 subunit_maxid = table_entry & 0x07;
210                 subunit_type  = (table_entry >> 3) & 0x1F;
211
212                 //debugPrint (DEBUG_LEVEL_DEVICE,"AvDevice: Page %d, item %d: Table entry=0x%02X, subunit_maxid=0x%02X, subunit_type=0x%02X\n",i,j,table_entry,subunit_maxid,subunit_type);
213
214                 // according to spec we could stop processing at the
215                 // first 0xFF entry, but doing it this way is a little
216                 // more robust
217
218                 if ( table_entry != 0xFF ) {
219                     for ( unsigned char subunit_id = 0;
220                           subunit_id < subunit_maxid+1;
221                           subunit_id++ )
222                     {
223
224                         // only two types of specific subunits are
225                         // supported: audio and music
226                         switch ( subunit_type ) {
227                         case 0x01: // audio subunit
228                             tmpAvDeviceSubunit
229                                 = new AvDeviceAudioSubunit( this,  subunit_id);
230                             if ( tmpAvDeviceSubunit ) {
231                                 // test code
232                                 //tmpAvDeviceSubunit->printOutputPlugConnections();
233                             }
234                             break;
235                         case 0x0C: // music subunit
236                             tmpAvDeviceSubunit=new AvDeviceMusicSubunit(this,subunit_id);
237                             /*{ // just a test
238                               AvDeviceMusicSubunit tmpAvDeviceSubunit2(this,subunit_id);
239                               tmpAvDeviceSubunit2.printMusicPlugInfo();
240                               tmpAvDeviceSubunit2.printMusicPlugConfigurations();
241                               tmpAvDeviceSubunit2.printOutputPlugConnections();
242                               tmpAvDeviceSubunit2.test();
243                               }*/
244                             break;
245
246                         default: // generic
247                             tmpAvDeviceSubunit=new AvDeviceSubunit(this,subunit_type,subunit_id);
248                             break;
249                         }
250
251                         if ( tmpAvDeviceSubunit
252                              && tmpAvDeviceSubunit->isValid() )
253                         {
254                             cSubUnits.push_back(tmpAvDeviceSubunit);
255                             //setDebugLevel(DEBUG_LEVEL_ALL);
256                             debugPrint( DEBUG_LEVEL_DEVICE,
257                                         "Trying to reserve the "
258                                         "subunit...\n" );
259                             tmpAvDeviceSubunit->reserve( 0x01 );
260                             debugPrint( DEBUG_LEVEL_DEVICE,
261                                         "  isReserved?: %d\n",
262                                         tmpAvDeviceSubunit->isReserved());
263                             tmpAvDeviceSubunit->unReserve();
264                             //setDebugLevel(DEBUG_LEVEL_MODERATE);
265                         } else {
266                             if ( tmpAvDeviceSubunit ) {
267                                 debugPrint( DEBUG_LEVEL_DEVICE,  "AvDevice: Unsupported AvDeviceSubunit encountered. Page %d, item %d: Table entry=0x%02X, subunit_maxid=0x%02X, subunit_type=0x%02X, subunit_id=%0x02X\n",i,j,table_entry,subunit_maxid,subunit_type,subunit_id);
268
269                                 delete tmpAvDeviceSubunit;
270                             } else {
271                                 debugPrint( DEBUG_LEVEL_DEVICE,
272                                             "AvDevice: Could not create AvDeviceSubunit object.\n");
273                             }
274                         }
275                     }
276                 }
277             }
278         }
279     }
280     return eFBRC_Success;
281 }
282
283
284 FBReturnCodes AvDevice::setInputPlugSignalFormat(unsigned char plug, unsigned char fmt, quadlet_t fdf) {
285         quadlet_t request[6];
286         quadlet_t *response;
287
288         request[0] = AVC1394_CTYPE_CONTROL | AVC1394_SUBUNIT_TYPE_UNIT | AVC1394_SUBUNIT_ID_IGNORE
289                                         | AVC1394_COMMAND_INPUT_PLUG_SIGNAL_FORMAT | plug;
290         request[1] = (0x80000000) | ((fmt & 0x3F)<<24) | (fdf & 0x00FFFFFF);
291         response = Ieee1394Service::instance()->avcExecuteTransaction( m_iNodeId, request, 2, 2);
292         if (response != NULL) {
293
294         }
295         return eFBRC_Success;
296 }
297
298 FBReturnCodes AvDevice::getInputPlugSignalFormat(unsigned char plug, unsigned char *fmt, quadlet_t *fdf) {
299         quadlet_t request[6];
300         quadlet_t *response;
301
302         request[0] = AVC1394_CTYPE_STATUS | AVC1394_SUBUNIT_TYPE_UNIT | AVC1394_SUBUNIT_ID_IGNORE
303                                         | AVC1394_COMMAND_INPUT_PLUG_SIGNAL_FORMAT | plug;
304         request[1] = 0xFFFFFFFF;
305         response = Ieee1394Service::instance()->avcExecuteTransaction( m_iNodeId, request, 2, 2);
306         if (response != NULL) {
307                 *fmt=((response[1] >> 24) & 0x3F);
308                 *fdf=response[1]& 0x00FFFFFF;
309         }
310         return eFBRC_Success;
311 }
312
313 FBReturnCodes AvDevice::setOutputPlugSignalFormat(unsigned char plug, unsigned char fmt, quadlet_t fdf) {
314         quadlet_t request[6];
315         quadlet_t *response;
316
317         request[0] = AVC1394_CTYPE_CONTROL | AVC1394_SUBUNIT_TYPE_UNIT | AVC1394_SUBUNIT_ID_IGNORE
318                                         | AVC1394_COMMAND_OUTPUT_PLUG_SIGNAL_FORMAT | plug;
319         request[1] = (0x80000000) | ((fmt & 0x3F)<<24) | (fdf & 0x00FFFFFF);
320         response = Ieee1394Service::instance()->avcExecuteTransaction(m_iNodeId, request, 2, 2);
321         if (response != NULL) {
322
323         }
324         return eFBRC_Success;
325 }
326
327 FBReturnCodes AvDevice::getOutputPlugSignalFormat(unsigned char plug, unsigned char *fmt, quadlet_t *fdf) {
328         quadlet_t request[6];
329         quadlet_t *response;
330
331         request[0] = AVC1394_CTYPE_STATUS | AVC1394_SUBUNIT_TYPE_UNIT | AVC1394_SUBUNIT_ID_IGNORE
332                                         | AVC1394_COMMAND_OUTPUT_PLUG_SIGNAL_FORMAT | plug;
333         request[1] = 0xFFFFFFFF;
334         response = Ieee1394Service::instance()->avcExecuteTransaction(m_iNodeId, request, 2, 2);
335         if (response != NULL) {
336                 *fmt=((response[1] >> 24) & 0x3F);
337                 *fdf=response[1]& 0x00FFFFFF;
338         }
339         return eFBRC_Success;
340 }
341
342 AvDeviceSubunit *AvDevice::getSubunit(unsigned char type, unsigned char id) {
343         vector<AvDeviceSubunit *>::iterator it;
344         for( it = cSubUnits.begin(); it != cSubUnits.end(); it++ ) {
345                 if ((*it) && ((*it)->getType()==type) && ((*it)->getId()==id)) {
346                         return *it;
347                 }
348         }
349         return NULL;
350 }
351
352 #define AVC1394_COMMAND_SIGNAL_SOURCE 0x00001A00
353
354 void AvDevice::printConnections() {
355     quadlet_t request[6];
356     quadlet_t *response;
357     //setDebugLevel(DEBUG_LEVEL_ALL);
358
359     debugPrint (DEBUG_LEVEL_DEVICE,"AvDevice: ISO source connections:\n");
360
361     for (unsigned int i=0;i<getNbIsoSourcePlugs();i++) {
362         request[0] = AVC1394_CTYPE_STATUS
363                      | AVC1394_SUBUNIT_TYPE_UNIT
364                      | AVC1394_SUBUNIT_ID_IGNORE
365                      | AVC1394_COMMAND_SIGNAL_SOURCE
366                      | 0x00FF;
367         request[1]=0xFFFEFF00 | ((i & 0xFF));
368
369         response = Ieee1394Service::instance()->avcExecuteTransaction(m_iNodeId, request, 2, 2);
370
371         if ( response ) {
372             unsigned char output_status=(response[0]&0xE0) >> 5;
373             unsigned char conv=(response[0]&0x10) >> 4;
374             unsigned char signal_status=(response[0]&0x0F);
375
376             unsigned int signal_source=((response[1]>>16)&0xFFFF);
377
378             unsigned char source_subunit_type=(signal_source>>11)&0x1F;
379             unsigned char source_subunit_id=(signal_source>>8)&0x07;
380             unsigned char source_plug=signal_source&0xFF;
381
382             debugPrint (DEBUG_LEVEL_DEVICE,"AvDevice:   OPCR 0x%02X <- subunit: 0x%02X/0x%02X, plug: 0x%02X (0x%02X / %d / 0x%02X)\n",i, source_subunit_type,source_subunit_id,source_plug,output_status,conv,signal_status);
383             // find the subunit this plug is connected to
384             AvDeviceSubunit *tmpSubunit=getSubunit(source_subunit_type,source_subunit_id);
385             if ( tmpSubunit ) {
386                 tmpSubunit->printSourcePlugConnections(source_plug);
387             }
388
389         }
390     }
391
392     debugPrint (DEBUG_LEVEL_DEVICE,"AvDevice: External source connections:\n");
393
394     for (unsigned int i=0;i<getNbExtSourcePlugs();i++) {
395         request[0] = AVC1394_CTYPE_STATUS
396                      | AVC1394_SUBUNIT_TYPE_UNIT
397                      | AVC1394_SUBUNIT_ID_IGNORE
398                      | AVC1394_COMMAND_SIGNAL_SOURCE
399                      | 0x00FF;
400         request[1]=0xFFFEFF00 | ((i & 0xFF)|0x80);
401
402         response = Ieee1394Service::instance()->avcExecuteTransaction(m_iNodeId, request, 2, 2);
403
404         if ( response ) {
405             unsigned char output_status=(response[0]&0xE0) >> 5;
406             unsigned char conv=(response[0]&0x10) >> 4;
407             unsigned char signal_status=(response[0]&0x0F);
408
409             unsigned int signal_source=((response[1]>>16)&0xFFFF);
410
411             unsigned char source_subunit_type=(signal_source>>11)&0x1F;
412             unsigned char source_subunit_id=(signal_source>>8)&0x07;
413             unsigned char source_plug=signal_source&0xFF;
414
415             debugPrint (DEBUG_LEVEL_DEVICE,"AvDevice:   EXTOUT 0x%02X <- subunit: 0x%02X/0x%02X, plug: 0x%02X (0x%02X / %d / 0x%02X)\n",i, source_subunit_type,source_subunit_id,source_plug,output_status,conv,signal_status);
416
417             // find the subunit this plug is connected to
418             AvDeviceSubunit *tmpSubunit=getSubunit(source_subunit_type,source_subunit_id);
419             if ( tmpSubunit ) {
420                 tmpSubunit->printSourcePlugConnections(source_plug);
421             }
422         }
423     }
424
425     debugPrint (DEBUG_LEVEL_DEVICE,"AvDevice: ISO sink connections:\n");
426
427     for (unsigned int i=0;i<getNbIsoDestinationPlugs();i++) {
428         request[0] = AVC1394_CTYPE_STATUS
429                      | AVC1394_SUBUNIT_TYPE_UNIT
430                      | AVC1394_SUBUNIT_ID_IGNORE
431                      | AVC1394_COMMAND_SIGNAL_SOURCE
432                      | 0x00FF;
433         request[1] = 0xFFFEFF00 | ((i & 0xFF));
434
435         response = Ieee1394Service::instance()->avcExecuteTransaction(m_iNodeId, request, 2, 2);
436
437         if ( response ) {
438             unsigned char output_status=(response[0]&0xE0) >> 5;
439             unsigned char conv=(response[0]&0x10) >> 4;
440             unsigned char signal_status=(response[0]&0x0F);
441
442             unsigned int signal_source=((response[1]>>16)&0xFFFF);
443
444             unsigned char source_subunit_type=(signal_source>>11)&0x1F;
445             unsigned char source_subunit_id=(signal_source>>8)&0x07;
446             unsigned char source_plug=signal_source&0xFF;
447
448             debugPrint (DEBUG_LEVEL_DEVICE,"AvDevice:   OPCR 0x%02X <- subunit: 0x%02X/0x%02X, plug: 0x%02X (0x%02X / %d / 0x%02X)\n",i, source_subunit_type,source_subunit_id,source_plug,output_status,conv,signal_status);
449             // find the subunit this plug is connected to
450             AvDeviceSubunit *tmpSubunit
451                 = getSubunit(source_subunit_type,source_subunit_id);
452             if ( tmpSubunit ) {
453                 //tmpSubunit->printDestinationPlugConnections(source_plug);
454             }
455
456         }
457     }
458
459     debugPrint (DEBUG_LEVEL_DEVICE,"AvDevice: External sink connections:\n");
460
461     for (unsigned int i=0;i<getNbExtDestinationPlugs();i++) {
462         request[0] = AVC1394_CTYPE_STATUS
463                      | AVC1394_SUBUNIT_TYPE_UNIT
464                      | AVC1394_SUBUNIT_ID_IGNORE
465                      | AVC1394_COMMAND_SIGNAL_SOURCE
466                      | 0x00FF;
467         request[1]=0xFFFEFF00 | ((i & 0xFF)|0x80);
468
469         response = Ieee1394Service::instance()->avcExecuteTransaction(m_iNodeId, request, 2, 2);
470
471         if ( response ) {
472             unsigned char output_status=(response[0]&0xE0) >> 5;
473             unsigned char conv=(response[0]&0x10) >> 4;
474             unsigned char signal_status=(response[0]&0x0F);
475
476             unsigned int signal_source=((response[1]>>16)&0xFFFF);
477
478             unsigned char source_subunit_type=(signal_source>>11)&0x1F;
479             unsigned char source_subunit_id=(signal_source>>8)&0x07;
480             unsigned char source_plug=signal_source&0xFF;
481
482             debugPrint (DEBUG_LEVEL_DEVICE,"AvDevice:   EXTOUT 0x%02X <- subunit: 0x%02X/0x%02X, plug: 0x%02X (0x%02X / %d / 0x%02X)\n",i, source_subunit_type,source_subunit_id,source_plug,output_status,conv,signal_status);
483
484             // find the subunit this plug is connected to
485             AvDeviceSubunit *tmpSubunit
486                 = getSubunit(source_subunit_type,source_subunit_id);
487             if ( tmpSubunit ) {
488                 //tmpSubunit->printDestinationPlugConnections(source_plug);
489             }
490         }
491     }
492 }
Note: See TracBrowser for help on using the browser.