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

Revision 2802, 17.7 kB (checked in by jwoithe, 3 years ago)

Cosmetic: "Firewire" becomes "FireWire?".

Officially both the "F" and "W" were capitalised in the FireWire? name, so
reflect this throughout FFADO's source tree. This mostly affects comments.

This patch originated from pander on the ffado-devel mailing list. To
maintain consistency, the committed version has been expanded to include
files not originally included in the original patch.

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