root/trunk/libffado/tests/systemtests/test-isoxmit-1.cpp

Revision 1700, 8.6 kB (checked in by arnonym, 14 years ago)

Use the libraw1394 in the correct way by only checking errno if an error actually occured.

Line 
1 /*
2  * Parts Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 /*
25  * ISO xmit stall test
26  * This test stalls on certain controllers from a packet size = 225 on
27  *
28  * Controllers affected:
29  *  O2 Micro, Inc. Firewire (IEEE 1394) (rev 02)
30  *  Texas Instruments XIO2200(A) IEEE-1394a-2000 Controller (PHY/Link) (rev 01)
31  * not affected:
32  *  NEC Corporation uPD72874 IEEE1394 OHCI 1.1 3-port PHY-Link Ctrlr (rev 01)
33  *
34  * gcc -g -O2 -Wall -D_REENTRANT -std=c99 -D_GNU_SOURCE -o testxmitstall testxmitstall.c -lm -lpthread -lraw1394
35  *
36  */
37
38 /*
39  * based on howdysend.c (unknown source, maybe Maas Digital LLC)
40  */
41
42 #include <libraw1394/raw1394.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <stdint.h>
47 #include <stdlib.h>
48 #include <argp.h>
49
50 #include "debugmodule/debugmodule.h"
51 #include "realtimetools.h"
52
53 #define SPEED           RAW1394_ISO_SPEED_400
54
55 uint32_t count = 0;
56
57 DECLARE_GLOBAL_DEBUG_MODULE;
58
59 #define MAX_EXTRA_ARGS 2
60 // Program documentation.
61 // Program documentation.
62 static char doc[] = "FFADO -- ISO transmit stall test\n\n";
63
64 // A description of the arguments we accept.
65 static char args_doc[] = "";
66
67 struct arguments
68 {
69     long int verbose;
70     long int port;
71     long int channel;
72     long int packetsize;
73     long int buffersize;
74     long int interval;
75     long int prebuffers;
76     long int startoncycle;
77     long int countdown;
78     long int printinterval;
79     long int rtprio;
80     char* args[MAX_EXTRA_ARGS];
81 };
82
83 // The options we understand.
84 static struct argp_option options[] = {
85     {"verbose",  'v', "level",    0,  "Verbose level" },
86     {"port",  'p', "port",  0,  "firewire port to use" },
87     {"channel",  'c', "channel",  0,  "iso channel to use" },
88     {"packetsize",  's', "packetsize",  0,  "packet size to use" },
89     {"buffersize",  'b', "buffersize",  0,  "number of packets to buffer" },
90     {"interval",  'i', "interval",  0,  "interrupt interval in packets" },
91     {"prebuffers",  'x', "packets",  0,  "number of packets to prebuffer" },
92     {"startoncycle",  't', "cycle",  0,  "start on a specific cycle" },
93     {"countdown",  'u', "count",  0,  "number of iterations to run" },
94     {"printinterval",  'r', "packets",  0,  "number of packets between successive status prints" },
95     {"rtprio",  'P', "prio",  0,  "real time priority of the iterator process/thread (0 = no RT)" },
96     { 0 }
97 };
98
99 // Parse a single option.
100 #define PARSE_ARG_LONG(XXletterXX, XXvarXX, XXdescXX) \
101     case XXletterXX: \
102         if (arg) { \
103             XXvarXX = strtol( arg, &tail, 0 ); \
104             if ( errno ) { \
105                 fprintf( stderr,  "Could not parse '%s' argument\n", XXdescXX ); \
106                 return ARGP_ERR_UNKNOWN; \
107             } \
108         } \
109         break;
110
111 static error_t
112 parse_opt( int key, char* arg, struct argp_state* state )
113 {
114     // Get the input argument from `argp_parse', which we
115     // know is a pointer to our arguments structure.
116     struct arguments* arguments = ( struct arguments* ) state->input;
117     char* tail;
118
119     errno = 0;
120     switch (key) {
121     PARSE_ARG_LONG('v', arguments->verbose, "verbose");
122     PARSE_ARG_LONG('p', arguments->port, "port");
123     PARSE_ARG_LONG('c', arguments->channel, "channel");
124     PARSE_ARG_LONG('s', arguments->packetsize, "packetsize");
125     PARSE_ARG_LONG('b', arguments->buffersize, "buffersize");
126     PARSE_ARG_LONG('i', arguments->interval, "interval");
127     PARSE_ARG_LONG('x', arguments->prebuffers, "prebuffers");
128     PARSE_ARG_LONG('t', arguments->startoncycle, "startoncycle");
129     PARSE_ARG_LONG('u', arguments->countdown, "countdown");
130     PARSE_ARG_LONG('r', arguments->printinterval, "printinterval");
131     PARSE_ARG_LONG('P', arguments->rtprio, "rtprio");
132
133     case ARGP_KEY_ARG:
134         break;
135     case ARGP_KEY_END:
136         break;
137     default:
138         return ARGP_ERR_UNKNOWN;
139     }
140     return 0;
141 }
142
143 // Our argp parser.
144 static struct argp argp = { options, parse_opt, args_doc, doc };
145
146 // the global arguments struct
147 struct arguments arguments;
148
149 int32_t last_cycle = -1;
150
151 static enum raw1394_iso_disposition myISOSender(raw1394handle_t handle,
152         unsigned char *data,
153         uint32_t *len,
154         unsigned char *tag,
155         unsigned char *sy,
156         int32_t cycle,
157         uint32_t dropped1)
158 {
159     unsigned int skipped = (dropped1 & 0xFFFF0000) >> 16;
160     unsigned int dropped = dropped1 & 0xFFFF;
161
162     //debugOutput(DEBUG_LEVEL_INFO, "In handler\n");
163     sprintf((char *)data, "Hello World %8u\n", count);
164     if (last_cycle >= 0) {
165         if (cycle != (last_cycle + 1) % 8000) {
166             debugOutput(DEBUG_LEVEL_INFO, "nonmonotonic cycles: this: %04d, last: %04d, dropped: 0x%08X\n", cycle, last_cycle, dropped1);
167         }
168     }
169     last_cycle = cycle;
170     count++;
171     *len = arguments.packetsize;
172     *tag = 1;
173     *sy = 0;
174     if(dropped) debugOutput(DEBUG_LEVEL_INFO, "Dropped packets! (%d)\n", dropped);
175     if(skipped) debugOutput(DEBUG_LEVEL_INFO, "Skipped packets! (%d)\n", skipped);
176     if (count % arguments.printinterval == 0) debugOutput(DEBUG_LEVEL_INFO, "cycle=%d count=%d\n", cycle, count);
177     return RAW1394_ISO_OK;
178 }
179
180 void prepareXmit(raw1394handle_t handle)
181 {
182     debugOutput(DEBUG_LEVEL_INFO, "prepareXmit(handle)\n");
183     if(raw1394_iso_xmit_init(handle,
184                 myISOSender,
185                 arguments.buffersize,
186                 arguments.packetsize,
187                 arguments.channel,
188                 SPEED,
189                 arguments.interval))
190     {
191         perror("raw1394_iso_xmit_init");
192         exit(1);
193     }
194
195     if(raw1394_iso_xmit_start(handle, arguments.startoncycle, arguments.prebuffers))
196     {
197         perror("raw1394_iso_xmit_start");
198         exit(1);
199     }
200 }
201
202 int32_t myResetHandler(raw1394handle_t handle, uint32_t generation)
203 {   
204     debugOutput(DEBUG_LEVEL_INFO, "Reset happened\n");   
205     raw1394_iso_shutdown(handle);
206     raw1394_update_generation(handle, generation);
207     prepareXmit(handle);
208     return 0;
209 }
210
211 int32_t main(int32_t argc, char **argv)
212 {
213     raw1394handle_t handle;
214
215     // Default values.
216     arguments.verbose = DEBUG_LEVEL_VERBOSE;
217     arguments.port = 0;
218     arguments.channel = 0;
219     arguments.packetsize = 1024;
220     arguments.buffersize = 100;
221     arguments.interval = -1;
222     arguments.prebuffers = 0;
223     arguments.startoncycle = -1;
224     arguments.countdown = 10000;
225     arguments.printinterval = 100;
226     arguments.rtprio = 0;
227
228     // Parse our arguments; every option seen by `parse_opt' will
229     // be reflected in `arguments'.
230     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
231         debugError("Could not parse command line\n" );
232         return -1;
233     }
234
235     debugOutput(DEBUG_LEVEL_NORMAL, "verbose level = %d\n", arguments.verbose);
236     setDebugLevel(arguments.verbose);
237
238     debugOutput(DEBUG_LEVEL_INFO, "Get 1394 handle...\n");
239     handle = raw1394_new_handle();
240     if(!handle)
241     {
242         perror("raw1394_new_handle");
243         return -1;
244     }
245
246     debugOutput(DEBUG_LEVEL_INFO, "Select 1394 port %d...\n", arguments.port);
247     int ret = -1;
248     do
249     {
250         if (raw1394_get_port_info(handle, NULL, 0) < 0)
251         {
252             perror("raw1394_get_port_info");
253             return 1;
254         }
255         ret = raw1394_set_port(handle, arguments.port );
256     } while (ret != 0 && errno == ESTALE);
257
258     if(ret != 0 && errno)
259     {
260         perror("raw1394_set_port");
261         return 1;
262     }
263
264     if(raw1394_busreset_notify(handle, RAW1394_NOTIFY_ON))
265     {
266         perror("raw1394_busreset_notify");
267         exit(1);
268     }
269     raw1394_set_bus_reset_handler(handle, myResetHandler);
270
271     debugOutput(DEBUG_LEVEL_INFO, "Setting RT priority (%d)...\n", arguments.rtprio);
272     set_realtime_priority(arguments.rtprio);
273
274     debugOutput(DEBUG_LEVEL_INFO, "Prepare/start ISO transmit...\n");
275     prepareXmit(handle);
276
277     int countdown = arguments.countdown;
278     debugOutput(DEBUG_LEVEL_INFO, "Starting iterate loop...\n");
279     while(countdown--)
280     {
281         if(raw1394_loop_iterate(handle))
282         {
283             perror("raw1394_loop_iterate");
284             return 1;
285         }
286     }
287     return 0;
288 }
Note: See TracBrowser for help on using the browser.