root/trunk/freebob/src/avdevice.cpp

Revision 57, 17.0 kB (checked in by wagi, 18 years ago)

Use Ieee1394Service::avcExecuteTransaction instead of AvDevice::avcExecuteTransaction

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