root/trunk/libffado/tests/scan-devreg.cpp

Revision 1135, 9.1 kB (checked in by ppalmers, 16 years ago)

centralize byteswapping and make it conditional

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  * Copyright (C) 2005-2008 by Daniel Wagner
4  * Copyright (C) 2008 by Jonathan Woithe
5  *
6  * This file is part of FFADO
7  * FFADO = Free Firewire (pro-)audio drivers for linux
8  *
9  * FFADO is based upon FreeBoB
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 2 of the License, or
14  * (at your option) version 3 of the License.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  *
24  */
25
26 #include <libraw1394/raw1394.h>
27 #include "libutil/ByteSwap.h"
28
29 #include "debugmodule/debugmodule.h"
30
31 #include "libieee1394/configrom.h"
32 #include "libieee1394/ieee1394service.h"
33 #include "libutil/Time.h"
34
35 #include <argp.h>
36 #include <stdlib.h>
37 #include <iostream>
38
39 using namespace std;
40
41 DECLARE_GLOBAL_DEBUG_MODULE;
42
43 #define MAX_ARGS 1000
44
45 #define MOTU_BASE_ADDR 0xfffff0000000ULL
46
47 // If changing these be sure to update the option help text
48 #define DEFAULT_SCAN_START_REG 0x0b00
49 #define DEFAULT_SCAN_LENGTH    0x0200
50
51 ////////////////////////////////////////////////
52 // arg parsing
53 ////////////////////////////////////////////////
54 const char *argp_program_version = "scan-devreg 0.1";
55 const char *argp_program_bug_address = "<ffado-devel@lists.sf.net>";
56 static char doc[] = "scan-devreg -- scan device registers for changes.";
57 static char args_doc[] = "NODE_ID";
58 static struct argp_option options[] = {
59     {"verbose",   'v', "LEVEL",     0,  "Set verbose level" },
60     {"port",      'p', "PORT",      0,  "Set port" },
61     {"node",      'n', "NODE",      0,  "Set node" },
62     {"start",     's', "REG",       0,  "Register to start scan at (default: 0x0b00)" },
63     {"length",    'l', "LENGTH",    0,  "Number of bytes of register space to scan (default: 0x0200)" },
64    { 0 }
65 };
66
67 struct arguments
68 {
69     arguments()
70         : nargs ( 0 )
71         , verbose( 0 )
72         , test( false )
73         , port( -1 )
74         , node ( -1 )
75         , scan_start ( DEFAULT_SCAN_START_REG )
76         , scan_length ( DEFAULT_SCAN_LENGTH )
77         {
78             args[0] = 0;
79         }
80
81     char*        args[MAX_ARGS];
82     int          nargs;
83     signed int   verbose;
84     bool         test;
85     signed int   port;
86     signed int   node;
87     signed int   scan_start;
88     signed int   scan_length;
89 } arguments;
90
91 // Parse a single option.
92 static error_t
93 parse_opt( int key, char* arg, struct argp_state* state )
94 {
95     // Get the input argument from `argp_parse', which we
96     // know is a pointer to our arguments structure.
97     struct arguments* arguments = ( struct arguments* ) state->input;
98
99     char* tail;
100     switch (key) {
101     case 'v':
102         errno = 0;
103         arguments->verbose = strtol(arg, &tail, 0);
104         if (errno) {
105              perror("argument parsing failed:");
106              return errno;
107         }
108         break;
109     case 't':
110         arguments->test = true;
111         break;
112     case 's':
113         errno = 0;
114         arguments->scan_start = strtol(arg, &tail, 0);
115         if (errno) {
116             perror("argument parsing failed:");
117             return errno;
118         }
119         if (arguments->scan_start < 0) {
120             fprintf(stderr, "Start of scan must be >= 0\n");
121             return -1;
122         }
123         break;
124     case 'l':
125         errno = 0;
126         arguments->scan_length = strtol(arg, &tail, 0);
127         if (errno) {
128             perror("argument parsing failed:");
129             return errno;
130         }
131         if (arguments->scan_length < 0) {
132             fprintf(stderr, "Scan length must be >= 0\n");
133             return -1;
134         }
135         break;
136     case 'p':
137         errno = 0;
138         arguments->port = strtol(arg, &tail, 0);
139         if (errno) {
140             perror("argument parsing failed:");
141             return errno;
142         }
143         break;
144     case 'n':
145         errno = 0;
146         arguments->node = strtol(arg, &tail, 0);
147         if (errno) {
148             perror("argument parsing failed:");
149             return errno;
150         }
151         break;
152     case ARGP_KEY_ARG:
153         if (state->arg_num >= MAX_ARGS) {
154             // Too many arguments.
155             argp_usage (state);
156         }
157         arguments->args[state->arg_num] = arg;
158         arguments->nargs++;
159         break;
160     case ARGP_KEY_END:
161         break;
162     default:
163         return ARGP_ERR_UNKNOWN;
164     }
165     return 0;
166 }
167
168 static struct argp argp = { options, parse_opt, args_doc, doc };
169
170 ///////////////////////////
171 // main
172 //////////////////////////
173 int
174 main(int argc, char **argv)
175 {
176     signed int loop = 0;
177     char chr[100];
178     signed int node_id = -1;
179     signed int port = -1;
180     signed int n_ports = -1;
181     signed int p1, p2, n1, n2;
182
183     // arg parsing
184     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
185         fprintf( stderr, "Could not parse command line\n" );
186         exit(-1);
187     }
188     errno = 0;
189
190     setDebugLevel(arguments.verbose);
191
192     // Do a really basic scan to find an audio device on the bus
193     n_ports = Ieee1394Service::detectNbPorts();
194     if (arguments.port < 0) {
195       p1 = 0;
196       p2 = n_ports;
197     } else {
198       // Scan a specific port if given on the command line
199       p1 = p2 = arguments.port;
200       p2++;
201     }
202     printf("Scanning %d firewire adapters (ports)\n", n_ports);
203     for (signed int i=p1; i<p2; i++) {
204         Ieee1394Service *tmp1394 = new Ieee1394Service();
205         if ( !tmp1394 ) {
206             debugFatal("Could not create Ieee1349Service for port %d\n", i);
207             return false;
208         }
209         tmp1394->setVerboseLevel(getDebugLevel());
210         if ( !tmp1394->initialize(i) ) {
211             delete tmp1394;
212             continue;
213         }
214
215         if (arguments.node < 0) {
216           n1 = 0;
217           n2 = tmp1394->getNodeCount();
218         } else {
219           // Scan a specific node if given on the command line
220           n1 = n2 = arguments.node;
221           n2++;
222         }
223         for (fb_nodeid_t node = n1; node < n2; node++) {
224             std::auto_ptr<ConfigRom> configRom =
225                 std::auto_ptr<ConfigRom>( new ConfigRom(*tmp1394, node));
226             if (!configRom->initialize()) {
227                 continue;
228             }
229             // Assume anything with suitable vendor IDs is an audio device.
230             // Stop at the first audio device found.  Currently we detect
231             // only MOTU devices but this can be expanded on an as-needs
232             // basis.
233             if (configRom->getNodeVendorId() == 0x1f2) {
234                 node_id = node;
235                 port = i;
236                 break;
237             }
238         }
239         delete tmp1394;
240     }
241     if (node_id == -1) {
242         printf("Could not find a target audio device on the firewire bus\n");
243         return false;
244     }
245     printf("Targetting device at port %d, node %d\n", port, node_id);
246
247     Ieee1394Service *m_1394Service = new Ieee1394Service();
248     if ( !m_1394Service ) {
249         debugFatal( "Could not create Ieee1349Service object\n" );
250         return false;
251     }
252     m_1394Service->setVerboseLevel(getDebugLevel());
253     if ( !m_1394Service->initialize(port) ) {
254         // This initialise call should never fail since it worked during the
255         // scan.  We live in a strange world though, so trap the error
256         // anyway.
257         debugFatal("Could not initialise ieee1394 on MOTU port\n");
258         delete m_1394Service;
259         return false;
260     }
261
262     quadlet_t old_vals[arguments.scan_length/4+1], quadlet;
263     unsigned int present[arguments.scan_length/(4*32)+1];
264     memset(old_vals, 0x00, sizeof(old_vals));
265     // Assume all registers are present until proven otherwise
266     memset(present, 0xff, sizeof(present));
267    
268     printf("Scanning initial register values, please wait\n");
269     chr[0] = 0;
270     while(chr[0]!='q') {
271         for (signed int reg=arguments.scan_start;
272              reg<arguments.scan_start+arguments.scan_length; reg+=4) {
273             unsigned int reg_index = (reg-arguments.scan_start)/4;
274             unsigned int pres_index = (reg-arguments.scan_start)/(4*32);
275             unsigned int pres_bit = ((reg-arguments.scan_start)/4) & 0x1f;
276
277             if (!(present[pres_index] & (1<<pres_bit))) {
278                 continue;
279             }
280
281             if (m_1394Service->read(0xffc0 | node_id, MOTU_BASE_ADDR+reg, 1, &quadlet) <= 0) {
282                 // Flag the register as not being present so we don't keep trying to read it
283                 present[pres_index] &= ~(1<<pres_bit);
284                 continue;
285             } else {
286                 quadlet = CondSwap32(quadlet);
287             }
288            
289             if (old_vals[reg_index] != quadlet) {
290                 if (loop != 0) {
291                     printf("0x%04x changed from %08X to %08X\n", reg,  old_vals[reg_index], quadlet);
292                 }
293                 old_vals[reg_index] = quadlet;
294             }
295         }
296         printf("Press <Enter> to scan, \"q<Enter>\" to exit\n");
297         fgets(chr, sizeof(chr), stdin);
298         loop++;
299     }
300
301     delete m_1394Service;
302
303     return 0;
304 }
305
Note: See TracBrowser for help on using the browser.