root/trunk/libffado/tests/test-ffado.cpp

Revision 1948, 17.7 kB (checked in by adi, 13 years ago)

Fix ListDevices? on Juju stack

Patch by Stefan Richter. He writes:

The fix is straightforward: Let ListDevices? continue at the next node ID
when the configuration ROM of a lower node could not be fetched or parsed
successfully.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Daniel Wagner
3  * Copyright (C) 2005-2008 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 program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 /*
26  * This version uses the CPP API
27  */
28
29 #include "version.h"
30
31 #include "libffado/ffado.h"
32
33 #include "debugmodule/debugmodule.h"
34 #include "fbtypes.h"
35 #include "devicemanager.h"
36 #include "ffadodevice.h"
37
38 #include <signal.h>
39
40 #include <argp.h>
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44
45 #include <vector>
46 #include <string>
47 #include <iostream>
48 #include <sstream>
49
50 #include "libieee1394/cycletimer.h"
51
52 using namespace std;
53
54 DECLARE_GLOBAL_DEBUG_MODULE;
55
56 #define MAX_ARGS 5
57
58 // global's
59 const char *argp_program_version = PACKAGE_STRING;
60 const char *argp_program_bug_address = PACKAGE_BUGREPORT;
61
62 // Program documentation.
63 static char doc[] = "FFADO -- a driver for Firewire Audio devices (test application)\n\n"
64                     "OPERATION: Discover\n"
65                     "           SetSamplerate samplerate\n"
66                     "           SetClockSource [id]\n"
67                     "           BusReset\n"
68                     "           ListDevices\n"
69                     "           SetSplitTimeout timeout_usec\n"
70                     "           GetSplitTimeout\n"
71                     ;
72
73 // A description of the arguments we accept.
74 static char args_doc[] = "OPERATION";
75
76 struct arguments
77 {
78     unsigned int nargs;
79     short    silent;
80     long int verbose;
81     long int port;
82     long int use_cache;
83     long int node_id;
84     long int node_id_set;
85     const char* args[MAX_ARGS];
86 };
87
88 // The options we understand.
89 static struct argp_option options[] = {
90     {"quiet",    'q',       0,    0,  "Don't produce any output" },
91     {"silent",   's',       0,    OPTION_ALIAS },
92
93     {"verbose",  'v', "level",    0,  "Produce verbose output" },
94 #if ENABLE_DISCOVERY_CACHE
95     {"cache",    'c', "enable",   0,  "Use AVC model cache" },
96 #endif
97
98     {"node",     'n',    "id",    0,  "Node to use" },
99     {"port",     'p',    "nr",    0,  "IEEE1394 Port to use" },
100     { 0 }
101 };
102
103 //-------------------------------------------------------------
104
105 // Parse a single option.
106 static error_t
107 parse_opt( int key, char* arg, struct argp_state* state )
108 {
109     // Get the input argument from `argp_parse', which we
110     // know is a pointer to our arguments structure.
111     struct arguments* arguments = ( struct arguments* ) state->input;
112     char* tail;
113
114     errno = 0;
115     switch (key) {
116     case 'q': case 's':
117         arguments->silent = 1;
118         break;
119     case 'v':
120         if (arg) {
121             arguments->verbose = strtol( arg, &tail, 0 );
122             if ( errno ) {
123                 fprintf( stderr,  "Could not parse 'verbose' argument\n" );
124                 return ARGP_ERR_UNKNOWN;
125             }
126         }
127         break;
128     case 'c':
129         if (arg) {
130             arguments->use_cache = strtol( arg, &tail, 0 );
131             if ( errno ) {
132                 fprintf( stderr,  "Could not parse 'cache' argument\n" );
133                 return ARGP_ERR_UNKNOWN;
134             }
135         }
136         break;
137     case 'p':
138         if (arg) {
139             arguments->port = strtol( arg, &tail, 0 );
140             if ( errno ) {
141                 fprintf( stderr,  "Could not parse 'port' argument\n" );
142                 return ARGP_ERR_UNKNOWN;
143             }
144         } else {
145             if ( errno ) {
146                 fprintf( stderr, "Could not parse 'port' argumen\n" );
147                 return ARGP_ERR_UNKNOWN;
148             }
149         }
150         break;
151     case 'n':
152         if (arg) {
153             arguments->node_id = strtol( arg, &tail, 0 );
154             if ( errno ) {
155                 fprintf( stderr,  "Could not parse 'node' argument\n" );
156                 return ARGP_ERR_UNKNOWN;
157             }
158             arguments->node_id_set=1;
159         } else {
160             if ( errno ) {
161                 fprintf( stderr, "Could not parse 'node' argumen\n" );
162                 return ARGP_ERR_UNKNOWN;
163             }
164         }
165         break;
166     case ARGP_KEY_ARG:
167         if (state->arg_num >= MAX_ARGS) {
168             // Too many arguments.
169             argp_usage( state );
170         }
171         arguments->args[state->arg_num] = arg;
172         arguments->nargs++;
173         break;
174     case ARGP_KEY_END:
175         if (state->arg_num < 1) {
176         // Not enough arguments.
177         argp_usage( state );
178         }
179         break;
180     default:
181         return ARGP_ERR_UNKNOWN;
182     }
183     return 0;
184 }
185
186 // Our argp parser.
187 static struct argp argp = { options, parse_opt, args_doc, doc };
188
189 int exitfunction( int retval ) {
190     debugOutput( DEBUG_LEVEL_NORMAL, "Debug output flushed...\n" );
191     flushDebugOutput();
192
193     return retval;
194 }
195
196 void
197 printDeviceList(unsigned int port)
198 {
199     Ieee1394Service service;
200     // switch off all messages since they mess up the list
201     service.setVerboseLevel(0);
202     if ( !service.initialize( port ) ) {
203         printf("Could not initialize IEEE 1394 service on port %d\n", port);
204         exit(-1);
205     }
206
207     printf("=== 1394 PORT %d ===\n", port);
208     printf("  Node id  GUID                  VendorId     ModelId   Vendor - Model\n");
209     for (int i = 0; i < service.getNodeCount(); i++) {
210         ConfigRom crom(service, i);
211         if (crom.initialize())
212             printf("  %2d       0x%s  0x%08X  0x%08X   %s - %s\n",
213                    i, crom.getGuidString().c_str(),
214                    crom.getNodeVendorId(), crom.getModelId(),
215                    crom.getVendorName().c_str(),
216                    crom.getModelName().c_str());
217     }
218 }
219
220 void
221 busreset(unsigned int port)
222 {
223     Ieee1394Service service;
224     // switch off all messages since they mess up the list
225     service.setVerboseLevel(0);
226     if ( !service.initialize( port ) ) {
227         printf("Could not initialize IEEE 1394 service on port %d\n", port);
228         exit(-1);
229     }
230
231     printf("Doing busreset on port %d\n", port);
232     service.doBusReset();
233 }
234
235 int
236 main( int argc, char **argv )
237 {
238     struct arguments arguments;
239
240     printf("-----------------------------------------------\n");
241     printf("FFADO test and diagnostic utility\n");
242     printf("Part of the FFADO project -- www.ffado.org\n");
243     printf("Version: %s\n", PACKAGE_VERSION);
244     printf("(C) 2008, Daniel Wagner, Pieter Palmers\n");
245     printf("This program comes with ABSOLUTELY NO WARRANTY.\n");
246     printf("-----------------------------------------------\n\n");
247
248     // check the library version
249     const char *libversion = ffado_get_version();
250     const char *progversion = PACKAGE_STRING;
251     if(strcmp(libversion, progversion) != 0) {
252         printf("Library version mismatch. (required: %s, present: %s)\n", progversion, libversion);
253         printf("Please run this application against the exact corresponding library\n");
254         printf("it was compiled for. The most common cause for this is having more\n");
255         printf("than one version of libffado installed.\n\n");
256         return exitfunction(-1);
257     }
258
259     // Default values.
260     arguments.nargs       = 0;
261     arguments.silent      = 0;
262     arguments.verbose     = 0;
263     arguments.use_cache   = 1;
264     arguments.port        = 0;
265     arguments.node_id     = 0;
266     arguments.node_id_set = 0; // if we don't specify a node, discover all
267     arguments.args[0]     = "";
268     arguments.args[1]     = "";
269
270     // Parse our arguments; every option seen by `parse_opt' will
271     // be reflected in `arguments'.
272     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
273         fprintf( stderr, "Could not parse command line\n" );
274         return exitfunction(-1);
275     }
276     setDebugLevel(arguments.verbose);
277
278     if ( strcmp( arguments.args[0], "Discover" ) == 0 ) {
279         DeviceManager *m_deviceManager = new DeviceManager();
280         if ( !m_deviceManager ) {
281             fprintf( stderr, "Could not allocate device manager\n" );
282             return exitfunction(-1);
283         }
284         if ( arguments.verbose ) {
285             m_deviceManager->setVerboseLevel(arguments.verbose);
286         }
287         if ( !m_deviceManager->initialize() ) {
288             fprintf( stderr, "Could not initialize device manager\n" );
289             delete m_deviceManager;
290             return exitfunction(-1);
291         }
292         if ( arguments.verbose ) {
293             m_deviceManager->setVerboseLevel(arguments.verbose);
294         }
295         if ( !m_deviceManager->discover(arguments.use_cache) ) {
296             fprintf( stderr, "Could not discover devices\n" );
297             delete m_deviceManager;
298             return exitfunction(-1);
299         }
300         delete m_deviceManager;
301         return exitfunction(0);
302     } else if ( strcmp( arguments.args[0], "BusReset" ) == 0 ) {
303         busreset(arguments.port);
304     } else if ( strcmp( arguments.args[0], "ListDevices" ) == 0 ) {
305         unsigned int nb_ports = Ieee1394Service::detectNbPorts();
306         for (unsigned int i=0;i<nb_ports;i++) {
307             printDeviceList(i);
308         }
309     } else if ( strcmp( arguments.args[0], "SetSamplerate" ) == 0 ) {
310         char* tail;
311         int samplerate = strtol( arguments.args[1], &tail, 0 );
312         if ( errno ) {
313             fprintf( stderr,  "Could not parse samplerate argument\n" );
314             return exitfunction(-1);
315         }
316
317         DeviceManager *m_deviceManager = new DeviceManager();
318         if ( !m_deviceManager ) {
319             fprintf( stderr, "Could not allocate device manager\n" );
320             return exitfunction(-1);
321         }
322         if ( arguments.verbose ) {
323             m_deviceManager->setVerboseLevel(arguments.verbose);
324         }
325         if ( !m_deviceManager->initialize() ) {
326             fprintf( stderr, "Could not initialize device manager\n" );
327             delete m_deviceManager;
328             return exitfunction(-1);
329         }
330         if ( arguments.verbose ) {
331             m_deviceManager->setVerboseLevel(arguments.verbose);
332         }
333         if ( !m_deviceManager->discover(arguments.use_cache) ) {
334             fprintf( stderr, "Could not discover devices\n" );
335             delete m_deviceManager;
336             return exitfunction(-1);
337         }
338
339         if(arguments.node_id_set) {
340             FFADODevice* avDevice = m_deviceManager->getAvDevice( arguments.node_id );
341             if ( avDevice ) {
342                 avDevice->setVerboseLevel(arguments.verbose);
343                 if ( ! avDevice->setSamplingFrequency( samplerate ) ) {
344                     fprintf( stderr, "Could not set samplerate\n" );
345                 }
346             }
347         } else {
348             int i=0;
349
350             int devices_on_bus = m_deviceManager->getNbDevices();
351             printf("  port = %d, devices_on_bus = %d\n", (int)arguments.port, devices_on_bus);
352
353             for(i=0;i<devices_on_bus;i++) {
354                 int node_id=m_deviceManager->getDeviceNodeId(i);
355                 printf("  set samplerate for device = %d, node = %d\n", i, node_id);
356                 FFADODevice* avDevice = m_deviceManager->getAvDevice( node_id );
357                 if ( avDevice ) {
358                     avDevice->setVerboseLevel(arguments.verbose);
359                     if ( !avDevice->setSamplingFrequency( samplerate ) ) {
360                         fprintf( stderr, "Could not set samplerate\n" );
361                     }
362                 }
363             }
364         }
365         delete m_deviceManager;
366         return exitfunction(0);
367     } else if ( strcmp( arguments.args[0], "SetClockSource" ) == 0 ) {
368         char* tail;
369         unsigned int targetid = (unsigned int)strtol( arguments.args[1], &tail, 0 );
370         if ( errno ) {
371             fprintf( stderr,  "Could not parse clock source argument\n" );
372             targetid=0xFFFF;
373         }
374         DeviceManager *m_deviceManager = new DeviceManager();
375         if ( !m_deviceManager ) {
376             fprintf( stderr, "Could not allocate device manager\n" );
377             return exitfunction(-1);
378         }
379         if ( arguments.verbose ) {
380             m_deviceManager->setVerboseLevel(arguments.verbose);
381         }
382         if ( !m_deviceManager->initialize() ) {
383             fprintf( stderr, "Could not initialize device manager\n" );
384             delete m_deviceManager;
385             return exitfunction(-1);
386         }
387         if ( arguments.verbose ) {
388             m_deviceManager->setVerboseLevel(arguments.verbose);
389         }
390         if ( !m_deviceManager->discover(arguments.use_cache) ) {
391             fprintf( stderr, "Could not discover devices\n" );
392             delete m_deviceManager;
393             return exitfunction(-1);
394         }
395
396         if(arguments.node_id_set) {
397             FFADODevice* avDevice = m_deviceManager->getAvDevice( arguments.node_id );
398             if ( avDevice ) {
399                 FFADODevice::ClockSource s;
400            
401                 avDevice->setVerboseLevel(arguments.verbose);
402                 FFADODevice::ClockSourceVector sources=avDevice->getSupportedClockSources();
403                 for ( FFADODevice::ClockSourceVector::const_iterator it
404                         = sources.begin();
405                     it != sources.end();
406                     ++it )
407                 {
408                     FFADODevice::ClockSource c=*it;
409                     printf( " Type: %s, Id: %d, Valid: %d, Active: %d, Description: %s\n",
410                         FFADODevice::ClockSourceTypeToString(c.type), c.id, c.valid, c.active, c.description.c_str());
411                    
412                     if (c.id==targetid) {
413                         s=*it;
414                     }
415                 }
416                
417                 if (s.type != FFADODevice::eCT_Invalid) {
418                     printf("  set clock source to %d\n", s.id);
419                     if ( ! avDevice->setActiveClockSource( s ) ) {
420                         fprintf( stderr, "Could not set clock source\n" );
421                     }
422                 } else {
423                     printf("  no clock source with id %d found\n", targetid);
424                 }
425             }
426         } else {
427             fprintf( stderr, "please specify a node\n" );
428         }
429         delete m_deviceManager;
430         return exitfunction(0);
431     } else if ( strcmp( arguments.args[0], "SetSplitTimeout" ) == 0 ) {
432         char* tail;
433         int usecs = strtol( arguments.args[1], &tail, 0 );
434         if ( errno ) {
435             fprintf( stderr,  "Could not parse timeout argument\n" );
436             return exitfunction(-1);
437         }
438
439         Ieee1394Service service;
440         // switch off all messages since they mess up the list
441         service.setVerboseLevel(arguments.verbose);
442         if ( !service.initialize( arguments.port ) ) {
443             printf("Could not initialize IEEE 1394 service on port %d\n", (int)arguments.port);
444             return exitfunction(-1);
445         }
446
447         nodeid_t nodeid;
448         if(arguments.node_id_set) {
449             nodeid = arguments.node_id;
450         } else {
451             nodeid = service.getLocalNodeId();
452         }
453        
454         if (!service.setSplitTimeoutUsecs(nodeid, usecs)) {
455             printf("Failed to set SPLIT_TIMEOUT to %u for node %X on port %d\n",
456                    usecs, nodeid, (int)arguments.port);
457             return exitfunction(-1);
458         }
459
460         return exitfunction(0);
461     } else if ( strcmp( arguments.args[0], "GetSplitTimeout" ) == 0 ) {
462         Ieee1394Service service;
463         // switch off all messages since they mess up the list
464         service.setVerboseLevel(arguments.verbose);
465         if ( !service.initialize( arguments.port ) ) {
466             printf("Could not initialize IEEE 1394 service on port %d\n", (int)arguments.port);
467             return exitfunction(-1);
468         }
469
470         nodeid_t nodeid;
471         if(arguments.node_id_set) {
472             nodeid = arguments.node_id;
473         } else {
474             nodeid = service.getLocalNodeId();
475         }
476         int usecs = service.getSplitTimeoutUsecs(nodeid);
477         if (usecs < 0) {
478             printf("Failed to get SPLIT_TIMEOUT for node %X on port %d\n",
479                    nodeid, (int)arguments.port);
480             return exitfunction(-1);
481         }
482         printf("SPLIT_TIMEOUT for node %X on port %d is %u\n",
483                nodeid, (int)arguments.port, usecs);
484
485         return exitfunction(0);
486     } else if ( strcmp( arguments.args[0], "SytCalcTest" ) == 0 ) {
487         if (arguments.nargs < 4) {
488             fprintf( stderr,"Not enough arguments\n");
489             return -1;
490         }
491         uint64_t syt_timestamp = strtol(arguments.args[1], NULL, 0);
492         if (errno) {
493             fprintf( stderr,"syt_timestamp parsing failed: %s\n",
494                      strerror(errno));
495             return errno;
496         }
497         uint32_t rcv_cycle = strtol(arguments.args[2], NULL, 0);
498         if (errno) {
499             fprintf( stderr,"rcv_cycle parsing failed: %s\n",
500                      strerror(errno));
501             return errno;
502         }
503         uint64_t ctr_now = strtoll(arguments.args[3], NULL, 0);
504         if (errno) {
505             fprintf( stderr,"ctr_now parsing failed: %s\n",
506                      strerror(errno));
507             return errno;
508         }
509         uint64_t result_rcv = sytRecvToFullTicks(syt_timestamp, rcv_cycle, ctr_now);
510         uint64_t result_xmt = sytXmitToFullTicks(syt_timestamp, rcv_cycle, ctr_now);
511         printf("RCV: 0x%010"PRIX64" %010"PRIu64"  XMT: 0x%010"PRIX64" %010"PRIu64" CTR: %010"PRIu64"\n",
512                result_rcv, result_rcv, result_xmt, result_xmt, CYCLE_TIMER_TO_TICKS(ctr_now));
513
514     } else {
515         fprintf( stderr, "please specify a command\n" );
516     }
517 }
Note: See TracBrowser for help on using the browser.