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

Revision 1022, 14.1 kB (checked in by ppalmers, 16 years ago)

add ListDevices? operation

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
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                     ;
68
69 // A description of the arguments we accept.
70 static char args_doc[] = "OPERATION";
71
72 struct arguments
73 {
74     unsigned int nargs;
75     short    silent;
76     long int verbose;
77     long int port;
78     long int use_cache;
79     long int node_id;
80     long int node_id_set;
81     const char* args[MAX_ARGS];
82 };
83
84 // The options we understand.
85 static struct argp_option options[] = {
86     {"quiet",    'q',       0,    0,  "Don't produce any output" },
87     {"silent",   's',       0,    OPTION_ALIAS },
88
89     {"verbose",  'v', "level",    0,  "Produce verbose output" },
90     {"cache",    'c', "enable",   0,  "Use AVC model cache (default=enabled)" },
91
92
93     {"node",     'n',    "id",    0,  "Node to use" },
94     {"port",     'p',    "nr",    0,  "IEEE1394 Port to use" },
95     { 0 }
96 };
97
98 //-------------------------------------------------------------
99
100 // Parse a single option.
101 static error_t
102 parse_opt( int key, char* arg, struct argp_state* state )
103 {
104     // Get the input argument from `argp_parse', which we
105     // know is a pointer to our arguments structure.
106     struct arguments* arguments = ( struct arguments* ) state->input;
107     char* tail;
108
109     switch (key) {
110     case 'q': case 's':
111         arguments->silent = 1;
112         break;
113     case 'v':
114         if (arg) {
115             arguments->verbose = strtol( arg, &tail, 0 );
116             if ( errno ) {
117                 fprintf( stderr,  "Could not parse 'verbose' argument\n" );
118                 return ARGP_ERR_UNKNOWN;
119             }
120         }
121         break;
122     case 'c':
123         if (arg) {
124             arguments->use_cache = strtol( arg, &tail, 0 );
125             if ( errno ) {
126                 fprintf( stderr,  "Could not parse 'cache' argument\n" );
127                 return ARGP_ERR_UNKNOWN;
128             }
129         }
130         break;     
131     case 'p':
132         if (arg) {
133             arguments->port = strtol( arg, &tail, 0 );
134             if ( errno ) {
135                 fprintf( stderr,  "Could not parse 'port' argument\n" );
136                 return ARGP_ERR_UNKNOWN;
137             }
138         } else {
139             if ( errno ) {
140                 fprintf( stderr, "Could not parse 'port' argumen\n" );
141                 return ARGP_ERR_UNKNOWN;
142             }
143         }
144         break;
145     case 'n':
146         if (arg) {
147             arguments->node_id = strtol( arg, &tail, 0 );
148             if ( errno ) {
149                 fprintf( stderr,  "Could not parse 'node' argument\n" );
150                 return ARGP_ERR_UNKNOWN;
151             }
152             arguments->node_id_set=1;
153         } else {
154             if ( errno ) {
155                 fprintf( stderr, "Could not parse 'node' argumen\n" );
156                 return ARGP_ERR_UNKNOWN;
157             }
158         }
159         break;
160     case ARGP_KEY_ARG:
161         if (state->arg_num >= MAX_ARGS) {
162             // Too many arguments.
163             argp_usage( state );
164         }
165         arguments->args[state->arg_num] = arg;
166         arguments->nargs++;
167         break;
168     case ARGP_KEY_END:
169         if (state->arg_num < 1) {
170         // Not enough arguments.
171         argp_usage( state );
172         }
173         break;
174     default:
175         return ARGP_ERR_UNKNOWN;
176     }
177     return 0;
178 }
179
180 // Our argp parser.
181 static struct argp argp = { options, parse_opt, args_doc, doc };
182
183 int exitfunction( int retval ) {
184     debugOutput( DEBUG_LEVEL_NORMAL, "Debug output flushed...\n" );
185     flushDebugOutput();
186    
187     return retval;
188 }
189
190 void
191 printDeviceList(unsigned int port)
192 {
193     Ieee1394Service service;
194     // switch off all messages since they mess up the list
195     service.setVerboseLevel(0);
196     if ( !service.initialize( port ) ) {
197         printf("Could not initialize IEEE 1394 service on port %d\n", port);
198         exit(-1);
199     }
200
201     printf("=== 1394 PORT %d ===\n", port);
202     printf("  Node id  GUID                  VendorId     ModelId   Vendor - Model\n");
203     for (int i = 0; i < service.getNodeCount(); i++) {
204         ConfigRom crom(service, i);
205         if (!crom.initialize())
206             break;
207
208         printf("  %2d       0x%s  0x%08X  0x%08X   %s - %s\n",
209                i, crom.getGuidString().c_str(),
210                crom.getNodeVendorId(), crom.getModelId(),
211                crom.getVendorName().c_str(),
212                crom.getModelName().c_str());
213     }
214 }
215
216
217 int
218 main( int argc, char **argv )
219 {
220     struct arguments arguments;
221
222     // Default values.
223     arguments.nargs       = 0;
224     arguments.silent      = 0;
225     arguments.verbose     = 0;
226     arguments.use_cache   = 1;
227     arguments.port        = 0;
228     arguments.node_id     = 0;
229     arguments.node_id_set = 0; // if we don't specify a node, discover all
230     arguments.args[0]     = "";
231     arguments.args[1]     = "";
232
233     // Parse our arguments; every option seen by `parse_opt' will
234     // be reflected in `arguments'.
235     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
236         fprintf( stderr, "Could not parse command line\n" );
237         return exitfunction(-1);
238     }
239
240     printf("verbose level = %ld\n", arguments.verbose);
241     setDebugLevel(arguments.verbose);
242
243     printf( "Using ffado library version: %s\n\n", ffado_get_version() );
244
245     if ( strcmp( arguments.args[0], "Discover" ) == 0 ) {
246         DeviceManager *m_deviceManager = new DeviceManager();
247         if ( !m_deviceManager ) {
248             fprintf( stderr, "Could not allocate device manager\n" );
249             return exitfunction(-1);
250         }
251         if ( arguments.verbose ) {
252             m_deviceManager->setVerboseLevel(arguments.verbose);
253         }
254         if ( !m_deviceManager->initialize() ) {
255             fprintf( stderr, "Could not initialize device manager\n" );
256             delete m_deviceManager;
257             return exitfunction(-1);
258         }
259         if ( arguments.verbose ) {
260             m_deviceManager->setVerboseLevel(arguments.verbose);
261         }
262         if ( !m_deviceManager->discover(arguments.use_cache) ) {
263             fprintf( stderr, "Could not discover devices\n" );
264             delete m_deviceManager;
265             return exitfunction(-1);
266         }
267         delete m_deviceManager;
268         return exitfunction(0);
269     } else if ( strcmp( arguments.args[0], "ListDevices" ) == 0 ) {
270         unsigned int nb_ports = Ieee1394Service::detectNbPorts();
271         for (unsigned int i=0;i<nb_ports;i++) {
272             printDeviceList(i);
273         }
274     } else if ( strcmp( arguments.args[0], "SetSamplerate" ) == 0 ) {
275         char* tail;
276         int samplerate = strtol( arguments.args[1], &tail, 0 );
277         if ( errno ) {
278             fprintf( stderr,  "Could not parse samplerate argument\n" );
279             return exitfunction(-1);
280         }
281
282         DeviceManager *m_deviceManager = new DeviceManager();
283         if ( !m_deviceManager ) {
284             fprintf( stderr, "Could not allocate device manager\n" );
285             return exitfunction(-1);
286         }
287         if ( arguments.verbose ) {
288             m_deviceManager->setVerboseLevel(arguments.verbose);
289         }
290         if ( !m_deviceManager->initialize() ) {
291             fprintf( stderr, "Could not initialize device manager\n" );
292             delete m_deviceManager;
293             return exitfunction(-1);
294         }
295         if ( arguments.verbose ) {
296             m_deviceManager->setVerboseLevel(arguments.verbose);
297         }
298         if ( !m_deviceManager->discover(arguments.use_cache) ) {
299             fprintf( stderr, "Could not discover devices\n" );
300             delete m_deviceManager;
301             return exitfunction(-1);
302         }
303
304         if(arguments.node_id_set) {
305             FFADODevice* avDevice = m_deviceManager->getAvDevice( arguments.node_id );
306             if ( avDevice ) {
307                 avDevice->setVerboseLevel(arguments.verbose);
308                 if ( ! avDevice->setSamplingFrequency( samplerate ) ) {
309                     fprintf( stderr, "Could not set samplerate\n" );
310                 }
311             }
312         } else {
313             int i=0;
314
315             int devices_on_bus = m_deviceManager->getNbDevices();
316             printf("  port = %ld, devices_on_bus = %d\n", arguments.port, devices_on_bus);
317
318             for(i=0;i<devices_on_bus;i++) {
319                 int node_id=m_deviceManager->getDeviceNodeId(i);
320                 printf("  set samplerate for device = %d, node = %d\n", i, node_id);
321                 FFADODevice* avDevice = m_deviceManager->getAvDevice( node_id );
322                 if ( avDevice ) {
323                     avDevice->setVerboseLevel(arguments.verbose);
324                     if ( !avDevice->setSamplingFrequency( samplerate ) ) {
325                         fprintf( stderr, "Could not set samplerate\n" );
326                     }
327                 }
328             }
329         }
330         delete m_deviceManager;
331         return exitfunction(0);
332     } else if ( strcmp( arguments.args[0], "SetClockSource" ) == 0 ) {
333         char* tail;
334         unsigned int targetid = (unsigned int)strtol( arguments.args[1], &tail, 0 );
335         if ( errno ) {
336             fprintf( stderr,  "Could not parse clock source argument\n" );
337             targetid=0xFFFF;
338         }
339         DeviceManager *m_deviceManager = new DeviceManager();
340         if ( !m_deviceManager ) {
341             fprintf( stderr, "Could not allocate device manager\n" );
342             return exitfunction(-1);
343         }
344         if ( arguments.verbose ) {
345             m_deviceManager->setVerboseLevel(arguments.verbose);
346         }
347         if ( !m_deviceManager->initialize() ) {
348             fprintf( stderr, "Could not initialize device manager\n" );
349             delete m_deviceManager;
350             return exitfunction(-1);
351         }
352         if ( arguments.verbose ) {
353             m_deviceManager->setVerboseLevel(arguments.verbose);
354         }
355         if ( !m_deviceManager->discover(arguments.use_cache) ) {
356             fprintf( stderr, "Could not discover devices\n" );
357             delete m_deviceManager;
358             return exitfunction(-1);
359         }
360
361         if(arguments.node_id_set) {
362             FFADODevice* avDevice = m_deviceManager->getAvDevice( arguments.node_id );
363             if ( avDevice ) {
364                 FFADODevice::ClockSource s;
365            
366                 avDevice->setVerboseLevel(arguments.verbose);
367                 FFADODevice::ClockSourceVector sources=avDevice->getSupportedClockSources();
368                 for ( FFADODevice::ClockSourceVector::const_iterator it
369                         = sources.begin();
370                     it != sources.end();
371                     ++it )
372                 {
373                     FFADODevice::ClockSource c=*it;
374                     printf( " Type: %s, Id: %d, Valid: %d, Active: %d, Description: %s\n",
375                         FFADODevice::ClockSourceTypeToString(c.type), c.id, c.valid, c.active, c.description.c_str());
376                    
377                     if (c.id==targetid) {
378                         s=*it;
379                     }
380                 }
381                
382                 if (s.type != FFADODevice::eCT_Invalid) {
383                     printf("  set clock source to %d\n", s.id);
384                     if ( ! avDevice->setActiveClockSource( s ) ) {
385                         fprintf( stderr, "Could not set clock source\n" );
386                     }
387                 } else {
388                     printf("  no clock source with id %d found\n", targetid);
389                 }
390             }
391         } else {
392             fprintf( stderr, "please specify a node\n" );
393         }
394         delete m_deviceManager;
395         return exitfunction(0);
396     } else if ( strcmp( arguments.args[0], "SytCalcTest" ) == 0 ) {
397         if (arguments.nargs < 4) {
398             fprintf( stderr,"Not enough arguments\n");
399             return -1;
400         }
401         uint64_t syt_timestamp = strtol(arguments.args[1], NULL, 0);
402         if (errno) {
403             fprintf( stderr,"syt_timestamp parsing failed: %s\n",
404                      strerror(errno));
405             return errno;
406         }
407         uint32_t rcv_cycle = strtol(arguments.args[2], NULL, 0);
408         if (errno) {
409             fprintf( stderr,"rcv_cycle parsing failed: %s\n",
410                      strerror(errno));
411             return errno;
412         }
413         uint64_t ctr_now = strtoll(arguments.args[3], NULL, 0);
414         if (errno) {
415             fprintf( stderr,"ctr_now parsing failed: %s\n",
416                      strerror(errno));
417             return errno;
418         }
419         uint64_t result_rcv = sytRecvToFullTicks(syt_timestamp, rcv_cycle, ctr_now);
420         uint64_t result_xmt = sytXmitToFullTicks(syt_timestamp, rcv_cycle, ctr_now);
421         printf("RCV: 0x%010llX %010llu  XMT: 0x%010llX %010llu CTR: %010llu\n",
422                result_rcv, result_rcv, result_xmt, result_xmt, CYCLE_TIMER_TO_TICKS(ctr_now));
423
424     } else {
425         fprintf( stderr, "please specify a command\n" );
426     }
427 }
Note: See TracBrowser for help on using the browser.