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

Revision 1163, 14.6 kB (checked in by ppalmers, 16 years ago)

make dbus server handle busresets cleanly (fixes #102)

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