Attachment 'firewire_tester.c'
Download
Toggle line numbers
1 /*
2 * firewire_tester
3 * Copyright (c) 2006 by Jim Westfall
4 * Distributed as part of MythTV under GPL v2 and later.
5 *
6 * $ gcc -Wall -o firewire_tester firewire_tester.c -liec61883 -lraw1394
7 */
8
9 #include <unistd.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <sys/select.h>
13 #include <libraw1394/raw1394.h>
14 #include <libiec61883/iec61883.h>
15
16 #define ACTION_NONE -1
17 #define ACTION_TEST_BCAST 0
18 #define ACTION_TEST_P2P 1
19 #define ACTION_FIX_BCAST 2
20
21 #define SYNC_BYTE 0x47
22 #define MIN_PACKETS 25
23
24 #define VERBOSE(args...) do { if (verbose) printf(args); } while (0)
25
26 int verbose = 0;
27 int sync_failed = 0;
28
29 static int read_packet (unsigned char *tspacket, int len,
30 unsigned int dropped, void *callback_data)
31 {
32 int *count = (int *)callback_data;
33
34 if (dropped)
35 {
36 printf("Dropped %d packet(s).\n", dropped);
37 return 0;
38 }
39
40 if (tspacket[0] != SYNC_BYTE)
41 {
42 sync_failed = 1;
43 return 0;
44 }
45 *count = *count + 1;
46 return 1;
47 }
48
49 int test_connection(raw1394handle_t handle, int channel)
50 {
51 int count = 0;
52 int retry = 0;
53 int fd = raw1394_get_fd(handle);
54 iec61883_mpeg2_t mpeg;
55 struct timeval tv;
56 fd_set rfds;
57
58 sync_failed = 0;
59 mpeg = iec61883_mpeg2_recv_init(handle, read_packet, (void*) &count);
60 iec61883_mpeg2_recv_start(mpeg, channel);
61 while(count < MIN_PACKETS && retry < 2 && !sync_failed)
62 {
63 FD_ZERO(&rfds);
64 FD_SET(fd, &rfds);
65 tv.tv_sec = 1;
66 tv.tv_usec = 0;
67
68 if (select(fd + 1, &rfds, NULL, NULL, &tv) > 0)
69 {
70 raw1394_loop_iterate(handle);
71 }
72 else
73 {
74 retry++;
75 }
76 }
77 iec61883_mpeg2_recv_stop(mpeg);
78 iec61883_mpeg2_close(mpeg);
79
80 if (sync_failed)
81 return 0;
82
83 return count;
84 }
85
86 // create and test a p2p connection
87 // returns 1 on success, 0 on failure
88 int test_p2p(raw1394handle_t handle, nodeid_t node) {
89 int channel, count, success = 0;
90 channel = node;
91
92
93 VERBOSE("P2P: Creating, node %d, channel %d\n", node, channel);
94
95 printf("P2P: Testing...");
96 fflush(stdout);
97
98 // make connection
99 if (iec61883_cmp_create_p2p_output(handle, node | 0xffc0, 0, channel,
100 1 /* fix me, speed */ ) != 0)
101 {
102 printf("iec61883_cmp_create_p2p_output failed\n");
103 return 0;
104 }
105
106 count = test_connection(handle, channel);
107 if (count >= MIN_PACKETS)
108 {
109 printf("Success, %d packets received\n", count);
110 success = 1;
111 }
112 else
113 {
114 printf("Failed%s\n", (sync_failed ? " (sync failed)":""));
115 }
116
117 VERBOSE("P2P: Disconnecting.\n");
118 iec61883_cmp_disconnect(handle, node | 0xffc0, 0,
119 raw1394_get_local_id (handle),
120 -1, channel, 0);
121 return success;
122 }
123
124 // create and test a broadcast connection
125 // returns 1 on success, 0 on failure
126 int test_broadcast(raw1394handle_t handle, nodeid_t node) {
127 int channel, count, success = 0;
128 channel = 63 - node;
129
130 VERBOSE("Broadcast: Creating, node %d, channel %d\n", node, channel);
131
132 printf("Broadcast: Testing...");
133 fflush(stdout);
134
135 // open connection
136 if (iec61883_cmp_create_bcast_output(handle, node | 0xffc0, 0, channel,
137 1 /* fix me, speed */ ) != 0)
138 {
139 printf("iec61883_cmp_create_bcast_output failed\n");
140 return 0;
141 }
142 count = test_connection(handle, channel);
143
144 if (count >= MIN_PACKETS)
145 {
146 printf("Success, %d packets\n", count);
147 success = 1;
148 }
149 else
150 {
151 printf("Failed%s\n", (sync_failed ? " (sync failed)":""));
152 }
153
154 VERBOSE("Broadcast: Disconnecting.\n");
155 iec61883_cmp_disconnect(handle, node | 0xffc0, 0,
156 raw1394_get_local_id (handle),
157 -1, channel, 0);
158 return success;
159 }
160
161 /*
162 * Attempt to get a reliable broadcast connection initialized
163 * This is done by first attempting multiple p2p connections until data is
164 * received, once data is seen we then attempt multiple (5) broadcast
165 * connections to verify the connection is stable.
166 * returns 1 on success, 0 on fail.
167 */
168 int fix_broadcast(raw1394handle_t handle, nodeid_t node) {
169 int p2p_retries = 0;
170 int bcast_success = 0;
171
172 // see if we even need to fix it
173 while (test_broadcast(handle, node))
174 {
175 bcast_success++;
176 if (bcast_success == 5)
177 {
178 printf("Broadcast Fix: Success (already stable)\n");
179 return 1;
180 }
181 }
182
183 // attempt upto 10 p2p connections looking for data
184 while (p2p_retries < 10)
185 {
186 if (test_p2p(handle, node))
187 {
188 // got data from p2p, try a few bcast connections
189 bcast_success = 0;
190 while (test_broadcast(handle, node))
191 {
192 bcast_success++;
193 if (bcast_success == 5)
194 {
195 printf("Broadcast Fix: Success\n");
196 return 1;
197 }
198 }
199 }
200 p2p_retries++;
201 }
202 printf("Broadcast Fix: Failed\n");
203 return 0;
204 }
205
206 void usage(void) {
207 printf("firewire_tester <action> -n <node> [-P <port>] [-r <n>] [-v]\n");
208 printf(" Actions: (one is required)\n");
209 printf(" -b - test broadcast connection\n");
210 printf(" -p - test p2p connection\n");
211 printf(" -B - attempt to fix/stabilize broadcast connection\n");
212 printf(" Options\n");
213 printf(" -n <node> - firewire node, required\n");
214 printf(" -P <port> - firewire port, default 0\n");
215 printf(" -r <n> - run action <n> times, default 1\n");
216 printf(" -v - verbose\n");
217 exit(1);
218 }
219
220 int main(int argc, char **argv) {
221 raw1394handle_t handle;
222 int node = -1;
223 int port = 0;
224 int runs = 1;
225 int c, i, success;
226 int action = ACTION_NONE;
227
228 opterr = 0;
229 while ((c = getopt(argc, argv, "Bbn:pP:r:v")) != -1)
230 {
231 switch (c)
232 {
233
234 // attempt to get a reliable bcast connection initialize
235 case 'B':
236 if (action != ACTION_NONE)
237 {
238 printf("Invalid command line\n");
239 usage();
240 }
241 action = ACTION_FIX_BCAST;
242 break;
243
244 // test broadcast connection
245 case 'b':
246 if (action != ACTION_NONE)
247 {
248 printf("Invalid command line\n");
249 usage();
250 }
251 action = ACTION_TEST_BCAST;
252 break;
253
254 // set the node, required
255 case 'n':
256 node = atoi(optarg);
257 if (node < 0 || node > 63)
258 {
259 printf("Invalid node: %d\n", node);
260 exit(1);
261 }
262 break;
263
264 // set the port, optional
265 case 'P':
266 port = atoi(optarg);
267 if (port < 0)
268 {
269 printf("Invalid port: %d\n", port);
270 }
271 break;
272
273 // test a p2p connection
274 case 'p':
275 if (action != ACTION_NONE)
276 {
277 printf("Invalid command line\n");
278 usage();
279 }
280 action = ACTION_TEST_P2P;
281 break;
282
283 // number of runs
284 case 'r':
285 runs = atoi(optarg);
286 if (runs <= 0)
287 {
288 printf("Run amount <= 0\n");
289 usage();
290 }
291 break;
292
293 // verbose
294 case 'v':
295 verbose = 1;
296 break;
297
298 // bad option
299 default:
300 printf("Invalid command line\n");
301 usage();
302
303 }
304 }
305
306 if (action == ACTION_NONE)
307 {
308 usage();
309 }
310
311 if (node == -1)
312 {
313 printf("-n <node> is a required option\n");
314 usage();
315 }
316
317 VERBOSE("raw1394: Allocating handle, port %d.\n", port);
318 handle = raw1394_new_handle_on_port(port);
319 if (!handle)
320 {
321 printf("Failed to create new raw1394 handle on port %d\n", port);
322 exit(1);
323 }
324
325 success = 0;
326 switch (action)
327 {
328 case ACTION_TEST_BCAST:
329 printf("Action: Test broadcast %d times, node %d, channel %d\n",
330 runs, node, 63 - node);
331 for (i = 0;i < runs;i++)
332 success += test_broadcast(handle, node);
333 break;
334 case ACTION_TEST_P2P:
335 printf("Action: Test P2P connection %d times, node %d, channel %d\n",
336 runs, node, node);
337 for (i = 0;i < runs;i++)
338 success += test_p2p(handle, node);
339 break;
340 case ACTION_FIX_BCAST:
341 printf("Action: Attempt to fix broadcast connection %d times, node %d\n",
342 runs, node);
343 for (i = 0;i < runs;i++)
344 success += fix_broadcast(handle, node);
345 break;
346 }
347
348 VERBOSE("raw1394: Releasing handle.\n");
349 raw1394_destroy_handle(handle);
350 exit(!(success == runs));
351 }
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.