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

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

Cosmetic: capitalise "L" in "Linux".

"Linux" is a proper noun so it should start with a capital letter. These
changes are almost all within comments.

This patch was originally proposed by pander on the ffado-devel mailing
list. It has been expanded to cover all similar cases to maintain
consistency throughout the source tree.

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.